Initial commit
svn path=/trunk/aspeditor/; revision=48204
This commit is contained in:
Родитель
13863abad8
Коммит
854c5c755e
|
@ -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.
|
||||
|
||||
|
||||
|
|
@ -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,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
|
|
@ -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
|
|
@ -0,0 +1 @@
|
|||
|
|
@ -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.
|
Разница между файлами не показана из-за своего большого размера
Загрузить разницу
|
@ -0,0 +1,4 @@
|
|||
automake -a
|
||||
aclocal
|
||||
autoconf
|
||||
./configure $*
|
|
@ -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 ""
|
|
@ -0,0 +1,2 @@
|
|||
#!/bin/sh
|
||||
exec @MONO@ --debug @prefix@/lib/aspnetedit/aspnetedit.exe $MONO_EXTRA_ARGS "$@"
|
|
@ -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@")]
|
|
@ -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@")]
|
|
@ -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
|
|
@ -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\"><null></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\"><" + parentRow.PropertyDescriptor.PropertyType.ToString() + "></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)
|
||||
|
|
@ -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
|
Загрузка…
Ссылка в новой задаче