* Added interface to add custom controls to toolbox

* Fixes to document saving. Moz still swallows directive placeholders...
* Changed the way editor commands are hooked up and exposed more
* Minor fix to string types used in c++ glue

svn path=/trunk/aspeditor/; revision=49229
This commit is contained in:
Michael Hutchinson 2005-08-31 23:15:00 +00:00
Родитель 6949554db7
Коммит ce74746f33
12 изменённых файлов: 526 добавлений и 152 удалений

Просмотреть файл

@ -46,7 +46,8 @@ namespace AspNetEdit.SampleHost
class SampleHost
{
static DesignerHost host;
static Frame geckoFrame;
static Frame geckoFrame;
static AspNetEdit.Editor.ComponentModel.ToolboxService toolboxService;
static void Main ()
{
@ -79,7 +80,9 @@ namespace AspNetEdit.SampleHost
#endregion
#region Toolbar
// * Save/Open
Toolbar buttons = new Toolbar ();
outerBox.PackStart (buttons, false, false, 0);
@ -89,7 +92,11 @@ namespace AspNetEdit.SampleHost
ToolButton openButton = new ToolButton(Stock.Open);
buttons.Add(openButton);
openButton.Clicked += new EventHandler(openButton_Clicked);
openButton.Clicked += new EventHandler(openButton_Clicked);
buttons.Add (new SeparatorToolItem());
// * Clipboard
ToolButton undoButton = new ToolButton (Stock.Undo);
buttons.Add (undoButton);
@ -109,7 +116,39 @@ namespace AspNetEdit.SampleHost
ToolButton pasteButton = new ToolButton (Stock.Paste);
buttons.Add (pasteButton);
pasteButton.Clicked += new EventHandler (pasteButton_Clicked);
pasteButton.Clicked += new EventHandler (pasteButton_Clicked);
buttons.Add (new SeparatorToolItem());
// * Text style
ToolButton boldButton = new ToolButton (Stock.Bold);
buttons.Add (boldButton);
boldButton.Clicked += new EventHandler (boldButton_Clicked);
ToolButton italicButton = new ToolButton (Stock.Italic);
buttons.Add (italicButton);
italicButton.Clicked += new EventHandler (italicButton_Clicked);
ToolButton underlineButton = new ToolButton (Stock.Underline);
buttons.Add (underlineButton);
underlineButton.Clicked += new EventHandler (underlineButton_Clicked);
ToolButton indentButton = new ToolButton (Stock.Indent);
buttons.Add (indentButton);
indentButton.Clicked += new EventHandler (indentButton_Clicked);
ToolButton unindentButton = new ToolButton (Stock.Unindent);
buttons.Add (unindentButton);
unindentButton.Clicked += new EventHandler (unindentButton_Clicked);
buttons.Add (new SeparatorToolItem());
// * Toolbox
ToolButton toolboxAddButton = new ToolButton (Stock.Add);
buttons.Add (toolboxAddButton);
toolboxAddButton.Clicked += new EventHandler (toolboxAddButton_Clicked);
#endregion
@ -117,15 +156,15 @@ namespace AspNetEdit.SampleHost
//set up the services
ServiceContainer services = new ServiceContainer ();
services.AddService (typeof (INameCreationService), new AspNetEdit.Editor.ComponentModel.NameCreationService ());
services.AddService (typeof (ISelectionService), new AspNetEdit.Editor.ComponentModel.SelectionService ());
services.AddService (typeof (IEventBindingService), new AspNetEdit.Editor.ComponentModel.EventBindingService (window));
services.AddService (typeof (ITypeResolutionService), new AspNetEdit.Editor.ComponentModel.TypeResolutionService ());
services.AddService (typeof (INameCreationService), new NameCreationService ());
services.AddService (typeof (ISelectionService), new SelectionService ());
services.AddService (typeof (IEventBindingService), new EventBindingService (window));
services.AddService (typeof (ITypeResolutionService), new TypeResolutionService ());
ExtenderListService extListServ = new AspNetEdit.Editor.ComponentModel.ExtenderListService ();
services.AddService (typeof (IExtenderListService), extListServ);
services.AddService (typeof (IExtenderProviderService), extListServ);
services.AddService (typeof (ITypeDescriptorFilterService), new TypeDescriptorFilterService ());
AspNetEdit.Editor.ComponentModel.ToolboxService toolboxService = new AspNetEdit.Editor.ComponentModel.ToolboxService ();
toolboxService = new ToolboxService ();
services.AddService (typeof (IToolboxService), toolboxService);
//create our host
@ -147,7 +186,8 @@ namespace AspNetEdit.SampleHost
Toolbox toolbox = new Toolbox (services);
leftBox.Pack1 (toolbox, false, false);
toolboxService.PopulateFromAssembly (System.Reflection.Assembly.GetAssembly (typeof (System.Web.UI.Control)));
toolboxService.PopulateFromAssembly (System.Reflection.Assembly.GetAssembly (typeof (System.Web.UI.Control)));
toolboxService.AddToolboxItem (new TextToolboxItem ("<table><tr><td></td><td></td></tr><tr><td></td><td></td></tr></table>", "Table"), "Html");
toolbox.UpdateCategories ();
#endregion
@ -193,7 +233,6 @@ namespace AspNetEdit.SampleHost
fcd.Filter = new FileFilter();
fcd.Filter.AddPattern ("*.aspx");
fcd.SelectMultiple = false;
fcd.SetFilename (((System.Web.UI.Control)host.RootComponent).ID + ".aspx");
ResponseType response = (ResponseType) fcd.Run( );
fcd.Hide ();
@ -214,27 +253,77 @@ namespace AspNetEdit.SampleHost
static void redoButton_Clicked (object sender, EventArgs e)
{
throw new NotImplementedException ();
host.RootDocument.DoCommand (EditorCommand.Redo);
}
static void undoButton_Clicked (object sender, EventArgs e)
{
throw new NotImplementedException ();
host.RootDocument.DoCommand (EditorCommand.Undo);
}
static void cutButton_Clicked (object sender, EventArgs e)
{
throw new NotImplementedException ();
host.RootDocument.DoCommand (EditorCommand.Cut);
}
static void copyButton_Clicked (object sender, EventArgs e)
{
throw new NotImplementedException ();
host.RootDocument.DoCommand (EditorCommand.Copy);
}
static void pasteButton_Clicked (object sender, EventArgs e)
{
throw new NotImplementedException ();
host.RootDocument.DoCommand (EditorCommand.Paste);
}
static void italicButton_Clicked (object sender, EventArgs e)
{
host.RootDocument.DoCommand (EditorCommand.Italic);
}
static void boldButton_Clicked (object sender, EventArgs e)
{
host.RootDocument.DoCommand (EditorCommand.Bold);
}
static void underlineButton_Clicked (object sender, EventArgs e)
{
host.RootDocument.DoCommand (EditorCommand.Underline);
}
static void indentButton_Clicked (object sender, EventArgs e)
{
host.RootDocument.DoCommand (EditorCommand.Indent);
}
static void unindentButton_Clicked (object sender, EventArgs e)
{
host.RootDocument.DoCommand (EditorCommand.Outdent);
}
static void toolboxAddButton_Clicked (object sender, EventArgs e)
{
FileChooserDialog fcd = new FileChooserDialog ("Add custom controls...", (Window)((Widget)sender).Toplevel, FileChooserAction.Open);
fcd.AddButton(Stock.Cancel, ResponseType.Cancel);
fcd.AddButton(Stock.Open, ResponseType.Ok);
fcd.DefaultResponse = ResponseType.Ok;
fcd.Filter = new FileFilter();
fcd.Filter.AddPattern ("*.dll");
fcd.SelectMultiple = false;
ResponseType response = (ResponseType) fcd.Run( );
fcd.Hide ();
if (response == ResponseType.Ok && fcd.Filename != null)
try{
System.Reflection.Assembly a = System.Reflection.Assembly.LoadFrom (fcd.Filename);
toolboxService.PopulateFromAssembly (a);
}
catch (Exception ex) {
//TODO: handle this better!
System.Diagnostics.Trace.WriteLine ("Could not load assembly \"" + fcd.Filename + "\".");
}
fcd.Destroy();
}
#endregion

Просмотреть файл

@ -80,7 +80,7 @@ namespace AspNetEdit.Editor.ComponentModel
//check arguments
if (componentClass == null)
throw new ArgumentNullException ("componentClass");
if (!componentClass.IsSubclassOf (typeof (System.Web.UI.Control)) && componentClass.GetType() != typeof (System.Web.UI.Control))
if (!componentClass.IsSubclassOf (typeof (System.Web.UI.Control)) && componentClass != typeof (System.Web.UI.Control))
throw new ArgumentException ("componentClass must be a subclass of System.Web.UI.Control", "componentClass");
if (componentClass.IsSubclassOf (typeof (System.Web.UI.Page)))

Просмотреть файл

@ -47,7 +47,7 @@ namespace AspNetEdit.Editor.ComponentModel
{
public static readonly string newDocument = "<html>\n<head>\n\t<title>{0}</title>\n</head>\n<body>\n<form runat=\"server\">\n\n</form></body>\n</html>";
public static readonly string ControlSubstituteStructure = "<aspcontrol id=\"{0}\" width=\"{1}\" height=\"{2}\" -md-can-drop=\"{3}\" -md-can-resize=\"{4}\">{5}</aspcontrol>";
public static readonly string DirectivePlaceholderStructure = "<directiveplaceholder id =\"{0}\" />";
public static readonly string DirectivePlaceholderStructure = "<!--<directiveplaceholder id =\"{0}\" />-->";
string document;
Hashtable directives;
@ -55,13 +55,14 @@ namespace AspNetEdit.Editor.ComponentModel
private Control parent;
private DesignerHost host;
private RootDesignerView view;
private RootDesignerView view;
private DesignTimeParser aspParser;
///<summary>Creates a new document</summary>
public Document (Control parent, DesignerHost host, string documentName)
{
initDocument (parent, host);
document = String.Format (newDocument, documentName);
this.document = String.Format (newDocument, documentName);
GetView ();
}
@ -70,20 +71,15 @@ namespace AspNetEdit.Editor.ComponentModel
{
initDocument (parent, host);
DesignTimeParser ps = new DesignTimeParser (host, this);
TextReader reader = new StreamReader (fileStream);
try {
Control[] controls;
ps.ParseDocument (reader.ReadToEnd (), out controls, out document);
foreach (Control c in controls)
host.Container.Add (c);
this.document = DeserializeAndAdd (reader.ReadToEnd ());
}
catch (ParseException ex) {
document = string.Format ("<html><head></head><body><h1>{0}</h1><p>{1}</p></body></html>", ex.Title, ex.Message);
this.document = string.Format ("<html><head></head><body><h1>{0}</h1><p>{1}</p></body></html>", ex.Title, ex.Message);
}
catch (Exception ex) {
document = string.Format ("<html><head></head><body><h1>{0}</h1><p>{1}</p><p>{2}</p></body></html>", "Error loading document", ex.Message, ex.StackTrace);
this.document = string.Format ("<html><head></head><body><h1>{0}</h1><p>{1}</p><p>{2}</p></body></html>", "Error loading document", ex.Message, ex.StackTrace);
}
GetView ();
@ -102,7 +98,9 @@ namespace AspNetEdit.Editor.ComponentModel
CaseInsensitiveHashCodeProvider provider = new CaseInsensitiveHashCodeProvider(CultureInfo.InvariantCulture);
CaseInsensitiveComparer comparer = new CaseInsensitiveComparer(CultureInfo.InvariantCulture);
directives = new Hashtable (provider, comparer);
directives = new Hashtable (provider, comparer);
this.aspParser = new DesignTimeParser (host, this);
}
private void GetView ()
@ -114,8 +112,7 @@ namespace AspNetEdit.Editor.ComponentModel
System.Diagnostics.Trace.WriteLine ("Document created.");
}
#region viewing
#region Some Gecko communication stuff
//we don't want to have the document lying around forever, but we
//want the RootDesignerview to be able to get it when Gecko XUL loads
@ -128,48 +125,154 @@ namespace AspNetEdit.Editor.ComponentModel
document = null;
return doc;
}
#endregion
public string PersistDocument ()
{
//TODO: Parse document instead of StringBuilder.Replace
string stringDocument = view.GetDocument ();
StringBuilder builder = new StringBuilder (stringDocument);
if (host == null)
throw new Exception("The WebFormsPage cannot be persisted without a host");
//substitute all components
foreach (IComponent comp in host.Container.Components)
{
if (comp is Page)
continue;
if (!(comp is Control) || comp.Site == null)
throw new Exception("The component is not a sited System.Web.UI.Control");
string substituteText = RenderDesignerControl ((Control)comp);
string persistedText = ControlPersister.PersistControl ((Control)comp, host);
builder.Replace(substituteText, persistedText);
}
//substitute all directive placeholders
for (int i = 0; i <= directivePlaceholderKey; i++)
{
string persistedText = RemoveDirective(i);
string substituteText = String.Format (DirectivePlaceholderStructure, i.ToString());
if (stringDocument.IndexOf(substituteText) > -1)
builder.Replace (substituteText, persistedText);
else
builder.Insert (0, persistedText);
}
return builder.ToString();
}
#region add/remove/update controls
///<summary>Serialises the entire document to ASP.NET code</summary>
public string PersistDocument ()
{
StringBuilder builder = new StringBuilder(this.Serialize (view.GetDocument ()));
//insert all remaining directives
for (int i = 0; i <= directivePlaceholderKey; i++)
{
builder.Insert (0, RemoveDirective(i));
}
return builder.ToString ();
}
public void DoCommand (string editorCommand)
{
view.DoCommand (editorCommand);
}
#endregion
#region Serialisation stuff
///<summary>Converts a designer document fragment to ASP.NET code</summary>
public string Serialize (string designerDocumentFragment)
{
if (host == null)
throw new Exception("The document cannot be persisted without a host");
string serializedDoc = string.Empty;
StringWriter writer = new StringWriter ();
//keep method argument meaningfully named, but keep code readable!
string frag = designerDocumentFragment;
int length = frag.Length;
int pos = 0;
SMode mode = SMode.Free;
while (pos < length)
{
char c = frag [pos];
switch (mode)
{
//it's freely copying to output, but watching for a directive or control placeholder
case SMode.Free:
if (c == '<')
{
if ((pos + 10 < length) && frag.Substring (pos + 1, 10) == "aspcontrol") {
mode = SMode.ControlId;
pos += 10;
break;
}
else if ((pos + 24 < length) && frag.Substring (pos + 1, 24) == "!--<directiveplaceholder") {
mode = SMode.DirectiveId;
pos += 24;
break;
}
}
writer.Write (c);
break;
//it's found a directive placeholder and is scanning for the ID
case SMode.DirectiveId:
if (c == 'i' && (pos + 4 < length) && frag.Substring (pos, 4) == "id=\"") {
int idEnd = frag.IndexOf ('"', pos + 4 + 1);
if (idEnd == -1) throw new Exception ("Identifier was unterminated");
int id = System.Convert.ToInt32 (frag.Substring (pos + 4 + 1, (idEnd - pos - 4)));
//TODO: more intelligent removal/copying of directives in case of fragments
//works fine with whole document.
string directive = RemoveDirective (id);
writer.Write (directive);
mode = SMode.DirectiveEnd;
pos = idEnd;
}
break;
//it's found a control placeholder and is scanning for the ID
case SMode.ControlId:
if (c == 'i' && (pos + 4 < length) && frag.Substring (pos, 4) == "id=\"") {
int idEnd = frag.IndexOf("\"", pos + 4);
if (idEnd == -1) throw new Exception ("Identifier was unterminated");
string id = frag.Substring (pos + 4, (idEnd - pos - 4));
System.Diagnostics.Trace.WriteLine ("Persisting control with id: " + id);
DesignContainer dc = (DesignContainer) host.Container;
Control control = dc.GetComponent (id) as Control;
if (control == null) throw new Exception ("Could not retrieve control "+id);
ControlPersister.PersistControl (writer, control);
mode = SMode.ControlEnd;
pos = idEnd;
}
break;
//it's found the control's ID and is looking for the end
case SMode.ControlEnd:
if (c == '<' && (pos + 13 < length) && frag.Substring (pos, 13) == "</aspcontrol>") {
pos += 12;
mode = SMode.Free;
}
break;
//it's found the placeholder's ID and is looking for the end
case SMode.DirectiveEnd:
mode = SMode.Free;
break;
}
pos++;
}
serializedDoc = writer.ToString ();
writer.Close ();
return serializedDoc;
}
///<summary>Converts a ASP.NET fragment to a a designer document fragment,
/// and adds the controls and directives etc to the host.</summary>
public string DeserializeAndAdd (string aspFragment)
{
string document;
Control[] controls;
aspParser.ParseDocument (aspFragment, out controls, out document);
foreach (Control c in controls)
host.Container.Add (c);
return document;
}
//modes for the Serializing parser
private enum SMode {
Free,
ControlId,
DirectiveId,
ControlEnd,
DirectiveEnd
}
///<summary>Renders the designer html for an ASP.NET Control</summary>
public static string RenderDesignerControl (Control control)
{
string height = "auto";
@ -181,7 +284,7 @@ namespace AspNetEdit.Editor.ComponentModel
WebControl wc = control as WebControl;
if (wc != null) {
height = wc.Height.ToString ();
width = wc.Height.ToString ();
width = wc.Width.ToString ();
}
else
{
@ -203,22 +306,30 @@ namespace AspNetEdit.Editor.ComponentModel
return string.Format (ControlSubstituteStructure, id, width, height, canDrop, canResize, content);
}
#endregion
#region add/remove/update controls
public void AddControl(Control control)
public void AddControl (Control control)
{
view.AddControl (control);
}
public void RemoveControl(Control control)
public void RemoveControl (Control control)
{
view.RemoveControl (control);
}
public void RenameControl(string oldName, string newName)
public void RenameControl (string oldName, string newName)
{
view.RenameControl (oldName, newName);
}
}
public void InsertFragment (string fragment)
{
view.InsertFragment (fragment);
}
#endregion

Просмотреть файл

@ -44,7 +44,14 @@ namespace AspNetEdit.Editor.ComponentModel
{
Hashtable categories = new Hashtable ();
private string selectedCategory;
private ToolboxItem selectedItem = null;
private ToolboxItem selectedItem = null;
public event EventHandler ToolboxChanged;
protected void OnToolboxChanged ()
{
ToolboxChanged (this, new EventArgs ());
}
#region IToolboxService Members
@ -76,8 +83,9 @@ namespace AspNetEdit.Editor.ComponentModel
public void AddToolboxItem (ToolboxItem toolboxItem, string category)
{
if (!categories.ContainsKey (category))
categories[category] = new ArrayList ();
categories[category] = new ArrayList ();
System.Diagnostics.Trace.WriteLine ("Adding ToolboxItem: " + toolboxItem.DisplayName + ", " + category);
((ArrayList) categories[category]).Add (toolboxItem);
}
@ -290,6 +298,8 @@ namespace AspNetEdit.Editor.ComponentModel
foreach (Type t in types)
{
if (t.IsAbstract || t.IsNotPublic) continue;
if (t.GetConstructor (new Type[] {}) == null) continue;
AttributeCollection atts = TypeDescriptor.GetAttributes (t);
@ -314,9 +324,10 @@ namespace AspNetEdit.Editor.ComponentModel
category = "Data Controls";
else if (t.IsSubclassOf (typeof (System.Web.UI.WebControls.WebControl)))
category = "Web Controls";
AddToolboxItem ((ToolboxItem) Activator.CreateInstance (toolboxItemType, new object[] {t}), category);
}
}
OnToolboxChanged ();
}
#endregion

Просмотреть файл

@ -43,10 +43,21 @@ using AspNetEdit.Editor.Persistence;
namespace AspNetEdit.Editor.ComponentModel
{
internal class WebFormPage : System.Web.UI.Page
{
{
private HttpRequest httpRequest;
public WebFormPage ()
{
pdc = TypeDescriptor.GetProperties (this);
pdc = TypeDescriptor.GetProperties (this);
//fake the request for some controls which need it
/*
HttpRequest request = new HttpRequest (string.Empty, "file:///", string.Empty);
System.IO.StringWriter strw = new System.IO.StringWriter ();
HttpResponse response = new HttpResponse (strw);
HttpContext context = new HttpContext (request, response);
this.ProcessRequest (context);
*/
}
//FIXME: enforce this...

Просмотреть файл

@ -263,7 +263,9 @@ namespace AspNetEdit.Editor.Persistence
PersistenceModeAttribute modeAttrib = prop.Attributes[typeof(PersistenceModeAttribute)] as PersistenceModeAttribute;
if (modeAttrib == null || modeAttrib.Mode == PersistenceMode.Attribute)
continue;
continue;
Console.WriteLine ("Prop: "+prop.Name+"PersistenceMode:"+modeAttrib.Mode.ToString());
//handle the different modes
switch (modeAttrib.Mode)
@ -279,7 +281,7 @@ namespace AspNetEdit.Editor.Persistence
case PersistenceMode.InnerDefaultProperty:
if (contentStarted)
throw new Exception("The Control has inner properties in addition to a default inner property");
PersistInnerProperty(prop,prop.GetValue (component), writer, host, true);
PersistInnerProperty(prop, prop.GetValue (component), writer, host, true);
return;
case PersistenceMode.InnerProperty:
PersistInnerProperty (prop, prop.GetValue (component), writer, host, false);
@ -293,33 +295,26 @@ namespace AspNetEdit.Editor.Persistence
//once we've determined we need to persist a property, this does the actual work
private static void PersistInnerProperty (PropertyDescriptor prop, object value, HtmlTextWriter writer, IDesignerHost host, bool isDefault)
{
//look up tag prefix from host
IWebFormReferenceManager refMan = host.GetService (typeof (IWebFormReferenceManager)) as IWebFormReferenceManager;
if (refMan == null)
throw new Exception("Could not obtain IWebFormReferenceManager service"); ;
string prefix = refMan.GetTagPrefix (prop.PropertyType);
{
//newline and indent
writer.WriteLine();
//trivial case
if (value == null) {
if (!isDefault) {
writer.WriteBeginTag (prefix + ":" + prop.Name);
writer.WriteBeginTag (prop.Name);
writer.Write (HtmlTextWriter.SelfClosingTagEnd);
}
return;
}
//Persist collections as tag with property name
//containing tags of object name, with object properties as attribs
//A collection? Persist individual objects.
if (value is ICollection) {
if (((ICollection) value).Count > 0) {
if (((ICollection) value).Count > 0) {
//if default property needs no surrounding tags
if(!isDefault) {
writer.WriteFullBeginTag(prefix + ":" + prop.Name);
writer.WriteFullBeginTag (prop.Name);
writer.Indent++;
}
@ -328,15 +323,21 @@ namespace AspNetEdit.Editor.Persistence
if(!isDefault) {
writer.Indent--;
writer.WriteEndTag (prefix + ":" + prop.Name);
writer.WriteEndTag (prop.Name);
}
}
}
//not a collection? Simple: a tag of object name, with object properties as attribs
else
{
//default but not collection: just write content
else if (isDefault) {
if (prop.Converter.CanConvertTo (typeof (string))){
writer.Write (prop.Converter.ConvertToString (value));
return;
}
}
//else: a tag of property name, with sub-properties as attribs
else {
//only want to render tag if it has any attributes
writer.WriteBeginTag (prefix + ":" + prop.Name);
writer.WriteBeginTag (prop.Name);
foreach (PropertyDescriptor p in TypeDescriptor.GetProperties(value))
ProcessAttribute (p, value, writer, string.Empty);

Просмотреть файл

@ -98,18 +98,15 @@ namespace AspNetEdit.Editor.UI
//Register incoming calls from JavaScript
comm.RegisterJSHandler ("Click", new ClrCall (JSClick));
comm.RegisterJSHandler ("SavePage", new ClrCall (JSSave));
comm.RegisterJSHandler ("Activate", new ClrCall (JSActivate));
comm.RegisterJSHandler ("ThrowException", new ClrCall (JSException));
comm.RegisterJSHandler ("DebugStatement", new ClrCall (JSDebugStatement));
comm.RegisterJSHandler ("ResizeControl", new ClrCall (JSResize));
comm.RegisterJSHandler ("DocumentReturn", new ClrCall (JSDocumentReturn));
System.Diagnostics.Trace.WriteLine ("RootDesignerView created");
//TODO: Gecko seems to be taking over DND
//register for drag+drop
//TargetEntry te = new TargetEntry(Toolbox.DragDropIdentifier, TargetFlags.App, 0);
//Drag.DestSet (this, DestDefaults.All, new TargetEntry[] { te }, Gdk.DragAction.Copy);
//this.DragDataReceived += new DragDataReceivedHandler(view_DragDataReceived);
comm.RegisterJSHandler ("DocumentReturn", new ClrCall (JSDocumentReturn));
comm.RegisterJSHandler ("RemoveControl", new ClrCall (JSRemoveControl));
comm.RegisterJSHandler ("DeserializeAndAdd", new ClrCall (JSDeserializeAndAdd));
comm.RegisterJSHandler ("Serialize", new ClrCall (JSSerialize));
System.Diagnostics.Trace.WriteLine ("RootDesignerView created");
}
internal void BeginLoad ()
@ -163,6 +160,12 @@ namespace AspNetEdit.Editor.UI
#region document modification accessors for AspNetEdit.Editor.ComponentModel.Document
internal void InsertFragment (string fragment)
{
System.Diagnostics.Trace.WriteLine ("Inserting document fragment: " + fragment);
comm.JSCall (GeckoFunctions.InsertFragment, null, fragment);
}
internal void AddControl(Control control)
{
if (!active) return;
@ -204,6 +207,24 @@ namespace AspNetEdit.Editor.UI
return d;
}
internal void DoCommand (string editorCommand)
{
System.Diagnostics.Trace.WriteLine ( "Executing command \"" + editorCommand +"\"");
comm.JSCall (GeckoFunctions.DoCommand, null, editorCommand);
}
#endregion
#region Inbound Gecko functions
///<summary>
/// Name: DocumentReturn
/// Callback function for when host initiates document save
/// Arguments:
/// string document: the document text, with placeholder'd controls
/// Returns: none
///</summary>
private string JSDocumentReturn (string[] args)
{
if (args.Length != 1)
@ -212,10 +233,6 @@ namespace AspNetEdit.Editor.UI
return string.Empty;
}
#endregion
#region Inbound Gecko functions
//this is because of the Gecko# not wanting to give up its DomDocument until it's been shown.
///<summary>
/// Name: Activate
@ -280,23 +297,6 @@ namespace AspNetEdit.Editor.UI
return string.Empty;
}
///<summary>
/// Name: SavePage
/// Callback function for when host initiates document save
/// Arguments:
/// string document: the document text, with placeholder'd controls
/// Returns: none
///</summary>
private string JSSave (string[] args)
{
if (args.Length != 1)
throw new InvalidJSArgumentException ("SavePage", -1);
throw new NotImplementedException (args[0]);
return string.Empty;
}
///<summary>
/// Name: ThrowException
/// Throws managed exceptions on behalf of Javascript
@ -358,13 +358,68 @@ namespace AspNetEdit.Editor.UI
pdc_h.SetValue (wc, pdc_h.Converter.ConvertFromInvariantString(args[2]));
return string.Empty;
}
///<summary>
/// Name: RemoveControl
/// Removes a control from the host when its Gecko representation is removed
/// Arguments:
/// string id: the control's ID
/// Returns: none
///</summary>
private string JSRemoveControl (string[] args)
{
if (args.Length != 1)
throw new InvalidJSArgumentException ("ResizeControl", -1);
//look up our component
DesignContainer container = (DesignContainer) host.Container;
IComponent component = container.GetComponent (args[0]);
if (component == null)
throw new InvalidJSArgumentException ("ResizeControl", 0);
//and remove it
container.Remove (component);
return string.Empty;
}
///<summary>
/// Name: Serialize
/// Serialises a fragment of a Gecko document into ASP.NET code
/// Arguments:
/// string designerDocumentFragment: the Gecko document fragment
/// Returns: the serialised document
///</summary>
private string JSSerialize (string[] args)
{
if (args.Length != 1)
throw new InvalidJSArgumentException ("Serialize", -1);
return host.RootDocument.Serialize (args [0]);
}
///<summary>
/// Name: DeserializeAndAdd
/// Deserialises a fragment of ASP.NET code into a Gecko designer document fragment
/// and adds the controls, directives etc to the host.
/// Arguments:
/// string designerDocumentFragment: the ASP.NET document fragment
/// Returns: the deserialised document
///</summary>
private string JSDeserializeAndAdd (string[] args)
{
if (args.Length != 1)
throw new InvalidJSArgumentException ("DeserializeAndAdd", -1);
return host.RootDocument.DeserializeAndAdd (args [0]);
}
#endregion
#region Outbound Gecko functions
public class GeckoFunctions
private class GeckoFunctions
{
///<summary>
/// Add a control to the document
@ -414,8 +469,72 @@ namespace AspNetEdit.Editor.UI
/// Returns: none
///</summary>
public static readonly string GetPage = "GetPage";
///<summary>
/// Passes a simple command to Gecko
/// Args:
/// string command: Use the enum EditorCommand
/// Returns: none
///</summary>
public static readonly string DoCommand = "DoCommand";
///<summary>
/// Inserts a document fragment. May contain HTML or ASP.NET; document should call host to deserialise it.
/// Args:
/// string fragment: The document fragment
/// Returns: none
///</summary>
public static readonly string InsertFragment = "InsertFragment";
}
#endregion
}
//TODO: GetCommandState to check whether we can perform these commands
//commands for DoCommand
//simply triggers functionality in Mozilla editor
public class EditorCommand
{
//clipboard
public static readonly string Cut = "cmd_cut";
public static readonly string Copy = "cmd_copy";
public static readonly string Paste = "cmd_paste";
public static readonly string Delete = "cmd_delete";
//transactions
public static readonly string Undo = "cmd_undo";
public static readonly string Redo = "cmd_redo";
//styles
public static readonly string Bold = "cmd_bold";
public static readonly string Italic = "cmd_italic";
public static readonly string Underline = "cmd_underline";
public static readonly string TeleType = "cmd_tt";
public static readonly string Strikethrough = "cmd_strikethru";
public static readonly string Superscript = "cmd_superscript";
public static readonly string Subscript = "cmd_subscript";
public static readonly string Indent = "cmd_indent";
public static readonly string Outdent = "cmd_outdent";
public static readonly string IncreaseFont = "cmd_increaseFont";
public static readonly string DecreaseFont = "cmd_decreaseFont";
//semantic
public static readonly string Emphasis = "cmd_em";
public static readonly string Strong = "cmd_strong";
public static readonly string Citation = "cmd_cite";
public static readonly string Abbreviation = "cmd_abbr";
public static readonly string Acronym = "cmd_acronym";
public static readonly string Code = "cmd_code";
//lists
public static readonly string OrderedList = "cmd_ol";
public static readonly string UnorderedList = "cmd_ul";
//public static readonly string NoBreak = "cmd_nobreak";
//public static readonly string Underline = "cmd_dt";
//public static readonly string Underline = "cmd_dd";
}
}

Просмотреть файл

@ -33,7 +33,8 @@ using Gtk;
using System.Collections;
using System.Drawing.Design;
using System.ComponentModel.Design;
using System.ComponentModel;
using System.ComponentModel;
using AspNetEdit.Editor.ComponentModel;
namespace AspNetEdit.Editor.UI
{
@ -42,7 +43,7 @@ namespace AspNetEdit.Editor.UI
private ServiceContainer parentServices;
Hashtable expanders = new Hashtable ();
private VBox vbox;
IToolboxService toolboxService;
ToolboxService toolboxService;
public Toolbox(ServiceContainer parentServices)
@ -50,11 +51,13 @@ namespace AspNetEdit.Editor.UI
this.parentServices = parentServices;
//we need this service, so create it if not present
toolboxService = parentServices.GetService (typeof (IToolboxService)) as IToolboxService;
toolboxService = parentServices.GetService (typeof (IToolboxService)) as ToolboxService;
if (toolboxService == null) {
toolboxService = new AspNetEdit.Editor.ComponentModel.ToolboxService ();
toolboxService = new ToolboxService ();
parentServices.AddService (typeof (IToolboxService), toolboxService);
}
}
toolboxService.ToolboxChanged += new EventHandler (tbsChanged);
base.VscrollbarPolicy = PolicyType.Automatic;
base.HscrollbarPolicy = PolicyType.Automatic;
@ -63,6 +66,11 @@ namespace AspNetEdit.Editor.UI
vbox = new VBox ();
base.AddWithViewport (vbox);
}
public void tbsChanged (object sender, EventArgs e)
{
UpdateCategories ();
}
#region GUI population
@ -109,7 +117,8 @@ namespace AspNetEdit.Editor.UI
EventBox bottomWidget = new EventBox ();
bottomWidget.CanFocus = true;
vbox.PackEnd (bottomWidget, true, true, 0);
}
}
public void ResetCategory (string category)
{
if (!expanders.ContainsKey(category))
@ -120,7 +129,13 @@ namespace AspNetEdit.Editor.UI
if (host == null) {
expanders.Clear ();
return;
}
}
//kill existing items
VBox vb = new VBox ();
((Expander) (expanders[category])).Child.Destroy ();
((Expander) (expanders[category])).Child = vb;
//get the items and add them all
ToolboxItemCollection tools = toolboxService.GetToolboxItems (category, host);
@ -134,8 +149,10 @@ namespace AspNetEdit.Editor.UI
itemBox.ButtonReleaseEvent += new ButtonReleaseEventHandler (itemBox_ButtonReleaseEvent);
itemBox.ButtonPressEvent += new ButtonPressEventHandler (itemBox_ButtonPressEvent);
itemBox.MotionNotifyEvent += new MotionNotifyEventHandler (itemBox_MotionNotifyEvent);
((VBox) ((Expander) (expanders[category])).Child).PackEnd (itemBox, false, false, 0);
}
vb.PackEnd (itemBox, false, false, 0);
}
vb.ShowAll ();
}
private class SortByName : IComparer
@ -208,8 +225,13 @@ namespace AspNetEdit.Editor.UI
void selectedBox_DragDataGet (object o, DragDataGetArgs args)
{
ToolboxItemBox itemBox = (ToolboxItemBox) o;
args.SelectionData.Text = (string) toolboxService.SerializeToolboxItem (itemBox.ToolboxItem);
TextToolboxItem textItem = itemBox.ToolboxItem as TextToolboxItem;
if (textItem != null)
args.SelectionData.Text = textItem.Text;
else
args.SelectionData.Text = (string) toolboxService.SerializeToolboxItem (itemBox.ToolboxItem);
}
void itemBox_ButtonReleaseEvent (object sender, ButtonReleaseEventArgs args)
@ -226,7 +248,14 @@ namespace AspNetEdit.Editor.UI
ToolboxItemBox itemBox = (ToolboxItemBox) o;
TargetEntry te = new TargetEntry (DragDropIdentifier, TargetFlags.App, 0);
TargetEntry te;
if (itemBox.ToolboxItem is TextToolboxItem)
te = new TargetEntry ("text/plain", TargetFlags.App, 0);
else
te = new TargetEntry (DragDropIdentifier, TargetFlags.App, 0);
TargetList tl = new TargetList (new TargetEntry[] { te } );
Gdk.DragContext context = Drag.Begin (itemBox, tl, Gdk.DragAction.Copy, 1, args.Event);

Просмотреть файл

@ -53,7 +53,8 @@ EDITOR_CSFILES = \
$(srcdir)/AspNetEdit.Editor.Persistence/TagAttributes.cs \
$(srcdir)/AspNetEdit.Editor.Persistence/TagType.cs \
$(srcdir)/AspNetEdit.Editor.ComponentModel/Document.cs \
$(srcdir)/AspNetEdit.Editor.ComponentModel/DocumentDirective.cs
$(srcdir)/AspNetEdit.Editor.ComponentModel/DocumentDirective.cs \
$(srcdir)/AspNetEdit.Editor.ComponentModel/TextToolboxItem.cs
$(ASSEMBLY): $(EDITOR_CSFILES)
$(MCS) $(MCS_OPTIONS) $(EDITOR_REFERENCES) -debug -target:library -out:$@ $(EDITOR_CSFILES)

Просмотреть файл

@ -56,6 +56,7 @@
<File name="./AspNetEdit.Editor.Persistence/StrUtils.cs" subtype="Code" buildaction="Compile" />
<File name="./AspNetEdit.Editor.Persistence/TagAttributes.cs" subtype="Code" buildaction="Compile" />
<File name="./AspNetEdit.Editor.Persistence/TagType.cs" subtype="Code" buildaction="Compile" />
<File name="./AspNetEdit.Editor.ComponentModel/TextToolboxItem.cs" subtype="Code" buildaction="Compile" />
</Contents>
<References>
<ProjectReference type="Project" localcopy="True" refto="jscall" />

Просмотреть файл

@ -101,7 +101,8 @@ namespace AspNetEdit.JSCall
argsOut += "|" + args[i];
}
}
if (returnTo == null) returnTo = string.Empty;
int result = PlaceFunctionCall (webControl.Handle, function, returnTo, argsOut);
string err;

Просмотреть файл

@ -97,9 +97,9 @@ int PlaceFunctionCall(GtkMozEmbed *embed, const PRUnichar *call, const PRUnichar
if(NS_FAILED(result) || !infunction) return 6;
//add the properties
result = infunction->SetAttribute(NS_ConvertUTF8toUTF16("call"), nsString(call));
result = infunction->SetAttribute(NS_ConvertUTF8toUTF16("returnto"), nsString(returnto));
result = infunction->SetAttribute(NS_ConvertUTF8toUTF16("args"), nsString(args));
result = infunction->SetAttribute(NS_ConvertUTF8toUTF16("call"), nsDependentString(call));
result = infunction->SetAttribute(NS_ConvertUTF8toUTF16("returnto"), nsDependentString(returnto));
result = infunction->SetAttribute(NS_ConvertUTF8toUTF16("args"), nsDependentString(args));
if(NS_FAILED(result)) return 7;
//append it to the jscall node