svn path=/trunk/aspeditor/; revision=48204
This commit is contained in:
Michael Hutchinson 2005-08-09 20:29:07 +00:00
Родитель 13863abad8
Коммит 854c5c755e
67 изменённых файлов: 8833 добавлений и 0 удалений

14
AUTHORS Normal file
Просмотреть файл

@ -0,0 +1,14 @@
The following developers have contributed to AspNetEdit.
Michael Hutchinson <m.j.hutchinson@dur.ac.uk>
C# lead developer.
Blagovest Dachev <blago@dachev.com>
Mozilla design surface.
Eric Butler <eric@extremeboredom.net>
Initial PropertyGrid development.

20
COPYING Normal file
Просмотреть файл

@ -0,0 +1,20 @@
Copyright (c) 2005 the individuals listed on the ChangeLog entries.
Permission is hereby granted, free of charge, to any person obtaining
a copy of this software and associated documentation files (the
"Software"), to deal in the Software without restriction, including
without limitation the rights to use, copy, modify, merge, publish,
distribute, sublicense, and/or sell copies of the Software, and to
permit persons to whom the Software is furnished to do so, subject to
the following conditions:
The above copyright notice and this permission notice shall be
included in all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.

0
ChangeLog Normal file
Просмотреть файл

35
INSTALL Normal file
Просмотреть файл

@ -0,0 +1,35 @@
Prerequisites
=============
You will need:
Mono 1.1.9 (okay, *very* recent subversion Mono class libraries will do)
Gtk# 2.5.5.99
Gecko# 0.10
GCC 3.3
Gtk+ 2.6.4
Mozilla 1.7.10
And of course the devoloper libraries for all of these.
Building AspNetEdit
===================
Open a terminal in the root aspnetedit director and run the following commands
./autoconf.sh --prefix=PREFIX
make
Running AspNetEdit
=================
You can run AspNetEdit out of the build directory with the command
make run
Installing AspNetEdit
=====================
To install AspNetEdit into the PREFIX directory you specified when running autoconf.sh, simly run
make install
The executable and libraries will be installed into PREFIX/lib, and a script 'aspnetedit' is provided in PREFIX/bin to launch the application

18
Makefile.am Normal file
Просмотреть файл

@ -0,0 +1,18 @@
SUBDIRS = src
bin_SCRIPTS = aspnetedit
EXTRA_DIST = script.in
REWRITE = \
sed -e "s|\@prefix\@|$(prefix)|g" \
-e "s|\@pkglibdir\@|$(pkglibdir)|g" \
-e "s|\@bindir\@|$(bindir)|g" \
-e "s|\@MONO\@|$(MONO)|g"
$(bin_SCRIPTS): $(srcdir)/script.in Makefile
$(REWRITE) $(srcdir)/script.in > $@.tmp
mv $@.tmp $@
run: runasp
runasp: $(PROGRAM)
cd $(top_builddir)/build/lib/ && LD_LIBRARY_PATH=`echo "$(LD_LIBRARY_PATH):$(MOZILLA_HOME)" | sed 's/^://g'` $(MONO) --debug aspnetedit.exe

1
NEWS Normal file
Просмотреть файл

@ -0,0 +1 @@

25
README Normal file
Просмотреть файл

@ -0,0 +1,25 @@
Introduction
============
This is a pre-release version of AspNetEdit, Mono's Graphical Editor for ASP.NET. This version is provided as a preview for curious developers only. Not all functionality is present or working, so please do not judge it until a final release is made.
At the moment you will need the cutting edge subversion Mono class libraries (module mcs).
Installation
============
For installation instruction please read the INSTALL file.
Developers
==========
A list of contributors can be found in the AUTHORS file.
If you are interested in contributing to AspNetEdit, please contact Michael Hutchinson <m.j.hutchinson@gmail.com>.
Release Notes
=============
Pre-alpha 0.0.1:
Initial commit to SVN.
The PropertyGrid and Toolbox are functional, but incomplete.
The design surface cannot yet be modified directly. Use the control selector above the PropertyGrid.
Saving ASPX files works, but page directives are not supported.

1118
aclocal.m4 поставляемый Normal file

Разница между файлами не показана из-за своего большого размера Загрузить разницу

4
autogen.sh Executable file
Просмотреть файл

@ -0,0 +1,4 @@
automake -a
aclocal
autoconf
./configure $*

72
configure.in Normal file
Просмотреть файл

@ -0,0 +1,72 @@
AC_INIT(README)
AC_CANONICAL_SYSTEM
AM_INIT_AUTOMAKE(aspnetedit, 0.0.1.0)
AM_MAINTAINER_MODE
AC_PROG_INSTALL
AC_PROG_CXX
dnl pkg-config
AC_PATH_PROG(PKG_CONFIG, pkg-config, no)
if test "x$PKG_CONFIG" = "xno"; then
AC_MSG_ERROR([You need to install pkg-config])
fi
dnl C# compiler
AC_PATH_PROG(CSC, csc, no)
AC_PATH_PROG(MCS, mcs, no)
AC_PATH_PROG(MONO, mono, no)
CS="C#"
if test "x$CSC" = "xno" -a "x$MCS" = "xno" ; then
dnl AC_MSG_ERROR([You need to install a C# compiler])
AC_MSG_ERROR([No $CS compiler found])
fi
if test "x$MCS" = "xno" ; then
MCS=$CSC
fi
if test "x$MONO" = "xno"; then
AC_MSG_ERROR([No mono runtime found])
fi
AC_SUBST(MCS)
dnl c# dependencies
GTKSHARP_REQUIRED_VERSION=2.5.5.99
GECKOSHARP_REQUIRED_VERSION=0.10
PKG_CHECK_MODULES(GTKSHARP, gtk-sharp-2.0 >= $GTKSHARP_REQUIRED_VERSION)
PKG_CHECK_MODULES(GECKOSHARP, gecko-sharp-2.0 >= $GECKOSHARP_REQUIRED_VERSION)
dnl c++ dependencies
GTK_VERSION=2.6.4
MOZILLA_VERSION=1.7.10
PKG_CHECK_MODULES(JSGLUEDEPS, mozilla-xpcom >= $MOZILLA_VERSION gtk+-2.0 >= $GTK_VERSION mozilla-gtkmozembed >= $MOZILLA_VERSION)
dnl Mozilla directory to install chrome
MOZILLA_HOME="`$PKG_CONFIG --variable=libdir mozilla-gtkmozembed`"
AC_SUBST(MOZILLA_HOME)
AC_OUTPUT([
Makefile
src/Makefile
src/propertygrid/Makefile
src/propertygrid/AssemblyInfo.cs
src/jscall/Makefile
src/jscall/AssemblyInfo.cs
src/jscall/jscallglue/Makefile
src/editor/Makefile
src/editor/AssemblyInfo.cs
src/aspnetedit/Makefile
src/aspnetedit/AssemblyInfo.cs
])
echo ""
echo "Configuration summary"
echo ""
echo " * Installation prefix = $prefix"
echo " * C# compiler = $MCS"
echo " * Mozilla home: $MOZILLA_HOME"
echo ""

2
script.in Normal file
Просмотреть файл

@ -0,0 +1,2 @@
#!/bin/sh
exec @MONO@ --debug @prefix@/lib/aspnetedit/aspnetedit.exe $MONO_EXTRA_ARGS "$@"

1
src/Makefile.am Normal file
Просмотреть файл

@ -0,0 +1 @@
SUBDIRS = propertygrid jscall editor aspnetedit

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

@ -0,0 +1,21 @@
//
// AssemblyInfo.cs.in for aspnetedit.exe
//
// Authors:
// Michael Hutchinson <m.j.hutchinson@gmail.com>
//
using System.Reflection;
using System.Runtime.CompilerServices;
[assembly: AssemblyTitle ("AspNetEdit")]
[assembly: AssemblyDescription ("AspNetEdit Graphical ASP.NET Editor ")]
[assembly: AssemblyCompany("")]
[assembly: AssemblyProduct("AspNetEdit")]
[assembly: AssemblyCopyright ("Copyright © 2005 Michael Hutchinson")]
[assembly: AssemblyTrademark("")]
[assembly: AssemblyCulture("")]
[assembly: AssemblyConfiguration("")]
[assembly: AssemblyVersion("@VERSION@")]
[assembly: AssemblyFileVersion("@VERSION@")]

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

@ -0,0 +1,31 @@
ASSEMBLY_NAME = aspnetedit
ASSEMBLY = $(top_builddir)/build/lib/$(ASSEMBLY_NAME).exe
TARGET = $(ASSEMBLY)
aspneteditdir=$(pkglibdir)
aspnetedit_SCRIPTS = $(ASSEMBLY)
aspnetedit_DATA = $(ASSEMBLY).mdb
ASPNETEDIT_REFERENCES = \
$(GTKSHARP_LIBS) \
$(GECKOSHARP_LIBS) \
-r:$(top_builddir)/build/lib/jscall.dll \
-r:$(top_builddir)/build/lib/propertygrid.dll \
-r:$(top_builddir)/build/lib/editor.dll \
-r:System.Web \
-r:System.Design \
-r:System.Drawing
ASPNETEDIT_CSFILES = \
$(srcdir)/SampleHost.cs \
$(srcdir)/AssemblyInfo.cs
$(ASSEMBLY): $(ASPNETEDIT_CSFILES)
$(MCS) $(ASPNETEDIT_REFERENCES) -debug -target:exe -out:$@ $(ASPNETEDIT_CSFILES)
$(ASSEMBLY).mdb: $(ASSEMBLY)
all: $(ASSEMBLY)
EXTRA_DIST = $(ASPNETEDIT_CSFILES)
CLEANFILES = $(ASSEMBLY) $(ASSEMBLY).mdb

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

@ -0,0 +1,204 @@
/*
* SampleHost.cs - A host for the AspNetEdit AASP.NET Graphical Designer
*
* Authors:
* Michael Hutchinson <m.j.hutchinson@gmail.com>
*
* Copyright (C) 2005 Michael Hutchinson
*
* This sourcecode is licenced under The MIT License:
*
* Permission is hereby granted, free of charge, to any person obtaining
* a copy of this software and associated documentation files (the
* "Software"), to deal in the Software without restriction, including
* without limitation the rights to use, copy, modify, merge, publish,
* distribute, sublicense, and/or sell copies of the Software, and to permit
* persons to whom the Software is furnished to do so, subject to the
* following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
* OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN
* NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM,
* DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
* OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE
* USE OR OTHER DEALINGS IN THE SOFTWARE.
*/
using System;
using Gtk;
using GtkSharp;
using AspNetEdit.Editor;
using AspNetEdit.Editor.UI;
using AspNetEdit.Editor.ComponentModel;
using System.ComponentModel;
using System.ComponentModel.Design;
using System.Drawing.Design;
using System.ComponentModel.Design.Serialization;
using System.IO;
namespace AspNetEdit.SampleHost
{
class SampleHost
{
static DesignerHost host;
static void Main ()
{
Application.Init ();
#region Packing and layout
Window window = new Window ("AspNetEdit Host Sample");
window.SetDefaultSize (1000, 700);
window.DeleteEvent += new DeleteEventHandler (window_DeleteEvent);
VBox outerBox = new VBox ();
window.Add (outerBox);
HPaned leftBox = new HPaned ();
outerBox.PackEnd (leftBox, true, true, 0);
HPaned rightBox = new HPaned ();
leftBox.Add2 (rightBox);
Frame geckoFrame = new Frame ();
geckoFrame.Shadow = ShadowType.In;
rightBox.Pack1 (geckoFrame, true, false);
#endregion
#region Toolbar
Toolbar buttons = new Toolbar ();
outerBox.PackStart (buttons, false, false, 0);
ToolButton saveButton = new ToolButton (Stock.Save);
buttons.Add (saveButton);
saveButton.Clicked += new EventHandler (saveButton_Clicked);
ToolButton undoButton = new ToolButton (Stock.Undo);
buttons.Add (undoButton);
undoButton.Clicked +=new EventHandler (undoButton_Clicked);
ToolButton redoButton = new ToolButton (Stock.Redo);
buttons.Add (redoButton);
redoButton.Clicked += new EventHandler (redoButton_Clicked);
ToolButton cutButton = new ToolButton (Stock.Cut);
buttons.Add (cutButton);
cutButton.Clicked += new EventHandler (cutButton_Clicked);
ToolButton copyButton = new ToolButton (Stock.Copy);
buttons.Add (copyButton);
copyButton.Clicked += new EventHandler (copyButton_Clicked);
ToolButton pasteButton = new ToolButton (Stock.Paste);
buttons.Add (pasteButton);
pasteButton.Clicked += new EventHandler (pasteButton_Clicked);
#endregion
#region Designer services and host
//set up the services
ServiceContainer services = new ServiceContainer ();
services.AddService (typeof (INameCreationService), new AspNetEdit.Editor.ComponentModel.NameCreationService ());
services.AddService (typeof (ITypeResolutionService), new AspNetEdit.Editor.ComponentModel.TypeResolutionService ());
services.AddService (typeof (ISelectionService), new AspNetEdit.Editor.ComponentModel.SelectionService ());
services.AddService (typeof (IEventBindingService), new AspNetEdit.Editor.ComponentModel.EventBindingService (window));
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 ();
services.AddService (typeof (IToolboxService), toolboxService);
//create our host
host = new DesignerHost(services);
host.NewFile();
host.Activate();
#endregion
#region Designer UI and panels
IRootDesigner rootDesigner = (IRootDesigner) host.GetDesigner (host.RootComponent);
RootDesignerView designerView = (RootDesignerView) rootDesigner.GetView (ViewTechnology.Passthrough);
geckoFrame.Add (designerView);
PropertyGrid p = new PropertyGrid (services);
p.WidthRequest = 200;
rightBox.Pack2 (p, false, false);
Toolbox toolbox = new Toolbox (services);
leftBox.Pack1 (toolbox, false, false);
toolboxService.PopulateFromAssembly (System.Reflection.Assembly.GetAssembly (typeof (System.Web.UI.Control)));
toolbox.UpdateCategories ();
#endregion
window.ShowAll ();
Application.Run ();
}
#region Toolbar click handlers
static void saveButton_Clicked (object sender, EventArgs e)
{
//FileChooserDialog fcd = new FileChooserDialog()
FileSelection fs = new FileSelection ("Choose a file");
fs.Filename = ((System.Web.UI.Control) host.RootComponent).ID + ".aspx";
fs.SelectMultiple = false;
fs.Run ();
fs.Hide ();
FileStream fileStream = new FileStream (fs.Filename, FileMode.Create);
if (fileStream == null)
return;
host.SaveDocument (fileStream);
fileStream.Close ();
}
static void redoButton_Clicked (object sender, EventArgs e)
{
throw new NotImplementedException ();
}
static void undoButton_Clicked (object sender, EventArgs e)
{
throw new NotImplementedException ();
}
static void cutButton_Clicked (object sender, EventArgs e)
{
throw new NotImplementedException ();
}
static void copyButton_Clicked (object sender, EventArgs e)
{
throw new NotImplementedException ();
}
static void pasteButton_Clicked (object sender, EventArgs e)
{
throw new NotImplementedException ();
}
#endregion
static void window_DeleteEvent (object o, DeleteEventArgs args)
{
Application.Quit ();
}
}
}

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

@ -0,0 +1,432 @@
/*
* DesignContainer.cs - Tracks ASP.NET controls in the DesignerHost
*
* Authors:
* Michael Hutchinson <m.j.hutchinson@gmail.com>
*
* Copyright (C) 2005 Michael Hutchinson
*
* This sourcecode is licenced under The MIT License:
*
* Permission is hereby granted, free of charge, to any person obtaining
* a copy of this software and associated documentation files (the
* "Software"), to deal in the Software without restriction, including
* without limitation the rights to use, copy, modify, merge, publish,
* distribute, sublicense, and/or sell copies of the Software, and to permit
* persons to whom the Software is furnished to do so, subject to the
* following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
* OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN
* NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM,
* DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
* OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE
* USE OR OTHER DEALINGS IN THE SOFTWARE.
*/
using System;
using System.ComponentModel;
using System.ComponentModel.Design;
using System.ComponentModel.Design.Serialization;
using System.Collections;
using System.Web.UI;
namespace AspNetEdit.Editor.ComponentModel
{
internal class DesignContainer : IContainer, IComponentChangeService
{
public DesignContainer (DesignerHost host)
{
this.host = host;
this.designers = new Hashtable ();
this.components = new ArrayList ();
}
#region IContainer Members
private DesignerHost host;
private Hashtable designers;
private ArrayList components;
public void Add (IComponent component)
{
Add (component, null);
}
public void Add (IComponent component, string name)
{
IDesigner designer = null;
//input checks
if (component == null)
throw new ArgumentException ("Cannot add null component to container", "component");
if (!(component is Control))
throw new ArgumentException ("This Container only accepts System.Web.UI.Control-derived components", "component");
if (component.Site != null && component.Site.Container != this)
component.Site.Container.Remove (component);
//Check the name and create one if necessary
INameCreationService nameService = host.GetService (typeof (INameCreationService)) as INameCreationService;
if (nameService == null)
throw new Exception ("The container must have access to a INameCreationService implementation");
if (name == null || nameService.IsValidName (name))
name = nameService.CreateName (this, component.GetType ());
//check we don't already have component with same name
if (GetComponent (name) != null)
throw new ArgumentException ("There is already a component with this name in the container", "name");
//we're definately adding it now, so broadcast
OnComponentAdding (component);
//get a site and set ID property
//this way (not PropertyDescriptor.SetValue) won't fire change events
((Control) component).ID = name;
component.Site = new DesignSite (component, this);
//Get designer. If first component, designer must be an IRootDesigner
if (components.Count == 0)
{
host.SetRootComponent (component);
designer = new RootDesigner (component);
}
//FIXME: Give Mono some base designers to find! We should never encounter this!
//else
// designer = TypeDescriptor.CreateDesigner (component, typeof(System.ComponentModel.Design.IDesigner));
if (designer == null) {
//component.Site = null;
//throw new Exception ("Designer could not be obtained for this component.");
}
else
{
//track and initialise it
designers.Add (component, designer);
designer.Initialize (component);
}
//add to document unless root
if (components.Count != 0)
((WebFormPage) host.RootComponent).AddControlAtCursor ((Control) component);
//TODO: add references to referenceManager
//Finally put in container
components.Add (component);
//and broadcast completion
OnComponentAdded (component);
}
internal IDesigner GetDesigner (IComponent component)
{
if (GetComponent (component.Site.Name) == null)
return null;
//throw new ArgumentException ("That component is not in the container", "component");
return designers[component] as IDesigner;
}
public IComponent GetComponent (string name)
{
foreach (IComponent component in components)
if (component.Site.Name == name)
return component;
return null;
}
protected System.Object GetService (System.Type service)
{
return host.GetService (service);
}
public void Remove (System.ComponentModel.IComponent component)
{
//safety checks
if (component == null)
throw new ArgumentNullException ("component");
if (component.Site == null || component.Site.Container != this)
throw new ArgumentException ("Component is not sited in this container");
if (component == host.RootComponent)
throw new Exception ("You cannot remove the root component directly");
//broadcast start of removal process
OnComponentRemoving (component);
//clean up component and designer
components.Remove (component);
IDesigner designer = GetDesigner (component);
if (designer != null)
{
designers.Remove (component);
designer.Dispose ();
}
component.Site = null;
//if someone tries to kill root component, must destroy all children too
if (component == host.RootComponent)
{
host.SetRootComponent (null);
//clean everything up
foreach (System.Web.UI.Control control in Components)
host.DestroyComponent (control);
host.Reset ();
}
//remove from container
((WebFormPage) host.RootComponent).RemoveControl ((Control) component);
//TODO: remove references from referenceManager
//broadcast completion of removal process
OnComponentRemoved (component);
}
public ComponentCollection Components {
get { return new ComponentCollection ((IComponent[]) components.ToArray(typeof (IComponent))); }
}
#endregion
#region IComponentChangeService Members
public event ComponentEventHandler ComponentAdded;
public event ComponentEventHandler ComponentAdding;
public event ComponentChangedEventHandler ComponentChanged;
public event ComponentChangingEventHandler ComponentChanging;
public event ComponentEventHandler ComponentRemoved;
public event ComponentEventHandler ComponentRemoving;
public event ComponentRenameEventHandler ComponentRename;
public void OnComponentChanged(object component, MemberDescriptor member, object oldValue, object newValue)
{
//the names of components in this container are actually the same as their IDs
//so if a change to the ID occurs, we hook in and change it back if not valid
if(component is Control && ((Control) component).Site.Container == this && member.Name == "ID") {
//check name is valid
bool goodVal = true;
if (newValue == null || !(newValue is String))
goodVal = false;
else
foreach (IComponent Comp in this.Components)
if (Comp != component && Comp.Site != null && Comp.Site.Name == ((string) newValue))
goodVal = false;
if (goodVal)
//success, raise change event
OnComponentRename (component, (string) oldValue, (string) newValue);
else
//bad value, change back
((PropertyDescriptor) member).SetValue (component, oldValue);
}
if (ComponentChanged != null)
ComponentChanged (this, new ComponentChangedEventArgs (component, member, oldValue, newValue));
}
public void OnComponentChanging (object component, MemberDescriptor member)
{
if (ComponentChanging != null)
ComponentChanging (this, new ComponentChangingEventArgs (component, member));
}
protected void OnComponentAdded(IComponent component)
{
if (ComponentAdded != null)
ComponentAdded (this, new ComponentEventArgs(component));
}
protected void OnComponentAdding(IComponent component)
{
if (ComponentAdding != null)
ComponentAdding (this, new ComponentEventArgs(component));
}
protected void OnComponentRemoved(IComponent component)
{
if (ComponentRemoved != null)
ComponentRemoved (this, new ComponentEventArgs(component));
}
protected void OnComponentRemoving (IComponent component)
{
if (ComponentRemoving != null)
ComponentRemoving (this, new ComponentEventArgs(component));
}
protected void OnComponentRename(object component, string oldName, string newName)
{
((WebFormPage) host.RootComponent).RenameControl (oldName, newName);
if (ComponentRename != null)
ComponentRename (this, new ComponentRenameEventArgs (component, oldName, newName));
}
#endregion
//the ISite implementation we use to site the components in this container
//IDictionaryService is site-specific, so why not implement in site
private class DesignSite : ISite, IDictionaryService
{
private DesignContainer container;
private IComponent component;
public DesignSite (IComponent component, DesignContainer container)
{
this.container = container;
this.component = component;
}
#region ISite Members
public IComponent Component {
get { return component; }
}
public IContainer Container {
get { return container; }
}
public bool DesignMode {
get { return true; }
}
public string Name {
get { return ((Control) component).ID; }
set { ((Control) component).ID = value; }
}
#endregion
#region IServiceProvider Members
public object GetService (Type serviceType) {
if (serviceType == typeof (IDictionaryService)) {
if (dict == null)
dict = new Hashtable ();
return this;
}
return container.GetService (serviceType);
}
#endregion
#region IDictionaryService members
private Hashtable dict = null;
public void SetValue (object key, object value)
{
//TODO: more efficient, but is behaviour as expected?
//if ((value == null) && (dict.ContainsKey (key)))
// dict.Remove (key);
//else
dict[key] = value;
}
public object GetValue (object key)
{
return dict[key];
}
public object GetKey (object value)
{
foreach (DictionaryEntry entry in dict)
if (entry.Value == value)
return entry.Key;
return null;
}
#endregion
}
/* Decided to watch existing controls' ID property instead of messing about with hiding it and
* using this extender provider. May bring it back. Version control not online yet.
*
* [ProvideProperty("(ID)", typeof(IComponent))]
* ((IExtenderProviderService)host.GetService(typeof(IExtenderProviderService))).AddExtenderProvider(this);
*
#region IExtenderProvider Members
//we entend the "(ID)" property to childern of the container
public bool CanExtend(object extendee)
{
if ((extendee as IComponent).Site == this)
return true;
else
return false;
}
[Description("Programmatic name of the control")]
[Category("Misc")]
public string GetID(IComponent component)
{
return component.Site.Name;
}
public void SetID(IComponent component, string value)
{
component.Site.Name = value;
}
#endregion
*/
#region IDisposable Members
private bool disposed = false;
public void Dispose ()
{
this.Dispose (true);
}
public void Dispose (bool disposing)
{
if (disposed)
return;
disposed = true;
if (disposing)
{
foreach (IComponent comp in components)
comp.Dispose ();
components.Clear ();
foreach (IDesigner des in designers)
des.Dispose ();
designers.Clear ();
this.components = null;
this.designers = null;
}
}
~DesignContainer ()
{
this.Dispose (false);
}
#endregion
}
}

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

@ -0,0 +1,366 @@
/*
* DesignerHost.cs - IDesignerHost implementation. Designer transactions
* and service host. One level up from DesignContainer, tracks RootComponent.
*
* Authors:
* Michael Hutchinson <m.j.hutchinson@gmail.com>
*
* Copyright (C) 2005 Michael Hutchinson
*
* This sourcecode is licenced under The MIT License:
*
* Permission is hereby granted, free of charge, to any person obtaining
* a copy of this software and associated documentation files (the
* "Software"), to deal in the Software without restriction, including
* without limitation the rights to use, copy, modify, merge, publish,
* distribute, sublicense, and/or sell copies of the Software, and to permit
* persons to whom the Software is furnished to do so, subject to the
* following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
* OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN
* NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM,
* DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
* OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE
* USE OR OTHER DEALINGS IN THE SOFTWARE.
*/
using System;
using System.ComponentModel;
using System.ComponentModel.Design;
using System.Reflection;
using System.Collections;
using System.Drawing.Design;
using System.IO;
using System.Web.UI;
using System.Web.UI.Design;
namespace AspNetEdit.Editor.ComponentModel
{
public class DesignerHost : IDesignerHost, IDisposable
{
private ServiceContainer parentServices;
private WebFormReferenceManager referenceManager;
public DesignerHost (ServiceContainer parentServices)
{
this.parentServices = parentServices;
container = new DesignContainer (this);
referenceManager = new WebFormReferenceManager ();
//register services
parentServices.AddService (typeof (IDesignerHost), this);
parentServices.AddService (typeof (IComponentChangeService), container);
parentServices.AddService (typeof (IWebFormReferenceManager), referenceManager);
}
#region Component management
private DesignContainer container;
private IComponent rootComponent = null;
public IContainer Container
{
get { return container; }
}
public IComponent CreateComponent (Type componentClass, string name)
{
//check arguments
if (componentClass == null)
throw new ArgumentNullException ("componentClass");
if (!componentClass.IsSubclassOf (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)))
throw new InvalidOperationException ("You cannot directly add a page to the host. Use NewFile() instead");
//create the object
ConstructorInfo constructor = componentClass.GetConstructor (new Type[] { });
IComponent component = constructor.Invoke(new object[] { }) as IComponent;
//and add to container
container.Add (component, name);
return component;
}
public IComponent CreateComponent (Type componentClass)
{
return CreateComponent (componentClass, null);
}
public void DestroyComponent (IComponent component)
{
//remove from document
if ( !(component is Page))
((WebFormPage) RootComponent).RemoveControl ((Control) component);
//remove from container
container.Remove (component);
component.Dispose ();
}
public IDesigner GetDesigner (IComponent component)
{
if (component == null)
throw new ArgumentNullException ("component");
else
return container.GetDesigner (component);
}
public Type GetType (string typeName)
{
//use ITypeResolutionService if we have it, else Type.GetType();
object typeResSvc = GetService (typeof (ITypeResolutionService));
if (typeResSvc != null)
return (typeResSvc as ITypeResolutionService).GetType (typeName);
else
return Type.GetType (typeName);
}
public IComponent RootComponent {
get { return rootComponent; }
}
internal void SetRootComponent (IComponent rootComponent)
{
this.rootComponent = rootComponent;
}
public string RootComponentClassName {
get { return RootComponent.GetType ().Name; }
}
#endregion
#region Transaction stuff
private Stack transactionStack = new Stack ();
public DesignerTransaction CreateTransaction (string description)
{
OnTransactionOpening ();
Transaction trans = new Transaction (this, description);
transactionStack.Push (trans);
OnTransactionOpened ();
return trans;
}
public DesignerTransaction CreateTransaction ()
{
return CreateTransaction (null);
}
public bool InTransaction
{
get { return (transactionStack.Count > 0); }
}
public string TransactionDescription
{
get {
if (transactionStack.Count == 0)
return null;
else
return (transactionStack.Peek () as DesignerTransaction).Description;
}
}
public event DesignerTransactionCloseEventHandler TransactionClosed;
public event DesignerTransactionCloseEventHandler TransactionClosing;
public event EventHandler TransactionOpened;
public event EventHandler TransactionOpening;
internal void OnTransactionClosed (bool commit, DesignerTransaction trans)
{
DesignerTransaction t = (DesignerTransaction) transactionStack.Pop();
if (t != trans)
throw new Exception ("Transactions cannot be closed out of order");
if (TransactionClosed != null)
TransactionClosed (this, new DesignerTransactionCloseEventArgs(commit));
}
internal void OnTransactionClosing (bool commit)
{
if (TransactionClosing != null)
TransactionClosing (this, new DesignerTransactionCloseEventArgs(commit));
}
protected void OnTransactionOpening()
{
if (TransactionOpening != null)
TransactionOpening (this, EventArgs.Empty);
}
protected void OnTransactionOpened ()
{
if (TransactionOpened != null)
TransactionOpened (this, EventArgs.Empty);
}
#endregion
#region Loading etc
private bool loading = false;
private bool activated = false;
public event EventHandler Activated;
public event EventHandler Deactivated;
public event EventHandler LoadComplete;
public void Activate ()
{
if (activated)
throw new InvalidOperationException ("The host is already activated");
//select the root component
ISelectionService sel = GetService (typeof (ISelectionService)) as ISelectionService;
if (sel == null)
throw new Exception ("Could not obtain ISelectionService.");
if (this.RootComponent == null)
throw new InvalidOperationException ("The document must be loaded before the host can be activated");
sel.SetSelectedComponents (new object[] {this.RootComponent});
activated = true;
OnActivated ();
}
public bool Loading {
get { return loading; }
}
protected void OnLoadComplete ()
{
if (LoadComplete != null)
LoadComplete (this, EventArgs.Empty);
}
protected void OnActivated ()
{
if (Activated != null)
Activated (this, EventArgs.Empty);
}
protected void OnDeactivated ()
{
if (Deactivated != null)
Deactivated (this, EventArgs.Empty);
}
#endregion
#region Wrapping parent ServiceContainer
public void AddService (Type serviceType, ServiceCreatorCallback callback, bool promote)
{
parentServices.AddService (serviceType, callback, promote);
}
public void AddService (Type serviceType, object serviceInstance, bool promote)
{
parentServices.AddService (serviceType, serviceInstance, promote);
}
public void AddService (Type serviceType, ServiceCreatorCallback callback)
{
parentServices.AddService (serviceType, callback);
}
public void AddService (Type serviceType, object serviceInstance)
{
parentServices.AddService (serviceType, serviceInstance);
}
public void RemoveService (Type serviceType, bool promote)
{
parentServices.RemoveService (serviceType, promote);
}
public void RemoveService (Type serviceType)
{
parentServices.RemoveService (serviceType);
}
public object GetService (Type serviceType)
{
object service = parentServices.GetService (serviceType);
if (service != null)
return service;
else
return null;
}
#endregion
#region IDisposable Members
private bool disposed = false;
public void Dispose ()
{
if (!this.disposed) {
//clean up the services we've registered
parentServices.RemoveService (typeof (IComponentChangeService));
parentServices.RemoveService (typeof (IDesignerHost));
//and the container
container.Dispose ();
disposed = true;
}
}
#endregion
public void NewFile ()
{
if (activated)
throw new InvalidOperationException ("You must reset the host before creating another file.");
this.container.Add (new WebFormPage ("New document"));
}
public void Load(Stream file, string fileName)
{
if (activated)
throw new InvalidOperationException ("You must reset the host before loading another file.");
loading = true;
WebFormPage page = new WebFormPage (file, fileName);
this.Container.Add (page);
loading = false;
OnLoadComplete ();
}
public void Reset ()
{
//container automatically destroys all children when this happens
if (rootComponent != null)
DestroyComponent (rootComponent);
if (activated) {
OnDeactivated ();
this.activated = false;
}
}
public void SaveDocument (Stream file)
{
StreamWriter writer = new StreamWriter (file);
writer.Write(((WebFormPage) RootComponent).PersistDocument ());
writer.Flush ();
}
}
}

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

@ -0,0 +1,53 @@
/*
* Directive.cs - base class for tracking ASP.NET directives and their properties
*
* Authors:
* Michael Hutchinson <m.j.hutchinson@gmail.com>
*
* Copyright (C) 2005 Michael Hutchinson
*
* This sourcecode is licenced under The MIT License:
*
* Permission is hereby granted, free of charge, to any person obtaining
* a copy of this software and associated documentation files (the
* "Software"), to deal in the Software without restriction, including
* without limitation the rights to use, copy, modify, merge, publish,
* distribute, sublicense, and/or sell copies of the Software, and to permit
* persons to whom the Software is furnished to do so, subject to the
* following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
* OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN
* NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM,
* DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
* OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE
* USE OR OTHER DEALINGS IN THE SOFTWARE.
*/
using System;
namespace AspNetEdit.Editor.ComponentModel
{
//describes which ASP.NET directive tag a property on WebFormsPage applies to
internal abstract class Directive
{
public abstract string Tag {
get;
}
public string GetDirective ()
{
return string.Empty;
}
// public static Directive GetDirective (string tag, TagAttributes attributes)
// {
// return new PageDirective ();
// }
}
}

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

@ -0,0 +1,225 @@
/*
* EventBindingService.cs - handles binding of Control events to CodeBehind methods
*
* Authors:
* Michael Hutchinson <m.j.hutchinson@gmail.com>
*
* Copyright (C) 2005 Michael Hutchinson
*
* This sourcecode is licenced under The MIT License:
*
* Permission is hereby granted, free of charge, to any person obtaining
* a copy of this software and associated documentation files (the
* "Software"), to deal in the Software without restriction, including
* without limitation the rights to use, copy, modify, merge, publish,
* distribute, sublicense, and/or sell copies of the Software, and to permit
* persons to whom the Software is furnished to do so, subject to the
* following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
* OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN
* NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM,
* DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
* OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE
* USE OR OTHER DEALINGS IN THE SOFTWARE.
*/
using System;
using System.ComponentModel.Design;
using System.ComponentModel;
using System.Collections;
using System.Reflection;
namespace AspNetEdit.Editor.ComponentModel
{
public class EventBindingService : IEventBindingService
{
//TODO: Remove once we get code view
Gtk.Window parentWindow;
public EventBindingService (Gtk.Window parentWindow)
{
this.parentWindow = parentWindow;
}
//TODO: Remove after getting code view
private void ShowMessage (string mess)
{
Gtk.MessageDialog md = new Gtk.MessageDialog (parentWindow, Gtk.DialogFlags.DestroyWithParent, Gtk.MessageType.Info, Gtk.ButtonsType.Close, mess);
md.Run ();
md.Destroy ();
}
#region IEventBindingService Members
private Hashtable eventHandlers = new Hashtable ();
public string CreateUniqueMethodName (IComponent component, EventDescriptor e)
{
if (component.Site == null || component.Site.Name == null)
throw new ArgumentException ("IComponent must be sited and named");
//TODO: check component.Site.Name is valid as start of method name
string trialPrefix = component.Site.Name + "_" + e.Name;
string trialValue = trialPrefix;
for (int suffix = 1; suffix <= int.MaxValue; suffix++)
{
if (!eventHandlers.ContainsKey (trialValue))
return trialValue;
trialValue = trialPrefix + suffix.ToString ();
}
throw new Exception ("Tried method names up to " + trialValue + " and all already existed");
}
public System.Collections.ICollection GetCompatibleMethods (System.ComponentModel.EventDescriptor e)
{
ParameterInfo[] pi = GetEventParameters (e);
ArrayList arr = new ArrayList ();
foreach (DictionaryEntry de in eventHandlers)
if ( (ParameterInfo[]) de.Value == pi)
arr.Add (de.Key);
return arr.ToArray (typeof(string));
}
public System.ComponentModel.EventDescriptor GetEvent (System.ComponentModel.PropertyDescriptor property)
{
EventPropertyDescriptor epd = property as EventPropertyDescriptor;
if (epd == null)
return null;
return epd.InternalEventDescriptor;
}
public System.ComponentModel.PropertyDescriptorCollection GetEventProperties (System.ComponentModel.EventDescriptorCollection events)
{
ArrayList props = new ArrayList ();
foreach (EventDescriptor e in events)
props.Add (GetEventProperty (e));
return new PropertyDescriptorCollection ((PropertyDescriptor[]) props.ToArray (typeof (PropertyDescriptor)));
}
public System.ComponentModel.PropertyDescriptor GetEventProperty (System.ComponentModel.EventDescriptor e)
{
return new EventPropertyDescriptor (e);
}
//TODO: actually show code and return true if exists
public bool ShowCode (System.ComponentModel.IComponent component, System.ComponentModel.EventDescriptor e)
{
string name = (string) GetEventProperty (e).GetValue (component);
if (eventHandlers.ContainsKey (name))
ShowMessage("In an IDE this would show the existing CodeBehind method \"" + name + "\".");
else {
eventHandlers.Add ( e.EventType, GetEventParameters (e) );
ShowMessage("In an IDE this would create and show the CodeBehind method \"" + name + "\".");
}
return true;
}
//TODO: actually show code and return true if exists
public bool ShowCode (int lineNumber)
{
ShowMessage ("In an IDE this would show the code at line " + lineNumber.ToString ());
return true;
}
public bool ShowCode ()
{
return ShowCode (0);
}
#endregion
private ParameterInfo[] GetEventParameters (EventDescriptor e)
{
MethodInfo mi = e.EventType.GetMethod ("Invoke");
return mi.GetParameters ();
}
}
internal class EventPropertyDescriptor : PropertyDescriptor
{
private EventDescriptor eDesc;
public EventPropertyDescriptor (EventDescriptor eDesc)
: base (eDesc)
{
this.eDesc = eDesc;
}
public override bool CanResetValue (object component)
{
return true;
}
public override Type ComponentType
{
get { return eDesc.ComponentType; }
}
public override object GetValue(object component)
{
IDictionaryService dict = GetDictionaryService (component);
return dict.GetValue (base.Name);
}
public override bool IsReadOnly
{
get { return false; }
}
public override Type PropertyType
{
get { return eDesc.EventType; }
}
public override void ResetValue (object component)
{
SetValue (component, null);
}
public override void SetValue (object component, object value)
{
IDictionaryService dict = GetDictionaryService (component);
dict.SetValue (base.Name, value);
}
public override bool ShouldSerializeValue (object component)
{
if (GetValue (component) == null) return false;
return true;
}
IDictionaryService GetDictionaryService (object component)
{
if (component == null)
throw new ArgumentNullException ("component");
IComponent comp = component as IComponent;
if (comp == null || comp.Site == null)
throw new ArgumentException ("component must be a sited IComponent", "component");
IDictionaryService dict = comp.Site.GetService (typeof (IDictionaryService)) as IDictionaryService;
if (dict == null)
throw new InvalidOperationException ("could not obtain IDictionaryService implementation");
return dict;
}
internal EventDescriptor InternalEventDescriptor {
get { return eDesc; }
}
}
}

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

@ -0,0 +1,69 @@
/*
* ExtenderListService.cs - maintains list of property extenders
*
* Authors:
* Michael Hutchinson <m.j.hutchinson@gmail.com>
*
* Copyright (C) 2005 Michael Hutchinson
*
* This sourcecode is licenced under The MIT License:
*
* Permission is hereby granted, free of charge, to any person obtaining
* a copy of this software and associated documentation files (the
* "Software"), to deal in the Software without restriction, including
* without limitation the rights to use, copy, modify, merge, publish,
* distribute, sublicense, and/or sell copies of the Software, and to permit
* persons to whom the Software is furnished to do so, subject to the
* following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
* OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN
* NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM,
* DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
* OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE
* USE OR OTHER DEALINGS IN THE SOFTWARE.
*/
using System;
using System.ComponentModel;
using System.ComponentModel.Design;
using System.Collections;
namespace AspNetEdit.Editor.ComponentModel
{
public class ExtenderListService : IExtenderProviderService, IExtenderListService
{
private ArrayList extenders = new ArrayList ();
public ExtenderListService ()
{
}
#region IExtenderProviderService Members
public void AddExtenderProvider (IExtenderProvider provider)
{
extenders.Add (provider);
}
public void RemoveExtenderProvider (IExtenderProvider provider)
{
extenders.Remove (provider);
}
#endregion
#region IExtenderListService Members
public IExtenderProvider[] GetExtenderProviders ()
{
return extenders.ToArray (typeof (IExtenderProvider)) as IExtenderProvider[];
}
#endregion
}
}

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

@ -0,0 +1,128 @@
/*
* MenuCommandService.cs - Provides access to commands, and tracks designer verbs
*
* Authors:
* Michael Hutchinson <m.j.hutchinson@gmail.com>
*
* Copyright (C) 2005 Michael Hutchinson
*
* This sourcecode is licenced under The MIT License:
*
* Permission is hereby granted, free of charge, to any person obtaining
* a copy of this software and associated documentation files (the
* "Software"), to deal in the Software without restriction, including
* without limitation the rights to use, copy, modify, merge, publish,
* distribute, sublicense, and/or sell copies of the Software, and to permit
* persons to whom the Software is furnished to do so, subject to the
* following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
* OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN
* NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM,
* DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
* OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE
* USE OR OTHER DEALINGS IN THE SOFTWARE.
*/
using System;
using System.ComponentModel.Design;
using Gtk;
using System.Collections;
namespace AspNetEdit.Editor.ComponentModel
{
public class MenuCommandService : IMenuCommandService
{
private DesignerVerbCollection verbs;
private ArrayList commands;
private Menu contextMenu;
private MenuBar menuBar;
private int x = 0, y = 0;
public MenuCommandService()
{
commands = new ArrayList ();
this.contextMenu = new Menu ();
this.menuBar = new MenuBar ();
}
#region IMenuCommandService Members
public void AddCommand (MenuCommand command)
{
if (commands.Contains (command))
throw new InvalidOperationException ("A command with that CommandID already exists in the menu");
commands.Add (command);
//menuBar
}
public void AddVerb (DesignerVerb verb)
{
if (verbs.Contains (verb))
throw new InvalidOperationException ("The MenuCommandService already contains that Designer Verb");
verbs.Add (verb);
}
public MenuCommand FindCommand (CommandID commandID)
{
foreach (MenuCommand command in commands)
if (command.CommandID == commandID)
return command;
return null;
}
public bool GlobalInvoke (CommandID commandID)
{
MenuCommand command = FindCommand (commandID);
if (command == null)
return false;
command.Invoke ();
return true;
}
public void RemoveCommand (MenuCommand command)
{
if (commands.Contains (command))
commands.Remove (command);
}
public void RemoveVerb (DesignerVerb verb)
{
if (verbs.Contains (verb))
verbs.Remove (verb);
}
public void ShowContextMenu (CommandID menuID, int x, int y)
{
// Launch out menu as a GTK popup
// Due to weird callback semantics, have to cache x and y values
// Delegate doesn't accept the data pointer...?!
this.x = x;
this.y = y;
contextMenu.Popup(null, null, new MenuPositionFunc (positionFunc), new System.IntPtr (), 2, Gtk.Global.CurrentEventTime);
}
private void positionFunc (Gtk.Menu menu, out int x, out int y, out bool pushIn)
{
x = this.x;
y = this.y;
pushIn = false;
}
public DesignerVerbCollection Verbs {
get { return verbs; }
}
public MenuBar MenuBar {
get { return menuBar; }
}
#endregion
}
}

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

@ -0,0 +1,94 @@
/*
* NameCreationService.cs - Creates names for components, and checks name validity
*
* Authors:
* Michael Hutchinson <m.j.hutchinson@gmail.com>
*
* Copyright (C) 2005 Michael Hutchinson
*
* This sourcecode is licenced under The MIT License:
*
* Permission is hereby granted, free of charge, to any person obtaining
* a copy of this software and associated documentation files (the
* "Software"), to deal in the Software without restriction, including
* without limitation the rights to use, copy, modify, merge, publish,
* distribute, sublicense, and/or sell copies of the Software, and to permit
* persons to whom the Software is furnished to do so, subject to the
* following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
* OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN
* NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM,
* DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
* OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE
* USE OR OTHER DEALINGS IN THE SOFTWARE.
*/
using System;
using System.ComponentModel.Design.Serialization;
using System.ComponentModel;
namespace AspNetEdit.Editor.ComponentModel
{
public class NameCreationService : INameCreationService
{
public NameCreationService ()
{
}
#region INameCreationService Members
public string CreateName (System.ComponentModel.IContainer container, Type dataType)
{
int suffixNumber = 1;
//check existing components with name of same form
// and make suffixNumber bigger than the greatest of them
foreach (IComponent comp in container.Components) {
if (comp.Site.Name.StartsWith (dataType.Name)) {
string str = comp.Site.Name.Remove (0, dataType.Name.Length);
//TODO: Use int.TryParse in .NET 2.0
try {
int val = int.Parse (str);
if (val >= suffixNumber)
suffixNumber = val + 1;
}
catch (Exception ex) {}
}
}
return dataType.Name + suffixNumber.ToString ();
}
//TODO: make legal name checking less severe, more correct. Project language dependency.
public bool IsValidName (string name)
{
if (name.Length < 1)
return false;
char[] nameChar = name.ToCharArray ();
if (!char.IsLetter (nameChar[0]))
return false;
for (int i = 1; i < nameChar.Length; i++)
{
if (!char.IsLetterOrDigit (nameChar[i]) && !(nameChar[i] == '_'))
return false;
}
return true;
}
public void ValidateName (string name)
{
if (!IsValidName (name))
throw new Exception ("The name is not valid.");
}
#endregion
}
}

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

@ -0,0 +1,441 @@
/*
* PageDirective.cs - represents a page directive. Can be shown in PropertyBrowser.
*
* Authors:
* Michael Hutchinson <m.j.hutchinson@gmail.com>
*
* Copyright (C) 2005 Michael Hutchinson
*
* This sourcecode is licenced under The MIT License:
*
* Permission is hereby granted, free of charge, to any person obtaining
* a copy of this software and associated documentation files (the
* "Software"), to deal in the Software without restriction, including
* without limitation the rights to use, copy, modify, merge, publish,
* distribute, sublicense, and/or sell copies of the Software, and to permit
* persons to whom the Software is furnished to do so, subject to the
* following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
* OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN
* NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM,
* DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
* OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE
* USE OR OTHER DEALINGS IN THE SOFTWARE.
*/
using System;
using System.Globalization;
using System.Text;
using System.ComponentModel;
using System.Web;
namespace AspNetEdit.Editor.ComponentModel
{
internal class PageDirective
{
#region Property browser attributes for @Page attributes
private bool aspCompat = false;
[DefaultValue(false)]
[Category("Behaviour")]
//TODO: Add for .NET 2.0
//[DisplayNameAttribute("AspCompat")
[Description ("Whether the page can be executed on a single-threaded apartment thread")]
[Bindable(false)]
[Browsable(true)]
public bool AspCompat
{
get { return aspCompat; }
set { aspCompat = value; }
}
private bool autoEventWireup = true;
[DefaultValue(true)]
[Category("Compilation")]
[Description("Whether the page events are automatically wired up")]
[Bindable(false)]
[Browsable(true)]
public bool AutoEventWireup
{
get { return autoEventWireup; }
set { autoEventWireup = value; }
}
private bool buffer = true;
[DefaultValue(true)]
[Category("Behaviour")]
[Description("Whether HTTP response buffering is enabled")]
[Bindable(false)]
[Browsable(true)]
public new bool Buffer
{
get { return buffer; }
set { buffer = value; }
}
private string className = "";
[DefaultValue("")]
[Category("Compilation")]
[ReadOnly(true)]
[Description("The class name for the page when it is compiled")]
[Bindable(false)]
[Browsable(true)]
public string ClassName
{
get { return className; }
set { className = value; }
}
private string clientTarget = String.Empty;
[DefaultValue("")]
[Category("Behaviour")]
[Description("The user agent which controls should target when rendering")]
[Bindable(false)]
[Browsable(true)]
public new string ClientTarget
{
get { return clientTarget; }
set { clientTarget = value; }
}
private string codeBehind = "";
[DefaultValue("")]
[ReadOnly(true)]
[Category("Designer")]
[Description("The codebehind file associated with the page")]
[Bindable(false)]
[Browsable(true)]
public string CodeBehind
{
get { return codeBehind; }
set { codeBehind = value; }
}
private int codePage = 0;
[DefaultValue(0)]
[Category("Globalization")]
[Description("The code page used for the response")]
[Bindable(false)]
[Browsable(true)]
public new int CodePage
{
get { return codePage; }
set { codePage = value; }
}
private string compilerOptions = "";
[DefaultValue("")]
[Category("Compilation")]
[Description("Command-line options used when compiling the page")]
[Bindable(false)]
[Browsable(true)]
public string CompilerOptions
{
get { return compilerOptions; }
set { compilerOptions = value; }
}
private string contentType = "text/html";
[DefaultValue("text/html")]
[Category("Behaviour")]
[Description("The MIME type of the HTTP response content")]
[Bindable(false)]
[Browsable(true)]
public new string ContentType
{
get { return contentType; }
set { contentType = value; }
}
private CultureInfo culture;
[DefaultValue(null)]
[Category("Globalization")]
[Description("The culture setting for the page")]
[Bindable(false)]
[Browsable(true)]
public new CultureInfo Culture
{
get { return culture; }
set { culture = value; }
}
private bool debug = false;
[DefaultValue(false)]
[Category("Compilation")]
[Description("Whether the page should be compiled with debugging symbols")]
[Bindable(false)]
[Browsable(true)]
public bool Debug
{
get { return debug; }
set { debug = value; }
}
private string description = "";
[DefaultValue("")]
[Category("Designer")]
[Description("A description of the page")]
[Bindable(false)]
[Browsable(true)]
public string Description
{
get { return description; }
set { description = value; }
}
private string enableSessionState = "true";
[DefaultValue("true")]
[Category("Behaviour")]
[Description("Whether SessionState is enabled (true), read-only (ReadOnly) or disabled (false)")]
[Bindable(false)]
[Browsable(true)]
public string EnableSessionState
{
get { return enableSessionState; }
set { enableSessionState = value; }
}
private bool enableViewState = true;
[DefaultValue(true)]
[Category("Behaviour")]
[Description("Whether view state is enabled")]
[Bindable(false)]
[Browsable(true)]
public new bool EnableViewState
{
get { return enableViewState; }
set { enableViewState = value; }
}
private bool viewStateMac = false;
[DefaultValue(false)]
[Category("Behaviour")]
[Description("Whether a machine authentication check should be run on the view state")]
[Bindable(false)]
[Browsable(true)]
public bool ViewStateMac
{
get { return viewStateMac; }
set { viewStateMac = value; }
}
private string errorPage = "";
[DefaultValue("")]
[Category("Behaviour")]
[Description("The URL to redirect to in the event of an unhandled page exception")]
[Bindable(false)]
[Browsable(true)]
public new string ErrorPage
{
get { return errorPage; }
set { errorPage = value; }
}
private bool _explicit = false;
[DefaultValue(false)]
[Category("Compilation")]
[Description("Whether the page should be compiled with Option Explicit for VB 2005")]
[Bindable(false)]
[Browsable(true)]
public bool Explicit
{
get { return _explicit; }
set { _explicit = value; }
}
private string inherits;
[DefaultValue("")]
[Category("Compilation")]
[Description("The code-behind class from which the page inherits")]
[Bindable(false)]
[Browsable(true)]
public string Inherits
{
get { return inherits; }
set { inherits = value; }
}
private string language;
[DefaultValue("")]
[ReadOnly(true)]
[Category("Compilation")]
[Description("The language used for compiling inline rendering and block code")]
[Bindable(false)]
[Browsable(true)]
public string Language
{
get { return language; }
set { language = value; }
}
private int lcid = 0;
[DefaultValue(0)]
[Category("Globalization")]
[Description("The locale identifier of the page. Defaults to the web server's locale")]
[Bindable(false)]
[Browsable(true)]
public new int LCID
{
get { return lcid; }
set { lcid = value; }
}
private Encoding responseEncoding = null;
[DefaultValue(null)]
[Category("Globalization")]
[Description("The encoding of the HTTP response content")]
[Bindable(false)]
[Browsable(true)]
public new Encoding ResponseEncoding
{
get { return responseEncoding; }
set { responseEncoding = value; }
}
private string src = "";
[DefaultValue("")]
[ReadOnly(true)]
[Category("Compilation")]
[Description("The optional code-behind source file to compile when the page is requested")]
[Bindable(false)]
[Browsable(true)]
public string Src
{
get { return src; }
set { src = value; }
}
private bool smartNavigation = false;
[DefaultValue(false)]
[Category("Behaviour")]
[Description("Whether to maintain scroll position and focus during refreshes. IE5.5 or later only.")]
[Bindable(false)]
[Browsable(true)]
public new bool SmartNavigation
{
get { return smartNavigation; }
set { smartNavigation = value; }
}
private bool strict = false;
[DefaultValue(false)]
[Category("Compilation")]
[Description("Whether the page should be compiled with Option Strict for VB 2005")]
[Bindable(false)]
[Browsable(true)]
public bool Strict
{
get { return strict; }
set { strict = value; }
}
private bool trace = false;
[DefaultValue(false)]
[Category("Behaviour")]
[Description("Whether tracing is enabled")]
[Bindable(false)]
[Browsable(true)]
public new bool Trace
{
get { return trace; }
set { trace = value; }
}
private TraceMode traceMode = TraceMode.Default;
[DefaultValue(TraceMode.Default)]
[Category("Behaviour")]
[Description("The sorting mode for tracing message")]
[Bindable(false)]
[Browsable(true)]
public TraceMode TraceMode
{
get { return traceMode; }
set { traceMode = value; }
}
private string transaction = "Disabled";
[DefaultValue("Disabled")]
[Category("Behaviour")]
[Description("How transactions are supported. Disabled, NotSupported, Supported, Required, or RequiresNew")]
[Bindable(false)]
[Browsable(true)]
public string Transaction
{
get { return transaction; }
set { transaction = value; }
}
private CultureInfo uiCulture = null;
[DefaultValue(null)]
[Category("Globalization")]
[Description("The UI culture to use")]
[Bindable(false)]
[Browsable(true)]
public new CultureInfo UICulture
{
get { return uiCulture; }
set { uiCulture = value; }
}
private bool validateRequest = true;
[DefaultValue(true)]
[Category("Behaviour")]
[Description("Whether to use request validation to increase security")]
[Bindable(false)]
[Browsable(true)]
public bool ValidateRequest
{
get { return validateRequest; }
set { validateRequest = value; }
}
private int warningLevel = 4;
[DefaultValue(4)]
[Category("Compilation")]
[Description("The compiler warning level at which to abort compilation")]
[Bindable(false)]
[Browsable(true)]
public int WarningLevel
{
get { return warningLevel; }
set { warningLevel = value; }
}
#endregion
}
}

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

@ -0,0 +1,117 @@
/*
* RootDesigner.cs - a root designer for ASP.NET WebForms pages
*
* Authors:
* Michael Hutchinson <m.j.hutchinson@gmail.com>
*
* Copyright (C) 2005 Michael Hutchinson
*
* This sourcecode is licenced under The MIT License:
*
* Permission is hereby granted, free of charge, to any person obtaining
* a copy of this software and associated documentation files (the
* "Software"), to deal in the Software without restriction, including
* without limitation the rights to use, copy, modify, merge, publish,
* distribute, sublicense, and/or sell copies of the Software, and to permit
* persons to whom the Software is furnished to do so, subject to the
* following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
* OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN
* NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM,
* DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
* OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE
* USE OR OTHER DEALINGS IN THE SOFTWARE.
*/
using System;
using System.ComponentModel;
using System.ComponentModel.Design;
using System.Web.UI;
using System.Drawing.Design;
using AspNetEdit.Editor.UI;
namespace AspNetEdit.Editor.ComponentModel
{
internal class RootDesigner : IRootDesigner, IToolboxUser
{
private IComponent component;
private RootDesignerView view;
public RootDesigner (IComponent component)
{
view = new RootDesignerView (component.Site.GetService (typeof (IDesignerHost)) as IDesignerHost);
}
#region IRootDesigner Members
public object GetView (ViewTechnology technology) {
if (technology == ViewTechnology.Passthrough)
return view;
else return null;
}
public ViewTechnology[] SupportedTechnologies {
get {
ViewTechnology[] tech = { ViewTechnology.Passthrough };
return tech;
}
}
#endregion
#region IDesigner Members
public IComponent Component {
get { return component; }
}
public void DoDefaultAction ()
{
throw new NotImplementedException ();
}
public void Initialize (IComponent component)
{
if ( !(component is WebFormPage))
throw new ArgumentException ("component is not a page", "component");
this.component = component;
}
public DesignerVerbCollection Verbs {
get { return new DesignerVerbCollection (); }
}
#endregion
#region IDisposable Members
public void Dispose ()
{
view.Destroy ();
view.Dispose ();
}
#endregion
#region IToolboxUser Members
public bool GetToolSupported (ToolboxItem tool)
{
//TODO: Fix toolbox selection
return true;
}
public void ToolPicked (ToolboxItem tool)
{
throw new NotImplementedException ();
}
#endregion
}
}

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

@ -0,0 +1,148 @@
/*
* SelectionService.cs -tracks selected components
*
* Authors:
* Michael Hutchinson <m.j.hutchinson@gmail.com>
*
* Copyright (C) 2005 Michael Hutchinson
*
* This sourcecode is licenced under The MIT License:
*
* Permission is hereby granted, free of charge, to any person obtaining
* a copy of this software and associated documentation files (the
* "Software"), to deal in the Software without restriction, including
* without limitation the rights to use, copy, modify, merge, publish,
* distribute, sublicense, and/or sell copies of the Software, and to permit
* persons to whom the Software is furnished to do so, subject to the
* following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
* OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN
* NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM,
* DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
* OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE
* USE OR OTHER DEALINGS IN THE SOFTWARE.
*/
using System;
using System.ComponentModel.Design;
using System.Collections;
using System.ComponentModel;
namespace AspNetEdit.Editor.ComponentModel
{
public class SelectionService : ISelectionService
{
private ArrayList selections = new ArrayList ();
private object primary;
public bool GetComponentSelected (object component)
{
return selections.Contains (component);
}
public ICollection GetSelectedComponents ()
{
return (ArrayList.ReadOnly (selections) as ICollection);
}
public object PrimarySelection
{
get { return primary; }
}
public int SelectionCount
{
get { return selections.Count; }
}
//This is effectively .NET 2.0's SelectionTypes.Auto
//It duplicates VS.NET's selection behaviour
public void SetSelectedComponents (System.Collections.ICollection components)
{
OnSelectionChanging ();
//use control and shift modifier to change selection
//TODO: find a better way of checking key modifier status: this is BAD
int x, y;
bool modified = false;
Gdk.Window someWindow = Gdk.Window.AtPointer (out x, out y);
if (someWindow != null) {
Gdk.ModifierType mt;
someWindow.GetPointer (out x, out y, out mt);
modified = ((mt & Gdk.ModifierType.ShiftMask) == Gdk.ModifierType.ShiftMask) || ((mt & Gdk.ModifierType.ControlMask) == Gdk.ModifierType.ControlMask);
}
if (components == null)
{
selections.Clear ();
primary = null;
}
else {
foreach (object comp in components) {
if (! (comp is IComponent))
throw new ArgumentException ("All elements in collection must be components");
//what do we do with the component?
if (!selections.Contains (comp))
{
//a simple replacement
if (!modified) {
selections.Clear ();
selections.Add (comp);
}
//add to selection and make primary
else
selections.Add (comp);
primary = comp;
}
else
{
//only deselect or change selection if other components
//i.e. can't toggle selection status if is only component
if (selections.Count > 1)
//change primary selection
if (!modified)
primary = comp;
//remove and replace primary selection
else {
selections.Remove (comp);
if (selections.Count > 0)
primary = selections[selections.Count - 1];
}
}
}
}
//fire event to let everyone know, especially PropertyGrid
OnSelectionChanged();
}
public void SetSelectedComponents(System.Collections.ICollection components, SelectionTypes selectionType)
{
//TODO: Use .NET 2.0 SelectionTypes Primary, Add, Replace, Remove, Toggle
if ((selectionType & SelectionTypes.Valid) == SelectionTypes.Valid)
SetSelectedComponents(components);
}
public event EventHandler SelectionChanged;
public event EventHandler SelectionChanging;
protected void OnSelectionChanged()
{
if (SelectionChanged != null)
SelectionChanged(this, EventArgs.Empty);
}
protected void OnSelectionChanging()
{
if (SelectionChanging != null)
SelectionChanging(this, EventArgs.Empty);
}
}
}

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

@ -0,0 +1,416 @@
/*
* ToolboxService.cs - used to add/remove/find/select toolbox items
*
* Authors:
* Michael Hutchinson <m.j.hutchinson@gmail.com>
*
* Copyright (C) 2005 Michael Hutchinson
*
* This sourcecode is licenced under The MIT License:
*
* Permission is hereby granted, free of charge, to any person obtaining
* a copy of this software and associated documentation files (the
* "Software"), to deal in the Software without restriction, including
* without limitation the rights to use, copy, modify, merge, publish,
* distribute, sublicense, and/or sell copies of the Software, and to permit
* persons to whom the Software is furnished to do so, subject to the
* following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
* OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN
* NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM,
* DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
* OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE
* USE OR OTHER DEALINGS IN THE SOFTWARE.
*/
using System;
using System.Drawing.Design;
using System.Collections;
using System.IO;
using System.Xml;
using System.Reflection;
using System.ComponentModel;
using System.Runtime.Serialization.Formatters.Binary;
namespace AspNetEdit.Editor.ComponentModel
{
public class ToolboxService : IToolboxService
{
Hashtable categories = new Hashtable ();
private string selectedCategory;
private ToolboxItem selectedItem = null;
#region IToolboxService Members
public void AddCreator (ToolboxItemCreatorCallback creator, string format, System.ComponentModel.Design.IDesignerHost host)
{
throw new NotImplementedException ();
}
public void AddCreator (ToolboxItemCreatorCallback creator, string format)
{
throw new NotImplementedException ();
}
public void AddLinkedToolboxItem (ToolboxItem toolboxItem, string category, System.ComponentModel.Design.IDesignerHost host)
{
throw new NotImplementedException ();
}
public void AddLinkedToolboxItem (ToolboxItem toolboxItem, System.ComponentModel.Design.IDesignerHost host)
{
throw new NotImplementedException ();
}
public void AddToolboxItem (ToolboxItem toolboxItem)
{
AddToolboxItem (toolboxItem, "General");
}
public void AddToolboxItem (ToolboxItem toolboxItem, string category)
{
if (!categories.ContainsKey (category))
categories[category] = new ArrayList ();
((ArrayList) categories[category]).Add (toolboxItem);
}
public CategoryNameCollection CategoryNames
{
get {
string[] cats = new string[categories.Keys.Count];
categories.Keys.CopyTo (cats, 0);
return new CategoryNameCollection (cats);
}
}
public ToolboxItem DeserializeToolboxItem(object serializedObject, System.ComponentModel.Design.IDesignerHost host)
{
throw new NotImplementedException ();
}
public ToolboxItem DeserializeToolboxItem (object serializedObject)
{
if ( !(serializedObject is byte[])) return null;
MemoryStream ms = new MemoryStream( (byte[]) serializedObject);
object obj = BF.Deserialize (ms);
ms.Close ();
if (! (obj is ToolboxItem)) return null;
return (ToolboxItem) obj;
}
public ToolboxItem GetSelectedToolboxItem (System.ComponentModel.Design.IDesignerHost host)
{
IToolboxUser toolboxUser = (IToolboxUser) host.GetDesigner (host.RootComponent);
if (toolboxUser.GetToolSupported (selectedItem))
return selectedItem;
else
return null;
}
public ToolboxItem GetSelectedToolboxItem ()
{
return selectedItem;
}
public ToolboxItemCollection GetToolboxItems (string category, System.ComponentModel.Design.IDesignerHost host)
{
if (!categories.ContainsKey (category))
return null;
ArrayList tools = new ArrayList ();
foreach(ToolboxItem tool in ((ArrayList) categories[category]))
if (((IToolboxUser) host.GetDesigner (host.RootComponent)).GetToolSupported (tool))
tools.Add (tool);
return new ToolboxItemCollection ((ToolboxItem[]) tools.ToArray (typeof (ToolboxItem)));
}
public ToolboxItemCollection GetToolboxItems (string category)
{
if (!categories.ContainsKey (category))
return null;
ArrayList tools = (ArrayList) categories[category];
return new ToolboxItemCollection (tools.ToArray () as ToolboxItem[]);
}
public ToolboxItemCollection GetToolboxItems (System.ComponentModel.Design.IDesignerHost host)
{
ArrayList tools = new ArrayList();
IToolboxUser toolboxUser = (IToolboxUser) host.GetDesigner (host.RootComponent);
foreach (ArrayList arr in categories.Values)
foreach (ToolboxItem tool in arr)
if (toolboxUser.GetToolSupported (tool))
tools.Add (tool);
return new ToolboxItemCollection(tools.ToArray () as ToolboxItem[]);
}
public ToolboxItemCollection GetToolboxItems ()
{
ArrayList tools = new ArrayList ();
foreach (ArrayList arr in categories.Values)
tools.AddRange (arr);
return new ToolboxItemCollection(tools.ToArray () as ToolboxItem[]);
}
public bool IsSupported (object serializedObject, System.ComponentModel.Design.IDesignerHost host)
{
throw new NotImplementedException ();
}
public bool IsSupported (object serializedObject, System.Collections.ICollection filterAttributes)
{
throw new NotImplementedException ();
}
public bool IsToolboxItem (object serializedObject, System.ComponentModel.Design.IDesignerHost host)
{
throw new NotImplementedException ();
}
public bool IsToolboxItem (object serializedObject)
{
throw new NotImplementedException ();
}
public void Refresh ()
{
throw new NotImplementedException ();
}
public void RemoveCreator (string format, System.ComponentModel.Design.IDesignerHost host)
{
throw new NotImplementedException ();
}
public void RemoveCreator (string format)
{
throw new NotImplementedException ();
}
public void RemoveToolboxItem (ToolboxItem toolboxItem, string category)
{
throw new NotImplementedException ();
}
public void RemoveToolboxItem (ToolboxItem toolboxItem)
{
throw new NotImplementedException ();
}
public string SelectedCategory {
get {return selectedCategory;}
set {
if (categories.ContainsKey (value))
selectedCategory = value;
}
}
public void SelectedToolboxItemUsed ()
{
//throw new NotImplementedException ();
}
public object SerializeToolboxItem (ToolboxItem toolboxItem)
{
MemoryStream ms = new MemoryStream ();
BF.Serialize (ms, toolboxItem);
byte[] retval = ms.ToArray ();
ms.Close ();
return retval;
}
public bool SetCursor ()
{
throw new NotImplementedException ();
}
public void SetSelectedToolboxItem (ToolboxItem toolboxItem)
{
this.selectedItem = toolboxItem;
}
#endregion
#region Save/load routines
public void Persist (Stream stream)
{
StreamWriter strw = new StreamWriter (stream);
XmlTextWriter xw = new XmlTextWriter (strw);
xw.WriteStartDocument (true);
xw.WriteStartElement ("Toolbox");
foreach(string key in categories.Keys) {
xw.WriteStartElement ("ToolboxCategory");
xw.WriteAttributeString ("name", key);
foreach (ToolboxItem item in ((ArrayList)categories[key])) {
xw.WriteStartElement ("ToolboxItem");
xw.WriteAttributeString ("DisplayName", item.DisplayName);
//xw.WriteAttributeString ("AssemblyName", item.AssemblyName.ToString());
xw.WriteAttributeString ("TypeName", item.TypeName);
byte[] serItem = (byte[]) SerializeToolboxItem(item);
xw.WriteString (ToBinHexString(serItem));
xw.WriteEndElement ();
}
xw.WriteEndElement ();
}
xw.WriteEndElement ();
xw.Close ();
strw.Close ();
}
//temporary method until we get a UI and some form of persistence)
public void PopulateFromAssembly (Assembly assembly)
{
Type[] types = assembly.GetTypes ();
AssemblyName assemblyName = assembly.GetName ();
foreach (Type t in types)
{
if (t.IsAbstract) continue;
AttributeCollection atts = TypeDescriptor.GetAttributes (t);
bool containsAtt = false;
foreach (Attribute a in atts)
if (a.GetType() == typeof (ToolboxItemAttribute))
containsAtt = true;
if (!containsAtt) continue;
ToolboxItemAttribute tba = (ToolboxItemAttribute) atts[typeof(ToolboxItemAttribute)];
if (tba.Equals (ToolboxItemAttribute.None)) continue;
Type toolboxItemType = (tba.ToolboxItemType == null) ? typeof (ToolboxItem) : tba.ToolboxItemType;
string category = "General";
if (t.IsSubclassOf (typeof (System.Web.UI.WebControls.BaseValidator)))
category = "Validation";
else if (t.Namespace == "System.Web.UI.HtmlControls" && t.IsSubclassOf (typeof (System.Web.UI.HtmlControls.HtmlControl)))
category = "Html Elements";
else if (t.IsSubclassOf (typeof (System.Web.UI.WebControls.BaseDataList)))
category = "Data Controls";
else if (t.IsSubclassOf (typeof (System.Web.UI.WebControls.WebControl)))
category = "Web Controls";
AddToolboxItem(new ToolboxItem (t), category);
}
}
#endregion
private BinaryFormatter bf = null;
private BinaryFormatter BF {
get {
if (bf == null)
bf = new BinaryFormatter ();
return bf;
}
}
#region Borrowed from System.Xml.XmlConvert. If only the methods were public as documented...
// Authors: Dwivedi, Ajay kumar (Adwiv@Yahoo.com), Gonzalo Paniagua Javier (gonzalo@ximian.com)
// Alan Tam Siu Lung (Tam@SiuLung.com), Atsushi Enomoto (ginga@kit.hi-ho.ne.jp)
// License: MIT X11 (same as file)
// Copyright: (C) 2002 Ximian, Inc (http://www.ximian.com
// LAMESPEC: It has been documented as public, but is marked as internal.
private string ToBinHexString (byte [] buffer)
{
StringWriter w = new StringWriter ();
WriteBinHex (buffer, 0, buffer.Length, w);
return w.ToString ();
}
internal static void WriteBinHex (byte [] buffer, int index, int count, TextWriter w)
{
if (buffer == null)
throw new ArgumentNullException ("buffer");
if (index < 0)
throw new ArgumentOutOfRangeException ("index", index, "index must be non negative integer.");
if (count < 0)
throw new ArgumentOutOfRangeException ("count", count, "count must be non negative integer.");
if (buffer.Length < index + count)
throw new ArgumentOutOfRangeException ("index and count must be smaller than the length of the buffer.");
// Copied from XmlTextWriter.WriteBinHex ()
int end = index + count;
for (int i = index; i < end; i++) {
int val = buffer [i];
int high = val >> 4;
int low = val & 15;
if (high > 9)
w.Write ((char) (high + 55));
else
w.Write ((char) (high + 0x30));
if (low > 9)
w.Write ((char) (low + 55));
else
w.Write ((char) (low + 0x30));
}
}
// It is documented as public method, but in fact it is not.
private byte [] FromBinHexString (string s)
{
char [] chars = s.ToCharArray ();
byte [] bytes = new byte [chars.Length / 2 + chars.Length % 2];
FromBinHexString (chars, 0, chars.Length, bytes);
return bytes;
}
private int FromBinHexString (char [] chars, int offset, int charLength, byte [] buffer)
{
int bufIndex = offset;
for (int i = 0; i < charLength - 1; i += 2) {
buffer [bufIndex] = (chars [i] > '9' ?
(byte) (chars [i] - 'A' + 10) :
(byte) (chars [i] - '0'));
buffer [bufIndex] <<= 4;
buffer [bufIndex] += chars [i + 1] > '9' ?
(byte) (chars [i + 1] - 'A' + 10) :
(byte) (chars [i + 1] - '0');
bufIndex++;
}
if (charLength %2 != 0)
buffer [bufIndex++] = (byte)
((chars [charLength - 1] > '9' ?
(byte) (chars [charLength - 1] - 'A' + 10) :
(byte) (chars [charLength - 1] - '0'))
<< 4);
return bufIndex - offset;
}
#endregion
}
}

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

@ -0,0 +1,65 @@
/*
* DesignerTransaction.cs - Skeleton transactions for designer support.
* Does not yet track changes.
*
* Authors:
* Michael Hutchinson <m.j.hutchinson@gmail.com>
*
* Copyright (C) 2005 Michael Hutchinson
*
* This sourcecode is licenced under The MIT License:
*
* Permission is hereby granted, free of charge, to any person obtaining
* a copy of this software and associated documentation files (the
* "Software"), to deal in the Software without restriction, including
* without limitation the rights to use, copy, modify, merge, publish,
* distribute, sublicense, and/or sell copies of the Software, and to permit
* persons to whom the Software is furnished to do so, subject to the
* following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
* OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN
* NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM,
* DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
* OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE
* USE OR OTHER DEALINGS IN THE SOFTWARE.
*/
using System;
using System.ComponentModel.Design;
namespace AspNetEdit.Editor.ComponentModel
{
internal class Transaction : DesignerTransaction
{
private DesignerHost host;
public Transaction (DesignerHost host, string description)
: base (description)
{
this.host = host;
}
protected override void OnCancel ()
{
if (host == null)
return;
host.OnTransactionClosing ( false);
host.OnTransactionClosed (false, this);
host = null;
}
protected override void OnCommit ()
{
if (host == null)
return;
host.OnTransactionClosing (true);
host.OnTransactionClosed (true, this);
host = null;
}
}
}

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

@ -0,0 +1,91 @@
/*
* TypeDescriptorFilterService.cs - performs property/event/attribute filtering
*
* Authors:
* Michael Hutchinson <m.j.hutchinson@gmail.com>
*
* Copyright (C) 2005 Michael Hutchinson
*
* This sourcecode is licenced under The MIT License:
*
* Permission is hereby granted, free of charge, to any person obtaining
* a copy of this software and associated documentation files (the
* "Software"), to deal in the Software without restriction, including
* without limitation the rights to use, copy, modify, merge, publish,
* distribute, sublicense, and/or sell copies of the Software, and to permit
* persons to whom the Software is furnished to do so, subject to the
* following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
* OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN
* NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM,
* DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
* OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE
* USE OR OTHER DEALINGS IN THE SOFTWARE.
*/
using System;
using System.ComponentModel.Design;
using System.Web.UI.Design;
using System.ComponentModel;
namespace AspNetEdit.Editor.ComponentModel
{
public class TypeDescriptorFilterService : ITypeDescriptorFilterService
{
public bool FilterAttributes (IComponent component, System.Collections.IDictionary attributes)
{
//get the IDesignerFilter interface
IDesignerHost host = component.Site.GetService (typeof (IDesignerHost)) as IDesignerHost;
if (host == null)
return true;
IDesignerFilter designer = host.GetDesigner (component) as IDesignerFilter;
if (designer == null)
return true;
//Invoke the filtering methods
designer.PreFilterAttributes (attributes);
designer.PostFilterAttributes (attributes);
return true;
}
public bool FilterEvents (IComponent component, System.Collections.IDictionary events)
{
//get the IDesignerFilter interface
IDesignerHost host = component.Site.GetService (typeof (IDesignerHost)) as IDesignerHost;
if (host == null)
return false;
IDesignerFilter designer = host.GetDesigner (component) as IDesignerFilter;
if (designer == null)
return false;
//Invoke the filtering methods
designer.PreFilterEvents (events);
designer.PostFilterEvents (events);
return true;
}
public bool FilterProperties (IComponent component, System.Collections.IDictionary properties)
{
//get the IDesignerFilter interface
IDesignerHost host = component.Site.GetService (typeof (IDesignerHost)) as IDesignerHost;
if (host == null)
return false;
IDesignerFilter designer = host.GetDesigner (component) as IDesignerFilter;
if (designer == null)
return false;
//Invoke the filtering methods
designer.PreFilterProperties (properties);
designer.PostFilterProperties (properties);
return true;
}
}
}

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

@ -0,0 +1,97 @@
/*
* TypeResolutionService.cs - resolves types in referenced assemblies
*
* Authors:
* Michael Hutchinson <m.j.hutchinson@gmail.com>
*
* Copyright (C) 2005 Michael Hutchinson
*
* This sourcecode is licenced under The MIT License:
*
* Permission is hereby granted, free of charge, to any person obtaining
* a copy of this software and associated documentation files (the
* "Software"), to deal in the Software without restriction, including
* without limitation the rights to use, copy, modify, merge, publish,
* distribute, sublicense, and/or sell copies of the Software, and to permit
* persons to whom the Software is furnished to do so, subject to the
* following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
* OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN
* NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM,
* DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
* OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE
* USE OR OTHER DEALINGS IN THE SOFTWARE.
*/
using System;
using System.ComponentModel.Design;
using System.Reflection;
namespace AspNetEdit.Editor.ComponentModel
{
public class TypeResolutionService : ITypeResolutionService
{
#region ITypeResolutionService Members
public TypeResolutionService ()
{
}
public Assembly GetAssembly (AssemblyName name, bool throwOnError)
{
Assembly assembly = GetAssembly (name);
if (assembly == null)
throw new Exception ("The assembly could not be found");
return assembly;
}
//TODO: make this work properly!
//for now, special-casing for System.Web
public Assembly GetAssembly (AssemblyName name)
{
Assembly web = typeof (System.Web.UI.Control).Assembly;
if (web.GetName ().FullName == name.FullName)
return web;
else
throw new NotImplementedException ();
}
public string GetPathOfAssembly (AssemblyName name)
{
throw new NotImplementedException();
}
public Type GetType (string name, bool throwOnError, bool ignoreCase)
{
throw new NotImplementedException ();
}
public Type GetType (string name, bool throwOnError)
{
//TODO: Look up in other referenced assemblies (project support)
return Type.GetType (name, throwOnError);
}
public Type GetType (string name)
{
//TODO: Look up in other referenced assemblies (project support)
return Type.GetType (name);
}
public void ReferenceAssembly (AssemblyName name)
{
//TODO: Actually add reference: need project support
//throw new NotImplementedException ();
}
#endregion
}
}

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

@ -0,0 +1,240 @@
/*
* WebFormsPage.cs - Represents an ASP.NET Page in the designer
*
* Authors:
* Michael Hutchinson <m.j.hutchinson@gmail.com>
*
* Copyright (C) 2005 Michael Hutchinson
*
* This sourcecode is licenced under The MIT License:
*
* Permission is hereby granted, free of charge, to any person obtaining
* a copy of this software and associated documentation files (the
* "Software"), to deal in the Software without restriction, including
* without limitation the rights to use, copy, modify, merge, publish,
* distribute, sublicense, and/or sell copies of the Software, and to permit
* persons to whom the Software is furnished to do so, subject to the
* following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
* OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN
* NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM,
* DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
* OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE
* USE OR OTHER DEALINGS IN THE SOFTWARE.
*/
using System;
using System.ComponentModel;
using System.Globalization;
using System.Text;
using System.Web;
using System.IO;
using System.Web.Compilation;
using System.Collections;
using System.Web.UI;
using System.Web.UI.Design;
using System.ComponentModel.Design;
namespace AspNetEdit.Editor.ComponentModel
{
internal class WebFormPage : System.Web.UI.Page
{
private const string newDocument = "<html>\n<head>\n\t<title>{0}</title>\n</head>\n<body>\n<form runat=\"server\"\n<cursor/>\n</form></body>\n</html>";
private const string cursor = "<cursor/>";
private const string controlSubstitute = "<aspcontrol name=\"{0}\" />";
private StringBuilder document;
private Hashtable directives;
//loads an existing page from a file stream
public WebFormPage (Stream fileStream, string fileName)
: base ()
{
//this is where the parsed, substituted document goes
document = new StringBuilder ();
directives = new Hashtable ();
}
//new blank document
public WebFormPage (string documentName)
{
document = new StringBuilder (String.Format (newDocument, documentName));
}
#region Parser
/*
//initialise our parser and hook up events
//StreamReader reader = new StreamReader(fileStream);
//AspParser parser = new System.Web.Compilation.AspParser(fileName, reader);
//reader.Close();
//parser.Error += new ParseErrorHandler(parser_Error);
//parser.TagParsed += new TagParsedHandler(parser_TagParsed);
//parser.TextParsed += new TextParsedHandler(parser_TextParsed);
//and go!
//parser.Parse();
*
#region Parser event handlers
void parser_TextParsed(ILocation location, string text)
{
//This one's simple. Nothing to initialise or worry about
document.Append(text);
}
void parser_TagParsed(ILocation location, TagType tagtype, string id, TagAttributes attributes)
{
switch (tagtype)
{
case TagType.Directive:
AddDirective(id, attributes);
break;
case TagType.Close:
break;
case TagType.CodeRender:
break;
case TagType.CodeRenderExpression:
break;
case TagType.DataBinding:
break;
case TagType.Include:
break;
case TagType.SelfClosing:
break;
case TagType.ServerComment:
break;
case TagType.Tag:
break;
case TagType.Text:
break;
}
}
private void parser_Error(ILocation location, string message)
{
document = new StringBuilder();
document.Append(ErrorDocument("Error loading document", message + "on line " + location.BeginLine));
throw new Exception("The method or operation is not implemented.");
}
#endregion
#region Parser eventhandler support
private void AddDirective(string id, TagAttributes attributes)
{
document.Append("<directive no=''>");
//directives.Add(directiveIndex);
}
private string ErrorDocument(string errorTitle, string errorDetails)
{
return "<html><body fgcolor='red'><h1>"
+ errorTitle
+ "</h1><p>"
+ errorDetails
+ "</p></body></html>";
}
#endregion
*/
#endregion
#region Document handling
public string ViewDocument ()
{
//TODO: Parse document instead of StringBuilder.Replace
StringBuilder builder = new StringBuilder (document.ToString ());
//get a host to work with
if (Site == null)
throw new Exception ("The WebFormsPage cannot be persisted without a site");
IDesignerHost host = Site.GetService (typeof(IDesignerHost)) as IDesignerHost;
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 Control) || comp.Site == null)
throw new Exception ("The component is not a sited System.Web.UI.Control");
System.IO.StringWriter strWriter = new System.IO.StringWriter ();
System.Web.UI.HtmlTextWriter writer = new System.Web.UI.HtmlTextWriter (strWriter);
string substituteText = String.Format (controlSubstitute, comp.Site.Name);
((Control) comp).RenderControl (writer);
writer.Flush ();
strWriter.Flush ();
builder.Replace(substituteText, strWriter.ToString ());
}
//remove cursor
builder.Replace (cursor, string.Empty);
return builder.ToString ();
}
public string PersistDocument()
{
//TODO: Parse document instead of StringBuilder.Replace
StringBuilder builder = new StringBuilder (document.ToString ());
//get a host to work with
if (Site == null)
throw new Exception ("The WebFormsPage cannot be persisted without a site");
IDesignerHost host = Site.GetService (typeof (IDesignerHost)) as IDesignerHost;
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 Control) || comp.Site == null)
throw new Exception ("The component is not a sited System.Web.UI.Control");
((Control) comp).ID = comp.Site.Name;
string substituteText = String.Format (controlSubstitute, comp.Site.Name);
string persistedControl = ControlPersister.PersistControl ((Control) comp, host);
builder.Replace (substituteText, persistedControl);
}
//remove cursor
builder.Replace (cursor, string.Empty);
return builder.ToString ();
}
public void AddControlAtCursor (Control control)
{
string subst = String.Format (controlSubstitute, control.Site.Name);
document.Replace (cursor, subst+cursor);
}
public void RemoveControl (Control control)
{
string subst = String.Format (controlSubstitute, control.Site.Name);
document.Replace (subst, string.Empty);
}
internal void RenameControl (string oldName, string newName)
{
string oldSubstituteText = String.Format (controlSubstitute, oldName);
string newSubstituteText = String.Format (controlSubstitute, newName);
document.Replace (oldSubstituteText, newSubstituteText);
}
#endregion
}
}

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

@ -0,0 +1,57 @@
/*
* WebFormReferenceManager.cs - tracks references in a WebForm page
*
* Authors:
* Michael Hutchinson <m.j.hutchinson@gmail.com>
*
* Copyright (C) 2005 Michael Hutchinson
*
* This sourcecode is licenced under The MIT License:
*
* Permission is hereby granted, free of charge, to any person obtaining
* a copy of this software and associated documentation files (the
* "Software"), to deal in the Software without restriction, including
* without limitation the rights to use, copy, modify, merge, publish,
* distribute, sublicense, and/or sell copies of the Software, and to permit
* persons to whom the Software is furnished to do so, subject to the
* following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
* OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN
* NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM,
* DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
* OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE
* USE OR OTHER DEALINGS IN THE SOFTWARE.
*/
using System;
using System.Web.UI.Design;
namespace AspNetEdit.Editor.ComponentModel
{
public class WebFormReferenceManager : IWebFormReferenceManager
{
#region IWebFormReferenceManager Members
public Type GetObjectType(string tagPrefix, string typeName)
{
throw new NotImplementedException ();
}
public string GetRegisterDirectives ()
{
throw new NotImplementedException ();
}
public string GetTagPrefix (Type objectType)
{
return "asp";
}
#endregion
}
}

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

@ -0,0 +1,157 @@
/*
* PropertyGrid.cs - PropertyGrid wrapper. Hooks into ISelectionService.
*
* Authors:
* Michael Hutchinson <m.j.hutchinson@gmail.com>
*
* Copyright (C) 2005 Michael Hutchinson
*
* This sourcecode is licenced under The MIT License:
*
* Permission is hereby granted, free of charge, to any person obtaining
* a copy of this software and associated documentation files (the
* "Software"), to deal in the Software without restriction, including
* without limitation the rights to use, copy, modify, merge, publish,
* distribute, sublicense, and/or sell copies of the Software, and to permit
* persons to whom the Software is furnished to do so, subject to the
* following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
* OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN
* NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM,
* DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
* OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE
* USE OR OTHER DEALINGS IN THE SOFTWARE.
*/
using System;
using System.ComponentModel.Design;
using Gtk;
using System.ComponentModel;
using System.Collections;
using AspNetEdit.UI;
namespace AspNetEdit.Editor.UI
{
public class PropertyGrid : Gtk.VBox
{
private ServiceContainer parentServices = null;
private ISelectionService selectionService = null;
private IExtenderListService extenderListService = null;
private IComponentChangeService changeService = null;
private ITypeDescriptorFilterService typeDescriptorFilterService = null;
private AspNetEdit.UI.PropertyGrid grid;
private ListStore components;
private ComboBox combo;
public PropertyGrid (ServiceContainer parentServices)
{
this.parentServices = parentServices;
grid = new AspNetEdit.UI.PropertyGrid ();
this.PackEnd (grid, true, true, 0);
components = new ListStore (typeof (string), typeof (IComponent));
combo = new ComboBox (components);
CellRenderer rdr = new CellRendererText ();
combo.PackStart (rdr, true);
combo.AddAttribute (rdr, "text", 0);
this.PackStart (combo, false, false, 3);
combo.Changed += new EventHandler (combo_Changed);
InitialiseServices();
}
void combo_Changed (object sender, EventArgs e)
{
TreeIter t;
combo.GetActiveIter(out t);
IComponent comp = (IComponent) components.GetValue(t, 1);
//Tell everybody about the new selection. We'll hear about this too.
selectionService.SetSelectedComponents (new IComponent[] { comp });
}
// We need these services to be present, but we cache references for efficiency
// Whenever new designer host loaded etc, must reinitialise the services
public void InitialiseServices ()
{
//unregister old event handlers
if (selectionService != null)
selectionService.SelectionChanged -= new EventHandler(selectionService_SelectionChanged);
//update references
extenderListService = parentServices.GetService (typeof (IExtenderListService)) as IExtenderListService;
selectionService = parentServices.GetService (typeof (ISelectionService)) as ISelectionService;
changeService = parentServices.GetService (typeof (IComponentChangeService)) as IComponentChangeService;
typeDescriptorFilterService = parentServices.GetService (typeof (ITypeDescriptorFilterService)) as ITypeDescriptorFilterService;
//register event handlers
if (selectionService != null)
selectionService.SelectionChanged += new EventHandler (selectionService_SelectionChanged);
if (changeService != null) {
changeService.ComponentAdded += new ComponentEventHandler (changeService_ComponentAdded);
changeService.ComponentRemoved += new ComponentEventHandler (changeService_ComponentRemoved);
changeService.ComponentRename += new ComponentRenameEventHandler (changeService_ComponentRename);
}
//get existing components for combo list
IDesignerHost host = parentServices.GetService (typeof (IDesignerHost)) as IDesignerHost;
if (host != null)
foreach (IComponent comp in host.Container.Components)
changeService_ComponentAdded(host.Container, new ComponentEventArgs (comp));
}
void changeService_ComponentRename (object sender, ComponentRenameEventArgs e)
{
//We just need to rename the right component in the combobox list
TreeIter t;
components.GetIterFirst (out t);
do {
if ((IComponent)components.GetValue (t, 1) == e.Component && (string) components.GetValue(t, 0) == e.OldName) {
components.SetValue (t, 0, e.NewName);
return;
}
} while (components.IterNext (ref t));
}
void changeService_ComponentRemoved (object sender, ComponentEventArgs e)
{
//remove component from combobox list
//need a variable external to foreach so we can pass by ref
TreeIter iter;
components.GetIterFirst (out iter);
do
{
if ((IComponent) components.GetValue (iter, 1) == e.Component)
{
components.Remove (ref iter);
break;
}
}
while (components.IterNext (ref iter));
}
void changeService_ComponentAdded (object sender, ComponentEventArgs e)
{
//simply add to the combobox list
components.AppendValues (new object[] { e.Component.Site.Name, e.Component} );
}
private void selectionService_SelectionChanged (object sender, EventArgs e)
{
grid.CurrentObject = selectionService.PrimarySelection;
}
}
}

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

@ -0,0 +1,184 @@
/*
* RootDesignerView.cs - The Gecko# design surface returned by the WebForms Root Designer.
*
* Authors:
* Michael Hutchinson <m.j.hutchinson@gmail.com>
*
* Copyright (C) 2005 Michael Hutchinson
*
* This sourcecode is licenced under The MIT License:
*
* Permission is hereby granted, free of charge, to any person obtaining
* a copy of this software and associated documentation files (the
* "Software"), to deal in the Software without restriction, including
* without limitation the rights to use, copy, modify, merge, publish,
* distribute, sublicense, and/or sell copies of the Software, and to permit
* persons to whom the Software is furnished to do so, subject to the
* following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
* OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN
* NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM,
* DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
* OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE
* USE OR OTHER DEALINGS IN THE SOFTWARE.
*/
using System;
using AspNetEdit.JSCall;
using System.ComponentModel.Design;
using System.ComponentModel;
using System.Text;
using AspNetEdit.Editor.ComponentModel;
using Gtk;
namespace AspNetEdit.Editor.UI
{
public class RootDesignerView : Gecko.WebControl
{
private CommandManager comm;
private IDesignerHost host;
private IComponentChangeService changeService;
private ISelectionService selectionService;
private IMenuCommandService menuService;
private string mozPath;
private StringBuilder document;
public RootDesignerView (IDesignerHost host)
: base()
{
//it's through this that we communicate with JavaScript
comm = new CommandManager (this);
//we use the host to get services and designers
this.host = host;
if (host == null)
throw new ArgumentNullException ("host");
//We use this to monitor component changes and update as necessary
changeService = host.GetService (typeof (IComponentChangeService)) as IComponentChangeService;
if (changeService == null)
throw new Exception ("Could not obtain IComponentChangeService from host");
//We use this to monitor and set selections
selectionService = host.GetService (typeof (ISelectionService)) as ISelectionService;
if (selectionService == null)
throw new Exception ("Could not obtain ISelectionService from host");
//This is used to add undo/redo, cut/paste etc commands to menu
//Also to launch right-click menu
menuService = host.GetService (typeof (IMenuCommandService)) as IMenuCommandService;
//if (menuService == null)
// return;
//Now we've got all services, register our events
changeService.ComponentAdded += new ComponentEventHandler (changeService_ComponentAdded);
changeService.ComponentChanged += new ComponentChangedEventHandler (changeService_ComponentChanged);
changeService.ComponentRemoved += new ComponentEventHandler (changeService_ComponentRemoved);
selectionService.SelectionChanged += new EventHandler (selectionService_SelectionChanged);
//Register incoming calls from JavaScript
comm.RegisterJSHandler ("Click", new ClrCall (JSClick));
//Find our Mozilla JS and XUL files and load them
//TODO: use resources for Mozilla JS and XUL files
mozPath = System.Reflection.Assembly.GetAssembly (typeof(RootDesignerView)).Location;
mozPath = mozPath.Substring(0, mozPath.LastIndexOf (System.IO.Path.DirectorySeparatorChar))
+ System.IO.Path.DirectorySeparatorChar + "Mozilla" + System.IO.Path.DirectorySeparatorChar;
//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);
}
#region Change service handlers
void selectionService_SelectionChanged (object sender, EventArgs e)
{
//TODO: selection
//throw new NotImplementedException ();
}
void changeService_ComponentRemoved (object sender, ComponentEventArgs e)
{
//TODO: component removal
//throw new NotImplementedException ();
}
void changeService_ComponentChanged (object sender, ComponentChangedEventArgs e)
{
//TODO: FIX!!!!
System.IO.FileStream stream = new System.IO.FileStream(mozPath + "temp.html", System.IO.FileMode.Create);
System.IO.StreamWriter w = new System.IO.StreamWriter(stream);
string doc = ((WebFormPage) host.RootComponent).ViewDocument();
w.Write(doc);
w.Flush();
stream.Close();
base.LoadUrl(mozPath + "temp.html");
}
void changeService_ComponentAdded (object sender, ComponentEventArgs e)
{
//TODO: FIX!!!!
System.IO.FileStream stream = new System.IO.FileStream (mozPath + "temp.html", System.IO.FileMode.Create);
System.IO.StreamWriter w = new System.IO.StreamWriter (stream);
string doc = ((WebFormPage) host.RootComponent).ViewDocument ();
w.Write (doc);
w.Flush ();
stream.Close ();
base.LoadUrl (mozPath + "temp.html");
}
#endregion
#region JS handlers
//JS call handler
// Name: Call
// Arguments: ClickType (single, double, right)
// Component (Asp Component ID, or empty if other)
// Returns: n/a
private string JSClick (string[] args)
{
if (args.Length != 2)
return string.Empty;
//lookup our component
IComponent component = null;
if (args[1] != string.Empty)
component = ((DesignContainer) host.Container).GetComponent (args[1]);
//decide which action to perfom and use services to perfom it
switch (args[0]) {
case "single":
selectionService.SetSelectedComponents (new IComponent[] {component});
break;
case "double":
IDesigner designer = host.GetDesigner (component);
if (designer != null)
designer.DoDefaultAction ();
break;
case "right":
//TODO: show context menu menuService.ShowContextMenu
break;
}
return string.Empty;
}
#endregion
}
}

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

@ -0,0 +1,241 @@
/*
* Toolbox.cs - A toolbox widget
*
* Authors:
* Michael Hutchinson <m.j.hutchinson@gmail.com>
*
* Copyright (C) 2005 Michael Hutchinson
*
* This sourcecode is licenced under The MIT License:
*
* Permission is hereby granted, free of charge, to any person obtaining
* a copy of this software and associated documentation files (the
* "Software"), to deal in the Software without restriction, including
* without limitation the rights to use, copy, modify, merge, publish,
* distribute, sublicense, and/or sell copies of the Software, and to permit
* persons to whom the Software is furnished to do so, subject to the
* following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
* OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN
* NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM,
* DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
* OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE
* USE OR OTHER DEALINGS IN THE SOFTWARE.
*/
using System;
using Gtk;
using System.Collections;
using System.Drawing.Design;
using System.ComponentModel.Design;
using System.ComponentModel;
namespace AspNetEdit.Editor.UI
{
public class Toolbox : ScrolledWindow
{
private ServiceContainer parentServices;
Hashtable expanders = new Hashtable ();
private VBox vbox;
IToolboxService toolboxService;
public Toolbox(ServiceContainer parentServices)
{
this.parentServices = parentServices;
//we need this service, so create it if not present
toolboxService = parentServices.GetService (typeof (IToolboxService)) as IToolboxService;
if (toolboxService == null) {
toolboxService = new AspNetEdit.Editor.ComponentModel.ToolboxService ();
parentServices.AddService (typeof (IToolboxService), toolboxService);
}
base.VscrollbarPolicy = PolicyType.Automatic;
base.HscrollbarPolicy = PolicyType.Automatic;
base.WidthRequest = 150;
vbox = new VBox ();
base.AddWithViewport (vbox);
}
#region GUI population
public void UpdateCategories ()
{
//get the services we need
IDesignerHost host = parentServices.GetService (typeof (IDesignerHost)) as IDesignerHost;
IToolboxService toolboxService = parentServices.GetService (typeof (IToolboxService)) as IToolboxService;
if (toolboxService == null || host == null) {
expanders.Clear ();
return;
}
CategoryNameCollection catNames = toolboxService.CategoryNames;
//clear out old categories
foreach (string name in expanders.Keys)
{
if (!catNames.Contains (name))
expanders.Remove (name);
vbox.Remove ((Expander) (expanders[name]));
}
//create expanders for new ones
foreach (string name in catNames) {
if (!expanders.ContainsKey (name))
{
Expander exp = new Expander ("<b>"+name+"</b>");
((Label) exp.LabelWidget).UseMarkup = true;
exp.Expanded = false;
exp.Add (new VBox());
expanders[name] = exp;
}
}
//repopulate all of the categories
foreach (string name in expanders.Keys)
{
vbox.PackStart ((Expander) (expanders[name]), false, false, 0);
ResetCategory (name);
}
EventBox bottomWidget = new EventBox ();
bottomWidget.CanFocus = true;
vbox.PackEnd (bottomWidget, true, true, 0);
}
public void ResetCategory (string category)
{
if (!expanders.ContainsKey(category))
return;
//get the services we need
IDesignerHost host = parentServices.GetService (typeof (IDesignerHost)) as IDesignerHost;
if (host == null) {
expanders.Clear ();
return;
}
//get the items and add them all
ToolboxItemCollection tools = toolboxService.GetToolboxItems (category, host);
foreach (ToolboxItem item in tools) {
ToolboxItemBox itemBox = new ToolboxItemBox (item);
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);
}
}
#endregion
#region Click handlers, drag'n'drop source, selection state
public const string DragDropIdentifier = "aspnetedit_toolbox_item";
private const double DragSensitivity = 1;
private ToolboxItemBox selectedBox;
uint lastClickTime = 0;
bool dndPrimed;
double dndX, dndY;
void itemBox_ButtonPressEvent (object o, ButtonPressEventArgs args)
{
if (args.Event.Type != Gdk.EventType.ButtonPress)
return;
//TODO: context menu for manipulation of items
if (args.Event.Button != 1)
return;
ToolboxItem item = ((ToolboxItemBox) o).ToolboxItem;
//get the services
IDesignerHost host = parentServices.GetService (typeof (IDesignerHost)) as IDesignerHost;
IToolboxService toolboxService = parentServices.GetService (typeof (IToolboxService)) as IToolboxService;
if (toolboxService == null || host == null)
return;
if (selectedBox == (ToolboxItemBox) o) {
//check for doubleclick and create an item
if (toolboxService.GetSelectedToolboxItem (host) == item) {
if (args.Event.Time - lastClickTime <= Settings.DoubleClickTime) {
item.CreateComponents (host);
toolboxService.SelectedToolboxItemUsed ();
return;
}
}
}
else {
//select item
if (selectedBox != null) {
selectedBox.DragDataGet -= selectedBox_DragDataGet;
selectedBox.Deselect ();
}
selectedBox = (ToolboxItemBox)o;
selectedBox.Select ();
selectedBox.DragDataGet += new DragDataGetHandler (selectedBox_DragDataGet);
toolboxService.SetSelectedToolboxItem (item);
}
lastClickTime = args.Event.Time;
dndPrimed = true;
dndX = args.Event.X;
dndY = args.Event.Y;
}
void selectedBox_DragDataGet (object o, DragDataGetArgs args)
{
ToolboxItemBox itemBox = (ToolboxItemBox) o;
args.SelectionData.Text = (string) toolboxService.SerializeToolboxItem (itemBox.ToolboxItem);
}
void itemBox_ButtonReleaseEvent (object sender, ButtonReleaseEventArgs args)
{
dndPrimed = false;
}
void itemBox_MotionNotifyEvent (object o, MotionNotifyEventArgs args)
{
if (!dndPrimed
|| Math.Abs (args.Event.X - dndX) < DragSensitivity
|| Math.Abs (args.Event.Y - dndY) < DragSensitivity)
return;
ToolboxItemBox itemBox = (ToolboxItemBox) o;
TargetEntry 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);
Image im = itemBox.Image;
switch (im.StorageType)
{
case ImageType.Stock:
Drag.SetIconStock (context, im.Stock, 0, 0);
break;
case ImageType.Pixmap:
Drag.SetIconPixmap (context, im.Colormap, im.Pixmap, im.Mask, 0, 0);
break;
case ImageType.Pixbuf:
Drag.SetIconStock (context, im.Stock, 0, 0);
break;
}
Console.WriteLine (toolboxService.SerializeToolboxItem (itemBox.ToolboxItem).ToString ());;
}
#endregion
}
}

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

@ -0,0 +1,83 @@
/*
* ToolboxItemBox.cs - Gtk widget representing a toolbox item
*
* Authors:
* Michael Hutchinson <m.j.hutchinson@gmail.com>
*
* Copyright (C) 2005 Michael Hutchinson
*
* This sourcecode is licenced under The MIT License:
*
* Permission is hereby granted, free of charge, to any person obtaining
* a copy of this software and associated documentation files (the
* "Software"), to deal in the Software without restriction, including
* without limitation the rights to use, copy, modify, merge, publish,
* distribute, sublicense, and/or sell copies of the Software, and to permit
* persons to whom the Software is furnished to do so, subject to the
* following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
* OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN
* NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM,
* DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
* OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE
* USE OR OTHER DEALINGS IN THE SOFTWARE.
*/
using System;
using Gtk;
using System.Drawing.Design;
namespace AspNetEdit.Editor.UI
{
internal class ToolboxItemBox : EventBox
{
private ToolboxItem item;
Image image;
public ToolboxItemBox (ToolboxItem item)
{
this.item = item;
//create all the widgets we need to display this item
Gtk.Label lab = new Label ();
lab.Text = item.DisplayName;
lab.Xalign = 0;
lab.Xpad = 3;
//TODO: load image from ToolboxItem's bitmap (need to implement that too!)
image = new Image (Stock.MissingImage, IconSize.SmallToolbar);
HBox hbox = new HBox ();
hbox.PackStart (image, false, false, 2);
hbox.PackEnd (lab, true, true, 2);
base.Add (hbox);
}
public ToolboxItem ToolboxItem {
get { return item; }
set { item = value; }
}
public void Select ()
{
base.ModifyBg (StateType.Normal, base.Style.Background (StateType.Selected));
base.ModifyFg (StateType.Normal, base.Style.Foreground (StateType.Selected));
}
public void Deselect ()
{
base.ModifyBg (StateType.Normal, Parent.Style.Background (StateType.Normal));
base.ModifyFg (StateType.Normal, Parent.Style.Foreground (StateType.Normal));
}
public Image Image {
get { return image; }
}
}
}

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

@ -0,0 +1,21 @@
//
// AssemblyInfo.cs.in for editor.dll in aspnetedit
//
// Authors:
// Michael Hutchinson <m.j.hutchinson@gmail.com>
//
using System.Reflection;
using System.Runtime.CompilerServices;
[assembly: AssemblyTitle ("AspNetEdit Editor")]
[assembly: AssemblyDescription ("Core library for AspNetEdit Graphical ASP.NET Editor ")]
[assembly: AssemblyCompany("")]
[assembly: AssemblyProduct("AspNetEdit")]
[assembly: AssemblyCopyright ("Copyright © 2005 Michael Hutchinson")]
[assembly: AssemblyTrademark("")]
[assembly: AssemblyCulture("")]
[assembly: AssemblyConfiguration("")]
[assembly: AssemblyVersion("@VERSION@")]
[assembly: AssemblyFileVersion("@VERSION@")]

53
src/editor/Makefile.am Normal file
Просмотреть файл

@ -0,0 +1,53 @@
ASSEMBLY_NAME = editor
ASSEMBLY = $(top_builddir)/build/lib/$(ASSEMBLY_NAME).dll
TARGET = $(ASSEMBLY)
editordir=$(pkglibdir)
editor_SCRIPTS = $(ASSEMBLY)
editor_DATA = $(ASSEMBLY).mdb
EDITOR_REFERENCES = \
$(GTKSHARP_LIBS) \
$(GECKOSHARP_LIBS) \
-r:$(top_builddir)/build/lib/jscall.dll \
-r:$(top_builddir)/build/lib/propertygrid.dll \
-r:System.Web \
-r:System.Design \
-r:System.Drawing \
-r:System.Windows.Forms \
-r:System.Data
EDITOR_CSFILES = \
$(srcdir)/AssemblyInfo.cs \
$(srcdir)/AspNetEdit.Editor.ComponentModel/DesignContainer.cs \
$(srcdir)/AspNetEdit.Editor.ComponentModel/SelectionService.cs \
$(srcdir)/AspNetEdit.Editor.ComponentModel/DesignerHost.cs \
$(srcdir)/AspNetEdit.Editor.ComponentModel/ToolboxService.cs \
$(srcdir)/AspNetEdit.Editor.ComponentModel/Directive.cs \
$(srcdir)/AspNetEdit.Editor.ComponentModel/EventBindingService.cs \
$(srcdir)/AspNetEdit.Editor.ComponentModel/Transaction.cs \
$(srcdir)/AspNetEdit.Editor.ComponentModel/ExtenderListService.cs \
$(srcdir)/AspNetEdit.Editor.ComponentModel/TypeDescriptorFilterService.cs \
$(srcdir)/AspNetEdit.Editor.ComponentModel/MenuCommandService.cs \
$(srcdir)/AspNetEdit.Editor.ComponentModel/TypeResolutionService.cs \
$(srcdir)/AspNetEdit.Editor.ComponentModel/WebFormPage.cs \
$(srcdir)/AspNetEdit.Editor.ComponentModel/WebFormReferenceManager.cs \
$(srcdir)/AspNetEdit.Editor.ComponentModel/RootDesigner.cs \
$(srcdir)/AspNetEdit.Editor.ComponentModel/NameCreationService.cs \
$(srcdir)/AspNetEdit.Editor.UI/PropertyGrid.cs \
$(srcdir)/AspNetEdit.Editor.UI/RootDesignerView.cs \
$(srcdir)/AspNetEdit.Editor.UI/Toolbox.cs \
$(srcdir)/AspNetEdit.Editor.UI/ToolboxItemBox.cs \
$(srcdir)/System.Web.UI.Design/ControlParser.cs \
$(srcdir)/System.Web.UI.Design/TODOAttribute.cs \
$(srcdir)/System.Web.UI.Design/ControlPersister.cs
$(ASSEMBLY): $(EDITOR_CSFILES)
$(MCS) $(EDITOR_REFERENCES) -debug -target:library -out:$@ $(EDITOR_CSFILES)
$(ASSEMBLY).mdb: $(ASSEMBLY)
all: $(ASSEMBLY) $(ASSEMBLY).mdb
EXTRA_DIST = $(EDITOR_CSFILES)
CLEANFILES = $(ASSEMBLY) $(ASSEMBLY).mdb

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

@ -0,0 +1,68 @@
//
// System.Web.UI.Design.ControlParser
//
// Authors:
// Gert Driesen (drieseng@users.sourceforge.net)
// Michael Hutchinson <m.j.hutchinson@dur.ac.uk>
//
// (C) 2004 Novell
//
//
// Permission is hereby granted, free of charge, to any person obtaining
// a copy of this software and associated documentation files (the
// "Software"), to deal in the Software without restriction, including
// without limitation the rights to use, copy, modify, merge, publish,
// distribute, sublicense, and/or sell copies of the Software, and to
// permit persons to whom the Software is furnished to do so, subject to
// the following conditions:
//
// The above copyright notice and this permission notice shall be
// included in all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
// LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
// OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
// WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
//
using System.ComponentModel.Design;
using System.Web.UI;
namespace System.Web.UI.Design
{
public sealed class ControlParser
{
private ControlParser ()
{
}
public static Control ParseControl (IDesignerHost designerHost, string controlText)
{
DesignTimeParseData data = new DesignTimeParseData (designerHost, controlText);
return DesignTimeTemplateParser.ParseControl (data);
}
public static Control ParseControl (IDesignerHost designerHost, string controlText, string directives)
{
DesignTimeParseData data = new DesignTimeParseData (designerHost, directives + " " + controlText);
return DesignTimeTemplateParser.ParseControl (data);
}
public static ITemplate ParseTemplate (IDesignerHost designerHost, string templateText)
{
DesignTimeParseData data = new DesignTimeParseData (designerHost, templateText);
return DesignTimeTemplateParser.ParseTemplate (data);
}
public static ITemplate ParseTemplate (IDesignerHost designerHost, string templateText, string directives)
{
DesignTimeParseData data = new DesignTimeParseData (designerHost, directives + " " + templateText);
return DesignTimeTemplateParser.ParseTemplate (data);
}
}
}

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

@ -0,0 +1,359 @@
//
// System.Web.UI.Design.ControlPersister
//
// Authors:
// Gert Driesen (drieseng@users.sourceforge.net)
// Michael Hutchinson <m.j.hutchinson@dur.ac.uk>
//
// (C) 2004 Novell
//
// Permission is hereby granted, free of charge, to any person obtaining
// a copy of this software and associated documentation files (the
// "Software"), to deal in the Software without restriction, including
// without limitation the rights to use, copy, modify, merge, publish,
// distribute, sublicense, and/or sell copies of the Software, and to
// permit persons to whom the Software is furnished to do so, subject to
// the following conditions:
//
// The above copyright notice and this permission notice shall be
// included in all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
// LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
// OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
// WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
//
using System.ComponentModel.Design;
using System.IO;
using System.ComponentModel;
using System.Collections;
using System.Text;
namespace System.Web.UI.Design
{
public sealed class ControlPersister
{
private ControlPersister ()
{
}
#region Public members. They call private methods with some checking and restrictions.
public static string PersistControl (Control control)
{
if (control.Site == null)
return string.Empty;
IDesignerHost host = control.Site.GetService (typeof(IDesignerHost)) as IDesignerHost;
return PersistControl (control, host);
}
public static void PersistControl (TextWriter sw, Control control)
{
if (control.Site == null)
return;
IDesignerHost host = control.Site.GetService (typeof(IDesignerHost)) as IDesignerHost;
PersistControl (sw, control, host);
}
public static string PersistControl (Control control, IDesignerHost host)
{
TextWriter writer = new StringWriter ();
PersistControl (writer, control, host);
writer.Flush ();
return writer.ToString ();
}
public static void PersistControl(TextWriter sw, Control control, IDesignerHost host)
{
//check input
if (host == null)
throw new ArgumentNullException ("host");
if (control == null)
throw new ArgumentNullException ("control");
if (sw == null)
throw new ArgumentNullException ("sw");
if (!(control is System.Web.UI.Control))
throw new InvalidOperationException ("Only components that derive from System.Web.UI.Control can be serialised");
//We use an HtmlTextWriter for output
HtmlTextWriter writer;
if (sw is HtmlTextWriter)
writer = (HtmlTextWriter) sw;
else
writer = new HtmlTextWriter (sw);
PersistObject(writer, control, host, true);
}
public static string PersistInnerProperties (object component, IDesignerHost host)
{
TextWriter sw = new StringWriter ();
PersistInnerProperties (sw, component, host);
sw.Flush();
return sw.ToString();
}
public static void PersistInnerProperties (TextWriter sw, object component, IDesignerHost host)
{
//check input
if (host == null)
throw new ArgumentNullException ("host");
if (component == null)
throw new ArgumentNullException ("component");
if (!(component is System.Web.UI.Control))
throw new InvalidOperationException ("Only components that derive from System.Web.UI.Control can be serialised");
//privte method needs an HtmlTextWriter
HtmlTextWriter writer;
if (sw is HtmlTextWriter)
writer = (HtmlTextWriter) sw;
else
writer = new HtmlTextWriter (sw);
//write and flush
PersistInnerProperties (writer, component, host);
writer.Flush();
}
#endregion
private static void PersistObject (HtmlTextWriter writer, Object control, IDesignerHost host, bool runAtServer)
{
//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 (control.GetType ());
//write tag to HtmlTextWriter
writer.WriteBeginTag (prefix + ":" + control.GetType().Name);
//go through all the properties and add attributes if necessary
PropertyDescriptorCollection properties = TypeDescriptor.GetProperties (control);
foreach (PropertyDescriptor prop in properties)
ProcessAttribute (prop, control, writer, string.Empty);
if (runAtServer)
writer.WriteAttribute ("runat", "server");
//ControlDesigner designer = (ControlDesigner) host.GetDesigner(control);
//TODO: we don't yet support designer.GetPersistInnerHtml() 'cause we don't have the designers...
if (HasInnerProperties(control)) {
writer.Write (HtmlTextWriter.TagRightChar);
writer.Indent++;
PersistInnerProperties (writer, control, host);
writer.Indent--;
writer.WriteEndTag (prefix + ":" + control.GetType ().Name);
}
else
writer.Write (HtmlTextWriter.SelfClosingTagEnd);
writer.WriteLine ();
writer.Flush ();
}
/// <summary>
/// Writes an attribute to an HtmlTextWriter if it needs serializing
/// </summary>
/// <returns>True if it does any writing</returns>
private static bool ProcessAttribute (PropertyDescriptor prop, object o, HtmlTextWriter writer, string prefix)
{
//check whether we're serialising it
if (prop.SerializationVisibility == DesignerSerializationVisibility.Hidden
|| prop.DesignTimeOnly
|| prop.IsReadOnly
|| !prop.ShouldSerializeValue (o)
|| prop.Converter == null
|| !prop.Converter.CanConvertTo (typeof(string)))
return false;
bool foundAttrib = false;
//is this an attribute? If it's content, we deal with it later.
PersistenceModeAttribute modeAttrib = prop.Attributes[typeof (PersistenceModeAttribute)] as PersistenceModeAttribute;
if (modeAttrib == null || modeAttrib.Mode == PersistenceMode.Attribute)
{
if (prop.SerializationVisibility == DesignerSerializationVisibility.Visible) {
if (prefix == string.Empty)
writer.WriteAttribute (prop.Name, prop.Converter.ConvertToString (prop.GetValue(o)));
else
writer.WriteAttribute (prefix + "-" + prop.Name, prop.Converter.ConvertToString (prop.GetValue(o)));
foundAttrib = true;
}
//recursively handle subproperties
else if (prop.SerializationVisibility == DesignerSerializationVisibility.Content) {
object val = prop.GetValue (o);
foreach (PropertyDescriptor p in prop.GetChildProperties (val))
if (ProcessAttribute (p, val, writer, prop.Name))
foundAttrib = true;
}
}
return foundAttrib;
}
private static void PersistInnerProperties (HtmlTextWriter writer, object component, IDesignerHost host)
{
//Do we have child controls as inner content of control?
PersistChildrenAttribute persAtt = TypeDescriptor.GetAttributes (component)[typeof (PersistChildrenAttribute)] as PersistChildrenAttribute;
if (persAtt != null && persAtt.Persist && (component is Control))
{
if (((Control)component).Controls.Count > 0)
{
writer.Indent++;
foreach (Control child in ((Control) component).Controls) {
PersistControl (writer, child, host);
}
writer.Indent--;
}
}
//We don't, so we're going to have to go though the properties
else
{
PropertyDescriptorCollection properties = TypeDescriptor.GetProperties (component);
bool contentStarted = false;
foreach (PropertyDescriptor prop in properties)
{
//check whether we're serialising it
if (prop.SerializationVisibility == DesignerSerializationVisibility.Hidden
|| prop.DesignTimeOnly
//|| !prop.ShouldSerializeValue (component) //confused by collections...
|| prop.Converter == null)
continue;
PersistenceModeAttribute modeAttrib = prop.Attributes[typeof(PersistenceModeAttribute)] as PersistenceModeAttribute;
if (modeAttrib == null || modeAttrib.Mode == PersistenceMode.Attribute)
continue;
//handle the different modes
switch (modeAttrib.Mode)
{
case PersistenceMode.EncodedInnerDefaultProperty:
if (contentStarted)
throw new Exception("The Control has inner properties in addition to a default inner property");
if (prop.Converter.CanConvertTo (typeof (string))){
writer.Write(System.Web.HttpUtility.HtmlEncode (prop.Converter.ConvertToString (prop.GetValue (component))));
return;
}
break;
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);
return;
case PersistenceMode.InnerProperty:
PersistInnerProperty (prop, prop.GetValue (component), writer, host, false);
contentStarted = true;
break;
}
}
writer.WriteLine();
}
}
//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.Write (HtmlTextWriter.SelfClosingTagEnd);
}
return;
}
//Persist collections as tag with property name
//containing tags of object name, with object properties as attribs
if (value is ICollection) {
if (((ICollection) value).Count > 0) {
if(!isDefault) {
writer.WriteFullBeginTag(prefix + ":" + prop.Name);
writer.Indent++;
}
foreach (object o in (ICollection)value)
PersistObject (writer, o, host, false);
if(!isDefault) {
writer.Indent--;
writer.WriteEndTag (prefix + ":" + prop.Name);
}
}
}
//not a collection? Simple: a tag of object name, with object properties as attribs
else
{
//only want to render tag if it has any attributes
writer.WriteBeginTag (prefix + ":" + prop.Name);
foreach (PropertyDescriptor p in TypeDescriptor.GetProperties(value))
ProcessAttribute (p, value, writer, string.Empty);
writer.Write (HtmlTextWriter.SelfClosingTagEnd);
}
}
//simply checks if there are any inner properties to render so we can use self-closing tags
private static bool HasInnerProperties (object component)
{
if (component == null)
throw new ArgumentNullException ("component");
//Do we have child controls as inner content of control?
PersistChildrenAttribute persAtt = TypeDescriptor.GetAttributes (component)[typeof(PersistChildrenAttribute)] as PersistChildrenAttribute;
if (persAtt != null && persAtt.Persist && (component is Control))
{
return true;
}
//We don't, so we're going to have to go though the properties
else
{
PropertyDescriptorCollection properties = TypeDescriptor.GetProperties (component);
foreach (PropertyDescriptor prop in properties)
{
//check whether we're serialising it
if (prop.SerializationVisibility == DesignerSerializationVisibility.Hidden
|| prop.DesignTimeOnly
//|| !prop.ShouldSerializeValue(component) //confused by collections....
|| prop.Converter == null)
continue;
PersistenceModeAttribute modeAttrib = prop.Attributes[typeof (PersistenceModeAttribute)] as PersistenceModeAttribute;
if (modeAttrib == null || modeAttrib.Mode == PersistenceMode.Attribute)
continue;
return true;
}
}
return false;
}
}
}

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

@ -0,0 +1,58 @@
//
// TODOAttribute.cs
//
// Author:
// Ravi Pratap (ravi@ximian.com)
//
// (C) Ximian, Inc. http://www.ximian.com
//
//
// Permission is hereby granted, free of charge, to any person obtaining
// a copy of this software and associated documentation files (the
// "Software"), to deal in the Software without restriction, including
// without limitation the rights to use, copy, modify, merge, publish,
// distribute, sublicense, and/or sell copies of the Software, and to
// permit persons to whom the Software is furnished to do so, subject to
// the following conditions:
//
// The above copyright notice and this permission notice shall be
// included in all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
// LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
// OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
// WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
//
using System;
namespace System.Web.UI.Design {
/// <summary>
/// The TODO attribute is used to flag all incomplete bits in our class libraries
/// </summary>
///
/// <remarks>
/// Use this to decorate any element which you think is not complete
/// </remarks>
[AttributeUsage (AttributeTargets.All)]
internal class MonoTODOAttribute : Attribute {
string comment;
public MonoTODOAttribute ()
{}
public MonoTODOAttribute (string comment)
{
this.comment = comment;
}
public string Comment {
get { return comment; }
}
}
}

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

@ -0,0 +1,212 @@
/*
* CommandManager.cs - The C# side of the JSCall Gecko#/C# glue layer
*
* Authors:
* Michael Hutchinson <m.j.hutchinson@gmail.com>
*
* Copyright (C) 2005 Michael Hutchinson
*
* This sourcecode is licenced under The MIT License:
*
* Permission is hereby granted, free of charge, to any person obtaining
* a copy of this software and associated documentation files (the
* "Software"), to deal in the Software without restriction, including
* without limitation the rights to use, copy, modify, merge, publish,
* distribute, sublicense, and/or sell copies of the Software, and to permit
* persons to whom the Software is furnished to do so, subject to the
* following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
* OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN
* NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM,
* DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
* OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE
* USE OR OTHER DEALINGS IN THE SOFTWARE.
*/
using System;
using System.Collections;
using Gecko;
using System.Text;
using System.Runtime.InteropServices;
namespace AspNetEdit.JSCall
{
public class CommandManager
{
[DllImport ("jscallglue.dll")]
static extern int PlaceFunctionCall (IntPtr embed, IntPtr call, IntPtr returnto, IntPtr args);
/*NB: Replaced this with webControl.Title. Simplifies interop,
* and doesn't seem to limit size of output - tested to output 88MB!
* This may be useful again at some point to improve performance.
*/
//[DllImport ("jscallglue.dll", CharSet=CharSet.Auto)]
//static extern IntPtr[] CollectFunctionCall (IntPtr embed);
private Hashtable functions;
private WebControl webControl;
private bool geckoShown;
public CommandManager (WebControl w)
{
functions = new Hashtable();
webControl = w;
webControl.Shown += new EventHandler (onShown);
}
//Gecko#'s nsIWebBrowser cannot be accessed until the control has been shown
private void onShown (object o, EventArgs e)
{
if (!geckoShown)
{
webControl.TitleChange += new EventHandler (webControl_ECMAStatus);
this.geckoShown = true;
}
}
private void webControl_ECMAStatus (object sender, EventArgs e)
{
if (!geckoShown || !webControl.Title.StartsWith ("JSCall"))
return;
string[] call = webControl.Title.Split ('|');
if (call.Length < 2)
throw new Exception ("Too few parameters in call from JavaScript");
string function = call[1];
string returnTo = call[2];
string[] args = (string[]) System.Array.CreateInstance (typeof(String), (call.Length - 3));
System.Array.Copy (call, 3, args, 0, (call.Length - 3));
if (!functions.Contains (function))
throw new Exception ("Unknown function name called from JavaScript");
ClrCall clrCall = (ClrCall) functions[function];
if (returnTo.Length == 0)
{
string result = clrCall (args);
}
else
{
string[] result = { clrCall (args) };
JSCall(returnTo, null, result);
}
}
public void JSCall (string function, string returnTo, string[] args)
{
if (!geckoShown)
{
throw new Exception ("You cannot access the document until the WebControl has been Shown");
}
string argsOut = String.Empty;
if (args != null)
{
argsOut += args[0];
for (int i = 1; i < args.Length - 1; i++)
{
argsOut += "|" + args[i];
}
}
IntPtr functionPtr = GLib.Marshaller.StringToPtrGStrdup (function);
IntPtr returnToPtr = GLib.Marshaller.StringToPtrGStrdup (returnTo);
IntPtr argsPtr = GLib.Marshaller.StringToPtrGStrdup (argsOut);
int result = PlaceFunctionCall (webControl.Handle, functionPtr, returnToPtr, argsPtr);
GLib.Marshaller.Free (functionPtr);
GLib.Marshaller.Free (returnToPtr);
GLib.Marshaller.Free (argsPtr);
string err;
switch (result)
{
case 0:
return;
case 1:
err = "Error finding 'jscall' nodes.";
break;
case 2:
err = "Error getting number of 'jscall' nodes.";
break;
case 3:
err = "More or fewer than one 'jscall' node.";
break;
case 4:
err = "Error getting 'jscall' node.";
break;
case 5:
err = "Error adding 'infunction' node.";
break;
case 6:
err = "Error setting attributes on 'infunction' node.";
break;
case 7:
err = "Error getting nsIDOMNode interface on 'infunction' node.";
break;
case 8:
err = "Error appending 'infunction' node to 'jscall' node.";
break;
default:
err = "Unknown error.";
break;
}
throw new Exception ("Glue function PlaceFunctionCall: "+err);
}
public void RegisterJSHandler (string name, ClrCall handler)
{
if (!functions.Contains (name))
{
functions.Add (name, handler);
}
else
{
throw new Exception ("A handler with this name already exists");
}
}
public void UnregisterJSHandler (string name)
{
if (functions.Contains (name))
{
functions.Remove (name);
}
else
{
throw new IndexOutOfRangeException ("A function with this name has not been registered");
}
}
}
public delegate string ClrCall (string[] args);
}

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

@ -0,0 +1,42 @@
/*
* InvalidJSArgumentException.cs - The exception to be thrown when an argument from a call from JavaScript is invalid
*
* Authors:
* Michael Hutchinson <m.j.hutchinson@gmail.com>
*
* Copyright (C) 2005 Michael Hutchinson
*
* This sourcecode is licenced under The MIT License:
*
* Permission is hereby granted, free of charge, to any person obtaining
* a copy of this software and associated documentation files (the
* "Software"), to deal in the Software without restriction, including
* without limitation the rights to use, copy, modify, merge, publish,
* distribute, sublicense, and/or sell copies of the Software, and to permit
* persons to whom the Software is furnished to do so, subject to the
* following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
* OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN
* NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM,
* DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
* OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE
* USE OR OTHER DEALINGS IN THE SOFTWARE.
*/
using System;
namespace AspNetEdit.JSCall
{
public class InvalidJSArgumentException : Exception
{
public InvalidJSArgumentException (string function, int argument, Exception e)
:base ("Invalid argument " + argument.ToString () + " in JavaScript call to \"" + function + "\".", e)
{
}
}
}

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

@ -0,0 +1,21 @@
//
// AssemblyInfo.cs.in for jscall.dll in aspnetedit
//
// Authors:
// Michael Hutchinson <m.j.hutchinson@gmail.com>
//
using System.Reflection;
using System.Runtime.CompilerServices;
[assembly: AssemblyTitle ("AspNetEdit JSCall")]
[assembly: AssemblyDescription ("JSCall library for AspNetEdit Graphical ASP.NET Editor ")]
[assembly: AssemblyCompany("")]
[assembly: AssemblyProduct("AspNetEdit")]
[assembly: AssemblyCopyright ("Copyright © 2005 Michael Hutchinson")]
[assembly: AssemblyTrademark("")]
[assembly: AssemblyCulture("")]
[assembly: AssemblyConfiguration("")]
[assembly: AssemblyVersion("@VERSION@")]
[assembly: AssemblyFileVersion("@VERSION@")]

29
src/jscall/Makefile.am Normal file
Просмотреть файл

@ -0,0 +1,29 @@
SUBDIRS = jscallglue
ASSEMBLY_NAME = jscall
ASSEMBLY = $(top_builddir)/build/lib/$(ASSEMBLY_NAME).dll
TARGET = $(ASSEMBLY)
jscalldir=$(pkglibdir)
jscall_SCRIPTS = $(ASSEMBLY)
jscall_DATA = $(ASSEMBLY).mdb
JSCALL_CSFILES = \
$(srcdir)/AssemblyInfo.cs \
$(srcdir)/AspNetEdit.JSCall/CommandManager.cs \
$(srcdir)/AspNetEdit.JSCall/InvalidJSArgumentException.cs
JSCALL_REFERENCES = \
$(GTKSHARP_LIBS) \
$(GECKOSHARP_LIBS)
$(ASSEMBLY): $(JSCALL_CSFILES)
$(MCS) $(JSCALL_REFERENCES) -debug -target:library -out:$@ $(JSCALL_CSFILES)
$(ASSEMBLY).mdb: $(ASSEMBLY)
all: $(ASSEMBLY)
EXTRA_DIST = $(JSCALL_CSFILES) $(srcdir)/README $(srcdir)/Resources/JSCall.js
CLEANFILES = $(ASSEMBLY) $(ASSEMBLY).mdb

25
src/jscall/README Normal file
Просмотреть файл

@ -0,0 +1,25 @@
INTRODUCTION
============
This is the AspNetEdit.JSGlue layer for calling C# functions from JavaScript in a Gecko# control, and vice versa. It should work with any .NET language but I've referrred to C# for simplicity. I don't expect many people to use this, so the documentation is little more than minimal; please contact me <m.j.hutchinson@gmail.com> if you need help working out how it works.
BUILDING
========
Use automake (./autogen.sh --prefix=/usr/local) at the application level.
USAGE
=====
On the CLR side of things, create an instance of AspNetEdit.JSGlue.CommandManager by passing the constructor the Gecko# control. This object has the following methods:
RegisterJSHandler(string name, ClrCall handler)
Register a ClrCall delegate as the handler when JS calls the named 'name' function.
UnregisterJSHandler(string name)
Unregister the 'name' function.
JSCall(string function, string returnTo, string[] args)
Call the 'function' JS function, with 'returnTo' as the callback for any return value. Arguments as a string array.
On the JS side, load the JSGlue.js file into your document and call JSGlueInit(). You then have the following functions available, mirroring the C# functions but a bit more "javascripty".
JSGluePlaceClrCall(fn, returnTo, args)
Call the 'fn' C# function, with 'returnTo' as the callback for any return value. Arguments as a string array.
JSGlueRegisterClrHandler(n, fn)
Register a the 'fn' function as the handler when C# calls the named 'n' function.
JSGlueUnregisterClrHandler()
Unregister the 'name' function.

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

@ -0,0 +1,118 @@
/*
* JSCall.js - The JS side of the JSCall Gecko#/C# glue layer
*
* Authors:
* Michael Hutchinson <m.j.hutchinson@gmail.com>
*
* Copyright (C) 2005 Michael Hutchinson
*
* This sourcecode is licenced under The MIT License:
*
* Permission is hereby granted, free of charge, to any person obtaining
* a copy of this software and associated documentation files (the
* "Software"), to deal in the Software without restriction, including
* without limitation the rights to use, copy, modify, merge, publish,
* distribute, sublicense, and/or sell copies of the Software, and to permit
* persons to whom the Software is furnished to do so, subject to the
* following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
* OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN
* NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM,
* DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
* OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE
* USE OR OTHER DEALINGS IN THE SOFTWARE.
*/
var JSCallFunctions;
function JSCallInit()
{
JSCallFunctions = Array();
if (document.getElementsByTagName("jscall").length != 0) {
throw "Error: the document already contains a <jscall> element";
}
el = document.createElement("jscall");
document.documentElement.appendChild(el);
el.addEventListener( "DOMNodeInserted", JSCallHandler, false );
//JSCallRegisterClrHandler("Redo", Redo);
}
//function Redo()
//{
// alert("Yay!");
//}
function JSCallHandler(e)
{
if ( e.target.nodeName == "infunction" && e.target.nodeType == 1 ){
fn = e.target.attributes[0].value;
returnTo = e.target.attributes[1].value;
args = e.target.attributes[2].value.split('|');
try {
if(JSCallFunctions[fn]) {
f = JSCallFunctions[fn];
result = f(args);
}
else {
throw "JSCall: The '"+fn+"' function has not been registered";
}
if (returnTo.length != 0) {
JSCallPlaceClrCall(returnTo, "", new Array(result));
}
}
catch(e) {
alert(e)
}
e.target.parentNode.removeChild(e.target);
}
}
function JSCallPlaceClrCall(fn, returnTo, args) {
str = "JSCall|" + fn + "|" + returnTo + "|1";
if (args && args.length > 0)
{
str += args.join("|");
}
document.title= str;
}
function JSCallUnregisterClrHandler() {
if(JSCallFunctions[n]) {
delete JSCallFunctions[n];
}
else {
throw "Function with that name not registered";
}
}
function JSCallRegisterClrHandler(n, fn) {
if((typeof fn) != "function") {
throw "The fn argument must be a function";
}
if(JSCallFunctions[n]) {
throw "Function with that name already registered";
}
else {
JSCallFunctions[n] = fn;
}
}

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

@ -0,0 +1,16 @@
jscallgluedir=$(pkglibdir)
dllfile = $(top_builddir)/build/lib/jscallglue.dll
jscallglue_SCRIPTS = $(dllfile)
CXXFLAGS = -shared -g -fPIC -fno-rtti $(JSGLUEDEPS_CFLAGS)
LDFLAGS = $(JSGLUEDEPS_CFLAGS)
all: $(dllfile)
$(dllfile): jscallglue.cpp
$(CXX) $(CXXFLAGS) -o $@ $^ $(LDFLAGS)
CLEANFILES = $(dllfile)
EXTRA_DIST = README

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

@ -0,0 +1,22 @@
The AspNetEdit XPCOM DOM Wrappers
=================================
A word of warning - this is a bit hacky, but will have to do until someone comes up with an XPConnect interface for Mono. The aim for now is to use a minimum of Gtk and XPCOM interop code to reuse existing components and simplify debugging.
We have two functions, PlaceFunctionCall and CollectFunctionCall. The document must contain a single node in the root called <aspnetcomm>, which contains the data to be communicated between C# and JavaScript, and these functions modify and read its contents.
The mechanism of invoking a C# method from JavaScript is as follows:
1. A JavaScript function representing the C# method is called. If it has a return value, it registers a callback function with a handler.
2. It calls a helper function that puts the data in the <aspnetcomm> node and sets the window 'status'. As Gecko# has no status bar this misuse doesn't adversely affect anything and is not visible to the user.
3. The modified Gecko# control catches the ECMAStatus event that is raised, reads and deletes the function call from the DOM using CollectFunctionCall, and calls the relevant C# method.
4. If there is a return value, a callback is placed in the reverse direction.
The reverse call is simple too:
1. A C# method of the modified Gecko# control representing a JavaScript function is called, and it writes to the DOM using PlaceFunctionCall. If it has a return value, it registers a callback delegate with a handler.
2. This raises the DOMNodeInserted event in JavaScript, which is caught by a handler.
3. The handler passes the arguments to the appropriate function.
4. If there is a return value, a callback is placed in the reverse direction.
Outbound (JS->C#) method calls are represented as a child of <aspnetcomm>, and are of the following form:
<outfunction call="functionName" args="encodedListOfArguments" >
Inbound calls are of the form:
<infunction call="functionName" args="encodedListOfArguments" >

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

@ -0,0 +1,170 @@
/*
* jscallglue.cpp - XPCOM DOM interop for communication between JavaScript and Mono/Gecko#
*
* Authors:
* Michael Hutchinson <m.j.hutchinson@gmail.com>
*
* Copyright (C) 2005 Michael Hutchinson
*
* This sourcecode is licenced under The MIT License:
*
* Permission is hereby granted, free of charge, to any person obtaining
* a copy of this software and associated documentation files (the
* "Software"), to deal in the Software without restriction, including
* without limitation the rights to use, copy, modify, merge, publish,
* distribute, sublicense, and/or sell copies of the Software, and to permit
* persons to whom the Software is furnished to do so, subject to the
* following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
* OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN
* NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM,
* DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
* OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE
* USE OR OTHER DEALINGS IN THE SOFTWARE.
*/
#include <gtkmozembed.h>
#include <gtkmozembed_internal.h>
#include <nsCOMPtr.h>
#include <nsString.h>
#include <nsIWebBrowser.h>
#include <nsIDOMWindow.h>
#include <nsIDOMDocument.h>
#include <nsIDOMElement.h>
#include <nsIDOMNode.h>
#include <nsIDOMNodeList.h>
extern "C"
{
int PlaceFunctionCall(GtkMozEmbed *embed, char *call, char*returnto, char *args);
//void CollectFunctionCall(GtkMozEmbed *embed, char *call, char *args, char*returnto);
}
/*
Gets the browser's IDomDocument.
*/
nsCOMPtr<nsIDOMDocument> GetIDOMDocument(GtkMozEmbed *embed)
{
//Get browser
nsCOMPtr<nsIWebBrowser> browser;
gtk_moz_embed_get_nsIWebBrowser(embed, getter_AddRefs(browser));
//if(!browser) return ;
nsCOMPtr<nsIDOMWindow> domWindow;
browser->GetContentDOMWindow(getter_AddRefs(domWindow));
nsCOMPtr<nsIDOMDocument> domDocument;
domWindow->GetDocument(getter_AddRefs(domDocument));
return domDocument;
}
/*
Places a <outfunction call="..." args="..." returnto="..." />
function call element in the <jscall> element.
*/
int PlaceFunctionCall(GtkMozEmbed *embed, char *call, char*returnto, char *args)
{
nsresult result;
nsCOMPtr<nsIDOMDocument> doc = GetIDOMDocument(embed);
//get the "jscall" node
nsCOMPtr<nsIDOMNodeList> nodes;
result = doc->GetElementsByTagName(NS_ConvertUTF8toUTF16("jscall"), getter_AddRefs(nodes));
if(NS_FAILED(result) || !nodes) return 1;
PRUint32 length = 0;
result = nodes -> GetLength(&length);
if(NS_FAILED(result)) return 2;
if(length != 1) return 3;
nsCOMPtr<nsIDOMNode> jscall;
result = nodes->Item(0, getter_AddRefs(jscall));
if(NS_FAILED(result) || !jscall) return 4;
//add an "infunction" node
nsCOMPtr<nsIDOMElement> infunction;
result = doc->CreateElement(NS_ConvertUTF8toUTF16("infunction"), getter_AddRefs(infunction));
if(NS_FAILED(result) || !infunction) return 5;
//add the properties
result = infunction->SetAttribute(NS_ConvertUTF8toUTF16("call"), NS_ConvertUTF8toUTF16(call));
result = infunction->SetAttribute(NS_ConvertUTF8toUTF16("returnto"), NS_ConvertUTF8toUTF16(returnto));
result = infunction->SetAttribute(NS_ConvertUTF8toUTF16("args"), NS_ConvertUTF8toUTF16(args));
if(NS_FAILED(result)) return 6;
//append it to the jscall node
nsCOMPtr<nsIDOMNode> domNodeInfunction = do_QueryInterface(infunction);
if(!domNodeInfunction) return 7;//return 9;
nsCOMPtr<nsIDOMNode> outchild;
result = jscall->AppendChild(domNodeInfunction, getter_AddRefs(outchild));
if(NS_FAILED(result) || !jscall) return 8;
return 0;
}
/*
Retrieves an <infunction call="..." args="..." returnto="..." />
function call element from the <jscall> element.
NB: Untested, and now deprecated to simplify interop.
May reinstate to improve performance.
*/
/*
void CollectFunctionCall(GtkMozEmbed *embed, char *call, char *args, char*returnto)
{
nsCOMPtr<nsIDOMDocument> doc = GetIDOMDocument(embed);
//get the "outfunction" node
nsCOMPtr<nsIDOMNodeList> nodes;
doc->GetElementsByTagName(NS_LITERAL_STRING("outfunction"), getter_AddRefs(nodes));
PRUint32 length;
nodes->GetLength(&length);
if(length != 1) return;// false;
nsCOMPtr<nsIDOMNode> domNodeOutfunction;
nodes->Item(0, getter_AddRefs(domNodeOutfunction));
//check it's what we want
nsCOMPtr<nsIDOMNode> parent;
domNodeOutfunction->GetParentNode(getter_AddRefs(parent));
nsAutoString str;
str = parent->GetNodeName(str);
if(!(str.Equals(NS_LITERAL_STRING("jscall")))) return;// false;
PRUint16 type;
domNodeOutfunction->GetNodeType(&type);
if(type != nsIDOMNode::ELEMENT_NODE) return;// false;
//get the data from the attributes
nsCOMPtr<nsIDOMElement> outfunction = do_QueryInterface(domNodeOutfunction);
PRBool valid;
outfunction->HasAttribute(NS_LITERAL_STRING("call"), &valid);
if(!valid) return; //false;
outfunction->GetAttribute(NS_LITERAL_STRING("call"), str);
call = ToNewUTF8String(str);
outfunction->GetAttribute(NS_LITERAL_STRING("args"), str);
args = ToNewUTF8String(str);
outfunction->GetAttribute(NS_LITERAL_STRING("returnto"), str);
returnto = ToNewUTF8String(str);
//remove node
nsCOMPtr<nsIDOMNode> outChild;
parent->RemoveChild(domNodeOutfunction, getter_AddRefs(outChild));
return;// true;
}
*/

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

@ -0,0 +1,174 @@
/*
* BaseEditor.cs - The base class for the visual type editors
*
* Part of PropertyGrid - A Gtk# widget that displays and allows
* editing of all of an object's public properties
*
* Authors:
* Michael Hutchinson <m.j.hutchinson@gmail.com>
*
* Copyright (C) 2005 Michael Hutchinson
*
* This sourcecode is licenced under The MIT License:
*
* Permission is hereby granted, free of charge, to any person obtaining
* a copy of this software and associated documentation files (the
* "Software"), to deal in the Software without restriction, including
* without limitation the rights to use, copy, modify, merge, publish,
* distribute, sublicense, and/or sell copies of the Software, and to permit
* persons to whom the Software is furnished to do so, subject to the
* following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
* OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN
* NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM,
* DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
* OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE
* USE OR OTHER DEALINGS IN THE SOFTWARE.
*/
using System;
using System.ComponentModel;
using System.Text;
using Gtk;
using System.Reflection;
using System.Drawing.Design;
namespace AspNetEdit.UI.PropertyEditors
{
public abstract class BaseEditor
{
protected GridRow parentRow;
public BaseEditor(GridRow parentRow)
{
this.parentRow = parentRow;
}
/// <summary>
/// whether the value can be changed
/// </summary>
public abstract bool InPlaceEdit {
get;
}
/// <summary>
/// Whether the editor should show a button.
/// </summary>
public abstract bool DialogueEdit {
get;
}
/// <summary>
/// If the property is read-only, is is usually not edited. If the editor
/// can edit sub-properties of a read-only complex object, this must return true.
/// <remarks>The default value is false.</remarks>
/// </summary>
/// <returns>True if the editor can edit read-only properties</returns>
public virtual bool EditsReadOnlyObject {
get { return false; }
}
/// <summary>
/// Opens a dialogue box which sets the property's value.
/// Must be overridden if DialogueEdit is true.
/// </summary>
public virtual void LaunchDialogue ()
{
if (DialogueEdit)
throw new NotImplementedException();
}
/// <summary>
/// Whether the editor can edit at all, whether in-place, by dialogue or both.
/// </summary>
public bool CanEdit
{
get { return (InPlaceEdit || DialogueEdit); }
}
/// <summary>
/// Displays the property's current value. Default implementation is simply ToString().
/// </summary>
/// <returns>A widget displaying the property's current value.</returns>
public virtual Widget GetDisplayWidget ()
{
object o = parentRow.PropertyValue;
return StringValue (o);
}
/// <summary>
/// Edits the property's value.
/// Must be overridden if InPlaceEdit is true.
/// </summary>
/// <returns>A widget that can edit the property's value.</returns>
public virtual Widget GetEditWidget ()
{
if (InPlaceEdit)
throw new NotImplementedException();
return null;
}
/// <summary>
/// A Gtk.Label suitable for returning by GetDisplayWidget (). Handles nulls.
/// </summary>
/// <param name="value">The new property value Label.</param>
/// <returns></returns>
protected Widget StringValue (object value)
{
if (value == null)
return StringValue (null, false);
else
return StringValue (value.ToString(), false);
}
/// <summary>
/// A Gtk.Label suitable for returning by GetDisplayWidget(). Handles nulls.
/// </summary>
/// <param name="value">The new property value Label.</param>
/// <param name="markup">Whether to use GTK markup on the label</param>
/// <returns></returns>
protected Widget StringValue (string value, bool markup)
{
Label valueLabel = new Label ();
valueLabel.Xalign = 0;
valueLabel.Xpad = 3;
if (value == null)
valueLabel.Markup = "<span foreground=\"grey\">&lt;null&gt;</span>";
else
{
//make value bold if changed from default
if (!IsDefaultValue ())
valueLabel.Markup = "<b>" + value + "</b>";
else
valueLabel.Text = value;
if (markup)
valueLabel.UseMarkup = true;
}
return valueLabel;
}
/// <summary>
/// Checks whether the current value of this property is the default value.
/// Use to decide whether to make value bold to indicate this.
/// </summary>
/// <returns>False if the value has been changed from the default,
/// and DefaultValueAttribute exists and is not null.</returns>
protected bool IsDefaultValue ()
{
DefaultValueAttribute attrib = (DefaultValueAttribute) parentRow.PropertyDescriptor.Attributes [typeof(DefaultValueAttribute)];
if (attrib != null && ((DefaultValueAttribute) attrib).Value != null)
if (((DefaultValueAttribute)attrib).Value == parentRow.PropertyValue)
return true;
return false;
}
}
}

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

@ -0,0 +1,75 @@
/*
* BoolEditor.cs - Visual type editor for boolean values
*
* Part of PropertyGrid - A Gtk# widget that displays and allows
* editing of all of an object's public properties
*
* Authors:
* Michael Hutchinson <m.j.hutchinson@gmail.com>
*
* Copyright (C) 2005 Michael Hutchinson
*
* This sourcecode is licenced under The MIT License:
*
* Permission is hereby granted, free of charge, to any person obtaining
* a copy of this software and associated documentation files (the
* "Software"), to deal in the Software without restriction, including
* without limitation the rights to use, copy, modify, merge, publish,
* distribute, sublicense, and/or sell copies of the Software, and to permit
* persons to whom the Software is furnished to do so, subject to the
* following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
* OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN
* NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM,
* DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
* OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE
* USE OR OTHER DEALINGS IN THE SOFTWARE.
*/
using System;
using System.ComponentModel;
using Gtk;
namespace AspNetEdit.UI.PropertyEditors
{
[PropertyEditorType (typeof (bool))]
public class BoolEditor : BaseEditor
{
public BoolEditor (GridRow parentRow)
: base (parentRow)
{
}
public override bool InPlaceEdit {
get { return true; }
}
public override Gtk.Widget GetEditWidget ()
{
CheckButton check = new CheckButton ();
check.Active = (bool) parentRow.PropertyValue;
check.Label = check.Active.ToString ();
check.Toggled += new EventHandler (check_Toggled);
return check;
}
void check_Toggled(object sender, EventArgs e)
{
CheckButton check = (CheckButton) sender;
check.Label = check.Active.ToString ();
parentRow.PropertyValue = check.Active;
}
public override bool DialogueEdit {
get { return false; }
}
}
}

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

@ -0,0 +1,409 @@
/*
* CollectionEditor.cs - The base class for the visual type editors
*
* Part of PropertyGrid - A Gtk# widget that displays and allows
* editing of all of an object's public properties
*
* Authors:
* Michael Hutchinson <m.j.hutchinson@gmail.com>
*
* Copyright (C) 2005 Michael Hutchinson
*
* This sourcecode is licenced under The MIT License:
*
* Permission is hereby granted, free of charge, to any person obtaining
* a copy of this software and associated documentation files (the
* "Software"), to deal in the Software without restriction, including
* without limitation the rights to use, copy, modify, merge, publish,
* distribute, sublicense, and/or sell copies of the Software, and to permit
* persons to whom the Software is furnished to do so, subject to the
* following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
* OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN
* NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM,
* DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
* OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE
* USE OR OTHER DEALINGS IN THE SOFTWARE.
*/
using System;
using Gtk;
using System.ComponentModel;
using System.ComponentModel.Design;
using System.Collections;
namespace AspNetEdit.UI.PropertyEditors
{
class CollectionEditor : BaseEditor
{
//TODO: Support for multiple object types
private Type[] types;
private ListStore itemStore;
private TreeView itemTree;
private PropertyGrid grid;
private TreeIter previousIter = TreeIter.Zero;
public CollectionEditor (GridRow parentRow, Type type)
: base (parentRow)
{
this.types = new Type[] { type };
}
public CollectionEditor (GridRow parentRow, Type[] types)
: base (parentRow)
{
this.types = types;
}
protected virtual Type[] NewItemTypes ()
{
return types;
}
public override bool InPlaceEdit
{
get { return false; }
}
public override bool DialogueEdit
{
get { return true; }
}
public override bool EditsReadOnlyObject {
get { return true; }
}
public override Gtk.Widget GetDisplayWidget()
{
return base.StringValue ("(Collection)", true);
}
public override void LaunchDialogue ()
{
//the Type in the collection
IList collection = (IList) parentRow.PropertyValue;
string displayName = parentRow.PropertyDescriptor.DisplayName;
//populate list with existing items
itemStore = new ListStore (typeof (object), typeof (int), typeof (string));
for (int i=0; i<collection.Count; i++)
{
itemStore.AppendValues(collection [i], i, collection [i].ToString ());
}
#region Building Dialogue
//dialogue and buttons
Dialog dialog = new Dialog ();
dialog.Title = displayName + " Editor";
dialog.Modal = true;
dialog.AllowGrow = true;
dialog.AllowShrink = true;
dialog.Modal = true;
dialog.AddActionWidget (new Button (Stock.Cancel), ResponseType.Cancel);
dialog.AddActionWidget (new Button (Stock.Ok), ResponseType.Ok);
//three columns for items, sorting, PropGrid
HBox hBox = new HBox ();
dialog.VBox.PackStart (hBox, true, true, 5);
//propGrid at end
grid = new PropertyGrid (parentRow.ParentGrid.EditorManager);
grid.CurrentObject = null;
grid.WidthRequest = 200;
grid.ShowHelp = false;
hBox.PackEnd (grid, true, true, 5);
//followed by item sorting buttons in ButtonBox
VButtonBox sortButtonBox = new VButtonBox ();
sortButtonBox.LayoutStyle = ButtonBoxStyle.Start;
Button upButton = new Button ();
Image upImage = new Image (Stock.GoUp, IconSize.SmallToolbar);
upButton.Child = upImage;
sortButtonBox.Add (upButton);
Button downButton = new Button ();
Image downImage = new Image (Stock.GoDown, IconSize.SmallToolbar);
downButton.Child = downImage;
sortButtonBox.Add (downButton);
hBox.PackEnd (sortButtonBox, false, false, 5);
//Third column is a VBox
VBox itemsBox = new VBox ();
hBox.PackStart (itemsBox, false, false, 5);
//which at bottom has add/remove buttons
HButtonBox addRemoveButtons = new HButtonBox();
addRemoveButtons.LayoutStyle = ButtonBoxStyle.End;
Button addButton = new Button (Stock.Add);
addRemoveButtons.Add (addButton);
if (types [0].IsAbstract)
addButton.Sensitive = false;
Button removeButton = new Button (Stock.Remove);
addRemoveButtons.Add (removeButton);
itemsBox.PackEnd (addRemoveButtons, false, false, 10);
//and at top has list (TreeView) in a ScrolledWindow
ScrolledWindow listScroll = new ScrolledWindow ();
listScroll.WidthRequest = 200;
listScroll.HeightRequest = 320;
itemsBox.PackStart (listScroll, true, true, 0);
itemTree = new TreeView (itemStore);
itemTree.Selection.Mode = SelectionMode.Single;
itemTree.HeadersVisible = false;
listScroll.AddWithViewport (itemTree);
//renderers and attribs for TreeView
CellRenderer rdr = new CellRendererText ();
itemTree.AppendColumn (new TreeViewColumn ("Index", rdr, "text", 1));
rdr = new CellRendererText ();
itemTree.AppendColumn (new TreeViewColumn ("Object", rdr, "text", 2));
#endregion
#region Events
addButton.Clicked += new EventHandler (addButton_Clicked);
removeButton.Clicked += new EventHandler (removeButton_Clicked);
itemTree.Selection.Changed += new EventHandler (Selection_Changed);
upButton.Clicked += new EventHandler (upButton_Clicked);
downButton.Clicked += new EventHandler (downButton_Clicked);
#endregion
//show and get response
dialog.ShowAll ();
ResponseType response = (ResponseType) dialog.Run();
dialog.Destroy ();
//if 'OK' put items back in collection
if (response == ResponseType.Ok)
{
DesignerTransaction tran = CreateTransaction (parentRow.ParentGrid.CurrentObject);
object old = collection;
try {
collection.Clear();
foreach (object[] o in itemStore)
collection.Add (o[0]);
EndTransaction (parentRow.ParentGrid.CurrentObject, tran, old, collection, true);
}
catch {
EndTransaction (parentRow.ParentGrid.CurrentObject, tran, old, collection, false);
throw;
}
}
//clean up so we start fresh if launched again
itemTree = null;
itemStore = null;
grid = null;
previousIter = TreeIter.Zero;
}
//This and EndTransaction are from Mono internal class System.ComponentModel.ReflectionPropertyDescriptor
// Lluis Sanchez Gual (lluis@ximian.com), (C) Novell, Inc, MIT X11 license
DesignerTransaction CreateTransaction (object obj)
{
IComponent com = obj as IComponent;
if (com == null || com.Site == null) return null;
IDesignerHost dh = (IDesignerHost) com.Site.GetService (typeof(IDesignerHost));
if (dh == null) return null;
DesignerTransaction tran = dh.CreateTransaction ();
IComponentChangeService ccs = (IComponentChangeService) com.Site.GetService (typeof(IComponentChangeService));
if (ccs != null)
ccs.OnComponentChanging (com, parentRow.PropertyDescriptor);
return tran;
}
void EndTransaction (object obj, DesignerTransaction tran, object oldValue, object newValue, bool commit)
{
if (tran == null) return;
if (commit) {
IComponent com = obj as IComponent;
IComponentChangeService ccs = (IComponentChangeService) com.Site.GetService (typeof(IComponentChangeService));
if (ccs != null)
ccs.OnComponentChanged (com, parentRow.PropertyDescriptor, oldValue, newValue);
tran.Commit ();
}
else
tran.Cancel ();
}
void downButton_Clicked (object sender, EventArgs e)
{
TreeIter iter, next;
TreeModel model;
if (!itemTree.Selection.GetSelected(out model, out iter))
return;
//get next iter
next = iter.Copy();
if (!itemStore.IterNext (ref next))
return;
//swap the two
itemStore.Swap (iter, next);
//swap indices too
object nextVal = itemStore.GetValue (next, 1);
object iterVal = itemStore.GetValue (iter, 1);
itemStore.SetValue (next, 1, iterVal);
itemStore.SetValue (iter, 1, nextVal);
}
void upButton_Clicked (object sender, EventArgs e)
{
TreeIter iter, prev;
TreeModel model;
if (!itemTree.Selection.GetSelected (out model, out iter))
return;
//get previous iter
prev = iter.Copy ();
if (!IterPrev (model, ref prev))
return;
//swap the two
itemStore.Swap (iter, prev);
//swap indices too
object prevVal = itemStore.GetValue (prev, 1);
object iterVal = itemStore.GetValue (iter, 1);
itemStore.SetValue (prev, 1, iterVal);
itemStore.SetValue (iter, 1, prevVal);
}
void removeButton_Clicked (object sender, EventArgs e)
{
//get selected iter and the replacement selection
TreeIter iter, newSelection;
TreeModel model;
if (!itemTree.Selection.GetSelected (out model, out iter))
return;
newSelection = iter.Copy ();
if (!IterPrev (model, ref newSelection)) {
newSelection = iter.Copy ();
if (!itemStore.IterNext (ref newSelection))
newSelection = TreeIter.Zero;
}
//new selection. Zeroing previousIter prevents trying to update name of deleted iter.
previousIter = TreeIter.Zero;
if (itemStore.IterIsValid (newSelection))
itemTree.Selection.SelectIter (newSelection);
//and the removal and index update
((ListStore) model).Remove (ref iter);
UpdateIndices ();
}
void Selection_Changed (object sender, EventArgs e)
{
//get selection
TreeIter iter;
TreeModel model;
if (!itemTree.Selection.GetSelected (out model, out iter))
return;
//update grid
object obj = model.GetValue (iter, 0);
grid.CurrentObject = obj;
//update previously selected iter's name
UpdateName (previousIter);
//update current selection so we can update
//name next selection change
previousIter = iter;
}
void addButton_Clicked (object sender, EventArgs e)
{
//create the object
object instance = System.Activator.CreateInstance (types[0]);
//get existing selection and insert after it
TreeIter oldIter, newIter;
TreeModel model;
if (itemTree.Selection.GetSelected (out model, out oldIter))
newIter = itemStore.InsertAfter (oldIter);
//or append if no previous selection
else
newIter = itemStore.Append ();
itemStore.SetValue (newIter, 0, instance);
//select, set name and update all the indices
itemTree.Selection.SelectIter (newIter);
UpdateName (newIter);
UpdateIndices ();
}
private void UpdateIndices ()
{
TreeIter iter;
int i = 0;
if (!itemStore.GetIterFirst (out iter))
return;
do {
itemStore.SetValue (iter, 1, i);
i++;
} while (itemStore.IterNext (ref iter));
}
private void UpdateName (TreeIter iter)
{
if (iter.Equals (TreeIter.Zero))
return;
object item = itemStore.GetValue (iter, 0);
string name = item.ToString ();
if (name.Length == 0)
name = item.GetType ().Name;
itemStore.SetValue(iter, 2, name);
}
//generally useful function... why not in model already?
private bool IterPrev (TreeModel model, ref TreeIter iter)
{
TreeIter prev, next;
if (!model.GetIterFirst (out prev))
return false;
do {
next = prev.Copy ();
if (!itemStore.IterNext (ref next))
return false;
//if next one on from prev is our iter
//then 'prev' is correct previous iter
if (next.Equals (iter)) {
iter = prev;
return true;
}
} while (itemStore.IterNext (ref prev));
return false;
}
}
}

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

@ -0,0 +1,115 @@
/*
* ColorEditor.cs - Visual type editor for System.Drawing.Color values
*
* Part of PropertyGrid - A Gtk# widget that displays and allows
* editing of all of an object's public properties
*
* Authors:
* Michael Hutchinson <m.j.hutchinson@gmail.com>
*
* Copyright (C) 2005 Michael Hutchinson
*
* This sourcecode is licenced under The MIT License:
*
* Permission is hereby granted, free of charge, to any person obtaining
* a copy of this software and associated documentation files (the
* "Software"), to deal in the Software without restriction, including
* without limitation the rights to use, copy, modify, merge, publish,
* distribute, sublicense, and/or sell copies of the Software, and to permit
* persons to whom the Software is furnished to do so, subject to the
* following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
* OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN
* NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM,
* DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
* OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE
* USE OR OTHER DEALINGS IN THE SOFTWARE.
*/
using System;
using System.ComponentModel;
using Gtk;
using Gdk;
namespace AspNetEdit.UI.PropertyEditors
{
[PropertyEditorType (typeof (System.Drawing.Color))]
public class ColorEditor : BaseEditor
{
public ColorEditor (GridRow parentRow)
: base (parentRow)
{
}
public override bool InPlaceEdit {
get { return false; }
}
public override Gtk.Widget GetDisplayWidget ()
{
DrawingArea colorPreview = new DrawingArea ();
colorPreview.ModifyBg(StateType.Normal, GetColor ());
colorPreview.WidthRequest = 15;
Alignment colorPreviewAlign = new Alignment (0, 0, 0, 1);
colorPreviewAlign.SetPadding (2, 2, 2, 2);
colorPreviewAlign.Add (colorPreview);
string labelText;
System.Drawing.Color color = (System.Drawing.Color) parentRow.PropertyValue;
//TODO: dropdown known color selector so this does something
if (color.IsKnownColor)
labelText = color.Name;
else if (color.IsEmpty)
labelText = "[empty]";
else
labelText = String.Format("#{0:x2}{1:x2}{2:x2}", color.R, color.G, color.B);
//we use StringValue as it auto-bolds the text for non-default values
Label theLabel = (Label) base.StringValue (labelText);
theLabel.Xalign = 0;
theLabel.Xpad = 3;
HBox hbox = new HBox ();
hbox.PackStart (colorPreviewAlign, false, false, 0);
hbox.PackStart (theLabel, true, true, 0);
return hbox;
}
public override bool DialogueEdit {
get { return true; }
}
private Gdk.Color GetColor ()
{
System.Drawing.Color color = (System.Drawing.Color) parentRow.PropertyValue;
//TODO: Property.Converter.ConvertTo() fails: why?
return new Gdk.Color (color.R, color.G, color.B);
}
public override void LaunchDialogue ()
{
ColorSelectionDialog dialog = new ColorSelectionDialog ("Select a new color");
dialog.ColorSelection.CurrentColor = GetColor ();
dialog.Run ();
dialog.Destroy ();
int red = (int) (255 * (float) dialog.ColorSelection.CurrentColor.Red / ushort.MaxValue);
int green = (int) (255 * (float) dialog.ColorSelection.CurrentColor.Green / ushort.MaxValue);
int blue = (int) (255 * (float) dialog.ColorSelection.CurrentColor.Blue / ushort.MaxValue);
System.Drawing.Color color = System.Drawing.Color.FromArgb (red, green, blue);
//TODO: Property.Converter.ConvertFrom() fails: why?
parentRow.PropertyValue = color;
}
}
}

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

@ -0,0 +1,61 @@
/*
* DefaultEditor.cs - The default visual 'editor' for types we don't have
* an editor for.
*
* Part of PropertyGrid - A Gtk# widget that displays and allows
* editing of all of an object's public properties
*
* Authors:
* Michael Hutchinson <m.j.hutchinson@gmail.com>
*
* Copyright (C) 2005 Michael Hutchinson
*
* This sourcecode is licenced under The MIT License:
*
* Permission is hereby granted, free of charge, to any person obtaining
* a copy of this software and associated documentation files (the
* "Software"), to deal in the Software without restriction, including
* without limitation the rights to use, copy, modify, merge, publish,
* distribute, sublicense, and/or sell copies of the Software, and to permit
* persons to whom the Software is furnished to do so, subject to the
* following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
* OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN
* NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM,
* DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
* OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE
* USE OR OTHER DEALINGS IN THE SOFTWARE.
*/
using System;
using Gtk;
using System.ComponentModel;
namespace AspNetEdit.UI.PropertyEditors
{
public class DefaultEditor : BaseEditor
{
public DefaultEditor (GridRow parentRow)
: base (parentRow)
{
}
public override bool InPlaceEdit {
get { return false; }
}
public override Gtk.Widget GetDisplayWidget ()
{
return base.StringValue ("<span foreground=\"grey\">&lt;" + parentRow.PropertyDescriptor.PropertyType.ToString() + "&gt;</span>", true);
}
public override bool DialogueEdit {
get { return false; }
}
}
}

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

@ -0,0 +1,102 @@
/*
* EnumEditor.cs - Visual editor for Enumerations
*
* Part of PropertyGrid - A Gtk# widget that displays and allows
* editing of all of an object's public properties
*
* Authors:
* Michael Hutchinson <m.j.hutchinson@gmail.com>
*
* Copyright (C) 2005 Michael Hutchinson
*
* This sourcecode is licenced under The MIT License:
*
* Permission is hereby granted, free of charge, to any person obtaining
* a copy of this software and associated documentation files (the
* "Software"), to deal in the Software without restriction, including
* without limitation the rights to use, copy, modify, merge, publish,
* distribute, sublicense, and/or sell copies of the Software, and to permit
* persons to whom the Software is furnished to do so, subject to the
* following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
* OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN
* NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM,
* DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
* OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE
* USE OR OTHER DEALINGS IN THE SOFTWARE.
*/
using System;
using System.ComponentModel;
using Gtk;
using System.Collections;
using AspNetEdit.UI;
namespace AspNetEdit.UI.PropertyEditors
{
[PropertyEditorType(typeof(System.Enum))]
public class EnumEditor : BaseEditor
{
ListStore namestore;
public EnumEditor (GridRow parentRow)
: base (parentRow)
{
if (!parentRow.PropertyDescriptor.PropertyType.IsEnum)
throw new Exception ("property is not an enum");
}
public override bool InPlaceEdit {
get { return true; }
}
public override Widget GetDisplayWidget ()
{
return base.StringValue (parentRow.PropertyDescriptor.Converter.ConvertToString (parentRow.PropertyValue));
}
public override Gtk.Widget GetEditWidget ()
{
namestore = new ListStore (typeof(string));
ComboBox combo = new ComboBox (namestore);
CellRenderer rdr = new CellRendererText ();
combo.PackStart (rdr, true);
combo.AddAttribute (rdr, "text", 0);
Array values = System.Enum.GetValues (parentRow.PropertyDescriptor.PropertyType);
foreach (object s in values) {
string str = parentRow.PropertyDescriptor.Converter.ConvertToString (s);
TreeIter t = namestore.AppendValues (str);
if (str == parentRow.PropertyDescriptor.Converter.ConvertToString (parentRow.PropertyValue))
combo.SetActiveIter (t);
}
combo.Changed += new EventHandler (combo_Changed);
combo.Destroyed += new EventHandler (combo_Destroyed);
return combo;
}
void combo_Destroyed (object sender, EventArgs e)
{
namestore.Dispose ();
}
void combo_Changed (object sender, EventArgs e)
{
TreeIter t;
((ComboBox) sender).GetActiveIter(out t);
parentRow.PropertyValue = parentRow.PropertyDescriptor.Converter.ConvertFromString ((string) namestore.GetValue (t, 0));
}
public override bool DialogueEdit {
get { return false; }
}
}
}

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

@ -0,0 +1,96 @@
/*
* NumberEditor.cs - Visual editor for most simple numerical types.
*
* Part of PropertyGrid - A Gtk# widget that displays and allows
* editing of all of an object's public properties
*
* Authors:
* Michael Hutchinson <m.j.hutchinson@gmail.com>
*
* Copyright (C) 2005 Michael Hutchinson
*
* This sourcecode is licenced under The MIT License:
*
* Permission is hereby granted, free of charge, to any person obtaining
* a copy of this software and associated documentation files (the
* "Software"), to deal in the Software without restriction, including
* without limitation the rights to use, copy, modify, merge, publish,
* distribute, sublicense, and/or sell copies of the Software, and to permit
* persons to whom the Software is furnished to do so, subject to the
* following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
* OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN
* NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM,
* DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
* OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE
* USE OR OTHER DEALINGS IN THE SOFTWARE.
*/
using System;
using System.ComponentModel;
using Gtk;
namespace AspNetEdit.UI.PropertyEditors
{
[PropertyEditorType (typeof (Int16)),
PropertyEditorType (typeof (Int32)),
PropertyEditorType (typeof (Int64)),
PropertyEditorType (typeof (Double)),
PropertyEditorType (typeof (Single)),
PropertyEditorType (typeof (Decimal))]
public class IntEditor : BaseEditor
{
public IntEditor (GridRow parentRow)
: base (parentRow)
{
}
public override bool InPlaceEdit {
get { return true; }
}
public override Gtk.Widget GetEditWidget ()
{
Gtk.SpinButton spin;
if (parentRow.PropertyDescriptor.PropertyType == typeof (Int16))
spin = new SpinButton(Int16.MinValue, Int16.MaxValue, 1);
else if (parentRow.PropertyDescriptor.PropertyType == typeof (Int32))
spin = new SpinButton(Int32.MinValue, Int32.MaxValue, 1);
else if (parentRow.PropertyDescriptor.PropertyType == typeof (Int64))
spin = new SpinButton(Int64.MinValue, Int64.MaxValue, 1);
else //TODO: process floats etc nicely
spin = new SpinButton(Int64.MinValue, Int64.MaxValue, 1);
spin.HasFrame = false;
spin.Value = Convert.ToDouble (parentRow.PropertyValue);
spin.ValueChanged += new EventHandler (spin_ValueChanged);
return spin;
}
void spin_ValueChanged (object sender, EventArgs e)
{
Gtk.SpinButton spin = (SpinButton) sender;
object newValue = Convert.ChangeType (spin.Value, parentRow.PropertyDescriptor.PropertyType);
parentRow.PropertyValue = newValue;
//if there's an error such as out-of-range, and value not accepted by parent, restore old value
if (parentRow.PropertyValue != newValue)
spin.Value = Convert.ToDouble (parentRow.PropertyValue);
}
public override bool DialogueEdit {
get { return false; }
}
}
}

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

@ -0,0 +1,92 @@
/*
* StringEditor.cs - Visual editor for strings, or values that
* convert to/from strings.
*
* Part of PropertyGrid - A Gtk# widget that displays and allows
* editing of all of an object's public properties
*
* Authors:
* Michael Hutchinson <m.j.hutchinson@gmail.com>
*
* Copyright (C) 2005 Michael Hutchinson
*
* This sourcecode is licenced under The MIT License:
*
* Permission is hereby granted, free of charge, to any person obtaining
* a copy of this software and associated documentation files (the
* "Software"), to deal in the Software without restriction, including
* without limitation the rights to use, copy, modify, merge, publish,
* distribute, sublicense, and/or sell copies of the Software, and to permit
* persons to whom the Software is furnished to do so, subject to the
* following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
* OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN
* NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM,
* DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
* OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE
* USE OR OTHER DEALINGS IN THE SOFTWARE.
*/
using System;
using System.ComponentModel;
using Gtk;
namespace AspNetEdit.UI.PropertyEditors
{
[PropertyEditorType (typeof (string))]
public class StringEditor : BaseEditor
{
public StringEditor (GridRow parentRow)
: base (parentRow)
{
}
public override bool InPlaceEdit {
get { return true; }
}
public override Widget GetEditWidget ()
{
Entry entry = new Entry ();
if (parentRow.PropertyValue == null)
entry.Text = null;
else
entry.Text = parentRow.PropertyDescriptor.Converter.ConvertToString (parentRow.PropertyValue);
entry.HasFrame = false;
entry.WidthRequest = 30; //Don't artificially inflate the width. It expands anyway.
//TODO: Is entry.Changed too responsive?
//entry.Changed += new EventHandler (entry_Changed);
entry.Destroyed += new EventHandler (entry_Changed);
entry.Activated += new EventHandler (entry_Changed);
return entry;
}
void entry_Changed (object sender, EventArgs e)
{
//Catching all exceptions is bad, but converter can throw all sorts of exception
//with invalid entries. We just want to ignore bad entries.
try {
string text = ((Entry) sender).Text;
//if value was null and new value is empty, leave as null
if (!(text == "" && parentRow.PropertyValue== null))
parentRow.PropertyValue = parentRow.PropertyDescriptor.Converter.ConvertFromString (((Entry) sender).Text);
}
catch (Exception ex) { }
}
public override bool DialogueEdit {
get { return false; }
}
}
}

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

@ -0,0 +1,126 @@
/*
* EditorManager.cs - Used to register, lookup and select visual editors.
*
* Part of PropertyGrid - A Gtk# widget that displays and allows
* editing of all of an object's public properties
*
* Authors:
* Michael Hutchinson <m.j.hutchinson@gmail.com>
*
* Copyright (C) 2005 Michael Hutchinson
*
* This sourcecode is licenced under The MIT License:
*
* Permission is hereby granted, free of charge, to any person obtaining
* a copy of this software and associated documentation files (the
* "Software"), to deal in the Software without restriction, including
* without limitation the rights to use, copy, modify, merge, publish,
* distribute, sublicense, and/or sell copies of the Software, and to permit
* persons to whom the Software is furnished to do so, subject to the
* following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
* OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN
* NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM,
* DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
* OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE
* USE OR OTHER DEALINGS IN THE SOFTWARE.
*/
using System;
using System.Collections;
using System.Reflection;
using System.ComponentModel;
using AspNetEdit.UI.PropertyEditors;
using System.Drawing.Design;
namespace AspNetEdit.UI
{
internal class EditorManager
{
private Hashtable editors = new Hashtable ();
private Hashtable surrogates = new Hashtable ();
internal EditorManager ()
{
LoadEditor (Assembly.GetAssembly (typeof (EditorManager)));
}
public void LoadEditor (Assembly editorAssembly)
{
foreach (Type t in editorAssembly.GetTypes ()) {
foreach (Attribute currentAttribute in Attribute.GetCustomAttributes (t)) {
if (currentAttribute.GetType() == typeof (PropertyEditorTypeAttribute)) {
Type editorType = (currentAttribute as PropertyEditorTypeAttribute).Type;
if (t.IsSubclassOf (typeof (BaseEditor)))
editors.Add (editorType, t);
}
else if (currentAttribute.GetType () == typeof (SurrogateUITypeEditorAttribute)) {
Type editorType = (currentAttribute as SurrogateUITypeEditorAttribute).Type;
surrogates.Add (editorType, t);
}
}
}
}
public BaseEditor GetEditor(PropertyDescriptor pd, GridRow parentRow)
{
//try to find a custom editor
//TODO: Find a way to provide a IWindowsFormsEditorService so this can work directly
//for now, substitute GTK#-based editors
/*
UITypeEditor UITypeEd = (UITypeEditor) pd.GetEditor(typeof (System.Drawing.Design.UITypeEditor));//first, does it have custom editors?
if (UITypeEd != null)
if (surrogates.Contains(UITypeEd.GetType ()))
return instantiateEditor((Type) surrogates[UITypeEd.GetType()], parentRow);
*/
//does a registered GTK# editor support this natively?
Type editType = pd.PropertyType;
if (editors.Contains (editType))
return instantiateEditor ((Type) editors[editType], parentRow);
//special cases
if (editType.IsEnum)
return new EnumEditor (parentRow);
//collections with items of single type that aren't just objects
if(editType.GetInterface ("IList") != null) {
PropertyInfo member = editType.GetProperty ("Item");
if (member != null)
if (member.PropertyType != typeof (object))
return new CollectionEditor (parentRow, member.PropertyType);
}
//TODO: support simple SWF collection editor derivatives that just override Types available
// and reflect protected Type[] NewItemTypes {get;} to get types
//if (UITypeEd is System.ComponentModel.Design.CollectionEditor)
// ((System.ComponentModel.Design.CollectionEditor)UITypeEd).
//can we use a type converter with a built-in editor?
TypeConverter tc = pd.Converter;
//This is a temporary workaround *and* and optimisation
//First, most unknown types will be most likely to convert to/from strings
//Second, System.Web.UI.WebControls/UnitConverter.cs dies on non-strings
if (tc.CanConvertFrom (typeof (string)) && tc.CanConvertTo (typeof(string)))
return new StringEditor (parentRow);
foreach (DictionaryEntry editor in editors)
if (tc.CanConvertFrom((Type) editor.Key) && tc.CanConvertTo((Type) editor.Key))
return instantiateEditor((Type) editor.Value, parentRow);
//nothing found - just display type
return new DefaultEditor (parentRow);
}
private BaseEditor instantiateEditor(Type type, GridRow parentRow)
{
ConstructorInfo ctor = type.GetConstructor( new Type[] { typeof (GridRow) });
return (BaseEditor) ctor.Invoke(new object[] { parentRow });
}
}
}

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

@ -0,0 +1,301 @@
/*
* GridRow.cs - Displays a row of a PropertyGrid
*
* Part of PropertyGrid - A Gtk# widget that displays and allows
* editing of all of an object's public properties
*
* Authors:
* Michael Hutchinson <m.j.hutchinson@gmail.com>
* Eric Butler <eric@extremeboredom.net>
*
* Copyright (C) 2005 Michael Hutchinson
* Copyright (C) 2005 Eric Butler
*
* This sourcecode is licenced under The MIT License:
*
* Permission is hereby granted, free of charge, to any person obtaining
* a copy of this software and associated documentation files (the
* "Software"), to deal in the Software without restriction, including
* without limitation the rights to use, copy, modify, merge, publish,
* distribute, sublicense, and/or sell copies of the Software, and to permit
* persons to whom the Software is furnished to do so, subject to the
* following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
* OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN
* NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM,
* DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
* OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE
* USE OR OTHER DEALINGS IN THE SOFTWARE.
*/
using System;
using System.Reflection;
using Gtk;
using System.ComponentModel;
namespace AspNetEdit.UI
{
public class GridRow
{
private PropertyGrid parent = null;
private PropertyDescriptor propertyDescriptor = null;
private EventBox propertyNameEventBox = null;
internal Label propertyNameLabel = null;
private EventBox propertyValueEventBox;
private HBox propertyValueHBox;
private bool isValidProperty = true;
private bool editing = false;
private bool selected = false;
private object valueBeforeEdit;
private PropertyEditors.BaseEditor editor;
public GridRow (PropertyGrid parentGrid, PropertyDescriptor descriptor)
{
this.parent = parentGrid;
this.propertyDescriptor = descriptor;
// TODO: Need a better way to check if the property has no get accessor.
// Write-only? Don't add this to the list.
try {object propertyValue = descriptor.GetValue (parent.CurrentObject);}
catch (Exception) {
isValidProperty = false;
return;
}
#region Name label
propertyNameLabel = new Label (descriptor.DisplayName);
propertyNameLabel.Xalign = 0;
propertyNameLabel.Xpad = 3;
propertyNameLabel.HeightRequest = 20;
propertyNameEventBox = new EventBox ();
propertyNameEventBox.ModifyBg (StateType.Normal, parent.Style.White);
propertyNameEventBox.Add (propertyNameLabel);
propertyNameEventBox.ButtonReleaseEvent += on_label_ButtonRelease;
if (propertyNameLabel.SizeRequest ().Width > 100) {
propertyNameLabel.WidthRequest = 100;
//TODO: Display tooltip of full name when truncated
//parent.tooltips.SetTip (propertyNameLabel, descriptor.DisplayName, descriptor.DisplayName);
}
#endregion
editor = parent.EditorManager.GetEditor(propertyDescriptor, this);
propertyValueHBox = new HBox();
//check if it needs a button. Note arrays are read-only but have buttons
if (editor.DialogueEdit && (!propertyDescriptor.IsReadOnly || editor.EditsReadOnlyObject)) {
Label buttonLabel = new Label ();
buttonLabel.UseMarkup = true;
buttonLabel.Xpad = 0; buttonLabel.Ypad = 0;
buttonLabel.Markup = "<span size=\"small\">...</span>";
Button dialogueButton = new Button (buttonLabel);
dialogueButton.Clicked += new EventHandler (dialogueButton_Clicked);
propertyValueHBox.PackEnd (dialogueButton, false, false, 0);
}
propertyValueEventBox = new EventBox ();
propertyValueEventBox.ModifyBg (StateType.Normal, parent.Style.White);
propertyValueEventBox.CanFocus = true;
propertyValueEventBox.ButtonReleaseEvent += on_value_ButtonRelease;
propertyValueEventBox.Focused += on_value_ButtonRelease;
propertyValueHBox.PackStart (propertyValueEventBox, true, true, 0);
valueBeforeEdit = propertyDescriptor.GetValue (parentGrid.CurrentObject);
DisplayRenderWidget ();
}
private void on_label_ButtonRelease (object o, EventArgs e)
{
if (!selected)
this.Selected = true;
}
private void on_value_ButtonRelease (object o, EventArgs e)
{
if (!selected)
this.Selected = true;
if (editor.InPlaceEdit && !propertyDescriptor.IsReadOnly)
DisplayEditWidget ();
}
void dialogueButton_Clicked (object sender, EventArgs e)
{
if (!selected)
this.Selected = true;
editor.LaunchDialogue ();
}
public Widget LabelWidget {
get { return propertyNameEventBox; }
}
public Widget ValueWidget {
get { return propertyValueHBox; }
}
public PropertyGrid ParentGrid {
get { return parent; }
}
public PropertyDescriptor PropertyDescriptor
{
get { return propertyDescriptor; }
}
#region Selection status
public bool IsValidProperty
{
get { return isValidProperty; }
set { isValidProperty = value; }
}
public bool Editing
{
get { return editing; }
set { editing = value; }
}
public bool Selected
{
get { return selected; }
set {
// slightly complicated logic here to allow for selection to take
// place from GridRow or PropertyGrid, and keep state in synch.
// Checks parent has handled change. If not, calls change on parent
// which then calls this again.
if (value) {
if (selected)
return;
if (parent.SelectedRow == this)
{
propertyNameEventBox.ModifyBg (StateType.Normal, parent.Style.Background (StateType.Selected));
propertyNameLabel.ModifyFg (StateType.Normal, parent.Style.Text (StateType.Selected));
parent.SetHelp(propertyDescriptor.DisplayName, propertyDescriptor.Description);
selected = true;
}
else
parent.SelectedRow = this; //fires other part of 'if', after setting parent's SelectedRow
}
else {
if (!selected)
return;
if (parent.SelectedRow != this) {
propertyNameEventBox.ModifyBg (StateType.Normal, parent.Style.White);
propertyNameLabel.ModifyFg (StateType.Normal, parent.Style.Foreground (StateType.Normal));
if (editing)
DisplayRenderWidget ();
parent.ClearHelp ();
selected = false;
}
else
parent.SelectedRow = null;
}
}
}
#endregion
//mainly intended for use by editors
public object PropertyValue
{
get { return this.valueBeforeEdit; }
set
{
if (value == this.valueBeforeEdit)
return;
//suppress conversion errors
try
{
//try to set value
propertyDescriptor.SetValue (parent.CurrentObject, value);
//if successful, fire change event and set old value
parent.OnPropertyValueChanged (this, this.valueBeforeEdit, value);
this.valueBeforeEdit = value;
}
catch (ArgumentOutOfRangeException ex)
{
//out of range, restore old value
propertyDescriptor.SetValue (parent.CurrentObject, this.valueBeforeEdit);
}
catch (Exception ex)
{
propertyDescriptor.SetValue(parent.CurrentObject, this.valueBeforeEdit);
throw new Exception ("Error converting property " + propertyDescriptor.Name, ex);
}
//update display widget
if (!editing)
DisplayRenderWidget ();
//TODO: Seems to lose keyboard input after value changed, despite still focussed. Fix?
//else
// propertyValueEventBox.Child.GrabFocus();
}
}
private void DisplayEditWidget()
{
if (propertyValueEventBox.Child != null)
propertyValueEventBox.Child.Destroy ();
if (!editing)
editing = true;
Widget editWidget = editor.GetEditWidget ();
propertyValueEventBox.Child = editWidget;
if (editWidget.SizeRequest ().Width > 50) {
editWidget.WidthRequest = 50;
//TODO: Display tooltip of full text when truncated
}
propertyValueEventBox.ShowAll ();
editWidget.GrabFocus ();
}
private void DisplayRenderWidget ()
{
if (propertyValueEventBox.Child != null)
propertyValueEventBox.Child.Destroy ();
if (editing)
editing = false;
Widget displayWidget = editor.GetDisplayWidget ();
propertyValueEventBox.Child = displayWidget;
if (propertyValueEventBox.Child.SizeRequest ().Width > 100) {
propertyValueEventBox.Child.WidthRequest = 100;
//TODO: Display proper tooltip of full text when truncated
//if (propertyValueEventBox.Child is Label)
// parent.tooltips.SetTip(propertyValueEventBox.Child, ((Label) propertyValueEventBox.Child).Text, string.Empty);
}
propertyValueEventBox.ShowAll ();
}
}
}

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

@ -0,0 +1,47 @@
/*
* PropertyTypeAttribute.cs - Shows which types a visual type editor can edit
*
* Part of PropertyGrid - A Gtk# widget that displays and allows
* editing of all of an object's public properties
*
* Authors:
* Eric Butler <eric@extremeboredom.net>
*
* Copyright (C) 2005 Eric Butler
*
* This sourcecode is licenced under The MIT License:
*
* Permission is hereby granted, free of charge, to any person obtaining
* a copy of this software and associated documentation files (the
* "Software"), to deal in the Software without restriction, including
* without limitation the rights to use, copy, modify, merge, publish,
* distribute, sublicense, and/or sell copies of the Software, and to permit
* persons to whom the Software is furnished to do so, subject to the
* following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
* OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN
* NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM,
* DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
* OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE
* USE OR OTHER DEALINGS IN THE SOFTWARE.
*/
using System;
namespace AspNetEdit.UI
{
[AttributeUsage (AttributeTargets.Class, AllowMultiple = true)]
public class PropertyEditorTypeAttribute : Attribute
{
public Type Type;
public PropertyEditorTypeAttribute (Type myType)
{
this.Type = myType;
}
}
}

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

@ -0,0 +1,472 @@
/*
* PropertyGrid.cs - A Gtk# widget that displays and allows
* editing of all of an object's public properties
*
* Authors:
* Michael Hutchinson <m.j.hutchinson@gmail.comk>
* Eric Butler <eric@extremeboredom.net>
*
* Copyright (C) 2005 Michael Hutchinson
* Copyright (C) 2005 Eric Butler
*
* This sourcecode is licenced under The MIT License:
*
* Permission is hereby granted, free of charge, to any person obtaining
* a copy of this software and associated documentation files (the
* "Software"), to deal in the Software without restriction, including
* without limitation the rights to use, copy, modify, merge, publish,
* distribute, sublicense, and/or sell copies of the Software, and to permit
* persons to whom the Software is furnished to do so, subject to the
* following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
* OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN
* NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM,
* DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
* OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE
* USE OR OTHER DEALINGS IN THE SOFTWARE.
*/
using System;
using System.Reflection;
using System.IO;
using Gtk;
using System.Collections;
using System.ComponentModel;
namespace AspNetEdit.UI
{
public class PropertyGrid : Gtk.VBox
{
private object currentObject = null;
private EditorManager editorManager;
private PropertyDescriptorCollection properties;
public ArrayList Rows = new ArrayList ();
private GridRow selectedRow;
private string defaultPropertyName;
private string defaultEventName;
private bool showHelp = true;
private Table table;
private VBox expanderBox;
private ScrolledWindow scrolledWindow;
private VPaned vpaned;
private Toolbar toolbar;
private ToggleButton catButton;
private ToggleButton alphButton;
private ScrolledWindow textScroll;
private VBox desc;
private Label descTitle;
private TextView descText;
private Frame descFrame;
public PropertyGrid()
: this(new EditorManager ())
{
}
internal PropertyGrid (EditorManager editorManager)
: base (false, 0)
{
this.editorManager = editorManager;
toolbar = new Toolbar ();
base.PackStart (toolbar, false, false, 0);
catButton = new ToggleButton ("Categorised");
catButton.Clicked += new EventHandler (toolbarClick);
//initial state of this widget is sorted by category
catButton.Active = true;
viewState = ViewState.ByCategory;
ToolItem t = new ToolItem ();
t.Add (catButton);
toolbar.Insert (t, 0);
alphButton = new ToggleButton ("Alphabetical");
alphButton.Clicked += new EventHandler (toolbarClick);
t = new ToolItem ();
t.Add (alphButton);
toolbar.Insert (t, 1);
vpaned = new VPaned ();
descFrame = new Frame ();
descFrame.Shadow = ShadowType.In;
desc = new VBox (false, 0);
descFrame.Add (desc);
descTitle = new Label ();
descTitle.SetAlignment(0, 0);
descTitle.SetPadding (5, 5);
descTitle.UseMarkup = true;
desc.PackStart (descTitle, false, false, 0);
textScroll = new ScrolledWindow ();
textScroll.HscrollbarPolicy = PolicyType.Never;
textScroll.VscrollbarPolicy = PolicyType.Automatic;
desc.PackEnd (textScroll, true, true, 0);
//TODO: Use label, but wrapping seems dodgy.
descText = new TextView ();
descText.WrapMode = WrapMode.Word;
descText.WidthRequest = 1;
descText.HeightRequest = 100;
descText.Editable = false;
descText.LeftMargin = 5;
descText.RightMargin = 5;
textScroll.Add (descText);
scrolledWindow = new ScrolledWindow ();
scrolledWindow.HscrollbarPolicy = PolicyType.Automatic;
scrolledWindow.VscrollbarPolicy = PolicyType.Automatic;
vpaned.Pack1 (scrolledWindow, true, true);
vpaned.Pack2 (descFrame, false, true);
base.PackEnd (vpaned);
Populate ();
}
internal EditorManager EditorManager {
get { return editorManager; }
}
#region Toolbar state and handlers
private ViewState viewState;
// FIXME: Hacky. For some reason, changing ToggleButton.Active
// on toolbar fires Clicked event as well as Toggle event.
private bool ignoreClicks = false;
void toolbarClick (object sender, EventArgs e)
{
if (ignoreClicks)
return;
ignoreClicks = true;
((ToggleButton) sender).Active = true;
ignoreClicks = false;
if (sender == alphButton)
View = ViewState.Alphabetical;
else if (sender == catButton)
View = ViewState.ByCategory;
}
void setButtonState ()
{
}
public ViewState View {
get { return viewState; }
set {
if (value != viewState) {
viewState = value;
Populate();
}
}
}
#endregion
private void Populate ()
{
ignoreClicks = true;
alphButton.Active = false;
catButton.Active = false;
if (viewState == ViewState.Alphabetical) {
alphButton.Active = true;
PopulateView (false);
}
else if (viewState == ViewState.ByCategory) {
catButton.Active = true;
PopulateView (true);
}
ignoreClicks = false;
}
private string DefaultPropertyName {
get { //only calculate once for each currentObject
if (defaultPropertyName == null) {
defaultPropertyName = string.Empty;
if (currentObject != null) {
DefaultPropertyAttribute defaultProperty = (DefaultPropertyAttribute) TypeDescriptor.GetAttributes (currentObject)[typeof (DefaultPropertyAttribute)];
if (defaultProperty != null)
defaultPropertyName = defaultProperty.Name;
}
}
return defaultPropertyName;
}
}
private string DefaultEventName {
get { //only calculate once for each currentObject
if (defaultEventName == null)
{
defaultEventName = string.Empty;
if (currentObject == null) {
DefaultEventAttribute defaultEvent = (DefaultEventAttribute) TypeDescriptor.GetAttributes (currentObject)[typeof (DefaultEventAttribute)];
if (defaultEvent != null)
defaultEventName = defaultEvent.Name;
}
}
return defaultPropertyName;
}
}
public object CurrentObject {
get { return currentObject; }
set {
if (this.currentObject == value)
return;
//want to drop reference to this or will cause
//problems when stopping editing
SelectedRow = null;
this.currentObject = value;
//reset these, but only calculate on demand
defaultPropertyName = null;
defaultEventName = null;
Populate();
}
}
private void PopulateView(bool categorised)
{
if (currentObject != null)
properties = TypeDescriptor.GetProperties (currentObject);
else
properties = new PropertyDescriptorCollection (new PropertyDescriptor[0] {});
//kill existing table
if (expanderBox != null) {
expanderBox.Destroy ();
expanderBox = null;
}
Rows.Clear();
//transcribe browsable properties
ArrayList sorted = new ArrayList();
foreach (PropertyDescriptor descriptor in properties) {
bool browsable = true;
foreach (Attribute attr in descriptor.Attributes)
if (attr is BrowsableAttribute)
browsable = ((BrowsableAttribute) attr).Browsable;
//TODO: Make this work under Linux Mono
//if (descriptor.IsBrowsable)
if (browsable)
sorted.Add (descriptor);
}
//expands to fill empty space
EventBox bottomWidget = new EventBox ();
bottomWidget.ModifyBg (StateType.Normal, new Gdk.Color (0xff, 0xff, 0xff));
bottomWidget.CanFocus = true;
bottomWidget.ButtonPressEvent += on_bottomWidget_ButtonPressEvent;
expanderBox = new VBox ();
//how are we displaying it?
if (!categorised) {
sorted.Sort(new SortByName ());
table = BuildTable (sorted);
expanderBox.PackStart (table, false, false, 0);
}
else {
sorted.Sort (new SortByCat ());
ArrayList tabList = new ArrayList ();
string oldCat = "";
int oldIndex = 0;
Expander catHead = null;
for (int i = 0; i < sorted.Count; i++) {
PropertyDescriptor pd = (PropertyDescriptor) sorted[i];
//Create category header
if (pd.Category != oldCat) {
if (catHead != null) {
Table t = BuildTable (sorted.GetRange(oldIndex, i - oldIndex));
catHead.Add (t);
}
catHead = new Expander ("<b>" + pd.Category + "</b>");
((Label) catHead.LabelWidget).UseMarkup = true;
catHead.Expanded = true;
expanderBox.PackStart (catHead, false, false, 0);
oldCat = pd.Category;
oldIndex = i;
}
}
if (catHead != null) {
Table t = BuildTable (sorted.GetRange (oldIndex, sorted.Count - oldIndex));
catHead.Add (t);
}
//TODO: Find better way of getting all tables same size, maybe resizable
int maxwidth = 1;
foreach (GridRow pgr in Rows) {
int width = pgr.propertyNameLabel.SizeRequest ().Width;
if (width > maxwidth)
maxwidth = width;
}
foreach (GridRow pgr in Rows)
pgr.propertyNameLabel.WidthRequest = maxwidth;
}
expanderBox.PackStart (bottomWidget, true, true, 1);
scrolledWindow.AddWithViewport (expanderBox);
expanderBox.ShowAll ();
}
private Table BuildTable (ArrayList arr)
{
//create new table
Table table = new Table (Convert.ToUInt32 (arr.Count), 2, false);
table.ColumnSpacing = 1;
table.RowSpacing = 1;
table.BorderWidth = 0;
UInt32 currentRow = 0;
for (int i = 0; i < arr.Count; i++) {
PropertyDescriptor pd = (PropertyDescriptor) arr[i];
//create item
//TODO: expand children of expandable objects with no editor. Use ExpandableObjectConverter?
GridRow newRow = new GridRow (this, pd);
if (newRow.IsValidProperty) {
table.Attach (newRow.LabelWidget, 0, 1, currentRow, currentRow + 1, AttachOptions.Fill, AttachOptions.Fill, 0, 0);
table.Attach (newRow.ValueWidget, 1, 2, currentRow, currentRow + 1, AttachOptions.Expand | AttachOptions.Fill, AttachOptions.Fill, 0, 0);
currentRow += 1;
Rows.Add (newRow);
if (newRow.PropertyDescriptor.Name == DefaultPropertyName)
this.SelectedRow = newRow;
}
}
return table;
}
private void on_bottomWidget_ButtonPressEvent (object o, EventArgs e)
{
(o as EventBox).GrabFocus ();
SelectedRow = null;
}
public GridRow SelectedRow
{
get { return selectedRow; }
set {
if (selectedRow == value)
return;
if (!Rows.Contains (value) && value != null)
throw new Exception("You cannot select a GridRow that is not in the PropertyGrid");
//slightly complicated logic here to allow for selection to take
//place from GridRow or PropertyGrid, and keep state in synch
GridRow oldSelectedRow = selectedRow;
selectedRow = value;
if (oldSelectedRow != null)
oldSelectedRow.Selected = false;
if (selectedRow != null)
selectedRow.Selected = true;
}
}
public void SetHelp(string title, string description)
{
descText.Buffer.Clear ();
descText.Buffer.InsertAtCursor (description);
descTitle.Markup = "<b>" + title + "</b>";
}
public void ClearHelp()
{
descTitle.Text = "";
descText.Buffer.Clear ();
}
public event PropertyValueChangedEventHandler PropertyValueChanged;
public void OnPropertyValueChanged (GridRow changedItem, object oldValue, object newValue)
{
if (PropertyValueChanged != null)
PropertyValueChanged (this, new PropertyValueChangedEventArgs (changedItem, oldValue, newValue));
}
private class SortByCat : IComparer
{
public int Compare (object x, object y)
{
int catcomp = (x as PropertyDescriptor).Category.CompareTo ((y as PropertyDescriptor).Category);
if (catcomp == 0)
return (x as PropertyDescriptor).DisplayName.CompareTo ((y as PropertyDescriptor).DisplayName);
else
return catcomp;
}
}
private class SortByName : IComparer
{
public int Compare(object x, object y)
{
return (x as PropertyDescriptor).DisplayName.CompareTo ((y as PropertyDescriptor).DisplayName);
}
}
public enum ViewState {
ByCategory,
Alphabetical
}
public bool ShowHelp
{
get { return showHelp; }
set {
if (value != showHelp)
if (value)
vpaned.Pack2 (descFrame, false, true);
else
vpaned.Remove (descFrame);
}
}
}
}

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

@ -0,0 +1,64 @@
/*
* PropertyValueChangedEventArgs.cs - The arguments for the PropertyGrid's PropertyValueChanged event
*
* Part of PropertyGrid - A Gtk# widget that displays and allows
* editing of all of an object's public properties
*
* Authors:
* Michael Hutchinson <m.j.hutchinson@gmail.com>
*
* Copyright (C) 2005 Michael Hutchinson
*
* This sourcecode is licenced under The MIT License:
*
* Permission is hereby granted, free of charge, to any person obtaining
* a copy of this software and associated documentation files (the
* "Software"), to deal in the Software without restriction, including
* without limitation the rights to use, copy, modify, merge, publish,
* distribute, sublicense, and/or sell copies of the Software, and to permit
* persons to whom the Software is furnished to do so, subject to the
* following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
* OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN
* NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM,
* DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
* OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE
* USE OR OTHER DEALINGS IN THE SOFTWARE.
*/
using System;
namespace AspNetEdit.UI
{
public class PropertyValueChangedEventArgs
{
private GridRow changedItem;
private object oldValue;
private object newValue;
public PropertyValueChangedEventArgs (GridRow changedItem, object oldValue, object newValue)
{
this.changedItem = changedItem;
this.oldValue = oldValue;
this.newValue = newValue;
}
public object OldValue {
get { return oldValue; }
}
public object NewValue
{
get { return newValue; }
}
public GridRow ChangedItem {
get { return changedItem; }
}
}
}

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

@ -0,0 +1,37 @@
/*
* PropertyValueChangedEventHandler.cs - The delegate for the PropertyGrid's PropertyValueChanged event
*
* Part of PropertyGrid - A Gtk# widget that displays and allows
* editing of all of an object's public properties
*
* Authors:
* Michael Hutchinson <m.j.hutchinson@gmail.com>
*
* Copyright (C) 2005 Michael Hutchinson
*
* This sourcecode is licenced under The MIT License:
*
* Permission is hereby granted, free of charge, to any person obtaining
* a copy of this software and associated documentation files (the
* "Software"), to deal in the Software without restriction, including
* without limitation the rights to use, copy, modify, merge, publish,
* distribute, sublicense, and/or sell copies of the Software, and to permit
* persons to whom the Software is furnished to do so, subject to the
* following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
* OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN
* NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM,
* DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
* OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE
* USE OR OTHER DEALINGS IN THE SOFTWARE.
*/
namespace AspNetEdit.UI
{
public delegate void PropertyValueChangedEventHandler (object sender, PropertyValueChangedEventArgs e);
}

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

@ -0,0 +1,61 @@
/*
* SurrogateUITypeEditorAttribute.cs - Marks a GTK# Visual Editor as a substitute
* for a particular System.Drawing.Design.UITypeEditor-derived SWF editor.
*
* Part of PropertyGrid - A Gtk# widget that displays and allows
* editing of all of an object's public properties
*
* Authors:
* Michael Hutchinson <m.j.hutchinson@gmail.com>
*
* Copyright (C) 2005 Michael Hutchinson
*
* This sourcecode is licenced under The MIT License:
*
* Permission is hereby granted, free of charge, to any person obtaining
* a copy of this software and associated documentation files (the
* "Software"), to deal in the Software without restriction, including
* without limitation the rights to use, copy, modify, merge, publish,
* distribute, sublicense, and/or sell copies of the Software, and to permit
* persons to whom the Software is furnished to do so, subject to the
* following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
* OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN
* NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM,
* DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
* OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE
* USE OR OTHER DEALINGS IN THE SOFTWARE.
*/
using System;
namespace AspNetEdit.UI
{
[AttributeUsage (AttributeTargets.Class, AllowMultiple = true)]
public class SurrogateUITypeEditorAttribute : Attribute
{
public Type Type;
public SurrogateUITypeEditorAttribute (Type myType)
{
this.Type = myType;
}
}
/* TODO: Surrogates for...
*
* System.Drawing.Design.FontEditor
* System.Drawing.Design.ImageEditor
* System.Web.UI.Design.DataBindingCollectionEditor
* System.Web.UI.Design.UrlEditor
* System.Web.UI.Design.WebControls.DataGridColumnCollectionEditor
* System.Web.UI.Design.WebControls.RegexTypeEditor
* System.Web.UI.Design.XmlFileEditor
* System.Web.UI.Design.TreeNodeCollectionEditor *STUPID: isn't based on CollectionEditor*
*/
}

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

@ -0,0 +1,21 @@
//
// AssemblyInfo.cs.in for propertyeditor.dll in aspnetedit
//
// Authors:
// Michael Hutchinson <m.j.hutchinson@gmail.com>
//
using System.Reflection;
using System.Runtime.CompilerServices;
[assembly: AssemblyTitle ("AspNetEdit PropertyGrid")]
[assembly: AssemblyDescription ("PropertyGrid library for AspNetEdit Graphical ASP.NET Editor ")]
[assembly: AssemblyCompany("")]
[assembly: AssemblyProduct("AspNetEdit")]
[assembly: AssemblyCopyright ("Copyright © 2005 Michael Hutchinson")]
[assembly: AssemblyTrademark("")]
[assembly: AssemblyCulture("")]
[assembly: AssemblyConfiguration("")]
[assembly: AssemblyVersion("@VERSION@")]
[assembly: AssemblyFileVersion("@VERSION@")]

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

@ -0,0 +1,42 @@
ASSEMBLY_NAME = propertygrid
ASSEMBLY = $(top_builddir)/build/lib/$(ASSEMBLY_NAME).dll
TARGET = $(ASSEMBLY)
propertygriddir=$(pkglibdir)
propertygrid_SCRIPTS = $(ASSEMBLY)
propertygrid_DATA = $(ASSEMBLY).mdb
PROPERTYGRID_REFERENCES = \
$(GTKSHARP_LIBS) \
-r:System.Web \
-r:System.Design \
-r:System.Drawing
PROPERTYGRID_CSFILES = \
$(srcdir)/AssemblyInfo.cs \
$(srcdir)/AspNetEdit.UI/EditorManager.cs \
$(srcdir)/AspNetEdit.UI/GridRow.cs \
$(srcdir)/AspNetEdit.UI/PropertyEditorTypeAttribute.cs \
$(srcdir)/AspNetEdit.UI/PropertyGrid.cs \
$(srcdir)/AspNetEdit.UI/PropertyValueChangedEventArgs.cs \
$(srcdir)/AspNetEdit.UI/PropertyValueChangedEventHandler.cs \
$(srcdir)/AspNetEdit.UI/SurrogateUITypeEditorAttribute.cs \
$(srcdir)/AspNetEdit.UI.Editors/StringEditor.cs \
$(srcdir)/AspNetEdit.UI.Editors/NumberEditor.cs \
$(srcdir)/AspNetEdit.UI.Editors/EnumEditor.cs \
$(srcdir)/AspNetEdit.UI.Editors/DefaultEditor.cs \
$(srcdir)/AspNetEdit.UI.Editors/ColorEditor.cs \
$(srcdir)/AspNetEdit.UI.Editors/CollectionEditor.cs \
$(srcdir)/AspNetEdit.UI.Editors/BoolEditor.cs \
$(srcdir)/AspNetEdit.UI.Editors/BaseEditor.cs
EXTRA_DIST = $(PROPERTYGRID_CSFILES)
CLEANFILES = $(ASSEMBLY) $(ASSEMBLY).mdb
$(ASSEMBLY): $(PROPERTYGRID_CSFILES)
$(MCS) $(PROPERTYGRID_REFERENCES) -debug -target:library -out:$@ $(PROPERTYGRID_CSFILES)
$(ASSEMBLY).mdb: $(ASSEMBLY)
all: $(ASSEMBLY)

54
svnci Executable file
Просмотреть файл

@ -0,0 +1,54 @@
#! /bin/bash
FILES=$@
echo "Creating commit message..."
MSG=`mktemp`
svn di $FILES | filterdiff -i'*ChangeLog' |
sed -e '/^[^+]/d' -e 's,^[+],,' -e '/^[^+]/b' -e 's,^[+][+],In,' -e 's,/ChangeLog.*$,:,' -e 's,ChangeLog.*$,.:,' >> $MSG
case `grep '^In' $MSG | wc -l` in
1) (echo 1d; echo w; echo q) | ed - $MSG ;;
*) ;;
esac
cat $MSG
echo About to commit
svn st $FILES
while [[ 1 ]]
do
read -a RESPONSE -p"Would you like to continue (Y)es/(N)o/(E)dit Message: "
if [[ $? != 0 ]]
then
RESPONSE="N"
fi
case $RESPONSE in
"Y" | "y" | "yes" | "Yes")
echo "Comitting..."
svn ci -F $MSG $FILES
rm $MSG
exit 0
;;
"N" | "n" | "no" | "No")
echo "Aborting..."
rm $MSG
exit 1
;;
"E" | "e" | "ed" | "Ed" | "Edit" | "edit")
vi $MSG
# try again
;;
*)
# try again
;;
esac
done