2006-02-24 Lluis Sanchez Gual <lluis@novell.com>

* libsteticui/Glade.cs: Use the new api for reading/writing.
	* libsteticui/Palette.cs: Update the palette when the
	  registry changes.
	* libsteticui/ProjectView.cs: Update the project tree when
	  the project has been reloaded (due for example to a
	  registry change).
	* libsteticui/Makefile.am: Updated.
	* libsteticui/Project.cs: Make it aware of changes in the
	  registry. When the registry changes, reload the project.
	  Added Read/Write and Load/Save methods, based on the
	  native format. Added ProjectReloaded event, which is fired
	  after the project has been reloaded due to a registry change.
	  Other minor changes.
	* libsteticui/SignalsEditor.cs: Refresh when the project is
	  reloaded. Addded SignalActivated, which is fired when double-
	  clicking an event.
	* libsteticui/ContextMenu.cs: Get class descriptors from wrappers,
	  instead of looking up in the registry. Track some other api
	  changes.
	* libsteticui/PropertyGrid.cs: Refresh when the project is
	  reloaded. Track some api changes.
	  
	* libstetic/ParamSpec.cs: Commented out some methods and
	  properties which depend on P/Invoke calls.
	* libstetic/ItemGroup.cs: Delegate item creation to the
	  owner class.
	* libstetic/wrapper/Button.cs:
	* libstetic/wrapper/Container.cs: Replaced glade export/import 
	  methods by Read/Write methods. Implemented code generation.
	* libstetic/wrapper/Widget.cs: Select the widget when it gets
	  the focus. Changed InternalChildId by InternalChildProperty,
	  which has more useful information. Made Visible a wrapper
	  property for all widgets. Replaced glade export/import 
	  methods by Read/Write methods. Implemented code generation.
	* libstetic/wrapper/Window.cs: Implemented code generation.
	* libstetic/wrapper/ComboBox.cs: Removed unneeded override.
	* libstetic/wrapper/objects.xml: Added some init-properties
	  and wrapper attributes. 
	* libstetic/wrapper/Table.cs: Fixed bug when setting column
	  count.
	* libstetic/wrapper/Dialog.cs: Track api changes. Don't throw
	  the buttons changed event while reading from xml.
	
	* libstetic/wrapper/RadioMenuItem.cs:
	* libstetic/wrapper/ImageMenuItem.cs:
	* libstetic/wrapper/Notebook.cs:
	* libstetic/wrapper/MenuItem.cs:
	* libstetic/wrapper/ButtonBox.cs:
	* libstetic/wrapper/Box.cs:
	* libstetic/wrapper/Expander.cs:
	* libstetic/wrapper/CheckButton.cs:
	* libstetic/wrapper/ToolButton.cs:
	* libstetic/wrapper/Frame.cs:
	* libstetic/wrapper/RadioButton.cs:
	* libstetic/wrapper/OptionMenu.cs:
	* libstetic/editor/ResponseId.cs:
	* libstetic/editor/Enumeration.cs:
	* libstetic/editor/GroupPicker.cs:
	* libstetic/editor/Flags.cs:
	* libstetic/ItemDescriptor.cs:
	* libstetic/wrapper/RadioToolButton.cs: Track api changes.
	
	* libstetic/SignalDescriptor.cs: Moved all code that depends
	  on Type and Reflection to TypedSignalDescriptor. Added
	  ParameterDescriptor, which replaces ParameterInfo.
	* libstetic/CommandDescriptor.cs: Made several changes to avoid
	  ClassDescriptor.WrapperType, which has been removed. Instead
	  of getting the method to call from the wrapped type, it gets
	  it from the type of the object when the command is invoked.
	* libstetic/editor/Char.cs: Fix worng type check.
	* libstetic/editor/Accelerator.cs: Removed glue P/Invokes.
	* libstetic/Placeholder.cs: Looks loke GdkWindow.SetBackPixmap
	  doesn't work very well. Draw filled rectangle instead.
	* libstetic/HandleWindow.cs:  If the window is embedded in a
	  preview box, use the gdk window of that box, which has more room
	  for drawing the handles.
	* libstetic/PropertyDescriptor.cs: Moved all code that depends
	  on Type and Reflection to TypedPropertyDescriptor. 
	  Added StringToValue and ValueToString methods for parsing and
	  converting values to string.
	
	* libstetic/GladeUtils.cs: Track api changes. Removed dependencies
	  to some ParamSpec properties that have been removed. The most
	  complex one to remove is the type of the glade property. Now it
	  is taken from the type of the corresponding class property.
	* libstetic/EnumDescriptor.cs: Use the registry to lookup the type
	  of the enum. The registry will look in all available libraries.
	* libstetic/ClassDescriptor.cs: Moved all code that depends
	  on Type and Reflection to TypedClassDescriptor.
	* libstetic/Makefile.am: Updated.
	* libstetic/ObjectWrapper.cs: Replaced glade export/import 
	  methods by Read/Write methods with support for native format.
	  Added ClassDescriptor property. There is no need to lookup
	  for classes in the registry since it can be accessed most of
	  the time from wrappers.
	* libstetic/Registry.cs: Added support for external widget
	  libraries.
	
	* ErrorWidget.cs:
	* EmbedWindow.cs:
	* Shadow.cs:
	* TypedClassDescriptor.cs:
	* TypedPropertyDescriptor.cs:
	* TypedSignalDescriptor.cs:
	* WidgetLibrary.cs:
	* Metacity/*:
	* wrapper/Entry.cs:
	* WidgetUtils.cs:
	* GeneratorContext.cs:
	* PreviewBox.cs:
	* AssemblyWidgetLibrary.cs:
	* WidgetLibrary.cs: New files.
	
	* Makefile.am:
	* configure.in: Removed glue directory from the build.
	
	* stetic/Stetic.cs: Added support for code generation from
	the command line.
	* stetic/stetic.in: Added debug option.
	* stetic/Makefile.am: Updated.
	* stetic/Glade.cs: Moved to libsteticui.
	* stetic/UIManager.cs: Added Load and Save commands.


svn path=/trunk/stetic/; revision=57239
This commit is contained in:
Lluis Sanchez 2006-02-24 16:59:47 +00:00
Родитель 15a5765eca af7029802b
Коммит d3d1029669
76 изменённых файлов: 3594 добавлений и 767 удалений

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

@ -1,3 +1,128 @@
2006-02-24 Lluis Sanchez Gual <lluis@novell.com>
* libsteticui/Glade.cs: Use the new api for reading/writing.
* libsteticui/Palette.cs: Update the palette when the
registry changes.
* libsteticui/ProjectView.cs: Update the project tree when
the project has been reloaded (due for example to a
registry change).
* libsteticui/Makefile.am: Updated.
* libsteticui/Project.cs: Make it aware of changes in the
registry. When the registry changes, reload the project.
Added Read/Write and Load/Save methods, based on the
native format. Added ProjectReloaded event, which is fired
after the project has been reloaded due to a registry change.
Other minor changes.
* libsteticui/SignalsEditor.cs: Refresh when the project is
reloaded. Addded SignalActivated, which is fired when double-
clicking an event.
* libsteticui/ContextMenu.cs: Get class descriptors from wrappers,
instead of looking up in the registry. Track some other api
changes.
* libsteticui/PropertyGrid.cs: Refresh when the project is
reloaded. Track some api changes.
* libstetic/ParamSpec.cs: Commented out some methods and
properties which depend on P/Invoke calls.
* libstetic/ItemGroup.cs: Delegate item creation to the
owner class.
* libstetic/wrapper/Button.cs:
* libstetic/wrapper/Container.cs: Replaced glade export/import
methods by Read/Write methods. Implemented code generation.
* libstetic/wrapper/Widget.cs: Select the widget when it gets
the focus. Changed InternalChildId by InternalChildProperty,
which has more useful information. Made Visible a wrapper
property for all widgets. Replaced glade export/import
methods by Read/Write methods. Implemented code generation.
* libstetic/wrapper/Window.cs: Implemented code generation.
* libstetic/wrapper/ComboBox.cs: Removed unneeded override.
* libstetic/wrapper/objects.xml: Added some init-properties
and wrapper attributes.
* libstetic/wrapper/Table.cs: Fixed bug when setting column
count.
* libstetic/wrapper/Dialog.cs: Track api changes. Don't throw
the buttons changed event while reading from xml.
* libstetic/wrapper/RadioMenuItem.cs:
* libstetic/wrapper/ImageMenuItem.cs:
* libstetic/wrapper/Notebook.cs:
* libstetic/wrapper/MenuItem.cs:
* libstetic/wrapper/ButtonBox.cs:
* libstetic/wrapper/Box.cs:
* libstetic/wrapper/Expander.cs:
* libstetic/wrapper/CheckButton.cs:
* libstetic/wrapper/ToolButton.cs:
* libstetic/wrapper/Frame.cs:
* libstetic/wrapper/RadioButton.cs:
* libstetic/wrapper/OptionMenu.cs:
* libstetic/editor/ResponseId.cs:
* libstetic/editor/Enumeration.cs:
* libstetic/editor/GroupPicker.cs:
* libstetic/editor/Flags.cs:
* libstetic/ItemDescriptor.cs:
* libstetic/wrapper/RadioToolButton.cs: Track api changes.
* libstetic/SignalDescriptor.cs: Moved all code that depends
on Type and Reflection to TypedSignalDescriptor. Added
ParameterDescriptor, which replaces ParameterInfo.
* libstetic/CommandDescriptor.cs: Made several changes to avoid
ClassDescriptor.WrapperType, which has been removed. Instead
of getting the method to call from the wrapped type, it gets
it from the type of the object when the command is invoked.
* libstetic/editor/Char.cs: Fix worng type check.
* libstetic/editor/Accelerator.cs: Removed glue P/Invokes.
* libstetic/Placeholder.cs: Looks loke GdkWindow.SetBackPixmap
doesn't work very well. Draw filled rectangle instead.
* libstetic/HandleWindow.cs: If the window is embedded in a
preview box, use the gdk window of that box, which has more room
for drawing the handles.
* libstetic/PropertyDescriptor.cs: Moved all code that depends
on Type and Reflection to TypedPropertyDescriptor.
Added StringToValue and ValueToString methods for parsing and
converting values to string.
* libstetic/GladeUtils.cs: Track api changes. Removed dependencies
to some ParamSpec properties that have been removed. The most
complex one to remove is the type of the glade property. Now it
is taken from the type of the corresponding class property.
* libstetic/EnumDescriptor.cs: Use the registry to lookup the type
of the enum. The registry will look in all available libraries.
* libstetic/ClassDescriptor.cs: Moved all code that depends
on Type and Reflection to TypedClassDescriptor.
* libstetic/Makefile.am: Updated.
* libstetic/ObjectWrapper.cs: Replaced glade export/import
methods by Read/Write methods with support for native format.
Added ClassDescriptor property. There is no need to lookup
for classes in the registry since it can be accessed most of
the time from wrappers.
* libstetic/Registry.cs: Added support for external widget
libraries.
* ErrorWidget.cs:
* EmbedWindow.cs:
* Shadow.cs:
* TypedClassDescriptor.cs:
* TypedPropertyDescriptor.cs:
* TypedSignalDescriptor.cs:
* WidgetLibrary.cs:
* Metacity/*:
* wrapper/Entry.cs:
* WidgetUtils.cs:
* GeneratorContext.cs:
* PreviewBox.cs:
* AssemblyWidgetLibrary.cs:
* WidgetLibrary.cs: New files.
* Makefile.am:
* configure.in: Removed glue directory from the build.
* stetic/Stetic.cs: Added support for code generation from
the command line.
* stetic/stetic.in: Added debug option.
* stetic/Makefile.am: Updated.
* stetic/Glade.cs: Moved to libsteticui.
* stetic/UIManager.cs: Added Load and Save commands.
2006-02-09 Lluis Sanchez Gual <lluis@novell.com>
* stetic.pc.in: Add a reference to the new libsteticui dll.

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

@ -1,4 +1,4 @@
SUBDIRS = glue libstetic libsteticui stetic
SUBDIRS = libstetic libsteticui stetic
pkgconfigdir = $(prefix)/lib/pkgconfig
pkgconfig_DATA = stetic.pc

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

@ -33,7 +33,6 @@ AC_SUBST(STETIC_LIBS)
AC_OUTPUT([
Makefile
glue/Makefile
libstetic/Makefile
libsteticui/Makefile
stetic/Makefile

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

@ -0,0 +1,54 @@
using System;
using System.Reflection;
using System.Xml;
namespace Stetic
{
public class AssemblyWidgetLibrary: WidgetLibrary
{
Assembly assembly;
public AssemblyWidgetLibrary (Assembly assembly)
{
this.assembly = assembly;
}
public AssemblyWidgetLibrary (string assemblyPath)
{
assembly = Assembly.LoadFrom (assemblyPath);
}
public override void Load ()
{
System.IO.Stream stream = assembly.GetManifestResourceStream ("objects.xml");
if (stream == null)
throw new InvalidOperationException ("objects.xml file not found in assembly: " + assembly.Location);
XmlDocument objects = new XmlDocument ();
objects.Load (stream);
stream.Close ();
Load (objects);
}
protected override ClassDescriptor LoadClassDescriptor (XmlElement element)
{
return new TypedClassDescriptor (assembly, element);
}
public override Type GetType (string typeName)
{
Type t = assembly.GetType (typeName, false);
if (t != null) return t;
// Look in referenced assemblies
foreach (AssemblyName an in assembly.GetReferencedAssemblies ()) {
Assembly a = Assembly.Load (an);
t = a.GetType (typeName);
if (t != null) return t;
}
return null;
}
}
}

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

@ -5,59 +5,38 @@ using System.Runtime.InteropServices;
using System.Xml;
namespace Stetic {
public class ClassDescriptor {
Type wrapped, wrapper;
GLib.GType gtype;
public abstract class ClassDescriptor
{
protected string label, category, cname;
protected bool deprecated, hexpandable, vexpandable, allowChildren = true;
protected ItemGroupCollection groups = new ItemGroupCollection ();
protected ItemGroupCollection signals = new ItemGroupCollection ();
MethodInfo ctorMethodInfo;
ConstructorInfo cinfo;
bool useGTypeCtor;
protected int importantGroups;
protected ItemGroup contextMenu;
protected ItemGroup internalChildren;
PropertyDescriptor[] initializationProperties;
string label, category, cname;
Gdk.Pixbuf icon;
bool deprecated, hexpandable, vexpandable;
ItemGroupCollection groups = new ItemGroupCollection ();
ItemGroupCollection signals = new ItemGroupCollection ();
int importantGroups;
ItemGroup contextMenu;
ItemGroup internalChildren;
public ClassDescriptor (Assembly assembly, XmlElement elem)
protected void Load (XmlElement elem)
{
wrapped = Type.GetType (elem.GetAttribute ("type"), true);
if (elem.HasAttribute ("wrapper"))
wrapper = Type.GetType (elem.GetAttribute ("wrapper"), true);
else {
for (Type type = wrapped.BaseType; type != null; type = type.BaseType) {
ClassDescriptor parent = Registry.LookupClass (type);
if (parent != null) {
wrapper = parent.WrapperType;
break;
}
}
if (wrapper == null)
throw new ArgumentException ("No wrapper type for class {0}", wrapped.FullName);
}
gtype = (GLib.GType)wrapped;
if (elem.HasAttribute ("cname"))
cname = elem.GetAttribute ("cname");
else
cname = gtype.ToString ();
else if (cname == null)
cname = elem.GetAttribute ("type");
label = elem.GetAttribute ("label");
if (label == "")
label = WrappedTypeName;
if (elem.HasAttribute ("allow-children"))
allowChildren = elem.GetAttribute ("allow-children") == "yes";
category = elem.GetAttribute ("palette-category");
string iconname = elem.GetAttribute ("icon");
try {
icon = new Gdk.Pixbuf (assembly, iconname);
} catch {
icon = Gtk.IconTheme.Default.LoadIcon (Gtk.Stock.MissingImage, 16, 0);
}
if (elem.HasAttribute ("deprecated"))
deprecated = true;
if (elem.HasAttribute ("hexpandable"))
@ -65,17 +44,6 @@ namespace Stetic {
if (elem.HasAttribute ("vexpandable"))
vexpandable = true;
ctorMethodInfo = wrapper.GetMethod ("CreateInstance",
BindingFlags.Static | BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.DeclaredOnly,
null, new Type[0], null);
if (ctorMethodInfo == null) {
cinfo = wrapped.GetConstructor (new Type[0]);
if (cinfo == null) {
useGTypeCtor = true;
cinfo = wrapped.GetConstructor (new Type[] { typeof (IntPtr) });
}
}
XmlElement groupsElem = elem["itemgroups"];
if (groupsElem != null) {
foreach (XmlElement groupElem in groupsElem.SelectNodes ("itemgroup")) {
@ -124,24 +92,29 @@ namespace Stetic {
internalChildren = new ItemGroup (ichildElem, this);
else
internalChildren = ItemGroup.Empty;
}
public Type WrappedType {
string initProps = elem.GetAttribute ("init-properties");
if (initProps.Length > 0) {
string[] props = initProps.Split (' ');
ArrayList list = new ArrayList ();
foreach (string prop in props) {
PropertyDescriptor idesc = this [prop] as PropertyDescriptor;
if (idesc == null)
throw new InvalidOperationException ("Initialization property not found: " + prop);
list.Add (idesc);
}
initializationProperties = (PropertyDescriptor[]) list.ToArray (typeof(PropertyDescriptor));
}
}
public virtual string Name {
get {
return wrapped;
return WrappedTypeName;
}
}
public Type WrapperType {
get {
return wrapper;
}
}
public GLib.GType GType {
get {
return gtype;
}
public abstract string WrappedTypeName {
get;
}
public string CName {
@ -174,10 +147,8 @@ namespace Stetic {
}
}
public Gdk.Pixbuf Icon {
get {
return icon;
}
public abstract Gdk.Pixbuf Icon {
get;
}
public string Category {
@ -185,37 +156,22 @@ namespace Stetic {
return category;
}
}
[DllImport("libgobject-2.0-0.dll")]
static extern IntPtr g_object_new (IntPtr gtype, IntPtr dummy);
int counter;
public PropertyDescriptor[] InitializationProperties {
get { return initializationProperties; }
}
public object NewInstance (IProject proj)
{
object inst;
if (ctorMethodInfo != null)
inst = ctorMethodInfo.Invoke (null, new object[0]);
else if (!useGTypeCtor)
inst = cinfo.Invoke (null, new object[0]);
else {
IntPtr raw = g_object_new (gtype.Val, IntPtr.Zero);
inst = cinfo.Invoke (new object[] { raw });
}
string name = wrapped.Name.ToLower () + (++counter).ToString ();
foreach (ItemGroup group in groups) {
foreach (ItemDescriptor item in group) {
PropertyDescriptor prop = item as PropertyDescriptor;
if (prop != null && prop.InitWithName)
prop.SetValue (inst, name);
}
}
ObjectWrapper.Create (proj, inst, false);
return inst;
object ob = CreateInstance (proj);
ObjectWrapper ow = CreateWrapper ();
ObjectWrapper.Bind (proj, this, ow, ob, false);
return ob;
}
public abstract object CreateInstance (IProject proj);
public abstract ObjectWrapper CreateWrapper ();
public ItemDescriptor this[string name] {
get {
@ -260,5 +216,17 @@ namespace Stetic {
return internalChildren;
}
}
public virtual bool AllowChildren {
get { return allowChildren; }
}
internal protected virtual ItemDescriptor CreateItemDescriptor (XmlElement elem, ItemGroup group)
{
if (elem.Name == "command")
return new CommandDescriptor (elem, group, this);
else
throw new ApplicationException ("Bad item name " + elem.Name + " in " + WrappedTypeName);
}
}
}

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

@ -7,9 +7,7 @@ namespace Stetic {
public class CommandDescriptor : ItemDescriptor {
string name, label, description;
bool needsContext;
MethodInfo checkInfo, doInfo;
string name, checkName, label, description;
const BindingFlags flags = BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.Instance;
@ -18,20 +16,7 @@ namespace Stetic {
name = elem.GetAttribute ("name");
label = elem.GetAttribute ("label");
description = elem.GetAttribute ("description");
doInfo = klass.WrapperType.GetMethod (name, flags, null, new Type[] { typeof (Gtk.Widget) }, null);
if (doInfo != null)
needsContext = true;
else
doInfo = klass.WrapperType.GetMethod (name, flags, null, new Type[0], null);
if (doInfo == null)
throw new ArgumentException ("Invalid command name " + klass.WrapperType.Name + "." + name);
if (elem.GetAttribute ("check") != "") {
checkInfo = klass.WrapperType.GetMethod (elem.GetAttribute ("check"), flags, null, needsContext ? new Type[] { typeof (Gtk.Widget) } : new Type[0], null);
if (checkInfo == null)
throw new ArgumentException ("Invalid checker name " + elem.GetAttribute ("check") + " for command " + klass.WrapperType.Name + "." + name);
}
checkName = elem.GetAttribute ("check");
}
public override string Name {
@ -52,44 +37,47 @@ namespace Stetic {
}
}
public bool NeedsContext {
get {
return needsContext;
}
}
public bool Enabled (object obj)
{
if (checkInfo == null)
if (checkName == "")
return EnabledFor (obj);
else
return (bool)checkInfo.Invoke (ObjectWrapper.Lookup (obj), new object[0]);
return (bool) InvokeMethod (ObjectWrapper.Lookup (obj), checkName, null, false);
}
public bool Enabled (object obj, Gtk.Widget context)
{
if (checkInfo == null)
if (checkName == "")
return EnabledFor (obj);
ObjectWrapper wrapper = ObjectWrapper.Lookup (obj);
if (needsContext)
return (bool)checkInfo.Invoke (wrapper, new object[] { context });
else
return (bool)checkInfo.Invoke (wrapper, new object[0]);
return (bool) InvokeMethod (wrapper, checkName, context, true);
}
public void Run (object obj)
{
doInfo.Invoke (ObjectWrapper.Lookup (obj), new object[0]);
InvokeMethod (ObjectWrapper.Lookup (obj), name, null, false);
}
public void Run (object obj, Gtk.Widget context)
{
ObjectWrapper wrapper = ObjectWrapper.Lookup (obj);
if (needsContext)
doInfo.Invoke (wrapper, new object[] { context });
else
doInfo.Invoke (wrapper, new object[0]);
InvokeMethod (wrapper, name, context, true);
}
object InvokeMethod (object target, string name, object context, bool withContext)
{
if (withContext) {
MethodInfo metc = target.GetType().GetMethod (name, flags, null, new Type[] {typeof(Gtk.Widget)}, null);
if (metc != null)
return metc.Invoke (target, new object[] { context });
}
MethodInfo met = target.GetType().GetMethod (name, flags, null, Type.EmptyTypes, null);
if (met != null)
return met.Invoke (target, new object[0]);
throw new ArgumentException ("Invalid command or checker name. Method '" + name +"' not found in class '" + target.GetType() + "'");
}
}
}

106
libstetic/EmbedWindow.cs Normal file
Просмотреть файл

@ -0,0 +1,106 @@
using Gtk;
using System;
using System.Collections;
namespace Stetic {
public class EmbedWindow {
public static PreviewBox Wrap (Gtk.Container container, int designWidth, int designHeight)
{
Window window = container as Gtk.Window;
if (window != null) {
if (window.IsRealized)
throw new ApplicationException ("Cannot make a realized window embeddable");
window.WidgetFlags &= ~(WidgetFlags.Toplevel);
window.SizeAllocated += new SizeAllocatedHandler (OnSizeAllocated);
window.Realized += new EventHandler (OnRealized);
PreviewBox prev = new PreviewBox (container, designWidth, designHeight);
prev.Title = window.Title;
prev.Theme = Theme;
return prev;
} else
return new PreviewBox (container, designWidth, designHeight);
}
static private void OnSizeAllocated (object obj, SizeAllocatedArgs args)
{
Window window = obj as Window;
if (obj == null) return;
Gdk.Rectangle allocation = args.Allocation;
if (window.IsRealized) {
window.GdkWindow.MoveResize (allocation.X,
allocation.Y,
allocation.Width,
allocation.Height);
}
}
static private void OnRealized (object obj, EventArgs args)
{
Window window = obj as Window;
if (obj == null) return;
window.WidgetFlags |= WidgetFlags.Realized;
Gdk.WindowAttr attrs = new Gdk.WindowAttr ();
attrs.Mask = window.Events |
(Gdk.EventMask.ExposureMask |
Gdk.EventMask.KeyPressMask |
Gdk.EventMask.KeyReleaseMask |
Gdk.EventMask.EnterNotifyMask |
Gdk.EventMask.LeaveNotifyMask |
Gdk.EventMask.StructureMask);
attrs.X = window.Allocation.X;
attrs.Y = window.Allocation.Y;
attrs.Width = window.Allocation.Width;
attrs.Height = window.Allocation.Height;
attrs.Wclass = Gdk.WindowClass.InputOutput;
attrs.Visual = window.Visual;
attrs.Colormap = window.Colormap;
attrs.WindowType = Gdk.WindowType.Child;
Gdk.WindowAttributesType mask =
Gdk.WindowAttributesType.X |
Gdk.WindowAttributesType.Y |
Gdk.WindowAttributesType.Colormap |
Gdk.WindowAttributesType.Visual;
window.GdkWindow = new Gdk.Window (window.ParentWindow, attrs, mask);
window.GdkWindow.UserData = window.Handle;
window.Style = window.Style.Attach (window.GdkWindow);
window.Style.SetBackground (window.GdkWindow, StateType.Normal);
// FIXME: gtk-sharp 2.6
// window.GdkWindow.EnableSynchronizedConfigure ();
}
static Metacity.Theme theme;
static Metacity.Theme Theme {
get {
if (theme == null) {
GConf.Client client = new GConf.Client ();
// client.AddNotify ("/apps/metacity/general", GConfNotify);
string themeName = (string)client.Get ("/apps/metacity/general/theme");
theme = Metacity.Theme.Load (themeName);
}
return theme;
}
}
/* static void GConfNotify (object obj, GConf.NotifyEventArgs args)
{
if (args.Key == "/apps/metacity/general/theme") {
theme = Metacity.Theme.Load ((string)args.Value);
foreach (Metacity.Preview prev in wrappers.Values)
prev.Theme = Theme;
}
}
*/ }
}

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

@ -22,10 +22,14 @@ namespace Stetic {
Type enumType;
Hashtable values;
Enum[] values_array;
string name;
public EnumDescriptor (XmlElement elem)
{
enumType = Type.GetType (elem.GetAttribute ("type"), true);
string cls = elem.GetAttribute ("type");
enumType = Registry.GetType (cls, true);
this.name = enumType.FullName;
values = new Hashtable ();
Array enumvalues = Enum.GetValues (enumType);
@ -50,6 +54,10 @@ namespace Stetic {
if (values.Count != evalues.Count)
throw new ArgumentException ("<enum> node for " + enumType.FullName + " is missing some values");
}
public string Name {
get { return name; }
}
public Type EnumType {
get {

54
libstetic/ErrorWidget.cs Normal file
Просмотреть файл

@ -0,0 +1,54 @@
using System;
using System.Xml;
using System.CodeDom;
namespace Stetic
{
// This widget is shown in place of widgets with unknown classes.
public class ErrorWidget: Gtk.Frame
{
readonly string className;
public ErrorWidget (string className)
{
this.className = className;
Gtk.Label lab = new Gtk.Label ();
lab.Markup = "<b><span foreground='red'>Unknown widget: " + className + "</span></b>";
this.CanFocus = false;
Add (lab);
this.ShadowType = Gtk.ShadowType.In;
ShowAll ();
}
public string ClassName {
get { return className; }
}
}
internal class ErrorWidgetWrapper: Wrapper.Widget
{
XmlElement elementData;
FileFormat format;
public override void Read (XmlElement elem, FileFormat format)
{
elementData = elem;
this.format = format;
}
public override XmlElement Write (XmlDocument doc, FileFormat format)
{
if (format != this.format)
throw new InvalidOperationException ("Can't export incomplete widget information");
return (XmlElement) doc.ImportNode (elementData, true);
}
internal protected override void GenerateBuildCode (GeneratorContext ctx, string varName, CodeStatementCollection statements)
{
ErrorWidget ew = (ErrorWidget) Wrapped;
throw new InvalidOperationException ("Can't generate code for unknown type: " + ew.ClassName);
}
}
}

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

@ -0,0 +1,116 @@
using System;
using System.CodeDom;
using System.Collections;
namespace Stetic
{
public class GeneratorContext
{
int n;
string idPrefix;
Hashtable vars = new Hashtable ();
Hashtable widgets = new Hashtable ();
WidgetMap map;
public GeneratorContext (string idPrefix)
{
this.idPrefix = idPrefix;
map = new WidgetMap (vars, widgets);
}
public string NewId ()
{
return idPrefix + (++n);
}
public string GenerateCreationCode (Wrapper.Widget widget, CodeStatementCollection statements)
{
string varName = NewId ();
CodeVariableDeclarationStatement varDec = new CodeVariableDeclarationStatement (widget.Wrapped.GetType (), varName);
statements.Add (varDec);
varDec.InitExpression = widget.GenerateWidgetCreation (this, statements);
GenerateBuildCode (widget, varName, statements);
return varName;
}
public virtual void GenerateBuildCode (Wrapper.Widget widget, string varName, CodeStatementCollection statements)
{
vars [widget.Wrapped.Name] = varName;
widgets [varName] = widget.Wrapped;
widget.GenerateBuildCode (this, varName, statements);
}
public CodeExpression GenerateValue (object value)
{
if (value == null)
return new CodePrimitiveExpression (value);
if (value.GetType ().IsEnum) {
long ival = (long) Convert.ChangeType (value, typeof(long));
return new CodeCastExpression (
new CodeTypeReference (value.GetType ()),
new CodePrimitiveExpression (ival)
);
}
if (value is Gtk.Adjustment) {
Gtk.Adjustment adj = value as Gtk.Adjustment;
return new CodeObjectCreateExpression (
typeof(Gtk.Adjustment),
new CodePrimitiveExpression (adj.Value),
new CodePrimitiveExpression (adj.Lower),
new CodePrimitiveExpression (adj.Upper),
new CodePrimitiveExpression (adj.StepIncrement),
new CodePrimitiveExpression (adj.PageIncrement),
new CodePrimitiveExpression (adj.PageSize));
}
if (value is ushort || value is uint) {
return new CodeCastExpression (
new CodeTypeReference (value.GetType ()),
new CodePrimitiveExpression (Convert.ChangeType (value, typeof(long))));
}
if (value is ulong) {
return new CodeMethodInvokeExpression (
new CodeTypeReferenceExpression (value.GetType ()),
"Parse",
new CodePrimitiveExpression (value.ToString ()));
}
return new CodePrimitiveExpression (value);
}
public WidgetMap WidgetMap {
get { return map; }
}
public void Reset ()
{
vars.Clear ();
n = 0;
}
}
public class WidgetMap
{
Hashtable vars;
Hashtable widgets;
internal WidgetMap (Hashtable vars, Hashtable widgets)
{
this.vars = vars;
this.widgets = widgets;
}
public string GetWidgetId (string widgetName)
{
return (string) vars [widgetName];
}
public Gtk.Widget GetWidgetFromId (string widgetId)
{
return (Gtk.Widget) widgets [widgetId];
}
}
}

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

@ -1,4 +1,5 @@
using System;
using System.Reflection;
using System.Collections;
using System.Runtime.InteropServices;
using System.Xml;
@ -70,7 +71,7 @@ namespace Stetic {
Stetic.Wrapper.Container parent = wrapper.ParentWrapper;
if (parent == null) {
elem = wrapper.GladeExport (doc);
elem = wrapper.Write (doc, FileFormat.Glade);
if (elem == null)
return null;
if (!(widget is Gtk.Window)) {
@ -86,9 +87,9 @@ namespace Stetic {
elem = doc.CreateElement ("widget");
// Set the class correctly (temporarily) so the XSL
// transforms will work correctly.
ClassDescriptor klass = Registry.LookupClass (parent.Wrapped.GetType ());
ClassDescriptor klass = parent.ClassDescriptor;
elem.SetAttribute ("class", klass.CName);
elem.AppendChild (parent.GladeExportChild (wrapper, doc));
elem.AppendChild (parent.WriteContainerChild (wrapper, doc, FileFormat.Glade));
}
toplevel.AppendChild (elem);
@ -115,7 +116,7 @@ namespace Stetic {
elem.GetAttribute ("id") != "glade-dummy-container") {
// Creating a new toplevel
Stetic.Wrapper.Widget toplevel = (Stetic.Wrapper.Widget)
Stetic.ObjectWrapper.GladeImport (project, elem);
Stetic.ObjectWrapper.Read (project, elem, FileFormat.Glade);
if (toplevel != null) {
project.AddWindow ((Gtk.Window)toplevel.Wrapped);
}
@ -123,7 +124,7 @@ namespace Stetic {
}
return (Stetic.Wrapper.Widget)
Stetic.ObjectWrapper.GladeImport (project, (XmlElement)elem.SelectSingleNode ("child/widget"));
Stetic.ObjectWrapper.Read (project, (XmlElement)elem.SelectSingleNode ("child/widget"), FileFormat.Glade);
}
public static void Copy (Gtk.Widget widget, Gtk.SelectionData seldata, bool copyAsText)
@ -293,8 +294,12 @@ namespace Stetic {
IntPtr gtype;
if (propType != null)
gtype = ((GLib.GType)propType).Val;
/*
FIXME: ValueType is not supported right now
else if (pspec != null)
gtype = pspec.ValueType;
*/
else
throw new GladeException ("Bad type");
@ -306,16 +311,49 @@ namespace Stetic {
return ParseEnum (gtype, strval);
else if (typef == GLib.TypeFundamentals.TypeFlags)
return ParseFlags (gtype, strval);
else if (pspec != null && pspec.IsUnichar)
return ParseUnichar (strval);
// FIXME: Enable when ParamSpec.IsUnichar is implemented.
// else if (pspec != null && pspec.IsUnichar)
// return ParseUnichar (strval);
else
return ParseBasicType (typef, strval);
}
static PropertyInfo FindClrProperty (Type type, string name, bool childprop)
{
if (childprop) {
Type[] types = type.GetNestedTypes ();
foreach (Type t in types) {
if (typeof(Gtk.Container.ContainerChild).IsAssignableFrom (t)) {
type = t;
break;
}
}
foreach (PropertyInfo pi in type.GetProperties ()) {
Gtk.ChildPropertyAttribute at = (Gtk.ChildPropertyAttribute) Attribute.GetCustomAttribute (pi, typeof(Gtk.ChildPropertyAttribute), false);
if (at != null && at.Name == name)
return pi;
}
if (typeof(GLib.Object).IsAssignableFrom (type.BaseType))
return FindClrProperty (type.BaseType, name, true);
}
foreach (PropertyInfo pi in type.GetProperties ()) {
GLib.PropertyAttribute at = (GLib.PropertyAttribute) Attribute.GetCustomAttribute (pi, typeof(GLib.PropertyAttribute), false);
if (at != null && at.Name == name)
return pi;
}
return null;
}
static GLib.Value ParseProperty (Type type, bool childprop, string name, string strval)
{
ParamSpec pspec;
// FIXME: this can be removed when GParamSpec supports ValueType.
PropertyInfo pi = FindClrProperty (type, name, childprop);
if (pi == null)
throw new GladeException ("Unknown property", type.ToString (), childprop, name, strval);
if (childprop)
pspec = ParamSpec.LookupChildProperty (type, name);
else
@ -324,7 +362,7 @@ namespace Stetic {
throw new GladeException ("Unknown property", type.ToString (), childprop, name, strval);
try {
return ParseProperty (pspec, null, strval);
return ParseProperty (pspec, pi.PropertyType, strval);
} catch {
throw new GladeException ("Could not parse property", type.ToString (), childprop, name, strval);
}
@ -359,14 +397,14 @@ namespace Stetic {
propVals = (GLib.Value[])values.ToArray (typeof (GLib.Value));
}
static void ExtractProperties (ClassDescriptor klass, XmlElement elem,
static void ExtractProperties (TypedClassDescriptor klass, XmlElement elem,
out Hashtable rawProps, out Hashtable overrideProps)
{
rawProps = new Hashtable ();
overrideProps = new Hashtable ();
foreach (ItemGroup group in klass.ItemGroups) {
foreach (ItemDescriptor item in group) {
PropertyDescriptor prop = item as PropertyDescriptor;
TypedPropertyDescriptor prop = item as TypedPropertyDescriptor;
if (prop == null)
continue;
prop = prop.GladeProperty;
@ -385,13 +423,13 @@ namespace Stetic {
}
}
static void ReadSignals (ClassDescriptor klass, ObjectWrapper wrapper, XmlElement elem)
static void ReadSignals (TypedClassDescriptor klass, ObjectWrapper wrapper, XmlElement elem)
{
Stetic.Wrapper.Widget ob = wrapper as Stetic.Wrapper.Widget;
if (ob == null) return;
foreach (ItemGroup group in klass.SignalGroups) {
foreach (SignalDescriptor signal in group) {
foreach (TypedSignalDescriptor signal in group) {
if (signal.GladeName == null)
continue;
@ -412,10 +450,14 @@ namespace Stetic {
if (className == null)
throw new GladeException ("<widget> node with no class name");
ClassDescriptor klass = Registry.LookupClass (className);
if (klass == null)
ClassDescriptor klassBase = Registry.LookupClassByCName (className);
if (klassBase == null)
throw new GladeException ("No stetic ClassDescriptor for " + className);
TypedClassDescriptor klass = klassBase as TypedClassDescriptor;
if (klass == null)
throw new GladeException ("The widget class " + className + " is not supported by Glade");
ReadSignals (klass, wrapper, elem);
Hashtable rawProps, overrideProps;
@ -439,7 +481,7 @@ namespace Stetic {
gtk_object_sink (raw);
throw new GladeException ("Could not create gtk# wrapper", className);
}
wrapper.Wrap (widget, true);
ObjectWrapper.Bind (wrapper.Project, klass, wrapper, widget, true);
} else {
widget = (Gtk.Widget)wrapper.Wrapped;
for (int i = 0; i < propNames.Length; i++)
@ -455,7 +497,7 @@ namespace Stetic {
static void SetOverrideProperties (ObjectWrapper wrapper, Hashtable overrideProps)
{
foreach (PropertyDescriptor prop in overrideProps.Keys) {
foreach (TypedPropertyDescriptor prop in overrideProps.Keys) {
XmlElement prop_elem = overrideProps[prop] as XmlElement;
try {
@ -500,9 +542,9 @@ namespace Stetic {
Gtk.Container.ContainerChild cc = wrapper.Wrapped as Gtk.Container.ContainerChild;
ClassDescriptor klass = Registry.LookupClass (cc.GetType ());
TypedClassDescriptor klass = wrapper.ClassDescriptor as TypedClassDescriptor;
if (klass == null)
throw new GladeException ("No stetic ClassDescriptor for " + cc.GetType ().FullName);
throw new GladeException ("The widget class " + cc.GetType () + " is not supported by Glade");
Hashtable rawProps, overrideProps;
ExtractProperties (klass, packing, out rawProps, out overrideProps);
@ -520,7 +562,7 @@ namespace Stetic {
MarkTranslatables (cc, overrideProps);
}
static string PropToString (ObjectWrapper wrapper, PropertyDescriptor prop)
static string PropToString (ObjectWrapper wrapper, TypedPropertyDescriptor prop)
{
object value;
@ -530,7 +572,7 @@ namespace Stetic {
if (ccwrap != null) {
Gtk.Container.ContainerChild cc = (Gtk.Container.ContainerChild)ccwrap.Wrapped;
gval = new GLib.Value (new GLib.GType (prop.ParamSpec.ValueType));
gval = new GLib.Value ((GLib.GType) prop.PropertyType);
gtk_container_child_get_property (cc.Parent.Handle, cc.Child.Handle, prop.GladeName, ref gval);
} else {
Gtk.Widget widget = wrapper.Wrapped as Gtk.Widget;
@ -544,7 +586,7 @@ namespace Stetic {
return null;
// If the property has its default value, we don't need to write it
if (prop.HasDefault && value.Equals (prop.ParamSpec.Default))
if (prop.HasDefault && prop.ParamSpec.IsDefaultValue (value))
return null;
if (value is Gtk.Adjustment) {
@ -554,7 +596,7 @@ namespace Stetic {
adj.StepIncrement, adj.PageIncrement,
adj.PageSize);
} else if (value is Enum && prop.ParamSpec != null) {
IntPtr klass = g_type_class_ref (prop.ParamSpec.ValueType);
IntPtr klass = g_type_class_ref (((GLib.GType)prop.PropertyType).Val);
if (prop.PropertyType.IsDefined (typeof (FlagsAttribute), false)) {
System.Text.StringBuilder sb = new System.Text.StringBuilder ();
@ -593,11 +635,8 @@ namespace Stetic {
static public XmlElement ExportWidget (ObjectWrapper wrapper, XmlDocument doc)
{
Type wrappedType = wrapper.Wrapped.GetType ();
ClassDescriptor klass = Registry.LookupClass (wrappedType);
XmlElement elem = doc.CreateElement ("widget");
elem.SetAttribute ("class", klass.CName);
elem.SetAttribute ("class", wrapper.ClassDescriptor.CName);
elem.SetAttribute ("id", ((Gtk.Widget)wrapper.Wrapped).Name);
GetProps (wrapper, elem);
@ -607,11 +646,11 @@ namespace Stetic {
static public void GetProps (ObjectWrapper wrapper, XmlElement parent_elem)
{
ClassDescriptor klass = Registry.LookupClass (wrapper.Wrapped.GetType ());
ClassDescriptor klass = wrapper.ClassDescriptor;
foreach (ItemGroup group in klass.ItemGroups) {
foreach (ItemDescriptor item in group) {
PropertyDescriptor prop = item as PropertyDescriptor;
TypedPropertyDescriptor prop = item as TypedPropertyDescriptor;
if (prop == null)
continue;
prop = prop.GladeProperty;
@ -650,13 +689,13 @@ namespace Stetic {
if (ob == null) return;
foreach (Signal signal in ob.Signals) {
if (signal.SignalDescriptor.GladeName == null)
if (((TypedSignalDescriptor)signal.SignalDescriptor).GladeName == null)
continue;
if (!signal.SignalDescriptor.VisibleFor (wrapper.Wrapped))
continue;
XmlElement signal_elem = parent_elem.OwnerDocument.CreateElement ("signal");
signal_elem.SetAttribute ("name", signal.SignalDescriptor.GladeName);
signal_elem.SetAttribute ("name", ((TypedSignalDescriptor)signal.SignalDescriptor).GladeName);
signal_elem.SetAttribute ("handler", signal.Handler);
if (signal.After)
signal_elem.SetAttribute ("after", "yes");

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

@ -32,7 +32,18 @@ namespace Stetic {
topLevel = parent;
parent = topLevel.Parent;
}
// If the window is embedded in a preview box, use
// the gdk window of that box, which has more room
// for drawing the handles.
while (parent != null) {
if (parent.Parent is PreviewBox || parent.Parent is Gtk.EventBox)
break;
parent = parent.Parent;
}
if (parent != null)
topLevel = parent;
selection.SizeAllocated += SelectionResized;
invis = new Gtk.Invisible ();
@ -114,7 +125,7 @@ namespace Stetic {
gc.SetDashes (0, new sbyte[] {1,1}, 2);
gc.SetLineAttributes (borderSize, Gdk.LineStyle.OnOffDash, Gdk.CapStyle.NotLast, Gdk.JoinStyle.Miter);
pixmap.DrawRectangle (gc, false, handleSize / 2, handleSize / 2,
width - handleSize, height - handleSize);
width - handleSize - 1, height - handleSize - 1);
if (dragHandles) {
gc.SetLineAttributes (1, Gdk.LineStyle.Solid, Gdk.CapStyle.NotLast, Gdk.JoinStyle.Miter);

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

@ -37,12 +37,7 @@ namespace Stetic {
if (values == null)
hash[prop] = values = new ArrayList ();
object val;
if (prop.PropertyType.IsEnum)
val = Enum.Parse (prop.PropertyType, value);
else
val = Convert.ChangeType (value, prop.PropertyType);
values.Add (val);
values.Add (prop.StringToValue (value));
}
return hash;
}

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

@ -9,7 +9,6 @@ namespace Stetic {
static ItemGroup ()
{
Empty = new ItemGroup ();
Empty.items = new ItemDescriptor[0];
}
private ItemGroup ()
@ -22,31 +21,25 @@ namespace Stetic {
name = elem.GetAttribute ("name");
XmlNodeList nodes = elem.SelectNodes ("property | command | signal");
items = new ItemDescriptor[nodes.Count];
for (int i = 0; i < nodes.Count; i++) {
XmlElement item = (XmlElement)nodes[i];
string refname = item.GetAttribute ("ref");
if (refname != "") {
if (refname.IndexOf ('.') != -1)
items[i] = Registry.LookupItem (refname);
items.Add (Registry.LookupItem (refname));
else
items[i] = klass[refname];
items.Add (klass[refname]);
continue;
}
if (item.Name == "property")
items[i] = new PropertyDescriptor ((XmlElement)item, this, klass);
else if (item.Name == "command")
items[i] = new CommandDescriptor ((XmlElement)item, this, klass);
else if (item.Name == "signal")
items[i] = new SignalDescriptor ((XmlElement)item, this, klass);
else
throw new ApplicationException ("Bad item name " + item.Name + " in " + klass.WrapperType.Name);
ItemDescriptor idesc = klass.CreateItemDescriptor ((XmlElement)item, this);
if (idesc != null)
items.Add (idesc);
}
}
string label, name;
ItemDescriptor[] items;
ArrayList items = new ArrayList ();
public string Label {
get {

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

@ -1,10 +1,14 @@
pkglib_DATA = libstetic.dll libstetic.dll.config
pkglib_DATA = libstetic.dll libstetic.dll.config libstetic.dll.mdb
libstetic_dll_sources = \
AssemblyWidgetLibrary.cs \
ClassDescriptor.cs \
CommandDescriptor.cs \
DND.cs \
ErrorWidget.cs \
EnumDescriptor.cs \
EmbedWindow.cs \
GeneratorContext.cs \
GladeException.cs \
GladeUtils.cs \
HandleWindow.cs \
@ -16,15 +20,22 @@ libstetic_dll_sources = \
ObjectWrapper.cs \
ParamSpec.cs \
Placeholder.cs \
PreviewBox.cs \
PropertyDescriptor.cs \
PropertyEditorAttribute.cs \
RadioGroupManager.cs \
Registry.cs \
Set.cs \
Shadow.cs \
SignalDescriptor.cs \
TextBox.cs \
Tooltips.cs \
TranslatableAttribute.cs \
TypedClassDescriptor.cs \
TypedPropertyDescriptor.cs \
TypedSignalDescriptor.cs \
WidgetLibrary.cs \
WidgetUtils.cs \
editor/Accelerator.cs \
editor/Boolean.cs \
editor/Char.cs \
@ -43,6 +54,13 @@ libstetic_dll_sources = \
editor/StringArray.cs \
editor/Text.cs \
editor/Translatable.cs \
Metacity/ButtonFunction.cs \
Metacity/ButtonLayout.cs \
Metacity/FrameFlags.cs \
Metacity/FrameType.cs \
Metacity/ObjectManager.cs \
Metacity/Preview.cs \
Metacity/Theme.cs \
wrapper/Box.cs \
wrapper/Button.cs \
wrapper/ButtonBox.cs \
@ -53,6 +71,7 @@ libstetic_dll_sources = \
wrapper/Container.cs \
wrapper/Custom.cs \
wrapper/Dialog.cs \
wrapper/Entry.cs \
wrapper/Expander.cs \
wrapper/FontButton.cs \
wrapper/FontSelectionDialog.cs \
@ -100,7 +119,7 @@ libstetic.dll: $(libstetic_dll_sources) $(libstetic_dll_resources)
@rm -f sources.rsp
@echo $(libstetic_dll_sources:%=$(srcdir)/%) > sources.rsp
@for resource in $(libstetic_dll_resources); do echo -resource:$$resource,`basename $$resource` >> sources.rsp; done
$(MCS) -debug -pkg:gnome-sharp-2.0 -target:library -out:$@ @sources.rsp
$(MCS) -debug -unsafe -pkg:gnome-sharp-2.0 -pkg:gconf-sharp-2.0 -target:library -out:$@ @sources.rsp
CLEANFILES = libstetic.dll libstetic.dll.mdb sources.rsp

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

@ -0,0 +1,19 @@
// This file was generated by the Gtk# code generator.
// Any changes made will be lost if regenerated.
namespace Metacity {
using System;
using System.Runtime.InteropServices;
#region Autogenerated code
public enum ButtonFunction {
Menu,
Minimize,
Maximize,
Close,
Last,
}
#endregion
}

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

@ -0,0 +1,35 @@
// This file was generated by the Gtk# code generator.
// Any changes made will be lost if regenerated.
namespace Metacity {
using System;
using System.Collections;
using System.Runtime.InteropServices;
#region Autogenerated code
[StructLayout(LayoutKind.Sequential)]
public struct ButtonLayout {
[MarshalAs (UnmanagedType.ByValArray, SizeConst=4)]
public Metacity.ButtonFunction[] LeftButtons;
[MarshalAs (UnmanagedType.ByValArray, SizeConst=4)]
public Metacity.ButtonFunction[] RightButtons;
public static Metacity.ButtonLayout Zero = new Metacity.ButtonLayout ();
public static Metacity.ButtonLayout New(IntPtr raw) {
if (raw == IntPtr.Zero) {
return Metacity.ButtonLayout.Zero;
}
Metacity.ButtonLayout self = new Metacity.ButtonLayout();
self = (Metacity.ButtonLayout) Marshal.PtrToStructure (raw, self.GetType ());
return self;
}
private static GLib.GType GType {
get { return GLib.GType.Pointer; }
}
#endregion
}
}

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

@ -0,0 +1,29 @@
// This file was generated by the Gtk# code generator.
// Any changes made will be lost if regenerated.
namespace Metacity {
using System;
using System.Runtime.InteropServices;
#region Autogenerated code
[Flags]
public enum FrameFlags {
AllowsDelete = 1 << 0,
AllowsMenu = 1 << 1,
AllowsMinimize = 1 << 2,
AllowsMaximize = 1 << 3,
AllowsVerticalResize = 1 << 4,
AllowsHorizontalResize = 1 << 5,
HasFocus = 1 << 6,
Shaded = 1 << 7,
Stuck = 1 << 8,
Maximized = 1 << 9,
AllowsShade = 1 << 10,
AllowsMove = 1 << 11,
Fullscreen = 1 << 12,
IsFlashing = 1 << 13,
}
#endregion
}

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

@ -0,0 +1,21 @@
// This file was generated by the Gtk# code generator.
// Any changes made will be lost if regenerated.
namespace Metacity {
using System;
using System.Runtime.InteropServices;
#region Autogenerated code
public enum FrameType {
Normal,
Dialog,
ModalDialog,
Utility,
Menu,
Border,
Last,
}
#endregion
}

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

@ -0,0 +1,19 @@
// This file was generated by the Gtk# code generator.
// Any changes made will be lost if regenerated.
namespace GtkSharp.MetacitySharp {
public class ObjectManager {
static bool initialized = false;
// Call this method from the appropriate module init function.
public static void Initialize ()
{
if (initialized)
return;
initialized = true;
GLib.GType.Register (Metacity.Preview.GType, typeof (Metacity.Preview));
}
}
}

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

@ -0,0 +1,121 @@
// This file was generated by the Gtk# code generator.
// Any changes made will be lost if regenerated.
namespace Metacity {
using System;
using System.Collections;
using System.Runtime.InteropServices;
#region Autogenerated code
public class Preview : Gtk.Bin {
~Preview()
{
Dispose();
}
[Obsolete]
protected Preview(GLib.GType gtype) : base(gtype) {}
public Preview(IntPtr raw) : base(raw) {}
[DllImport("libmetacity-private.so.0")]
static extern IntPtr meta_preview_new();
public Preview () : base (IntPtr.Zero)
{
if (GetType () != typeof (Preview)) {
CreateNativeObject (new string [0], new GLib.Value[0]);
return;
}
Raw = meta_preview_new();
}
[DllImport("libmetacity-private.so.0")]
static extern void meta_preview_set_title(IntPtr raw, IntPtr title);
public string Title {
set {
IntPtr title_as_native = GLib.Marshaller.StringToPtrGStrdup (value);
meta_preview_set_title(Handle, title_as_native);
GLib.Marshaller.Free (title_as_native);
}
}
[DllImport("libmetacity-private.so.0")]
static extern void meta_preview_set_button_layout(IntPtr raw, ref Metacity.ButtonLayout button_layout);
public Metacity.ButtonLayout ButtonLayout {
set {
meta_preview_set_button_layout(Handle, ref value);
}
}
[DllImport("libmetacity-private.so.0")]
static extern void meta_preview_set_theme(IntPtr raw, IntPtr theme);
public Metacity.Theme Theme {
set {
meta_preview_set_theme(Handle, (value == null ? IntPtr.Zero : value.Handle));
}
}
[DllImport("libmetacity-private.so.0")]
static extern IntPtr meta_preview_get_mini_icon();
public static Gdk.Pixbuf MiniIcon {
get {
IntPtr raw_ret = meta_preview_get_mini_icon();
Gdk.Pixbuf ret = GLib.Object.GetObject(raw_ret) as Gdk.Pixbuf;
return ret;
}
}
[DllImport("libmetacity-private.so.0")]
static extern IntPtr meta_preview_get_icon();
public static Gdk.Pixbuf Icon {
get {
IntPtr raw_ret = meta_preview_get_icon();
Gdk.Pixbuf ret = GLib.Object.GetObject(raw_ret) as Gdk.Pixbuf;
return ret;
}
}
[DllImport("libmetacity-private.so.0")]
static extern void meta_preview_set_frame_type(IntPtr raw, int type);
public Metacity.FrameType FrameType {
set {
meta_preview_set_frame_type(Handle, (int) value);
}
}
[DllImport("libmetacity-private.so.0")]
static extern IntPtr meta_preview_get_type();
public static new GLib.GType GType {
get {
IntPtr raw_ret = meta_preview_get_type();
GLib.GType ret = new GLib.GType(raw_ret);
return ret;
}
}
[DllImport("libmetacity-private.so.0")]
static extern void meta_preview_set_frame_flags(IntPtr raw, int flags);
public Metacity.FrameFlags FrameFlags {
set {
meta_preview_set_frame_flags(Handle, (int) value);
}
}
static Preview ()
{
GtkSharp.MetacitySharp.ObjectManager.Initialize ();
}
#endregion
}
}

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

@ -0,0 +1,40 @@
namespace Metacity {
using System;
using System.Runtime.InteropServices;
public class Theme : GLib.Opaque {
public Theme (IntPtr raw) : base (raw) {}
[DllImport("libmetacity-private.so.0")]
static extern IntPtr meta_theme_get_current ();
public static Theme Current {
get {
IntPtr raw = meta_theme_get_current ();
return (Theme)GetOpaque (raw, typeof (Metacity.Theme), true);
}
}
[DllImport("libmetacity-private.so.0")]
static extern IntPtr meta_theme_load (string theme_name, IntPtr err);
public static Theme Load (string name)
{
IntPtr raw = meta_theme_load (name, IntPtr.Zero);
if (raw == IntPtr.Zero)
return null;
else
return (Theme)GetOpaque (raw, typeof (Metacity.Theme), true);
}
[DllImport("libmetacity-private.so.0")]
static extern void meta_theme_free (IntPtr raw);
protected override void Free (IntPtr raw)
{
meta_theme_free (Raw);
}
}
}

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

@ -5,10 +5,17 @@ using System.Runtime.InteropServices;
using System.Xml;
namespace Stetic {
public enum FileFormat {
Native,
Glade
}
public abstract class ObjectWrapper : IDisposable {
protected IProject proj;
protected object wrapped;
protected ClassDescriptor classDescriptor;
public virtual void Wrap (object obj, bool initialized)
{
@ -25,43 +32,50 @@ namespace Stetic {
public static ObjectWrapper Create (IProject proj, object wrapped)
{
return Create (proj, wrapped, true);
}
public static ObjectWrapper Create (IProject proj, object wrapped, bool initialized)
{
ClassDescriptor klass = Registry.LookupClass (wrapped.GetType ());
if (klass == null)
throw new ApplicationException ("No wrapper for " + wrapped.GetType ().FullName);
ObjectWrapper wrapper = Activator.CreateInstance (klass.WrapperType) as ObjectWrapper;
if (wrapper == null)
return null;
ClassDescriptor klass = Registry.LookupClassByName (wrapped.GetType ().FullName);
ObjectWrapper wrapper = klass.CreateWrapper ();
wrapper.proj = proj;
wrapper.Wrap (wrapped, initialized);
wrapper.classDescriptor = klass;
wrapper.Wrap (wrapped, true);
return wrapper;
}
public static ObjectWrapper GladeImport (IProject proj, XmlElement elem)
internal static void Bind (IProject proj, ClassDescriptor klass, ObjectWrapper wrapper, object wrapped, bool initialized)
{
wrapper.proj = proj;
wrapper.classDescriptor = klass;
wrapper.Wrap (wrapped, initialized);
}
public virtual void Read (XmlElement elem, FileFormat format)
{
throw new System.NotSupportedException ();
}
public virtual XmlElement Write (XmlDocument doc, FileFormat format)
{
throw new System.NotSupportedException ();
}
public static ObjectWrapper Read (IProject proj, XmlElement elem, FileFormat format)
{
string className = elem.GetAttribute ("class");
ClassDescriptor klass = Registry.LookupClass (className);
if (klass == null)
throw new GladeException ("No Stetic wrapper for type", className);
MethodInfo info = klass.WrapperType.GetMethod ("GladeImport", BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic);
if (info == null)
throw new GladeException ("No Import method for type " + klass.WrapperType.FullName, className);
ObjectWrapper wrapper = Activator.CreateInstance (klass.WrapperType) as ObjectWrapper;
if (wrapper == null)
throw new GladeException ("Can't create wrapper for type " + klass.WrapperType.FullName, className);
wrapper.proj = proj;
try {
info.Invoke (wrapper, new object[] { elem });
} catch (TargetInvocationException tie) {
throw tie.InnerException;
ClassDescriptor klass;
if (format == FileFormat.Native)
klass = Registry.LookupClassByName (className);
else
klass = Registry.LookupClassByCName (className);
if (klass == null) {
ErrorWidget we = new ErrorWidget (className);
ErrorWidgetWrapper wrap = (ErrorWidgetWrapper) Create (proj, we);
wrap.Read (elem, format);
return wrap;
}
ObjectWrapper wrapper = klass.CreateWrapper ();
wrapper.proj = proj;
wrapper.Read (elem, format);
return wrapper;
}
@ -85,6 +99,10 @@ namespace Stetic {
}
}
public ClassDescriptor ClassDescriptor {
get { return classDescriptor; }
}
public delegate void WrapperNotificationDelegate (object obj, string propertyName);
public event WrapperNotificationDelegate Notify;

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

@ -58,7 +58,7 @@ namespace Stetic {
}
}
[DllImport("libsteticglue")]
/* [DllImport("libsteticglue")]
static extern bool stetic_param_spec_get_minimum (IntPtr pspec, ref GLib.Value value);
public object Minimum {
@ -71,8 +71,14 @@ namespace Stetic {
return null;
}
}
*/
public object Minimum {
get {
return null;
}
}
[DllImport("libsteticglue")]
/* [DllImport("libsteticglue")]
static extern bool stetic_param_spec_get_maximum (IntPtr pspec, ref GLib.Value value);
public object Maximum {
@ -85,8 +91,20 @@ namespace Stetic {
return null;
}
}
*/
public object Maximum {
get {
return null;
}
}
[DllImport("libsteticglue")]
public bool IsDefaultValue (object value)
{
GLib.Value gvalue = new GLib.Value (value);
return g_param_value_defaults (Raw, ref gvalue);
}
/* [DllImport("libsteticglue")]
static extern bool stetic_param_spec_get_default (IntPtr pspec, ref GLib.Value value);
public object Default {
get {
@ -98,7 +116,7 @@ namespace Stetic {
return null;
}
}
[DllImport("libsteticglue")]
static extern IntPtr stetic_param_spec_get_value_type (IntPtr obj);
@ -107,8 +125,9 @@ namespace Stetic {
return stetic_param_spec_get_value_type (_obj);
}
}
*/
[DllImport("libsteticglue")]
/* [DllImport("libsteticglue")]
static extern bool stetic_param_spec_is_unichar (IntPtr pspec);
public bool IsUnichar {
@ -116,7 +135,7 @@ namespace Stetic {
return stetic_param_spec_is_unichar (_obj);
}
}
*/
static Hashtable props = new Hashtable (), childProps = new Hashtable ();
private class ParamSpecTypeHack : GLib.Object {
@ -191,6 +210,9 @@ namespace Stetic {
[DllImport("libgobject-2.0-0.dll")]
static extern IntPtr g_param_spec_get_blurb (IntPtr obj);
[DllImport("libgobject-2.0-0.dll")]
static extern bool g_param_value_defaults (IntPtr obj, ref GLib.Value value);
[DllImport("libgobject-2.0-0.dll")]
static extern IntPtr g_type_class_ref (IntPtr gtype);

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

@ -36,13 +36,14 @@ namespace Stetic {
" .. "
};
Gdk.Pixmap pixmap;
protected override void OnRealized ()
{
base.OnRealized ();
Gdk.Pixmap pixmap, mask;
Gdk.Pixmap mask;
pixmap = Gdk.Pixmap.CreateFromXpmD (GdkWindow, out mask, new Gdk.Color (99, 99, 99), placeholder_xpm);
GdkWindow.SetBackPixmap (pixmap, false);
}
protected override bool OnExposeEvent (Gdk.EventExpose evt)
@ -57,6 +58,13 @@ namespace Stetic {
light = Style.LightGC (StateType.Normal);
dark = Style.DarkGC (StateType.Normal);
// Looks like GdkWindow.SetBackPixmap doesn't work very well,
// so draw the pixmap manually.
light.Fill = Gdk.Fill.Tiled;
light.Tile = pixmap;
GdkWindow.DrawRectangle (light, true, 0, 0, width, height);
light.Fill = Gdk.Fill.Solid;
GdkWindow.DrawLine (light, 0, 0, width - 1, 0);
GdkWindow.DrawLine (light, 0, 0, 0, height - 1);
GdkWindow.DrawLine (dark, 0, height - 1, width - 1, height - 1);

348
libstetic/PreviewBox.cs Normal file
Просмотреть файл

@ -0,0 +1,348 @@
//
// PreviewBox.cs
//
// Author:
// Lluis Sanchez Gual
//
// Copyright (C) 2006 Novell, Inc (http://www.novell.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;
using Gtk;
using Gdk;
namespace Stetic
{
public class PreviewBox: ScrolledWindow
{
Gtk.Widget preview;
Metacity.Preview metacityPreview;
internal Metacity.Theme Theme {
set {
if (metacityPreview != null)
metacityPreview.Theme = value;
}
}
internal string Title {
set {
if (metacityPreview != null)
metacityPreview.Title = value;
}
}
internal PreviewBox (Gtk.Container container, int designWidth, int designHeight)
{
ShadowType = ShadowType.None;
HscrollbarPolicy = PolicyType.Automatic;
VscrollbarPolicy = PolicyType.Automatic;
ResizableFixed fixd = new ResizableFixed ();
Gtk.Window window = container as Gtk.Window;
if (window != null) {
try {
metacityPreview = CreateMetacityPreview (window);
preview = metacityPreview;
} catch (DllNotFoundException ex) {
if (ex.Message.IndexOf ("libmetacity") != -1) {
// If metacity is not available, use a regular box.
EventBox eventBox = new EventBox ();
eventBox.Add (container);
preview = eventBox;
} else
throw;
}
} else {
EventBox eventBox = new EventBox ();
eventBox.Add (container);
preview = eventBox;
}
fixd.Put (preview, container);
preview.WidthRequest = designWidth;
preview.HeightRequest = designHeight;
preview.SizeAllocated += new Gtk.SizeAllocatedHandler (OnResized);
AddWithViewport (fixd);
}
Metacity.Preview CreateMetacityPreview (Gtk.Window window)
{
Metacity.Preview metacityPreview = new Metacity.Preview ();
switch (window.TypeHint) {
case Gdk.WindowTypeHint.Normal:
metacityPreview.FrameType = Metacity.FrameType.Normal;
break;
case Gdk.WindowTypeHint.Dialog:
metacityPreview.FrameType = window.Modal ? Metacity.FrameType.ModalDialog : Metacity.FrameType.Dialog;
break;
case Gdk.WindowTypeHint.Menu:
metacityPreview.FrameType = Metacity.FrameType.Menu;
break;
case Gdk.WindowTypeHint.Splashscreen:
metacityPreview.FrameType = Metacity.FrameType.Border;
break;
case Gdk.WindowTypeHint.Utility:
metacityPreview.FrameType = Metacity.FrameType.Utility;
break;
default:
metacityPreview.FrameType = Metacity.FrameType.Normal;
break;
}
Metacity.FrameFlags flags =
Metacity.FrameFlags.AllowsDelete |
Metacity.FrameFlags.AllowsVerticalResize |
Metacity.FrameFlags.AllowsHorizontalResize |
Metacity.FrameFlags.AllowsMove |
Metacity.FrameFlags.AllowsShade |
Metacity.FrameFlags.HasFocus;
if (window.Resizable)
flags = flags | Metacity.FrameFlags.AllowsMaximize;
metacityPreview.FrameFlags = flags;
metacityPreview.ShowAll ();
metacityPreview.Add (window);
return metacityPreview;
}
protected override void OnParentSet (Gtk.Widget previousParent)
{
base.OnParentSet (previousParent);
if (Parent != null) {
if (Parent.IsRealized)
ShowAll ();
else
Parent.Realized += OnParentRealized;
}
}
void OnParentRealized (object s, EventArgs args)
{
Parent.Realized -= OnParentRealized;
ShowAll ();
// Make sure everything is in place before continuing
while (Gtk.Application.EventsPending ())
Gtk.Application.RunIteration ();
}
void OnResized (object s, Gtk.SizeAllocatedArgs a)
{
if (DesignSizeChanged != null)
DesignSizeChanged (this, a);
}
public int DesignWidth {
get { return preview.WidthRequest; }
}
public int DesignHeight {
get { return preview.HeightRequest; }
}
public event EventHandler DesignSizeChanged;
}
class ResizableFixed: EventBox
{
Gtk.Widget child;
int difX, difY;
bool resizingX;
bool resizingY;
Fixed fixd;
Gtk.Container container;
Cursor cursorX = new Cursor (CursorType.RightSide);
Cursor cursorY = new Cursor (CursorType.BottomSide);
Cursor cursorXY = new Cursor (CursorType.BottomRightCorner);
const int padding = 6;
const int selectionBorder = 6;
Requisition currentSizeRequest;
public ResizableFixed ()
{
fixd = new Fixed ();
Add (fixd);
this.Events = EventMask.ButtonPressMask | EventMask.ButtonReleaseMask | EventMask.PointerMotionMask;
// fixd.ModifyBg (Gtk.StateType.Normal, this.Style.Mid (Gtk.StateType.Normal));
// VisibleWindow = false;
}
public void Put (Gtk.Widget child, Gtk.Container container)
{
this.child = child;
this.container = container;
fixd.Put (child, selectionBorder + padding, selectionBorder + padding);
child.SizeRequested += new SizeRequestedHandler (OnSizeReq);
}
void OnSizeReq (object o, SizeRequestedArgs a)
{
currentSizeRequest = a.Requisition;
Rectangle alloc = child.Allocation;
int nw = alloc.Width;
int nh = alloc.Height;
if (a.Requisition.Width > nw) nw = a.Requisition.Width;
if (a.Requisition.Height > nh) nh = a.Requisition.Height;
if (nw != alloc.Width || nh != alloc.Height) {
int ow = child.WidthRequest;
int oh = child.HeightRequest;
child.SetSizeRequest (nw, nh);
if (ow > nw)
child.WidthRequest = ow;
if (oh > nh)
child.HeightRequest = oh;
QueueDraw ();
}
}
protected override void OnSizeRequested (ref Requisition req)
{
req = child.SizeRequest ();
// Make some room for the border
req.Width += padding * 2 + selectionBorder * 2;
req.Height += padding * 2 + selectionBorder * 2;
}
protected override bool OnMotionNotifyEvent (Gdk.EventMotion ev)
{
if (resizingX || resizingY) {
if (resizingX) {
int nw = (int)(ev.X - difX - padding - selectionBorder);
if (nw < currentSizeRequest.Width) nw = currentSizeRequest.Width;
child.WidthRequest = nw;
}
if (resizingY) {
int nh = (int)(ev.Y - difY - padding - selectionBorder);
if (nh < currentSizeRequest.Height) nh = currentSizeRequest.Height;
child.HeightRequest = nh;
}
QueueDraw ();
} else {
if (GetAreaResizeXY ().Contains ((int) ev.X, (int) ev.Y))
GdkWindow.Cursor = cursorXY;
else if (GetAreaResizeX ().Contains ((int) ev.X, (int) ev.Y))
GdkWindow.Cursor = cursorX;
else if (GetAreaResizeY ().Contains ((int) ev.X, (int) ev.Y))
GdkWindow.Cursor = cursorY;
else
GdkWindow.Cursor = null;
}
return base.OnMotionNotifyEvent (ev);
}
protected override bool OnButtonPressEvent (Gdk.EventButton ev)
{
Gdk.Rectangle rectArea = child.Allocation;
rectArea.Inflate (selectionBorder, selectionBorder);
if (rectArea.Contains ((int) ev.X, (int) ev.Y)) {
Stetic.Wrapper.Widget gw = Stetic.Wrapper.Widget.Lookup (container);
gw.Select ();
Rectangle rect = GetAreaResizeXY ();
if (rect.Contains ((int) ev.X, (int) ev.Y)) {
resizingX = resizingY = true;
difX = (int) (ev.X - rect.X);
difY = (int) (ev.Y - rect.Y);
GdkWindow.Cursor = cursorXY;
}
rect = GetAreaResizeY ();
if (rect.Contains ((int) ev.X, (int) ev.Y)) {
resizingY = true;
difY = (int) (ev.Y - rect.Y);
GdkWindow.Cursor = cursorY;
}
rect = GetAreaResizeX ();
if (rect.Contains ((int) ev.X, (int) ev.Y)) {
resizingX = true;
difX = (int) (ev.X - rect.X);
GdkWindow.Cursor = cursorX;
}
} else {
Stetic.Wrapper.Widget gw = Stetic.Wrapper.Widget.Lookup (container);
gw.Project.Selection = null;
}
return base.OnButtonPressEvent (ev);
}
Rectangle GetAreaResizeY ()
{
Gdk.Rectangle rect = child.Allocation;
return new Gdk.Rectangle (rect.X - selectionBorder, rect.Y + rect.Height, rect.Width + selectionBorder, selectionBorder);
}
Rectangle GetAreaResizeX ()
{
Gdk.Rectangle rect = child.Allocation;
return new Gdk.Rectangle (rect.X + rect.Width, rect.Y - selectionBorder, selectionBorder, rect.Height + selectionBorder);
}
Rectangle GetAreaResizeXY ()
{
Gdk.Rectangle rect = child.Allocation;
return new Gdk.Rectangle (rect.X + rect.Width, rect.Y + rect.Height, selectionBorder, selectionBorder);
}
protected override bool OnButtonReleaseEvent (Gdk.EventButton ev)
{
resizingX = resizingY = false;
GdkWindow.Cursor = null;
return base.OnButtonReleaseEvent (ev);
}
protected override bool OnExposeEvent (Gdk.EventExpose ev)
{
bool r = base.OnExposeEvent (ev);
//this.Style.DarkGC (Gtk.StateType.Normal)
// GdkWindow.DrawRectangle (Style.MidGC (Gtk.StateType.Normal), true, 0, 0, 1000, 1000);
Gdk.Rectangle rect = child.Allocation;
/* rect.Inflate (selectionBorder, selectionBorder);
GdkWindow.DrawRectangle (Style.BlackGC, false, rect.X, rect.Y, rect.Width, rect.Height);
*/
Pixbuf sh = Shadow.AddShadow (rect.Width, rect.Height);
GdkWindow.DrawPixbuf (this.Style.BackgroundGC (StateType.Normal), sh, 0, 0, rect.X - 5, rect.Y - 5, sh.Width, sh.Height, RgbDither.None, 0, 0);
return r;
}
}
}

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

@ -1,4 +1,5 @@
using System;
using System.ComponentModel;
using System.Collections;
using System.Reflection;
using System.Xml;
@ -10,79 +11,45 @@ namespace Stetic {
public string Context, Comment;
}
public class PropertyDescriptor : ItemDescriptor {
public abstract class PropertyDescriptor : ItemDescriptor
{
protected string label, description, gladeName;
protected bool gladeOverride;
protected bool isWrapperProperty, hasDefault, initWithName;
protected Type editorType;
protected object minimum, maximum;
protected object defaultValue;
PropertyInfo memberInfo, propertyInfo;
bool isWrapperProperty, hasDefault, gladeOverride, initWithName;
ParamSpec pspec;
Type editorType;
string label, description, gladeName;
object minimum, maximum;
PropertyDescriptor gladeProperty;
Hashtable translationInfo;
const BindingFlags flags = BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.Instance;
public PropertyDescriptor (XmlElement elem, ItemGroup group, ClassDescriptor klass) : base (elem, group, klass)
protected Hashtable translationInfo;
protected PropertyDescriptor ()
{
string propertyName = elem.GetAttribute ("name");
int dot = propertyName.IndexOf ('.');
if (dot != -1) {
// Sub-property (eg, "Alignment.Value")
memberInfo = FindProperty (klass.WrapperType, klass.WrappedType, propertyName.Substring (0, dot));
isWrapperProperty = memberInfo.DeclaringType.IsSubclassOf (typeof (ObjectWrapper));
gladeProperty = new PropertyDescriptor (isWrapperProperty ? klass.WrapperType : klass.WrappedType, memberInfo.Name);
propertyInfo = FindProperty (memberInfo.PropertyType, propertyName.Substring (dot + 1));
} else {
// Basic simple property
propertyInfo = FindProperty (klass.WrapperType, klass.WrappedType, propertyName);
isWrapperProperty = propertyInfo.DeclaringType.IsSubclassOf (typeof (ObjectWrapper));
}
if (!IsInternal && propertyInfo.PropertyType.IsEnum &&
Registry.LookupEnum (propertyInfo.PropertyType) == null)
throw new ArgumentException ("No EnumDescriptor for " + propertyInfo.PropertyType.FullName + "(" + klass.WrappedType.FullName + "." + propertyName + ")");
pspec = FindPSpec (propertyInfo);
if (isWrapperProperty && pspec == null) {
PropertyInfo pinfo = klass.WrappedType.GetProperty (propertyInfo.Name, flags);
if (pinfo != null)
pspec = FindPSpec (pinfo);
}
}
protected PropertyDescriptor (XmlElement elem, ItemGroup group, ClassDescriptor klass): base (elem, group, klass)
{
}
protected void Load (XmlElement elem)
{
if (elem.HasAttribute ("label"))
label = elem.GetAttribute ("label");
else if (pspec != null)
label = pspec.Nick;
else
label = propertyInfo.Name;
if (label == null)
label = elem.GetAttribute ("name");
if (elem.HasAttribute ("description"))
description = elem.GetAttribute ("description");
else if (pspec != null)
description = pspec.Blurb;
if (elem.HasAttribute ("min"))
minimum = Convert.ChangeType (elem.GetAttribute ("min"), propertyInfo.PropertyType);
else if (pspec != null)
minimum = pspec.Minimum;
minimum = StringToValue (elem.GetAttribute ("min"));
if (elem.HasAttribute ("max"))
maximum = Convert.ChangeType (elem.GetAttribute ("max"), propertyInfo.PropertyType);
else if (pspec != null)
maximum = pspec.Maximum;
if (pspec != null && !elem.HasAttribute ("ignore-default"))
hasDefault = true;
editorType = Type.GetType (elem.GetAttribute ("editor"));
maximum = StringToValue (elem.GetAttribute ("max"));
if (elem.HasAttribute ("glade-override"))
gladeOverride = true;
else
gladeOverride = (pspec == null);
if (elem.HasAttribute ("glade-name"))
gladeName = elem.GetAttribute ("glade-name");
@ -94,124 +61,52 @@ namespace Stetic {
translationInfo = new Hashtable ();
}
PropertyDescriptor (Type objectType, string propertyName)
{
propertyInfo = FindProperty (objectType, propertyName);
isWrapperProperty = false;
pspec = FindPSpec (propertyInfo);
if (pspec != null) {
label = pspec.Nick;
description = pspec.Blurb;
minimum = pspec.Minimum;
maximum = pspec.Maximum;
hasDefault = true;
} else
label = propertyInfo.Name;
}
static PropertyInfo FindProperty (Type type, string propertyName) {
return FindProperty (null, type, propertyName);
}
static PropertyInfo FindProperty (Type wrapperType, Type objectType, string propertyName)
{
PropertyInfo info;
if (wrapperType != null) {
info = wrapperType.GetProperty (propertyName, flags);
if (info != null)
return info;
}
info = objectType.GetProperty (propertyName, flags);
if (info != null)
return info;
throw new ArgumentException ("Invalid property name " + objectType.Name + "." + propertyName);
}
ParamSpec FindPSpec (PropertyInfo pinfo)
{
foreach (object attr in pinfo.GetCustomAttributes (false)) {
if (attr is GLib.PropertyAttribute) {
GLib.PropertyAttribute pattr = (GLib.PropertyAttribute)attr;
return ParamSpec.LookupObjectProperty (pinfo.DeclaringType, pattr.Name);
}
if (attr is Gtk.ChildPropertyAttribute) {
Gtk.ChildPropertyAttribute cpattr = (Gtk.ChildPropertyAttribute)attr;
return ParamSpec.LookupChildProperty (pinfo.DeclaringType.DeclaringType, cpattr.Name);
}
}
return null;
}
// The property's internal name
public override string Name {
get {
return propertyInfo.Name;
}
}
// The property's user-visible name
public string Label {
public virtual string Label {
get {
return label;
}
}
// The property's type
public abstract Type PropertyType {
get ;
}
// The property's user-visible description
public string Description {
public virtual string Description {
get {
return description;
}
}
// The property's type
public Type PropertyType {
get {
return propertyInfo.PropertyType;
}
}
// The property's PropertyInfo
public PropertyInfo PropertyInfo {
get {
return propertyInfo;
}
}
// The property's ParamSpec
public ParamSpec ParamSpec {
get {
return pspec;
}
}
// The property's GUI editor type, if overridden
public Type EditorType {
public virtual Type EditorType {
get {
return editorType;
}
}
// The property's minimum value, if declared
public object Minimum {
public virtual object Minimum {
get {
return minimum;
}
}
// The property's maximum value, if declared
public object Maximum {
public virtual object Maximum {
get {
return maximum;
}
}
public virtual string InternalChildId {
get { return null; }
}
// Whether or not the property has a default value
public bool HasDefault {
public virtual bool HasDefault {
get {
return hasDefault;
}
@ -219,73 +114,59 @@ namespace Stetic {
hasDefault = value;
}
}
// Gets the value of the property on @obj
public object GetValue (object obj)
public virtual bool IsDefaultValue (object value)
{
if (isWrapperProperty)
obj = ObjectWrapper.Lookup (obj);
if (memberInfo != null)
obj = memberInfo.GetValue (obj, null);
return propertyInfo.GetValue (obj, null);
if (value == null)
return true;
if (defaultValue != null)
return value.Equals (defaultValue);
return false;
}
// Gets the value of the property on @obj
public abstract object GetValue (object obj);
// Whether or not the property is writable
public bool CanWrite {
get {
return propertyInfo.CanWrite;
}
public virtual bool CanWrite {
get { return true; }
}
// Sets the value of the property on @obj
public void SetValue (object obj, object value)
public abstract void SetValue (object obj, object value);
// Parses a string an returns a value valid for this property
public virtual object StringToValue (string value)
{
if (isWrapperProperty)
obj = ObjectWrapper.Lookup (obj);
if (memberInfo != null)
obj = memberInfo.GetValue (obj, null);
propertyInfo.SetValue (obj, value, null);
if (PropertyType.IsEnum)
return Enum.Parse (PropertyType, value);
else
return Convert.ChangeType (value, PropertyType);
}
// Returns a string representation of the provided property value
public virtual string ValueToString (object value)
{
return value.ToString ();
}
public bool GladeOverride {
get {
return gladeOverride;
}
}
public PropertyDescriptor GladeProperty {
get {
if (gladeProperty != null)
return gladeProperty;
else
return this;
}
}
public string GladeName {
get {
if (gladeName != null)
return gladeName;
else if (pspec != null)
return pspec.Name.Replace ('-', '_');
else
return null;
}
}
public bool InitWithName {
public virtual bool InitWithName {
get {
return initWithName;
}
}
public virtual bool IsWrapperProperty {
get { return isWrapperProperty; }
}
public bool Translatable {
public virtual bool Translatable {
get {
return translationInfo != null;
}
}
public bool IsTranslated (object obj)
public virtual bool IsTranslated (object obj)
{
TranslationInfo info = (TranslationInfo)translationInfo[obj];
@ -295,7 +176,7 @@ namespace Stetic {
return (info == null || info.Translated == true);
}
public void SetTranslated (object obj, bool translated)
public virtual void SetTranslated (object obj, bool translated)
{
TranslationInfo info = (TranslationInfo)translationInfo[obj];
if (info == null) {
@ -312,30 +193,30 @@ namespace Stetic {
// is still there.
}
public string TranslationContext (object obj)
public virtual string TranslationContext (object obj)
{
TranslationInfo info = (TranslationInfo)translationInfo[obj];
return info != null ? info.Context : null;
}
public void SetTranslationContext (object obj, string context)
public virtual void SetTranslationContext (object obj, string context)
{
SetTranslated (obj, true);
((TranslationInfo)translationInfo[obj]).Context = context;
}
public string TranslationComment (object obj)
public virtual string TranslationComment (object obj)
{
TranslationInfo info = (TranslationInfo)translationInfo[obj];
return info != null ? info.Comment : null;
}
public void SetTranslationComment (object obj, string comment)
public virtual void SetTranslationComment (object obj, string comment)
{
SetTranslated (obj, true);
((TranslationInfo)translationInfo[obj]).Comment = comment;
}
}
}
}

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

@ -7,49 +7,112 @@ using System.Xml.Xsl;
namespace Stetic {
public static class Registry {
static Hashtable classes_by_type = new Hashtable ();
static Hashtable classes_by_cname = new Hashtable ();
static Hashtable classes_by_csname = new Hashtable ();
static Hashtable enums = new Hashtable ();
static ArrayList libraries = new ArrayList ();
static ArrayList classes = new ArrayList ();
static XslTransform gladeImport, gladeExport;
static AssemblyWidgetLibrary coreLib;
public static event EventHandler RegistryChanging;
public static event EventHandler RegistryChanged;
static Registry ()
{
Assembly libstetic = Assembly.GetExecutingAssembly ();
System.IO.Stream stream = libstetic.GetManifestResourceStream ("objects.xml");
XmlDocument objects = new XmlDocument ();
objects.Load (stream);
stream.Close ();
coreLib = new AssemblyWidgetLibrary (Assembly.GetExecutingAssembly ());
RegisterWidgetLibrary (coreLib);
}
public static void RegisterWidgetLibrary (WidgetLibrary library)
{
NotifyChanging ();
libraries.Add (library);
library.Load ();
classes.AddRange (library.AllClasses);
UpdateGladeTransform ();
NotifyChanged ();
}
foreach (XmlElement element in objects.SelectNodes ("/objects/enum")) {
EnumDescriptor enm = new EnumDescriptor (element);
enums[enm.EnumType] = enm;
}
public static void UnregisterWidgetLibrary (WidgetLibrary library)
{
if (library == coreLib)
return;
foreach (XmlElement element in objects.SelectNodes ("/objects/object")) {
ClassDescriptor klass = new ClassDescriptor (libstetic, element);
classes_by_type[klass.WrappedType] = klass;
classes_by_cname[klass.CName] = klass;
classes_by_csname[klass.WrappedType.FullName] = klass;
}
NotifyChanging ();
libraries.Remove (library);
InternalUpdate ();
NotifyChanged ();
}
public static void ReloadWidgetLibrary (WidgetLibrary library)
{
NotifyChanging ();
foreach (WidgetLibrary lib in libraries)
if (lib != coreLib)
lib.Load ();
InternalUpdate ();
NotifyChanged ();
}
public static bool IsRegistered (WidgetLibrary library)
{
return libraries.Contains (library);
}
public static WidgetLibrary[] RegisteredWidgetLibraries {
get { return (WidgetLibrary[]) libraries.ToArray (typeof(WidgetLibrary)); }
}
static void NotifyChanging ()
{
if (RegistryChanging != null)
RegistryChanging (null, EventArgs.Empty);
}
static void NotifyChanged ()
{
if (RegistryChanged != null)
RegistryChanged (null, EventArgs.Empty);
}
static void InternalUpdate ()
{
classes.Clear ();
foreach (WidgetLibrary lib in libraries)
classes.AddRange (lib.AllClasses);
UpdateGladeTransform ();
}
static void UpdateGladeTransform ()
{
XmlDocument doc = CreateGladeTransformBase ();
XmlNamespaceManager nsm = new XmlNamespaceManager (doc.NameTable);
nsm.AddNamespace ("xsl", "http://www.w3.org/1999/XSL/Transform");
foreach (XmlElement elem in objects.SelectNodes ("/objects/object/glade-transform/import/xsl:*", nsm))
doc.FirstChild.PrependChild (doc.ImportNode (elem, true));
foreach (WidgetLibrary lib in libraries) {
foreach (XmlElement elem in lib.GetGladeImportTransformElements ())
doc.FirstChild.PrependChild (doc.ImportNode (elem, true));
}
gladeImport = new XslTransform ();
gladeImport.Load (doc, null, null);
doc = CreateGladeTransformBase ();
foreach (XmlElement elem in objects.SelectNodes ("/objects/object/glade-transform/export/xsl:*", nsm))
doc.FirstChild.PrependChild (doc.ImportNode (elem, true));
foreach (WidgetLibrary lib in libraries) {
foreach (XmlElement elem in lib.GetGladeExportTransformElements ())
doc.FirstChild.PrependChild (doc.ImportNode (elem, true));
}
gladeExport = new XslTransform ();
gladeExport.Load (doc, null, null);
}
static XmlDocument CreateGladeTransformBase ()
{
XmlDocument doc = new XmlDocument ();
@ -67,7 +130,7 @@ namespace Stetic {
public static IEnumerable AllClasses {
get {
return classes_by_type.Values;
return classes;
}
}
@ -83,19 +146,34 @@ namespace Stetic {
}
}
public static EnumDescriptor LookupEnum (Type type)
public static EnumDescriptor LookupEnum (string typeName)
{
return (EnumDescriptor)enums[type];
foreach (WidgetLibrary lib in libraries) {
EnumDescriptor desc = lib.LookupEnum (typeName);
if (desc != null)
return desc;
}
return null;
}
public static ClassDescriptor LookupClass (Type type)
public static ClassDescriptor LookupClassByCName (string cname)
{
return (ClassDescriptor)classes_by_type[type];
foreach (WidgetLibrary lib in libraries) {
ClassDescriptor desc = lib.LookupClassByCName (cname);
if (desc != null)
return desc;
}
return null;
}
public static ClassDescriptor LookupClass (string cname)
public static ClassDescriptor LookupClassByName (string cname)
{
return (ClassDescriptor)classes_by_cname[cname];
foreach (WidgetLibrary lib in libraries) {
ClassDescriptor desc = lib.LookupClassByName (cname);
if (desc != null)
return desc;
}
return null;
}
static ClassDescriptor FindGroupClass (string name, out string groupname)
@ -103,9 +181,9 @@ namespace Stetic {
int sep = name.LastIndexOf ('.');
string classname = name.Substring (0, sep);
groupname = name.Substring (sep + 1);
ClassDescriptor klass = (ClassDescriptor)classes_by_csname[classname];
ClassDescriptor klass = LookupClassByName (classname);
if (klass == null) {
klass = (ClassDescriptor)classes_by_csname[name];
klass = LookupClassByName (name);
if (klass == null)
throw new ArgumentException ("No class for itemgroup " + name);
classname = name;
@ -123,7 +201,7 @@ namespace Stetic {
if (group != null)
return group;
else
throw new ArgumentException ("No itemgroup '" + groupname + "' in class " + klass.WrappedType);
throw new ArgumentException ("No itemgroup '" + groupname + "' in class " + klass.WrappedTypeName);
}
public static ItemGroup LookupSignalGroup (string name)
@ -135,7 +213,7 @@ namespace Stetic {
if (group != null)
return group;
else
throw new ArgumentException ("No itemgroup '" + groupname + "' in class " + klass.WrappedType);
throw new ArgumentException ("No itemgroup '" + groupname + "' in class " + klass.WrappedTypeName);
}
public static ItemDescriptor LookupItem (string name)
@ -143,7 +221,7 @@ namespace Stetic {
int sep = name.LastIndexOf ('.');
string classname = name.Substring (0, sep);
string propname = name.Substring (sep + 1);
ClassDescriptor klass = (ClassDescriptor)classes_by_csname[classname];
ClassDescriptor klass = LookupClassByName (classname);
if (klass == null)
throw new ArgumentException ("No class " + classname + " for property " + propname);
return klass[propname];
@ -151,15 +229,31 @@ namespace Stetic {
public static ItemGroup LookupContextMenu (string classname)
{
ClassDescriptor klass = (ClassDescriptor)classes_by_csname[classname];
ClassDescriptor klass = LookupClassByName (classname);
if (klass == null)
throw new ArgumentException ("No class for contextmenu " + classname);
return klass.ContextMenu;
}
public static object NewInstance (Type type, IProject proj)
public static object NewInstance (string typeName, IProject proj)
{
return LookupClass (type).NewInstance (proj);
return LookupClassByName (typeName).NewInstance (proj);
}
public static Type GetType (string typeName, bool throwOnError)
{
Type t = Type.GetType (typeName, false);
if (t != null) return t;
foreach (WidgetLibrary lib in libraries) {
t = lib.GetType (typeName);
if (t != null) return t;
}
if (throwOnError)
throw new TypeLoadException ("Could not load type '" + typeName + "'");
return null;
}
}
}

116
libstetic/Shadow.cs Normal file
Просмотреть файл

@ -0,0 +1,116 @@
/* Shadow code from anders */
using System;
using Gdk;
public class ConvFilter
{
public int size;
public double[] data;
}
public class Shadow
{
public const int BLUR_RADIUS = 5;
public const int SHADOW_OFFSET = (BLUR_RADIUS * 4 / 5);
public const double SHADOW_OPACITY = 0.5;
static ConvFilter filter;
static double Gaussian (double x, double y, double r)
{
return ((1 / (2 * System.Math.PI * r)) *
System.Math.Exp ((- (x * x + y * y)) / (2 * r * r)));
}
static ConvFilter CreateBlurFilter (int radius)
{
ConvFilter filter;
int x, y;
double sum;
filter = new ConvFilter ();
filter.size = radius * 2 + 1;
filter.data = new double [filter.size * filter.size];
sum = 0.0;
for (y = 0 ; y < filter.size; y++) {
for (x = 0 ; x < filter.size; x++) {
sum += filter.data [y * filter.size + x] = Gaussian (x - (filter.size >> 1),
y - (filter.size >> 1),
radius);
}
}
for (y = 0; y < filter.size; y++) {
for (x = 0; x < filter.size; x++)
filter.data [y * filter.size + x] /= sum;
}
return filter;
}
unsafe static Pixbuf CreateEffect (int src_width, int src_height, ConvFilter filter, int radius, int offset, double opacity)
{
Pixbuf dest;
int x, y, i, j;
int src_x, src_y;
int suma;
int dest_width, dest_height;
int dest_rowstride;
byte* dest_pixels;
dest_width = src_width + 2 * radius + offset;
dest_height = src_height + 2 * radius + offset;
dest = new Pixbuf (Colorspace.Rgb, true, 8, dest_width, dest_height);
dest.Fill (0);
dest_pixels = (byte*) dest.Pixels;
dest_rowstride = dest.Rowstride;
for (y = 0; y < dest_height; y++)
{
for (x = 0; x < dest_width; x++)
{
suma = 0;
src_x = x - radius;
src_y = y - radius;
/* We don't need to compute effect here, since this pixel will be
* discarded when compositing */
if (src_x >= 0 && src_x < src_width && src_y >= 0 && src_y < src_height)
continue;
for (i = 0; i < filter.size; i++)
{
for (j = 0; j < filter.size; j++)
{
src_y = -(radius + offset) + y - (filter.size >> 1) + i;
src_x = -(radius + offset) + x - (filter.size >> 1) + j;
if (src_y < 0 || src_y >= src_height ||
src_x < 0 || src_x >= src_width)
continue;
suma += (int) (((byte)0xFF) * filter.data [i * filter.size + j]);
}
}
byte r = (byte) (suma * opacity);
dest_pixels [y * dest_rowstride + x * 4 + 3] = r;
}
}
return dest;
}
public static Pixbuf AddShadow (int width, int height)
{
if (filter == null)
filter = CreateBlurFilter (BLUR_RADIUS);
return CreateEffect (width, height, filter, BLUR_RADIUS, SHADOW_OFFSET, SHADOW_OPACITY);
}
}

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

@ -4,32 +4,22 @@ using System.Xml;
namespace Stetic
{
public class SignalDescriptor: ItemDescriptor
public abstract class SignalDescriptor: ItemDescriptor
{
string name, label, description;
EventInfo eventInfo;
MethodInfo handler;
string gladeName;
const BindingFlags flags = BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.Instance;
protected string name, label, description;
protected string handlerTypeName;
protected string handlerReturnTypeName;
protected ParameterDescriptor[] handlerParameters;
public SignalDescriptor (XmlElement elem, ItemGroup group, ClassDescriptor klass) : base (elem, group, klass)
{
}
protected virtual void Load (XmlElement elem)
{
name = elem.GetAttribute ("name");
label = elem.GetAttribute ("label");
description = elem.GetAttribute ("description");
eventInfo = FindEvent (klass.WrapperType, klass.WrappedType, name);
handler = eventInfo.EventHandlerType.GetMethod ("Invoke");
if (elem.HasAttribute ("glade-name"))
gladeName = elem.GetAttribute ("glade-name");
else {
object[] att = eventInfo.GetCustomAttributes (typeof(GLib.SignalAttribute), true);
if (att.Length > 0)
gladeName = ((GLib.SignalAttribute)att[0]).CName;
}
}
public override string Name {
@ -44,38 +34,36 @@ namespace Stetic
get { return description; }
}
public string GladeName {
get { return gladeName; }
}
public Type HandlerType {
get { return eventInfo.EventHandlerType; }
public string HandlerTypeName {
get { return handlerTypeName; }
}
public Type HandlerReturnType {
get { return handler.ReturnType; }
public string HandlerReturnTypeName {
get { return handlerReturnTypeName; }
}
public ParameterInfo[] HandlerParameters {
get { return handler.GetParameters (); }
public ParameterDescriptor[] HandlerParameters {
get { return handlerParameters; }
}
}
static EventInfo FindEvent (Type wrapperType, Type objectType, string name)
[Serializable]
public class ParameterDescriptor
{
string name, type;
public ParameterDescriptor (string name, string type)
{
EventInfo info;
if (wrapperType != null) {
info = wrapperType.GetEvent (name, flags);
if (info != null)
return info;
}
info = objectType.GetEvent (name, flags);
if (info != null)
return info;
throw new ArgumentException ("Invalid event name " + objectType.Name + "." + name);
this.name = name;
this.type = type;
}
public string Name {
get { return name; }
}
public string TypeName {
get { return type; }
}
}
}

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

@ -0,0 +1,133 @@
using System;
using System.Collections;
using System.Reflection;
using System.Runtime.InteropServices;
using System.Xml;
namespace Stetic
{
public class TypedClassDescriptor: ClassDescriptor
{
Type wrapped, wrapper;
GLib.GType gtype;
MethodInfo ctorMethodInfo;
ConstructorInfo cinfo;
bool useGTypeCtor;
Gdk.Pixbuf icon;
const BindingFlags flags = BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.Instance;
public TypedClassDescriptor (Assembly assembly, XmlElement elem)
{
wrapped = Registry.GetType (elem.GetAttribute ("type"), true);
if (elem.HasAttribute ("wrapper"))
wrapper = Registry.GetType (elem.GetAttribute ("wrapper"), true);
else {
for (Type type = wrapped.BaseType; type != null; type = type.BaseType) {
TypedClassDescriptor parent = Registry.LookupClassByName (type.FullName) as TypedClassDescriptor;
if (parent != null) {
wrapper = parent.WrapperType;
break;
}
}
if (wrapper == null)
throw new ArgumentException (string.Format ("No wrapper type for class {0}", wrapped.FullName));
}
gtype = (GLib.GType)wrapped;
cname = gtype.ToString ();
string iconname = elem.GetAttribute ("icon");
try {
icon = new Gdk.Pixbuf (assembly, iconname);
} catch {
icon = Gtk.IconTheme.Default.LoadIcon (Gtk.Stock.MissingImage, 16, 0);
}
ctorMethodInfo = wrapper.GetMethod ("CreateInstance",
BindingFlags.Static | BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.DeclaredOnly,
null, new Type[0], null);
if (ctorMethodInfo == null) {
cinfo = wrapped.GetConstructor (new Type[0]);
if (cinfo == null) {
useGTypeCtor = true;
cinfo = wrapped.GetConstructor (new Type[] { typeof (IntPtr) });
}
}
Load (elem);
}
public override Gdk.Pixbuf Icon {
get {
return icon;
}
}
public override string WrappedTypeName {
get { return WrappedType.FullName; }
}
public Type WrapperType {
get {
return wrapper;
}
}
public Type WrappedType {
get {
return wrapped;
}
}
public GLib.GType GType {
get {
return gtype;
}
}
public override ObjectWrapper CreateWrapper ()
{
return (ObjectWrapper) Activator.CreateInstance (WrapperType);
}
[DllImport("libgobject-2.0-0.dll")]
static extern IntPtr g_object_new (IntPtr gtype, IntPtr dummy);
int counter;
public override object CreateInstance (IProject proj)
{
object inst;
if (ctorMethodInfo != null)
inst = ctorMethodInfo.Invoke (null, new object[0]);
else if (!useGTypeCtor)
inst = cinfo.Invoke (null, new object[0]);
else {
IntPtr raw = g_object_new (gtype.Val, IntPtr.Zero);
inst = cinfo.Invoke (new object[] { raw });
}
string name = wrapped.Name.ToLower () + (++counter).ToString ();
foreach (ItemGroup group in groups) {
foreach (ItemDescriptor item in group) {
PropertyDescriptor prop = item as PropertyDescriptor;
if (prop != null && prop.InitWithName)
prop.SetValue (inst, name);
}
}
return inst;
}
internal protected override ItemDescriptor CreateItemDescriptor (XmlElement elem, ItemGroup group)
{
if (elem.Name == "property")
return new TypedPropertyDescriptor (elem, group, this);
else if (elem.Name == "signal")
return new TypedSignalDescriptor (elem, group, this);
else
return base.CreateItemDescriptor (elem, group);
}
}
}

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

@ -0,0 +1,221 @@
using System;
using System.ComponentModel;
using System.Collections;
using System.Reflection;
using System.Xml;
namespace Stetic
{
public class TypedPropertyDescriptor : PropertyDescriptor {
PropertyInfo memberInfo, propertyInfo;
ParamSpec pspec;
TypedPropertyDescriptor gladeProperty;
const BindingFlags flags = BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.Instance;
public TypedPropertyDescriptor (XmlElement elem, ItemGroup group, TypedClassDescriptor klass) : base (elem, group, klass)
{
string propertyName = elem.GetAttribute ("name");
int dot = propertyName.IndexOf ('.');
if (dot != -1) {
// Sub-property (eg, "Alignment.Value")
memberInfo = FindProperty (klass.WrapperType, klass.WrappedType, propertyName.Substring (0, dot));
isWrapperProperty = memberInfo.DeclaringType.IsSubclassOf (typeof (ObjectWrapper));
gladeProperty = new TypedPropertyDescriptor (isWrapperProperty ? klass.WrapperType : klass.WrappedType, memberInfo.Name);
propertyInfo = FindProperty (memberInfo.PropertyType, propertyName.Substring (dot + 1));
} else {
// Basic simple property
propertyInfo = FindProperty (klass.WrapperType, klass.WrappedType, propertyName);
isWrapperProperty = propertyInfo.DeclaringType.IsSubclassOf (typeof (ObjectWrapper));
}
if (!IsInternal && propertyInfo.PropertyType.IsEnum &&
Registry.LookupEnum (propertyInfo.PropertyType.FullName) == null)
throw new ArgumentException ("No EnumDescriptor for " + propertyInfo.PropertyType.FullName + "(" + klass.WrappedType.FullName + "." + propertyName + ")");
pspec = FindPSpec (propertyInfo);
if (isWrapperProperty && pspec == null) {
PropertyInfo pinfo = klass.WrappedType.GetProperty (propertyInfo.Name, flags);
if (pinfo != null)
pspec = FindPSpec (pinfo);
}
if (pspec != null) {
// This information will be overriden by what's specified in the xml file
description = pspec.Blurb;
minimum = pspec.Minimum;
maximum = pspec.Maximum;
label = pspec.Nick;
if (!elem.HasAttribute ("ignore-default"))
hasDefault = true;
} else {
label = propertyInfo.Name;
gladeOverride = true;
}
editorType = Registry.GetType (elem.GetAttribute ("editor"), false);
// Look for a default value attribute
object[] ats = propertyInfo.GetCustomAttributes (typeof(DefaultValueAttribute), true);
if (ats.Length > 0) {
DefaultValueAttribute at = (DefaultValueAttribute) ats [0];
defaultValue = at.Value;
}
// Load default data
Load (elem);
}
TypedPropertyDescriptor (Type objectType, string propertyName)
{
propertyInfo = FindProperty (objectType, propertyName);
isWrapperProperty = false;
pspec = FindPSpec (propertyInfo);
if (pspec != null) {
label = pspec.Nick;
description = pspec.Blurb;
minimum = pspec.Minimum;
maximum = pspec.Maximum;
hasDefault = true;
} else
label = propertyInfo.Name;
}
static PropertyInfo FindProperty (Type type, string propertyName) {
return FindProperty (null, type, propertyName);
}
static PropertyInfo FindProperty (Type wrapperType, Type objectType, string propertyName)
{
PropertyInfo info;
if (wrapperType != null) {
info = wrapperType.GetProperty (propertyName, flags);
if (info != null)
return info;
}
info = objectType.GetProperty (propertyName, flags);
if (info != null)
return info;
throw new ArgumentException ("Invalid property name " + objectType.Name + "." + propertyName);
}
ParamSpec FindPSpec (PropertyInfo pinfo)
{
foreach (object attr in pinfo.GetCustomAttributes (false)) {
if (attr is GLib.PropertyAttribute) {
GLib.PropertyAttribute pattr = (GLib.PropertyAttribute)attr;
return ParamSpec.LookupObjectProperty (pinfo.DeclaringType, pattr.Name);
}
if (attr is Gtk.ChildPropertyAttribute) {
Gtk.ChildPropertyAttribute cpattr = (Gtk.ChildPropertyAttribute)attr;
return ParamSpec.LookupChildProperty (pinfo.DeclaringType.DeclaringType, cpattr.Name);
}
}
return null;
}
// The property's internal name
public override string Name {
get {
return propertyInfo.Name;
}
}
// The property's type
public override Type PropertyType {
get {
return propertyInfo.PropertyType;
}
}
// The property's PropertyInfo
public PropertyInfo PropertyInfo {
get {
return propertyInfo;
}
}
// The property's ParamSpec
public virtual ParamSpec ParamSpec {
get {
return pspec;
}
}
public override bool IsDefaultValue (object value)
{
if (defaultValue != null)
return base.IsDefaultValue (value);
if (ParamSpec != null)
return ParamSpec.IsDefaultValue (value);
else
return false;
}
// Gets the value of the property on @obj
public override object GetValue (object obj)
{
if (isWrapperProperty)
obj = ObjectWrapper.Lookup (obj);
if (memberInfo != null)
obj = memberInfo.GetValue (obj, null);
return propertyInfo.GetValue (obj, null);
}
// Whether or not the property is writable
public override bool CanWrite {
get {
return propertyInfo.CanWrite;
}
}
// Sets the value of the property on @obj
public override void SetValue (object obj, object value)
{
if (isWrapperProperty)
obj = ObjectWrapper.Lookup (obj);
if (memberInfo != null)
obj = memberInfo.GetValue (obj, null);
propertyInfo.SetValue (obj, value, null);
}
public virtual bool GladeOverride {
get {
return gladeOverride;
}
}
public TypedPropertyDescriptor GladeProperty {
get {
if (gladeProperty != null)
return gladeProperty;
else
return this;
}
}
public virtual string GladeName {
get {
if (gladeName != null)
return gladeName;
else if (pspec != null)
return pspec.Name.Replace ('-', '_');
else
return null;
}
}
public override string InternalChildId {
get { return GladeName; }
}
}
}

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

@ -0,0 +1,60 @@
using System;
using System.Reflection;
using System.Xml;
namespace Stetic
{
public class TypedSignalDescriptor: SignalDescriptor
{
EventInfo eventInfo;
MethodInfo handler;
string gladeName;
const BindingFlags flags = BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.Instance;
public TypedSignalDescriptor (XmlElement elem, ItemGroup group, TypedClassDescriptor klass) : base (elem, group, klass)
{
Load (elem);
eventInfo = FindEvent (klass.WrapperType, klass.WrappedType, name);
handler = eventInfo.EventHandlerType.GetMethod ("Invoke");
if (elem.HasAttribute ("glade-name"))
gladeName = elem.GetAttribute ("glade-name");
else {
object[] att = eventInfo.GetCustomAttributes (typeof(GLib.SignalAttribute), true);
if (att.Length > 0)
gladeName = ((GLib.SignalAttribute)att[0]).CName;
}
handlerTypeName = eventInfo.EventHandlerType.FullName;
handlerReturnTypeName = handler.ReturnType.FullName;
ParameterInfo[] pars = handler.GetParameters ();
handlerParameters = new ParameterDescriptor [pars.Length];
for (int n=0; n<pars.Length; n++)
handlerParameters [n] = new ParameterDescriptor (pars[n].Name, pars [n].ParameterType.FullName);
}
public string GladeName {
get { return gladeName; }
}
static EventInfo FindEvent (Type wrapperType, Type objectType, string name)
{
EventInfo info;
if (wrapperType != null) {
info = wrapperType.GetEvent (name, flags);
if (info != null)
return info;
}
info = objectType.GetEvent (name, flags);
if (info != null)
return info;
throw new ArgumentException ("Invalid event name " + objectType.Name + "." + name);
}
}
}

103
libstetic/WidgetLibrary.cs Normal file
Просмотреть файл

@ -0,0 +1,103 @@
using System;
using System.Collections;
using System.Xml;
namespace Stetic
{
public abstract class WidgetLibrary: IDisposable
{
Hashtable classes_by_cname = new Hashtable ();
Hashtable classes_by_csname = new Hashtable ();
Hashtable enums = new Hashtable ();
XmlElement[] importElems = new XmlElement [0];
XmlElement[] exportElems = new XmlElement [0];
public event EventHandler Changed;
public virtual void Load ()
{
}
protected virtual void Load (XmlDocument objects)
{
classes_by_cname.Clear ();
classes_by_csname.Clear ();
enums.Clear ();
foreach (XmlElement element in objects.SelectNodes ("/objects/enum")) {
EnumDescriptor enm = new EnumDescriptor (element);
enums[enm.Name] = enm;
}
foreach (XmlElement element in objects.SelectNodes ("/objects/object")) {
ClassDescriptor klass = LoadClassDescriptor (element);
if (klass == null) continue;
classes_by_cname[klass.CName] = klass;
classes_by_csname[klass.WrappedTypeName] = klass;
}
XmlNamespaceManager nsm = new XmlNamespaceManager (objects.NameTable);
nsm.AddNamespace ("xsl", "http://www.w3.org/1999/XSL/Transform");
XmlNodeList nodes = objects.SelectNodes ("/objects/object/glade-transform/import/xsl:*", nsm);
importElems = new XmlElement [nodes.Count];
for (int n=0; n<nodes.Count; n++)
importElems [n] = (XmlElement) nodes[n];
nodes = objects.SelectNodes ("/objects/object/glade-transform/export/xsl:*", nsm);
exportElems = new XmlElement [nodes.Count];
for (int n=0; n<nodes.Count; n++)
exportElems [n] = (XmlElement) nodes[n];
}
public void Dispose ()
{
}
protected abstract ClassDescriptor LoadClassDescriptor (XmlElement element);
public virtual XmlElement[] GetGladeImportTransformElements ()
{
return importElems;
}
public virtual XmlElement[] GetGladeExportTransformElements ()
{
return exportElems;
}
public virtual ICollection AllClasses {
get {
return classes_by_csname.Values;
}
}
public virtual EnumDescriptor LookupEnum (string typeName)
{
return (EnumDescriptor)enums[typeName];
}
public virtual ClassDescriptor LookupClassByCName (string cname)
{
return (ClassDescriptor)classes_by_cname[cname];
}
public virtual ClassDescriptor LookupClassByName (string csname)
{
return (ClassDescriptor)classes_by_csname[csname];
}
public virtual Type GetType (string typeName)
{
return null;
}
protected virtual void OnChanged ()
{
if (Changed != null)
Changed (this, EventArgs.Empty);
}
}
}

199
libstetic/WidgetUtils.cs Normal file
Просмотреть файл

@ -0,0 +1,199 @@
using System;
using System.Reflection;
using System.Collections;
using System.Xml;
using Stetic.Wrapper;
namespace Stetic
{
public static class WidgetUtils
{
public static XmlDocument ExportWidget (Gtk.Widget widget)
{
XmlDocument doc = new XmlDocument ();
Stetic.Wrapper.Widget wrapper = Stetic.Wrapper.Widget.Lookup (widget);
if (wrapper == null)
throw new InvalidOperationException ();
XmlElement elem = wrapper.Write (doc, FileFormat.Native);
doc.AppendChild (elem);
return doc;
}
public static Gtk.Widget ImportWidget (IProject project, XmlDocument doc)
{
ObjectWrapper wrapper = Stetic.ObjectWrapper.Read (project, doc.DocumentElement, FileFormat.Native);
return wrapper.Wrapped as Gtk.Widget;
}
public static XmlElement Write (ObjectWrapper wrapper, XmlDocument doc)
{
ClassDescriptor klass = wrapper.ClassDescriptor;
XmlElement elem = doc.CreateElement ("widget");
elem.SetAttribute ("class", klass.Name);
elem.SetAttribute ("id", ((Gtk.Widget)wrapper.Wrapped).Name);
GetProps (wrapper, elem);
GetSignals (wrapper, elem);
return elem;
}
public static void GetProps (ObjectWrapper wrapper, XmlElement parent_elem)
{
ClassDescriptor klass = wrapper.ClassDescriptor;
foreach (ItemGroup group in klass.ItemGroups) {
foreach (ItemDescriptor item in group) {
PropertyDescriptor prop = item as PropertyDescriptor;
if (prop == null)
continue;
if (!prop.VisibleFor (wrapper.Wrapped) || !prop.CanWrite)
continue;
object value = prop.GetValue (wrapper.Wrapped);
// If the property has its default value, we don't need to write it
if (value == null || (prop.HasDefault && prop.IsDefaultValue (value)))
continue;
string val = prop.ValueToString (value);
if (val == null)
continue;
XmlElement prop_elem = parent_elem.OwnerDocument.CreateElement ("property");
prop_elem.SetAttribute ("name", prop.Name);
if (val.Length > 0)
prop_elem.InnerText = val;
if (prop.Translatable && prop.IsTranslated (wrapper.Wrapped)) {
prop_elem.SetAttribute ("translatable", "yes");
if (prop.TranslationContext (wrapper.Wrapped) != null) {
prop_elem.SetAttribute ("context", "yes");
prop_elem.InnerText = prop.TranslationContext (wrapper.Wrapped) + "|" + prop_elem.InnerText;
}
if (prop.TranslationComment (wrapper.Wrapped) != null)
prop_elem.SetAttribute ("comments", prop.TranslationComment (wrapper.Wrapped));
}
parent_elem.AppendChild (prop_elem);
}
}
}
static void GetSignals (ObjectWrapper wrapper, XmlElement parent_elem)
{
Stetic.Wrapper.Widget ob = wrapper as Stetic.Wrapper.Widget;
if (ob == null) return;
foreach (Signal signal in ob.Signals) {
if (!signal.SignalDescriptor.VisibleFor (wrapper.Wrapped))
continue;
XmlElement signal_elem = parent_elem.OwnerDocument.CreateElement ("signal");
signal_elem.SetAttribute ("name", signal.SignalDescriptor.Name);
signal_elem.SetAttribute ("handler", signal.Handler);
if (signal.After)
signal_elem.SetAttribute ("after", "yes");
parent_elem.AppendChild (signal_elem);
}
}
static public void Read (ObjectWrapper wrapper, XmlElement elem)
{
string className = elem.GetAttribute ("class");
if (className == null)
throw new GladeException ("<widget> node with no class name");
ClassDescriptor klass = Registry.LookupClassByName (className);
if (klass == null)
throw new GladeException ("No stetic ClassDescriptor for " + className);
Gtk.Widget widget = (Gtk.Widget) wrapper.Wrapped;
if (widget == null) {
widget = (Gtk.Widget) klass.CreateInstance (wrapper.Project);
widget.Name = elem.GetAttribute ("id");
ObjectWrapper.Bind (wrapper.Project, klass, wrapper, widget, true);
}
else
widget.Name = elem.GetAttribute ("id");
ReadSignals (klass, wrapper, elem);
ReadProperties (klass, wrapper, widget, elem);
if (!(widget is Gtk.Window))
widget.ShowAll ();
}
static void ReadSignals (ClassDescriptor klass, ObjectWrapper wrapper, XmlElement elem)
{
Stetic.Wrapper.Widget ob = wrapper as Stetic.Wrapper.Widget;
if (ob == null) return;
foreach (ItemGroup group in klass.SignalGroups) {
foreach (SignalDescriptor signal in group) {
XmlElement signal_elem = elem.SelectSingleNode ("signal[@name='" + signal.Name + "']") as XmlElement;
if (signal_elem == null)
continue;
string handler = signal_elem.GetAttribute ("handler");
bool after = signal_elem.GetAttribute ("after") == "yes";
ob.Signals.Add (new Signal (signal, handler, after));
}
}
}
static void ReadProperties (ClassDescriptor klass, ObjectWrapper wrapper, object wrapped, XmlElement elem)
{
foreach (ItemGroup group in klass.ItemGroups) {
foreach (ItemDescriptor item in group) {
PropertyDescriptor prop = item as PropertyDescriptor;
if (prop == null || !prop.CanWrite)
continue;
XmlElement prop_node = (XmlElement) elem.SelectSingleNode ("property[@name='" + prop.Name + "']");
if (prop_node == null)
continue;
string strval = prop_node.InnerText;
// Skip translation context
if (prop_node.GetAttribute ("context") == "yes" && strval.IndexOf ('|') != -1)
strval = strval.Substring (strval.IndexOf ('|') + 1);
object value = prop.StringToValue (strval);
prop.SetValue (wrapped, value);
if (prop.Translatable) {
if (prop_node.GetAttribute ("translatable") != "yes") {
prop.SetTranslated (wrapped, false);
}
else {
prop.SetTranslated (wrapped, true);
if (prop_node.GetAttribute ("context") == "yes") {
strval = prop_node.InnerText;
int bar = strval.IndexOf ('|');
if (bar != -1)
prop.SetTranslationContext (wrapped, strval.Substring (0, bar));
}
if (prop_node.HasAttribute ("comments"))
prop.SetTranslationComment (wrapped, prop_node.GetAttribute ("comments"));
}
}
}
}
}
static public void SetPacking (Stetic.Wrapper.Container.ContainerChild wrapper, XmlElement child_elem)
{
XmlElement packing = child_elem["packing"];
if (packing == null)
return;
Gtk.Container.ContainerChild cc = wrapper.Wrapped as Gtk.Container.ContainerChild;
ClassDescriptor klass = wrapper.ClassDescriptor;
ReadProperties (klass, wrapper, cc, packing);
}
}
}

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

@ -71,12 +71,16 @@ namespace Stetic.Editor {
Text = "New Accelerator...";
}
[DllImport ("libsteticglue")]
static extern bool stetic_keycode_is_modifier (uint keycode);
// [DllImport ("libsteticglue")]
// static extern bool stetic_keycode_is_modifier (uint keycode);
protected override bool OnKeyPressEvent (Gdk.EventKey evt)
{
if (!editing || stetic_keycode_is_modifier (evt.HardwareKeycode))
// if (!editing || stetic_keycode_is_modifier (evt.HardwareKeycode))
// return base.OnKeyPressEvent (evt);
// FIXME: check for modifier
if (!editing)
return base.OnKeyPressEvent (evt);
uint keyval;

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

@ -11,7 +11,7 @@ namespace Stetic.Editor {
public void Initialize (PropertyDescriptor descriptor)
{
if (descriptor.PropertyType != typeof(bool))
if (descriptor.PropertyType != typeof(char))
throw new ApplicationException ("Char editor does not support editing values of type " + descriptor.PropertyType);
}

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

@ -30,7 +30,7 @@ namespace Stetic.Editor {
tips = new Gtk.Tooltips ();
enm = Registry.LookupEnum (prop.PropertyType);
enm = Registry.LookupEnum (prop.PropertyType.FullName);
foreach (Enum value in enm.Values)
combo.AppendText (enm[value].Label);
}

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

@ -25,7 +25,7 @@ namespace Stetic.Editor {
tips = new Gtk.Tooltips ();
flags = new Hashtable ();
enm = Registry.LookupEnum (prop.PropertyType);
enm = Registry.LookupEnum (prop.PropertyType.FullName);
foreach (Enum value in enm.Values) {
EnumValue eval = enm[value];
if (eval.Label == "")

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

@ -14,6 +14,7 @@ namespace Stetic.Editor {
RadioGroupManager manager;
ArrayList values;
string group;
PropertyDescriptor prop;
const BindingFlags flags = BindingFlags.Static | BindingFlags.Public | BindingFlags.NonPublic;
@ -23,20 +24,21 @@ namespace Stetic.Editor {
public void Initialize (PropertyDescriptor prop)
{
PropertyInfo info = prop.PropertyInfo;
Type owner = info.DeclaringType;
FieldInfo managerInfo = owner.GetField (info.Name + "Manager", flags);
if (managerInfo == null || managerInfo.FieldType != typeof (Stetic.RadioGroupManager))
throw new ArgumentException ("No 'static RadioGroupManager " + info.Name + "Manager' property on " + owner.FullName);
manager = managerInfo.GetValue (null) as RadioGroupManager;
manager.GroupsChanged += GroupsChanged;
GroupsChanged ();
this.prop = prop;
}
public void AttachObject (object ob)
{
ob = ObjectWrapper.Lookup (ob);
Type owner = ob.GetType ();
FieldInfo managerInfo = owner.GetField (prop.Name + "Manager", flags);
if (managerInfo == null || managerInfo.FieldType != typeof (Stetic.RadioGroupManager))
throw new ArgumentException ("No 'static RadioGroupManager " + prop.Name + "Manager' property on " + owner.FullName);
manager = managerInfo.GetValue (null) as RadioGroupManager;
manager.GroupsChanged += GroupsChanged;
GroupsChanged ();
}
public override void Dispose ()

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

@ -21,7 +21,7 @@ namespace Stetic.Editor {
entry = combo.Child as Gtk.Entry;
entry.Changed += entry_Changed;
enm = Registry.LookupEnum (typeof (Gtk.ResponseType));
enm = Registry.LookupEnum ("Gtk.ResponseType");
values = new ArrayList ();
foreach (Enum value in enm.Values) {
if (enm[value].Label != "") {

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

@ -23,7 +23,7 @@ namespace Stetic.Wrapper {
protected override bool AllowPlaceholders {
get {
return InternalChildId != null;
return InternalChildProperty != null;
}
}

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

@ -1,4 +1,5 @@
using System;
using System.CodeDom;
using System.Collections;
using System.Xml;
@ -26,18 +27,13 @@ namespace Stetic.Wrapper {
}
}
public override void GladeImport (XmlElement elem)
{
base.GladeImport (elem);
}
public override Widget GladeImportChild (XmlElement child_elem)
protected override Widget ReadChild (XmlElement child_elem, FileFormat format)
{
Type = ButtonType.Custom;
if (button.Child != null)
button.Remove (button.Child);
Widget wrapper = base.GladeImportChild (child_elem);
Widget wrapper = base.ReadChild (child_elem, format);
FixupGladeChildren ();
return wrapper;
}
@ -75,9 +71,9 @@ namespace Stetic.Wrapper {
}
}
public override XmlElement GladeExport (XmlDocument doc)
public override XmlElement Write (XmlDocument doc, FileFormat format)
{
XmlElement elem = base.GladeExport (doc);
XmlElement elem = base.Write (doc, format);
if (Type == ButtonType.StockItem)
GladeUtils.SetProperty (elem, "label", stockId);
return elem;
@ -168,7 +164,7 @@ namespace Stetic.Wrapper {
} else
labelWidget = Gtk.Label.New (label);
Gtk.Image imageWidget = (Gtk.Image)Registry.NewInstance (typeof (Gtk.Image), proj);
Gtk.Image imageWidget = (Gtk.Image)Registry.NewInstance ("Gtk.Image", proj);
Image imageWrapper = (Image)Widget.Lookup (imageWidget);
imageWrapper.Unselectable = true;
if (type == ButtonType.StockItem) {
@ -319,5 +315,14 @@ namespace Stetic.Wrapper {
else
return 0;
}
internal protected override void GenerateBuildCode (GeneratorContext ctx, string varName, CodeStatementCollection statements)
{
base.GenerateBuildCode (ctx, varName, statements);
CodePropertyReferenceExpression cprop = new CodePropertyReferenceExpression (new CodeVariableReferenceExpression (varName), "Label");
CodeExpression val = ctx.GenerateValue (button.Label);
statements.Add (new CodeAssignStatement (cprop, val));
}
}
}

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

@ -1,4 +1,5 @@
using System;
using System.Xml;
using System.Collections;
namespace Stetic.Wrapper {
@ -16,8 +17,8 @@ namespace Stetic.Wrapper {
Gtk.Button NewButton ()
{
Gtk.Button button = (Gtk.Button)Registry.NewInstance (typeof (Gtk.Button), proj);
if (InternalChildId == "action_area")
Gtk.Button button = (Gtk.Button)Registry.NewInstance ("Gtk.Button", proj);
if (InternalChildProperty != null && InternalChildProperty.Name == "ActionArea")
((Button)Widget.Lookup (button)).IsDialogButton = true;
return button;
}
@ -91,6 +92,13 @@ namespace Stetic.Wrapper {
}
}
}
protected override void ReadChildren (XmlElement elem, FileFormat format)
{
// Reset the button count
Size = 0;
base.ReadChildren (elem, format);
}
public class ButtonBoxChild : Box.BoxChild {
@ -98,7 +106,7 @@ namespace Stetic.Wrapper {
get {
if (ParentWrapper == null)
return false;
return ParentWrapper.InternalChildId == "action_area";
return ParentWrapper.InternalChildProperty != null && ParentWrapper.InternalChildProperty.Name == "ActionArea";
}
}
}

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

@ -5,12 +5,12 @@ namespace Stetic.Wrapper {
public class CheckButton : Container {
public override Widget GladeImportChild (XmlElement child_elem)
protected override Widget ReadChild (XmlElement child_elem, FileFormat format)
{
hasLabel = false;
if (checkbutton.Child != null)
checkbutton.Remove (checkbutton.Child);
return base.GladeImportChild (child_elem);
return base.ReadChild (child_elem, format);
}
public Gtk.CheckButton checkbutton {

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

@ -10,12 +10,6 @@ namespace Stetic.Wrapper {
return Gtk.ComboBox.NewText ();
}
public override void GladeImport (XmlElement elem)
{
Wrap (CreateInstance (), false);
base.GladeImport (elem);
}
string items = "";
string[] item = new string[0];

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

@ -1,4 +1,5 @@
using System;
using System.CodeDom;
using System.Collections;
using System.Reflection;
using System.Runtime.InteropServices;
@ -14,15 +15,15 @@ namespace Stetic.Wrapper {
{
base.Wrap (obj, initialized);
ClassDescriptor klass = Registry.LookupClass (obj.GetType ());
ClassDescriptor klass = this.ClassDescriptor;
foreach (PropertyDescriptor prop in klass.InternalChildren) {
Gtk.Widget child = prop.GetValue (container) as Gtk.Widget;
if (child == null)
continue;
Widget wrapper = ObjectWrapper.Create (proj, child) as Stetic.Wrapper.Widget;
wrapper.InternalChildId = prop.GladeName;
wrapper.InternalChildProperty = prop;
if (child.Name == ((GLib.GType)child.GetType ()).ToString ())
child.Name = container.Name + "_" + prop.GladeName;
child.Name = container.Name + "_" + prop.Name;
}
if (!initialized && container.Children.Length == 0 && AllowPlaceholders)
@ -36,7 +37,7 @@ namespace Stetic.Wrapper {
else
ContainerOrientation = Gtk.Orientation.Vertical;
}
Gtk.Container container {
get {
return (Gtk.Container)Wrapped;
@ -85,18 +86,22 @@ namespace Stetic.Wrapper {
freeze = 0;
}
public override void GladeImport (XmlElement elem)
public override void Read (XmlElement elem, FileFormat format)
{
base.Read (elem, format);
ReadChildren (elem, format);
}
protected virtual void ReadChildren (XmlElement elem, FileFormat format)
{
base.GladeImport (elem);
foreach (XmlElement child_elem in elem.SelectNodes ("./child")) {
try {
if (child_elem.HasAttribute ("internal-child"))
GladeSetInternalChild (child_elem);
ReadInternalChild (child_elem, format);
else if (child_elem["widget"] == null)
AddPlaceholder ();
else
GladeImportChild (child_elem);
ReadChild (child_elem, format);
} catch (GladeException ge) {
Console.Error.WriteLine (ge.Message);
}
@ -112,54 +117,90 @@ namespace Stetic.Wrapper {
Sync ();
}
public virtual Widget GladeImportChild (XmlElement child_elem)
protected virtual Widget ReadChild (XmlElement child_elem, FileFormat format)
{
ObjectWrapper wrapper = Stetic.ObjectWrapper.GladeImport (proj, child_elem["widget"]);
ObjectWrapper wrapper = Stetic.ObjectWrapper.Read (proj, child_elem["widget"], format);
Gtk.Widget child = (Gtk.Widget)wrapper.Wrapped;
AutoSize[child] = false;
container.Add (child);
GladeUtils.SetPacking (ChildWrapper ((Widget)wrapper), child_elem);
if (format == FileFormat.Glade)
GladeUtils.SetPacking (ChildWrapper ((Widget)wrapper), child_elem);
else
WidgetUtils.SetPacking (ChildWrapper ((Widget)wrapper), child_elem);
return (Widget)wrapper;
}
public virtual Widget GladeSetInternalChild (XmlElement child_elem)
protected virtual Widget ReadInternalChild (XmlElement child_elem, FileFormat format)
{
ClassDescriptor klass = Registry.LookupClass (Wrapped.GetType ());
TypedClassDescriptor klass = base.ClassDescriptor as TypedClassDescriptor;
string childId = child_elem.GetAttribute ("internal-child");
foreach (PropertyDescriptor prop in klass.InternalChildren) {
if (prop.GladeName != childId)
if (format == FileFormat.Glade && ((TypedPropertyDescriptor)prop).GladeName != childId)
continue;
else if (format == FileFormat.Native && prop.Name != childId)
continue;
Gtk.Widget child = prop.GetValue (container) as Gtk.Widget;
Widget wrapper = Widget.Lookup (child);
if (wrapper != null) {
wrapper.GladeImport (child_elem["widget"]);
GladeUtils.SetPacking (ChildWrapper (wrapper), child_elem);
wrapper.Read (child_elem["widget"], format);
if (format == FileFormat.Glade)
GladeUtils.SetPacking (ChildWrapper (wrapper), child_elem);
else
WidgetUtils.SetPacking (ChildWrapper (wrapper), child_elem);
return (Widget)wrapper;
}
}
throw new GladeException ("Unrecognized internal child name", Wrapped.GetType ().FullName, false, "internal-child", childId);
}
public override XmlElement GladeExport (XmlDocument doc)
public override XmlElement Write (XmlDocument doc, FileFormat format)
{
XmlElement elem = base.GladeExport (doc);
XmlElement elem = base.Write (doc, format);
XmlElement child_elem;
foreach (Gtk.Widget child in GladeChildren) {
Widget wrapper = Widget.Lookup (child);
if (wrapper != null)
child_elem = GladeExportChild (wrapper, doc);
else {
child_elem = doc.CreateElement ("child");
child_elem.AppendChild (doc.CreateElement ("placeholder"));
if (ClassDescriptor.AllowChildren || format == FileFormat.Glade) {
foreach (Gtk.Widget child in GladeChildren) {
Widget wrapper = Widget.Lookup (child);
if (wrapper != null) {
// Iternal children are written later
if (format == FileFormat.Native && wrapper.InternalChildProperty != null)
continue;
child_elem = WriteChild (wrapper, doc, format);
} else {
child_elem = doc.CreateElement ("child");
child_elem.AppendChild (doc.CreateElement ("placeholder"));
}
elem.AppendChild (child_elem);
}
}
if (format == FileFormat.Native) {
foreach (PropertyDescriptor prop in this.ClassDescriptor.InternalChildren) {
Gtk.Widget child = prop.GetValue (Wrapped) as Gtk.Widget;
if (child == null)
continue;
child_elem = doc.CreateElement ("child");
Widget wrapper = Widget.Lookup (child);
if (wrapper == null) {
child_elem.AppendChild (doc.CreateElement ("placeholder"));
elem.AppendChild (child_elem);
continue;
}
XmlElement widget_elem = wrapper.Write (doc, format);
child_elem.SetAttribute ("internal-child", prop.Name);
child_elem.AppendChild (widget_elem);
elem.AppendChild (child_elem);
}
elem.AppendChild (child_elem);
}
if (DesignWidth != 0 || DesignHeight != 0)
@ -167,27 +208,136 @@ namespace Stetic.Wrapper {
return elem;
}
public virtual XmlElement GladeExportChild (Widget wrapper, XmlDocument doc)
protected virtual XmlElement WriteChild (Widget wrapper, XmlDocument doc, FileFormat format)
{
XmlElement child_elem = doc.CreateElement ("child");
XmlElement widget_elem = wrapper.GladeExport (doc);
XmlElement widget_elem = wrapper.Write (doc, format);
child_elem.AppendChild (widget_elem);
if (wrapper.InternalChildId != null)
child_elem.SetAttribute ("internal-child", wrapper.InternalChildId);
else {
ObjectWrapper childwrapper = ChildWrapper (wrapper);
if (childwrapper != null) {
XmlElement packing_elem = doc.CreateElement ("packing");
ObjectWrapper childwrapper = ChildWrapper (wrapper);
if (childwrapper != null) {
XmlElement packing_elem = doc.CreateElement ("packing");
if (format == FileFormat.Glade)
GladeUtils.GetProps (childwrapper, packing_elem);
if (packing_elem.HasChildNodes)
child_elem.AppendChild (packing_elem);
}
else
WidgetUtils.GetProps (childwrapper, packing_elem);
if (packing_elem.HasChildNodes)
child_elem.AppendChild (packing_elem);
}
return child_elem;
}
public XmlElement WriteContainerChild (Widget wrapper, XmlDocument doc, FileFormat format)
{
return WriteChild (wrapper, doc, format);
}
internal protected override void GenerateBuildCode (GeneratorContext ctx, string varName, CodeStatementCollection statements)
{
base.GenerateBuildCode (ctx, varName, statements);
foreach (Gtk.Widget child in GladeChildren) {
Widget wrapper = Widget.Lookup (child);
if (wrapper != null && wrapper.InternalChildProperty == null)
// Iternal children are written later
GenerateChildBuildCode (ctx, varName, wrapper, statements);
}
foreach (TypedPropertyDescriptor prop in this.ClassDescriptor.InternalChildren) {
GenerateSetInternalChild (ctx, varName, prop, statements);
}
}
protected virtual void GenerateChildBuildCode (GeneratorContext ctx, string parentVar, Widget wrapper, CodeStatementCollection statements)
{
ObjectWrapper childwrapper = ChildWrapper (wrapper);
if (childwrapper != null) {
statements.Add (new CodeCommentStatement ("Container child " + Wrapped.Name + "." + childwrapper.Wrapped.GetType ()));
string varName = ctx.GenerateCreationCode (wrapper, statements);
CodeMethodInvokeExpression invoke = new CodeMethodInvokeExpression (
new CodeVariableReferenceExpression (parentVar),
"Add",
new CodeVariableReferenceExpression (varName)
);
statements.Add (invoke);
GenerateSetPacking (ctx, parentVar, varName, childwrapper, statements);
}
}
void GenerateSetInternalChild (GeneratorContext ctx, string parentVar, TypedPropertyDescriptor prop, CodeStatementCollection statements)
{
Gtk.Widget child = prop.GetValue (container) as Gtk.Widget;
Widget cwrapper = Widget.Lookup (child);
if (cwrapper != null) {
statements.Add (new CodeCommentStatement ("Internal child " + Wrapped.Name + "." + prop.Name));
string childVar = ctx.NewId ();
CodeVariableDeclarationStatement varDec = new CodeVariableDeclarationStatement (child.GetType(), childVar);
statements.Add (varDec);
varDec.InitExpression = new CodePropertyReferenceExpression (new CodeVariableReferenceExpression (parentVar), prop.Name);
ctx.GenerateBuildCode (cwrapper, childVar, statements);
// GenerateSetPacking (ctx, parentVar, childVar, ChildWrapper (wrapper), statements);
return;
}
}
void GenerateSetPacking (GeneratorContext ctx, string parentVar, string childVar, ObjectWrapper containerChildWrapper, CodeStatementCollection statements)
{
Gtk.Container.ContainerChild cc = containerChildWrapper.Wrapped as Gtk.Container.ContainerChild;
ClassDescriptor klass = containerChildWrapper.ClassDescriptor;
// Generate a variable that holds the container child
string contChildVar = ctx.NewId ();
CodeVariableDeclarationStatement varDec = new CodeVariableDeclarationStatement (cc.GetType(), contChildVar);
varDec.InitExpression = new CodeCastExpression (
cc.GetType (),
new CodeIndexerExpression (new CodeVariableReferenceExpression (parentVar), new CodeVariableReferenceExpression (childVar))
);
CodeVariableReferenceExpression var = new CodeVariableReferenceExpression (contChildVar);
// Set the container child properties
CodeStatementCollection childStatements = new CodeStatementCollection ();
foreach (ItemGroup group in klass.ItemGroups) {
foreach (ItemDescriptor item in group) {
PropertyDescriptor prop = item as PropertyDescriptor;
if (prop == null || prop.IsWrapperProperty)
continue;
GenerateChildPropertySet (ctx, childStatements, var, klass, prop, cc);
}
}
if (childStatements.Count > 0) {
statements.Add (varDec);
statements.AddRange (childStatements);
}
}
protected virtual void GenerateChildPropertySet (GeneratorContext ctx, CodeStatementCollection statements, CodeVariableReferenceExpression var, ClassDescriptor containerChildClass, PropertyDescriptor prop, object child)
{
if (containerChildClass.InitializationProperties != null && Array.IndexOf (containerChildClass.InitializationProperties, prop) != -1)
return;
// Design time
if (prop.Name == "AutoSize")
return;
object oval = prop.GetValue (child);
if (oval == null || (prop.HasDefault && prop.IsDefaultValue (oval)))
return;
CodePropertyReferenceExpression cprop = new CodePropertyReferenceExpression (var, prop.Name);
CodeExpression val = ctx.GenerateValue (oval);
statements.Add (new CodeAssignStatement (cprop, val));
}
public virtual Placeholder AddPlaceholder ()
{
Placeholder ph = CreatePlaceholder ();
@ -381,7 +531,7 @@ namespace Stetic.Wrapper {
Select (null, false);
proj.Selection = null;
} else {
Select (wrapper.Wrapped, (wrapper.InternalChildId == null));
Select (wrapper.Wrapped, (wrapper.InternalChildProperty == null));
proj.Selection = wrapper.Wrapped;
}
}
@ -403,12 +553,23 @@ namespace Stetic.Wrapper {
if (widget == selection)
return;
if (selection != null)
Gtk.Window win = GetParentWindow ();
if (selection != null) {
selection.Destroyed -= SelectionDestroyed;
// Remove the focus from the window. In this way we ensure
// that the current selected widget will lose the focus,
// even if the new selection is not focusable.
if (win != null)
win.Focus = null;
}
if (handles != null)
handles.Dispose ();
selection = widget;
if (win != null && widget != null && widget.CanFocus)
win.Focus = widget;
if (selection != null)
selection.Destroyed += SelectionDestroyed;
@ -416,12 +577,20 @@ namespace Stetic.Wrapper {
// to be. (Eg, if you select a widget in a hidden window, the window
// should map. If you select a widget on a non-current notebook
// page, the notebook should switch pages, etc.)
if (selection != null && selection.IsDrawable) {
if (selection != null && selection.IsDrawable && Visible) {
handles = new HandleWindow (selection, dragHandles);
handles.Drag += HandleWindowDrag;
} else
handles = null;
}
Gtk.Window GetParentWindow ()
{
Gtk.Container cc = Wrapped as Gtk.Container;
while (cc.Parent != null)
cc = cc.Parent as Gtk.Container;
return cc as Gtk.Window;
}
void SelectionDestroyed (object obj, EventArgs args)
{

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

@ -1,4 +1,5 @@
using System;
using System.Xml;
using System.Collections;
namespace Stetic.Wrapper {
@ -24,6 +25,14 @@ namespace Stetic.Wrapper {
ActionArea.ContentsChanged += ButtonsChanged;
}
protected override void ReadChildren (XmlElement elem, FileFormat format)
{
// Ignore changes in the buttons while loading
ActionArea.ContentsChanged -= ButtonsChanged;
base.ReadChildren (elem, format);
ActionArea.ContentsChanged += ButtonsChanged;
}
Gtk.Dialog dialog {
get {
@ -84,7 +93,7 @@ namespace Stetic.Wrapper {
Stetic.Wrapper.Button wrapper;
Gtk.Button button;
button = (Gtk.Button)Registry.NewInstance (typeof (Gtk.Button), proj);
button = (Gtk.Button)Registry.NewInstance ("Gtk.Button", proj);
wrapper = (Stetic.Wrapper.Button) ObjectWrapper.Lookup (button);
if (stockId != null) {
wrapper.Type = Button.ButtonType.StockItem;

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

@ -0,0 +1,15 @@
using System;
using System.ComponentModel;
namespace Stetic.Wrapper
{
public class Entry: Widget
{
[DefaultValue ('*')]
public char InvisibleChar {
get { return ((Gtk.Entry)Wrapped).InvisibleChar; }
set { ((Gtk.Entry)Wrapped).InvisibleChar = value; }
}
}
}

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

@ -18,22 +18,23 @@ namespace Stetic.Wrapper {
expander.Label = expander.Name;
AddPlaceholder ();
}
ObjectWrapper.Create (proj, expander.LabelWidget);
if (expander.LabelWidget != null)
ObjectWrapper.Create (proj, expander.LabelWidget);
}
public override Widget GladeImportChild (XmlElement child_elem)
protected override Widget ReadChild (XmlElement child_elem, FileFormat format)
{
if ((string)GladeUtils.GetChildProperty (child_elem, "type", "") == "label_item") {
ObjectWrapper wrapper = Stetic.ObjectWrapper.GladeImport (proj, child_elem["widget"]);
ObjectWrapper wrapper = Stetic.ObjectWrapper.Read (proj, child_elem["widget"], format);
expander.LabelWidget = (Gtk.Widget)wrapper.Wrapped;
return (Widget)wrapper;
} else
return base.GladeImportChild (child_elem);
return base.ReadChild (child_elem, format);
}
public override XmlElement GladeExportChild (Widget wrapper, XmlDocument doc)
protected override XmlElement WriteChild (Widget wrapper, XmlDocument doc, FileFormat format)
{
XmlElement child_elem = base.GladeExportChild (wrapper, doc);
XmlElement child_elem = base.WriteChild (wrapper, doc, format);
if (wrapper.Wrapped == expander.LabelWidget)
GladeUtils.SetChildProperty (child_elem, "type", "label_item");
return child_elem;

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

@ -27,7 +27,7 @@ namespace Stetic.Wrapper {
void LabelWidgetChanged (object obj, GLib.NotifyArgs args)
{
if (frame.LabelWidget != null)
if (frame.LabelWidget != null && !(frame.LabelWidget is Stetic.Placeholder))
ObjectWrapper.Create (proj, frame.LabelWidget);
}
@ -37,19 +37,19 @@ namespace Stetic.Wrapper {
}
}
public override Widget GladeImportChild (XmlElement child_elem)
protected override Widget ReadChild (XmlElement child_elem, FileFormat format)
{
if ((string)GladeUtils.GetChildProperty (child_elem, "type", "") == "label_item") {
ObjectWrapper wrapper = Stetic.ObjectWrapper.GladeImport (proj, child_elem["widget"]);
ObjectWrapper wrapper = Stetic.ObjectWrapper.Read (proj, child_elem["widget"], format);
frame.LabelWidget = (Gtk.Widget)wrapper.Wrapped;
return (Widget)wrapper;
} else
return base.GladeImportChild (child_elem);
return base.ReadChild (child_elem, format);
}
public override XmlElement GladeExportChild (Widget wrapper, XmlDocument doc)
protected override XmlElement WriteChild (Widget wrapper, XmlDocument doc, FileFormat format)
{
XmlElement child_elem = base.GladeExportChild (wrapper, doc);
XmlElement child_elem = base.WriteChild (wrapper, doc, format);
if (wrapper.Wrapped == frame.LabelWidget)
GladeUtils.SetChildProperty (child_elem, "type", "label_item");
return child_elem;

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

@ -11,7 +11,7 @@ namespace Stetic.Wrapper {
return new Gtk.ImageMenuItem ("");
}
public override void GladeImport (XmlElement elem)
public override void Read (XmlElement elem, FileFormat format)
{
Gtk.StockItem stockItem = Gtk.StockItem.Zero;
bool use_stock = (bool)GladeUtils.ExtractProperty (elem, "use_stock", false);
@ -21,7 +21,7 @@ namespace Stetic.Wrapper {
if (stockItem.Label != null)
GladeUtils.ExtractProperty (elem, "label", "");
}
base.GladeImport (elem);
base.Read (elem, format);
if (stockItem.StockId != null)
Image = "stock:" + stockItem.StockId;

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

@ -16,9 +16,9 @@ namespace Stetic.Wrapper {
base.Wrap (obj, initialized);
}
public override Widget GladeImportChild (XmlElement child_elem)
protected override Widget ReadChild (XmlElement child_elem, FileFormat format)
{
ObjectWrapper wrapper = Stetic.ObjectWrapper.GladeImport (proj, child_elem["widget"]);
ObjectWrapper wrapper = Stetic.ObjectWrapper.Read (proj, child_elem["widget"], format);
menuitem.Submenu = (Gtk.Menu)wrapper.Wrapped;
return (Widget)wrapper;
}

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

@ -20,21 +20,21 @@ namespace Stetic.Wrapper {
}
}
public override Widget GladeImportChild (XmlElement child_elem)
protected override Widget ReadChild (XmlElement child_elem, FileFormat format)
{
if ((string)GladeUtils.GetChildProperty (child_elem, "type", "") == "tab") {
ObjectWrapper wrapper = Stetic.ObjectWrapper.GladeImport (proj, child_elem["widget"]);
ObjectWrapper wrapper = Stetic.ObjectWrapper.Read (proj, child_elem["widget"], format);
Gtk.Widget widget = (Gtk.Widget)wrapper.Wrapped;
notebook.SetTabLabel (notebook.GetNthPage (notebook.NPages - 1), widget);
tabs.Add (widget);
return (Widget)wrapper;
} else
return base.GladeImportChild (child_elem);
return base.ReadChild (child_elem, format);
}
public override XmlElement GladeExportChild (Widget wrapper, XmlDocument doc)
protected override XmlElement WriteChild (Widget wrapper, XmlDocument doc, FileFormat format)
{
XmlElement child_elem = base.GladeExportChild (wrapper, doc);
XmlElement child_elem = base.WriteChild (wrapper, doc, format);
if (tabs.Contains (wrapper.Wrapped))
GladeUtils.SetChildProperty (child_elem, "type", "tab");
return child_elem;
@ -74,7 +74,7 @@ namespace Stetic.Wrapper {
int InsertPage (int position)
{
Gtk.Label label = (Gtk.Label)Registry.NewInstance (typeof (Gtk.Label), proj);
Gtk.Label label = (Gtk.Label)Registry.NewInstance ("Gtk.Label", proj);
label.LabelProp = "page" + (notebook.NPages + 1).ToString ();
tabs.Insert (position, label);

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

@ -21,10 +21,10 @@ namespace Stetic.Wrapper {
base.Wrap (obj, initialized);
}
public override void GladeImport (XmlElement elem)
public override void Read (XmlElement elem, FileFormat format)
{
int history = (int)GladeUtils.ExtractProperty (elem, "history", -1);
base.GladeImport (elem);
base.Read (elem, format);
// Fiddle with things to make the optionmenu resize itself correctly
Gtk.Widget menu = optionmenu.Menu;
@ -39,18 +39,18 @@ namespace Stetic.Wrapper {
// Some versions of glade call the menu an internal child, some don't
public override Widget GladeSetInternalChild (XmlElement child_elem)
protected override Widget ReadInternalChild (XmlElement child_elem, FileFormat format)
{
if (child_elem.GetAttribute ("internal-child") == "menu")
return GladeImportChild (child_elem);
return ReadChild (child_elem, format);
else
return base.GladeSetInternalChild (child_elem);
return base.ReadInternalChild (child_elem, format);
}
public override Widget GladeImportChild (XmlElement child_elem)
protected override Widget ReadChild (XmlElement child_elem, FileFormat format)
{
Widget wrapper = Stetic.Wrapper.Widget.Lookup (optionmenu.Menu);
wrapper.GladeImport (child_elem["widget"]);
wrapper.Read (child_elem["widget"], format);
return wrapper;
}

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

@ -19,11 +19,11 @@ namespace Stetic.Wrapper {
Group = radiobutton.Name;
}
public override void GladeImport (XmlElement elem)
public override void Read (XmlElement elem, FileFormat format)
{
string group = (string)GladeUtils.ExtractProperty (elem, "group", "");
bool active = (bool)GladeUtils.ExtractProperty (elem, "active", false);
base.GladeImport (elem);
base.Read (elem, format);
if (group != "")
Group = group;
@ -33,9 +33,9 @@ namespace Stetic.Wrapper {
((Gtk.RadioButton)Wrapped).Active = true;
}
public override XmlElement GladeExport (XmlDocument doc)
public override XmlElement Write (XmlDocument doc, FileFormat format)
{
XmlElement elem = base.GladeExport (doc);
XmlElement elem = base.Write (doc, format);
string group = GroupManager.GladeGroupName (Wrapped);
if (group != Wrapped.Name)
GladeUtils.SetProperty (elem, "group", group);

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

@ -19,11 +19,11 @@ namespace Stetic.Wrapper {
Group = radio.Name;
}
public override void GladeImport (XmlElement elem)
public override void Read (XmlElement elem, FileFormat format)
{
string group = (string)GladeUtils.ExtractProperty (elem, "group", "");
bool active = (bool)GladeUtils.ExtractProperty (elem, "active", false);
base.GladeImport (elem);
base.Read (elem, format);
if (group != "")
Group = group;
@ -33,9 +33,9 @@ namespace Stetic.Wrapper {
((Gtk.RadioMenuItem)Wrapped).Active = true;
}
public override XmlElement GladeExport (XmlDocument doc)
public override XmlElement Write (XmlDocument doc, FileFormat format)
{
XmlElement elem = base.GladeExport (doc);
XmlElement elem = base.Write (doc, format);
string group = GroupManager.GladeGroupName (Wrapped);
if (group != Wrapped.Name)
GladeUtils.SetProperty (elem, "group", group);

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

@ -24,11 +24,11 @@ namespace Stetic.Wrapper {
Group = radio.Name;
}
public override void GladeImport (XmlElement elem)
public override void Read (XmlElement elem, FileFormat format)
{
string group = (string)GladeUtils.ExtractProperty (elem, "group", "");
bool active = (bool)GladeUtils.ExtractProperty (elem, "active", false);
base.GladeImport (elem);
base.Read (elem, format);
if (group != "")
Group = group;
@ -38,9 +38,9 @@ namespace Stetic.Wrapper {
((Gtk.RadioToolButton)Wrapped).Active = true;
}
public override XmlElement GladeExport (XmlDocument doc)
public override XmlElement Write (XmlDocument doc, FileFormat format)
{
XmlElement elem = base.GladeExport (doc);
XmlElement elem = base.Write (doc, format);
string group = GroupManager.GladeGroupName (Wrapped);
if (group != Wrapped.Name)
GladeUtils.SetProperty (elem, "group", group);

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

@ -43,15 +43,15 @@ namespace Stetic.Wrapper {
// First fill in the placeholders in the grid. If we find any
// placeholders covering more than one grid square, remove them.
// (New ones will be created below.)
foreach (Gtk.Widget child in children) {
foreach (Gtk.Widget child in children) {
if (!(child is Placeholder))
continue;
tc = table[child] as Gtk.Table.TableChild;
left = tc.LeftAttach;
right = tc.RightAttach;
top = tc.TopAttach;
bottom = tc.BottomAttach;
tc = table[child] as Gtk.Table.TableChild;
left = tc.LeftAttach;
right = tc.RightAttach;
top = tc.TopAttach;
bottom = tc.BottomAttach;
if (right == left + 1 && bottom == top + 1)
grid[top,left] = child;
@ -64,25 +64,25 @@ namespace Stetic.Wrapper {
// placeholders, neither will be knocked out, and the layout
// will probably end up wrong as well. But this situation
// happens at least temporarily during glade import.)
foreach (Gtk.Widget child in children) {
foreach (Gtk.Widget child in children) {
if (child is Placeholder)
continue;
tc = table[child] as Gtk.Table.TableChild;
left = tc.LeftAttach;
right = tc.RightAttach;
top = tc.TopAttach;
bottom = tc.BottomAttach;
for (row = top; row < bottom; row++) {
for (col = left; col < right; col++) {
tc = table[child] as Gtk.Table.TableChild;
left = tc.LeftAttach;
right = tc.RightAttach;
top = tc.TopAttach;
bottom = tc.BottomAttach;
for (row = top; row < bottom; row++) {
for (col = left; col < right; col++) {
w = grid[row,col];
if (w is Placeholder)
table.Remove (grid[row,col]);
grid[row,col] = child;
}
}
}
grid[row,col] = child;
}
}
}
// Scan each row; if there are any empty cells, fill them in
// with placeholders. If a row contains only placeholders, then
@ -151,6 +151,12 @@ namespace Stetic.Wrapper {
if (addedPlaceholders)
EmitContentsChanged ();
}
public override Placeholder AddPlaceholder ()
{
// Placeholders are added by Sync ()
return null;
}
public uint NRows {
get {
@ -172,7 +178,7 @@ namespace Stetic.Wrapper {
set {
Freeze ();
while (value < table.NColumns)
DeleteColumn (table.NColumns);
DeleteColumn (table.NColumns - 1);
table.NColumns = value;
Thaw ();
}
@ -311,7 +317,7 @@ namespace Stetic.Wrapper {
base.ChildContentsChanged (child);
}
public class TableChild : Container.ContainerChild {
Gtk.Table.TableChild tc {

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

@ -19,10 +19,10 @@ namespace Stetic.Wrapper {
icon = "stock:" + toolbutton.StockId;
}
public override void GladeImport (XmlElement elem)
public override void Read (XmlElement elem, FileFormat format)
{
string icon = (string)GladeUtils.ExtractProperty (elem, "icon", "");
base.GladeImport (elem);
base.Read (elem, format);
if (icon != "")
Icon = "file:" + icon;
else if (((Gtk.ToolButton)Wrapped).StockId == null)

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

@ -1,6 +1,7 @@
using System;
using System.Collections;
using System.Xml;
using System.CodeDom;
namespace Stetic.Wrapper {
@ -8,6 +9,14 @@ namespace Stetic.Wrapper {
string oldName;
SignalCollection signals;
bool hexpandable, vexpandable;
bool window_visible = true;
bool hasDefault;
Gdk.EventMask events;
bool set_events;
public bool Unselectable;
public Widget ()
{
@ -34,11 +43,19 @@ namespace Stetic.Wrapper {
Wrapped.ShowAll ();
Wrapped.PopupMenu += PopupMenu;
Wrapped.FocusInEvent += OnFocusIn;
InterceptClicks (Wrapped);
ClassDescriptor klass = Registry.LookupClass (obj.GetType ());
hexpandable = klass.HExpandable;
vexpandable = klass.VExpandable;
hexpandable = this.ClassDescriptor.HExpandable;
vexpandable = this.ClassDescriptor.VExpandable;
}
void OnFocusIn (object s, Gtk.FocusInEventArgs a)
{
if (!Unselectable)
Select ();
else if (ParentWrapper != null)
ParentWrapper.Select ();
}
void InterceptClicks (Gtk.Widget widget)
@ -74,7 +91,7 @@ namespace Stetic.Wrapper {
public SignalCollection Signals {
get { return signals; }
}
[GLib.ConnectBefore]
void WidgetEvent (object obj, Gtk.WidgetEventArgs args)
{
@ -140,7 +157,7 @@ namespace Stetic.Wrapper {
proj.PopupContextMenu (this);
}
public void Select ()
public virtual void Select ()
{
if (ParentWrapper != null)
ParentWrapper.Select (this);
@ -156,16 +173,73 @@ namespace Stetic.Wrapper {
Wrapped.Destroy ();
}
public virtual void GladeImport (XmlElement elem)
public override void Read (XmlElement elem, FileFormat format)
{
GladeUtils.ImportWidget (this, elem);
if (format == FileFormat.Native)
WidgetUtils.Read (this, elem);
else if (format == FileFormat.Glade)
GladeUtils.ImportWidget (this, elem);
}
public virtual XmlElement GladeExport (XmlDocument doc)
public override XmlElement Write (XmlDocument doc, FileFormat format)
{
XmlElement elem = GladeUtils.ExportWidget (this, doc);
GladeUtils.ExtractProperty (elem, "name", "");
return elem;
if (format == FileFormat.Native) {
return WidgetUtils.Write (this, doc);
}
else {
XmlElement elem = GladeUtils.ExportWidget (this, doc);
GladeUtils.ExtractProperty (elem, "name", "");
return elem;
}
}
internal protected virtual void GenerateBuildCode (GeneratorContext ctx, string varName, CodeStatementCollection statements)
{
CodeVariableReferenceExpression var = new CodeVariableReferenceExpression (varName);
TypedClassDescriptor klass = base.ClassDescriptor as TypedClassDescriptor;
if (klass == null)
throw new InvalidOperationException ("Can't generate code for untyped class descriptors");
foreach (ItemGroup group in klass.ItemGroups) {
foreach (ItemDescriptor item in group) {
TypedPropertyDescriptor prop = item as TypedPropertyDescriptor;
if (prop == null || prop.IsWrapperProperty)
continue;
GeneratePropertySet (ctx, statements, var, prop);
}
}
}
internal protected virtual CodeExpression GenerateWidgetCreation (GeneratorContext ctx, CodeStatementCollection statements)
{
if (ClassDescriptor.InitializationProperties != null) {
CodeExpression[] paramters = new CodeExpression [ClassDescriptor.InitializationProperties.Length];
for (int n=0; n < paramters.Length; n++)
paramters [n] = ctx.GenerateValue (ClassDescriptor.InitializationProperties [n].GetValue (Wrapped));
return new CodeObjectCreateExpression (Wrapped.GetType (), paramters);
} else
return new CodeObjectCreateExpression (Wrapped.GetType ());
}
protected virtual void GeneratePropertySet (GeneratorContext ctx, CodeStatementCollection statements, CodeVariableReferenceExpression var, TypedPropertyDescriptor prop)
{
if (ClassDescriptor.InitializationProperties != null && Array.IndexOf (ClassDescriptor.InitializationProperties, prop) != -1)
return;
object oval = prop.GetValue (Wrapped);
if (oval == null || (prop.HasDefault && prop.IsDefaultValue (oval)))
return;
CodeExpression val = ctx.GenerateValue (oval);
CodeExpression cprop;
if (prop.GladeProperty == prop) {
cprop = new CodePropertyReferenceExpression (var, prop.Name);
} else {
cprop = new CodePropertyReferenceExpression (var, prop.GladeProperty.Name);
cprop = new CodePropertyReferenceExpression (cprop, prop.Name);
}
statements.Add (new CodeAssignStatement (cprop, val));
}
public static new Widget Lookup (GLib.Object obj)
@ -173,13 +247,13 @@ namespace Stetic.Wrapper {
return Stetic.ObjectWrapper.Lookup (obj) as Stetic.Wrapper.Widget;
}
string internalChildId;
public string InternalChildId {
PropertyDescriptor internalChildProperty;
public PropertyDescriptor InternalChildProperty {
get {
return internalChildId;
return internalChildProperty;
}
set {
internalChildId = value;
internalChildProperty = value;
}
}
@ -188,30 +262,19 @@ namespace Stetic.Wrapper {
widget.Destroy ();
}
bool hexpandable, vexpandable;
public virtual bool HExpandable { get { return hexpandable; } }
public virtual bool VExpandable { get { return vexpandable; } }
public bool Unselectable;
bool window_visible;
public bool Visible {
get {
if (Wrapped is Gtk.Window)
return window_visible;
else
return Wrapped.Visible;
return window_visible;
}
set {
if (Wrapped is Gtk.Window) {
window_visible = value;
EmitNotify ("Visible");
} else
Wrapped.Visible = value;
window_visible = value;
EmitNotify ("Visible");
}
}
bool hasDefault;
public bool HasDefault {
get {
return hasDefault;
@ -243,8 +306,6 @@ namespace Stetic.Wrapper {
}
}
Gdk.EventMask events;
bool set_events;
public Gdk.EventMask Events {
get {
if (!set_events) {
@ -292,7 +353,8 @@ namespace Stetic.Wrapper {
// Don't notify parent change for top level widgets.
if (propertyName == "parent" || propertyName == "has-focus" ||
propertyName == "has-toplevel-focus" || propertyName == "is-active" ||
propertyName == "is-focus")
propertyName == "is-focus" || propertyName == "style" ||
propertyName == "visible" || propertyName == "scroll-offset")
return;
if (propertyName == "name") {
@ -302,8 +364,10 @@ namespace Stetic.Wrapper {
OnNameChanged (new WidgetNameChangedArgs (this, on, Wrapped.Name));
}
}
else
else {
// Console.WriteLine ("PROP: " + propertyName);
OnWidgetChanged (new WidgetEventArgs (this));
}
}
protected virtual void OnNameChanged (WidgetNameChangedArgs args)

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

@ -1,5 +1,6 @@
using GLib;
using System;
using System.CodeDom;
using System.Collections;
namespace Stetic.Wrapper {
@ -81,5 +82,33 @@ namespace Stetic.Wrapper {
}
}
}
internal protected override void GenerateBuildCode (GeneratorContext ctx, string varName, CodeStatementCollection statements)
{
base.GenerateBuildCode (ctx, varName, statements);
if (((Gtk.Window)Wrapped).DefaultWidth == -1) {
statements.Add (
new CodeAssignStatement (
new CodePropertyReferenceExpression (
new CodeVariableReferenceExpression (varName),
"DefaultWidth"
),
new CodePrimitiveExpression (DesignWidth)
)
);
}
if (((Gtk.Window)Wrapped).DefaultHeight == -1) {
statements.Add (
new CodeAssignStatement (
new CodePropertyReferenceExpression (
new CodeVariableReferenceExpression (varName),
"DefaultHeight"
),
new CodePrimitiveExpression (DesignHeight)
)
);
}
}
}
}

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

@ -312,7 +312,7 @@
</object>
<object type="Gtk.Arrow,gtk-sharp"
label="Arrow" icon="arrow.png" palette-category="widget">
label="Arrow" icon="arrow.png" palette-category="widget" init-properties="ArrowType ShadowType">
<itemgroups>
<itemgroup label="Arrow Properties">
<property name="ArrowType" />
@ -722,7 +722,7 @@
<object type="Gtk.Entry,gtk-sharp"
label="Entry" icon="entry.png" palette-category="widget"
hexpandable="true">
hexpandable="true" wrapper="Stetic.Wrapper.Entry">
<itemgroups>
<itemgroup label="Entry Properties">
<property name="Text" translatable="true" />
@ -1177,7 +1177,7 @@
<object type="Gtk.RadioButton,gtk-sharp" wrapper="Stetic.Wrapper.RadioButton"
label="Radio Button" icon="radiobutton.png" palette-category="widget"
hexpandable="true">
hexpandable="true" init-properties="Label">
<itemgroups>
<itemgroup label="Radio Button Properties">
<property ref="Gtk.CheckButton.Label" />
@ -1342,7 +1342,7 @@
</object>
<object type="Gtk.SpinButton,gtk-sharp" wrapper="Stetic.Wrapper.SpinButton"
label="Spin Button" icon="spinbutton.png" palette-category="widget">
label="Spin Button" icon="spinbutton.png" palette-category="widget" init-properties="Lower Upper StepIncrement">
<itemgroups>
<itemgroup label="Range Properties">
<property name="Adjustment.Lower" />
@ -1394,7 +1394,7 @@
</object>
<object type="Gtk.Table,gtk-sharp" wrapper="Stetic.Wrapper.Table"
label="Table" icon="table.png" palette-category="container">
label="Table" icon="table.png" palette-category="container" init-properties="NRows NColumns Homogeneous">
<itemgroups>
<itemgroup label="Table Properties">
<property name="NRows" />
@ -1877,7 +1877,7 @@
<object type="Gtk.FileChooserWidget,gtk-sharp" wrapper="Stetic.Wrapper.Widget"
label="File Chooser Widget" icon="fileselection.png" palette-category="widget"
hexpandable="true" vexpandable="true">
hexpandable="true" vexpandable="true" init-properties="Action">
<itemgroups>
<itemgroup label="File Chooser Widget Properties">
<property name="Action" />
@ -2003,6 +2003,9 @@
</internal-children>
</object>
<object type="Stetic.ErrorWidget" wrapper="Stetic.ErrorWidgetWrapper">
</object>
<enum type="Gdk.ExtensionMode,gdk-sharp">
<value name="None" label="None"
description="No extension events are desired" />

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

@ -0,0 +1,263 @@
using System;
using System.Reflection;
using System.CodeDom;
using System.CodeDom.Compiler;
using System.IO;
namespace Stetic
{
public static class CodeGenerator
{
static CodeExpression bindingFlags;
static CodeGenerator ()
{
CodeTypeReferenceExpression flagsType = new CodeTypeReferenceExpression ("System.Reflection.BindingFlags");
bindingFlags = new CodeBinaryOperatorExpression (
new CodeFieldReferenceExpression (flagsType, "Public"),
CodeBinaryOperatorType.BitwiseOr,
new CodeFieldReferenceExpression (flagsType, "NonPublic")
);
bindingFlags = new CodeBinaryOperatorExpression (
bindingFlags,
CodeBinaryOperatorType.BitwiseOr,
new CodeFieldReferenceExpression (flagsType, "Instance")
);
}
public static void GenerateProjectCode (string file, string namespaceName, CodeDomProvider provider, params Project[] projects)
{
CodeCompileUnit cunit = new CodeCompileUnit ();
CodeNamespace cns = new CodeNamespace (namespaceName);
cunit.Namespaces.Add (cns);
GenerateProjectCode (cns, projects);
ICodeGenerator gen = provider.CreateGenerator ();
StreamWriter fileStream = new StreamWriter (file);
try {
gen.GenerateCodeFromCompileUnit (cunit, fileStream, new CodeGeneratorOptions ());
} finally {
fileStream.Close ();
}
}
public static void GenerateProjectCode (CodeNamespace cns, params Project[] projects)
{
bool multiProject = projects.Length > 1;
CodeTypeDeclaration type = new CodeTypeDeclaration ("Gui");
cns.Types.Add (type);
CodeMemberMethod met = new CodeMemberMethod ();
met.Name = "Build";
type.Members.Add (met);
met.Parameters.Add (new CodeParameterDeclarationExpression (typeof(object), "obj"));
met.Parameters.Add (new CodeParameterDeclarationExpression (typeof(string), "id"));
if (multiProject)
met.Parameters.Add (new CodeParameterDeclarationExpression (typeof(string), "file"));
met.ReturnType = new CodeTypeReference (typeof(void));
met.Attributes = MemberAttributes.Public | MemberAttributes.Static;
CodeVariableReferenceExpression cobj = new CodeVariableReferenceExpression ("obj");
CodeVariableReferenceExpression cfile = new CodeVariableReferenceExpression ("file");
CodeVariableReferenceExpression cid = new CodeVariableReferenceExpression ("id");
CodeVariableDeclarationStatement varDecHash = new CodeVariableDeclarationStatement (typeof(System.Collections.Hashtable), "widgets");
met.Statements.Add (varDecHash);
varDecHash.InitExpression = new CodeObjectCreateExpression (
typeof(System.Collections.Hashtable),
new CodeExpression [0]
);
CodeStatementCollection projectCol = met.Statements;
foreach (Project gp in projects) {
CodeStatementCollection widgetCol;
if (multiProject) {
CodeConditionStatement pcond = new CodeConditionStatement ();
pcond.Condition = new CodeBinaryOperatorExpression (
cfile,
CodeBinaryOperatorType.IdentityEquality,
new CodePrimitiveExpression (gp.Id)
);
projectCol.Add (pcond);
widgetCol = pcond.TrueStatements;
projectCol = pcond.FalseStatements;
} else {
widgetCol = projectCol;
}
foreach (Gtk.Widget w in gp.Toplevels) {
CodeConditionStatement cond = new CodeConditionStatement ();
cond.Condition = new CodeBinaryOperatorExpression (
cid,
CodeBinaryOperatorType.IdentityEquality,
new CodePrimitiveExpression (w.Name)
);
widgetCol.Add (cond);
CodeVariableDeclarationStatement varDec = new CodeVariableDeclarationStatement (w.GetType(), "cobj");
varDec.InitExpression = new CodeCastExpression (w.GetType(), cobj);
cond.TrueStatements.Add (varDec);
Stetic.WidgetMap map = Stetic.CodeGenerator.GenerateBuildCode (w, "cobj", cond.TrueStatements);
Stetic.Wrapper.Widget wwidget = Stetic.Wrapper.Widget.Lookup (w);
BindSignalHandlers (wwidget, wwidget, map, cond.TrueStatements);
widgetCol = cond.FalseStatements;
}
}
// Bind the fields
CodeVariableDeclarationStatement varDecIndex = new CodeVariableDeclarationStatement (typeof(int), "n");
varDecIndex.InitExpression = new CodePrimitiveExpression (0);
CodeExpression varIndex = new CodeVariableReferenceExpression ("n");
CodeVariableDeclarationStatement varDecArray = new CodeVariableDeclarationStatement (typeof(FieldInfo[]), "fields");
varDecArray.InitExpression = new CodeMethodInvokeExpression (
new CodeMethodInvokeExpression (
cobj,
"GetType",
new CodeExpression [0]
),
"GetFields",
bindingFlags
);
met.Statements.Add (varDecArray);
CodeVariableReferenceExpression varArray = new CodeVariableReferenceExpression ("fields");
CodeIterationStatement iteration = new CodeIterationStatement ();
met.Statements.Add (iteration);
iteration.InitStatement = varDecIndex;
iteration.TestExpression = new CodeBinaryOperatorExpression (
varIndex,
CodeBinaryOperatorType.LessThan,
new CodePropertyReferenceExpression (varArray, "Length")
);
iteration.IncrementStatement = new CodeAssignStatement (
varIndex,
new CodeBinaryOperatorExpression (
varIndex,
CodeBinaryOperatorType.Add,
new CodePrimitiveExpression (1)
)
);
CodeVariableDeclarationStatement varDecField = new CodeVariableDeclarationStatement (typeof(FieldInfo), "field");
varDecField.InitExpression = new CodeArrayIndexerExpression (varArray, new CodeExpression [] {varIndex});
CodeVariableReferenceExpression varField = new CodeVariableReferenceExpression ("field");
iteration.Statements.Add (varDecField);
CodeVariableDeclarationStatement varDecWidget = new CodeVariableDeclarationStatement (typeof(object), "widget");
iteration.Statements.Add (varDecWidget);
varDecWidget.InitExpression = new CodeIndexerExpression (
new CodeVariableReferenceExpression ("widgets"),
new CodePropertyReferenceExpression (varField, "Name")
);
CodeVariableReferenceExpression varWidget = new CodeVariableReferenceExpression ("widget");
// Make sure the type of the field matches the type of the widget
CodeConditionStatement fcond = new CodeConditionStatement ();
iteration.Statements.Add (fcond);
fcond.Condition = new CodeBinaryOperatorExpression (
new CodeBinaryOperatorExpression (
varWidget,
CodeBinaryOperatorType.IdentityInequality,
new CodePrimitiveExpression (null)
),
CodeBinaryOperatorType.BooleanAnd,
new CodeMethodInvokeExpression (
new CodePropertyReferenceExpression (varField, "FieldType"),
"IsInstanceOfType",
varWidget
)
);
// Set the variable value
fcond.TrueStatements.Add (
new CodeMethodInvokeExpression (
varField,
"SetValue",
cobj,
varWidget
)
);
}
static void BindSignalHandlers (Stetic.Wrapper.Widget rootWidget, Stetic.Wrapper.Widget widget, Stetic.WidgetMap map, CodeStatementCollection statements)
{
foreach (Stetic.Wrapper.Signal signal in widget.Signals) {
TypedSignalDescriptor descriptor = signal.SignalDescriptor as TypedSignalDescriptor;
if (descriptor == null) continue;
CodeExpression createDelegate =
new CodeMethodInvokeExpression (
new CodeTypeReferenceExpression (typeof(Delegate)),
"CreateDelegate",
new CodeTypeOfExpression (descriptor.HandlerTypeName),
new CodeVariableReferenceExpression (map.GetWidgetId (rootWidget.Wrapped.Name)),
new CodePrimitiveExpression (signal.Handler));
createDelegate = new CodeCastExpression (descriptor.HandlerTypeName, createDelegate);
CodeAttachEventStatement cevent = new CodeAttachEventStatement (
new CodeEventReferenceExpression (
new CodeVariableReferenceExpression (map.GetWidgetId (widget.Wrapped.Name)),
descriptor.Name),
createDelegate);
statements.Add (cevent);
}
Gtk.Container cont = widget.Wrapped as Gtk.Container;
if (cont != null) {
foreach (Gtk.Widget child in cont.AllChildren) {
Stetic.Wrapper.Widget ww = Stetic.Wrapper.Widget.Lookup (child);
if (ww != null)
BindSignalHandlers (rootWidget, ww, map, statements);
}
}
}
public static WidgetMap GenerateBuildCode (Gtk.Widget w, string widgetVarName, CodeStatementCollection statements)
{
statements.Add (new CodeCommentStatement ("Widget " + w.Name));
GeneratorContext ctx = new ProjectGeneratorContext ();
Stetic.Wrapper.Widget ww = Stetic.Wrapper.Widget.Lookup (w);
ctx.GenerateBuildCode (ww, widgetVarName, statements);
return ctx.WidgetMap;
}
}
class ProjectGeneratorContext: GeneratorContext
{
public ProjectGeneratorContext (): base ("w")
{
}
public override void GenerateBuildCode (Wrapper.Widget widget, string varName, CodeStatementCollection statements)
{
base.GenerateBuildCode (widget, varName, statements);
statements.Add (
new CodeAssignStatement (
new CodeIndexerExpression (
new CodeVariableReferenceExpression ("widgets"),
new CodePrimitiveExpression (widget.Wrapped.Name)
),
new CodeVariableReferenceExpression (varName)
)
);
}
}
}

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

@ -35,7 +35,7 @@ namespace Stetic {
widget = wrapper.Wrapped;
if (widget == context) {
item = LabelItem (context);
item = LabelItem (widget);
item.Sensitive = false;
Add (item);
}
@ -44,7 +44,7 @@ namespace Stetic {
item.Activated += DoSelect;
Add (item);
ClassDescriptor klass = Registry.LookupClass (widget.GetType ());
ClassDescriptor klass = wrapper.ClassDescriptor;
if (klass != null) {
foreach (ItemDescriptor id in klass.ContextMenu) {
CommandDescriptor cmd = (CommandDescriptor)id;
@ -60,7 +60,7 @@ namespace Stetic {
}
}
BuildContextMenu (wrapper.ParentWrapper, true, wrapper.InternalChildId != null, widget == context, context);
BuildContextMenu (wrapper.ParentWrapper, true, wrapper.InternalChildProperty != null, widget == context, context);
}
void BuildContextMenu (Stetic.Wrapper.Widget parentWrapper, bool occupied, bool isInternal, bool top, Widget context)
@ -146,21 +146,25 @@ namespace Stetic {
{
ImageMenuItem item;
Label label;
label = new Label (widget is Placeholder ? "Placeholder" : widget.Name);
label.UseUnderline = false;
label.SetAlignment (0.0f, 0.5f);
item = new ImageMenuItem ();
item.Add (label);
ClassDescriptor klass = Registry.LookupClass (widget.GetType ());
if (klass != null) {
Gdk.Pixbuf pixbuf = klass.Icon;
int width, height;
Gtk.Icon.SizeLookup (Gtk.IconSize.Menu, out width, out height);
item.Image = new Gtk.Image (pixbuf.ScaleSimple (width, height, Gdk.InterpType.Bilinear));
Wrapper.Widget wrapper = Stetic.Wrapper.Widget.Lookup (widget);
if (wrapper != null) {
ClassDescriptor klass = wrapper.ClassDescriptor;
if (klass != null) {
Gdk.Pixbuf pixbuf = klass.Icon;
int width, height;
Gtk.Icon.SizeLookup (Gtk.IconSize.Menu, out width, out height);
item.Image = new Gtk.Image (pixbuf.ScaleSimple (width, height, Gdk.InterpType.Bilinear));
}
}
return item;
}
}

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

@ -15,19 +15,23 @@ namespace Stetic {
XmlDocument doc = new XmlDocument ();
doc.PreserveWhitespace = true;
doc.Load (filename);
project.Id = System.IO.Path.GetFileName (filename);
doc = GladeUtils.XslImportTransform (doc);
XmlNode node = doc.SelectSingleNode ("/glade-interface");
if (node == null)
throw new ApplicationException ("Not a glade file according to node name");
project.BeginGladeImport ();
foreach (XmlElement toplevel in node.SelectNodes ("widget")) {
Wrapper.Container wrapper = Stetic.ObjectWrapper.GladeImport (project, toplevel) as Wrapper.Container;
if (wrapper != null)
project.AddWidget ((Gtk.Widget)wrapper.Wrapped);
try {
project.BeginGladeImport ();
foreach (XmlElement toplevel in node.SelectNodes ("widget")) {
Wrapper.Container wrapper = Stetic.ObjectWrapper.Read (project, toplevel, FileFormat.Glade) as Wrapper.Container;
if (wrapper != null)
project.AddWidget ((Gtk.Widget)wrapper.Wrapped);
}
} finally {
project.EndGladeImport ();
}
project.EndGladeImport ();
}
public static void Export (Project project, string filename)
@ -43,11 +47,11 @@ namespace Stetic {
if (wrapper == null)
continue;
XmlElement elem = wrapper.GladeExport (doc);
XmlElement elem = wrapper.Write (doc, FileFormat.Glade);
if (elem != null)
toplevel.AppendChild (elem);
}
doc = GladeUtils.XslExportTransform (doc);
// FIXME; if you use UTF8, it starts with a BOM???

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

@ -1,8 +1,10 @@
pkglib_DATA = libsteticui.dll libsteticui.dll.config
pkglib_DATA = libsteticui.dll libsteticui.dll.config libsteticui.dll.mdb
libsteticui_dll_sources = \
Clipboard.cs \
CodeGenerator.cs \
ContextMenu.cs \
Glade.cs \
Grid.cs \
Palette.cs \
Project.cs \

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

@ -38,6 +38,13 @@ namespace Stetic {
public Palette () : base (false, 2)
{
groups = new Hashtable ();
Registry.RegistryChanged += OnRegistryChanged;
}
public override void Dispose ()
{
Registry.RegistryChanged -= OnRegistryChanged;
base.Dispose ();
}
public Palette (Project project): this ()
@ -53,6 +60,11 @@ namespace Stetic {
}
}
void OnRegistryChanged (object o, EventArgs args)
{
LoadWidgets (project);
}
public void LoadWidgets (Project project)
{
foreach (Group g in groups.Values)

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

@ -1,15 +1,21 @@
using Gtk;
using System;
using System.Xml;
using System.Collections;
using System.CodeDom;
namespace Stetic {
public class Project : IProject {
public class Project : IProject, IDisposable {
Hashtable nodes;
NodeStore store;
bool modified;
internal bool Syncing;
Gtk.Widget selection;
string id;
string fileName;
XmlDocument tempDoc;
bool loading;
public event Wrapper.WidgetNameChangedHandler WidgetNameChanged;
public event Wrapper.WidgetEventHandler WidgetAdded;
@ -20,13 +26,127 @@ namespace Stetic {
public event Wrapper.SignalChangedEventHandler SignalChanged;
public event SelectedHandler Selected;
public event EventHandler ModifiedChanged;
public event IProjectDelegate GladeImportComplete;
// Fired when the project has been reloaded, due for example to
// a change in the registry
public event EventHandler ProjectReloaded;
public Project ()
{
nodes = new Hashtable ();
store = new NodeStore (typeof (ProjectNode));
Registry.RegistryChanging += OnRegistryChanging;
Registry.RegistryChanged += OnRegistryChanged;
}
public void Dispose ()
{
Registry.RegistryChanging -= OnRegistryChanging;
Registry.RegistryChanged -= OnRegistryChanged;
foreach (Gtk.Widget w in Toplevels)
w.Destroy ();
}
public string FileName {
get { return fileName; }
}
public void Load (string fileName)
{
this.fileName = fileName;
Id = System.IO.Path.GetFileName (fileName);
XmlDocument doc = new XmlDocument ();
doc.PreserveWhitespace = true;
doc.Load (fileName);
Read (doc);
}
public void Read (XmlDocument doc)
{
loading = true;
try {
// Clean the existing tree
foreach (Gtk.Widget w in Toplevels)
w.Destroy ();
selection = null;
store.Clear ();
nodes.Clear ();
XmlNode node = doc.SelectSingleNode ("/stetic-interface");
if (node == null)
throw new ApplicationException ("Not a Stetic file according to node name");
foreach (XmlElement toplevel in node.SelectNodes ("widget")) {
Wrapper.Container wrapper = Stetic.ObjectWrapper.Read (this, toplevel, FileFormat.Native) as Wrapper.Container;
if (wrapper != null)
AddWidget ((Gtk.Widget)wrapper.Wrapped);
}
} finally {
loading = false;
}
}
public void Save (string fileName)
{
this.fileName = fileName;
XmlDocument doc = Write ();
XmlTextWriter writer = new XmlTextWriter (fileName, System.Text.Encoding.UTF8);
writer.Formatting = Formatting.Indented;
doc.Save (writer);
writer.Close ();
}
public XmlDocument Write ()
{
XmlDocument doc = new XmlDocument ();
doc.PreserveWhitespace = true;
XmlElement toplevel = doc.CreateElement ("stetic-interface");
doc.AppendChild (toplevel);
foreach (Widget w in Toplevels) {
Stetic.Wrapper.Container wrapper = Stetic.Wrapper.Container.Lookup (w);
if (wrapper == null)
continue;
XmlElement elem = wrapper.Write (doc, FileFormat.Native);
if (elem != null)
toplevel.AppendChild (elem);
}
return doc;
}
void OnRegistryChanging (object o, EventArgs args)
{
// Store a copy of the current tree. The tree will
// be recreated once the registry change is completed.
tempDoc = Write ();
Selection = null;
}
void OnRegistryChanged (object o, EventArgs args)
{
if (tempDoc != null) {
Read (tempDoc);
tempDoc = null;
if (ProjectReloaded != null)
ProjectReloaded (this, EventArgs.Empty);
}
}
public string Id {
get { return id; }
set { id = value; }
}
public bool Modified {
@ -68,14 +188,14 @@ namespace Stetic {
Stetic.Wrapper.Widget ww = Stetic.Wrapper.Widget.Lookup (widget);
if (ww == null)
return;
ww.WidgetChanged += OnWidgetChanged;
ww.NameChanged += OnWidgetNameChanged;
ww.SignalAdded += OnSignalAdded;
ww.SignalRemoved += OnSignalRemoved;
ww.SignalChanged += OnSignalChanged;
ProjectNode node = new ProjectNode (widget);
ProjectNode node = new ProjectNode (ww);
nodes[widget] = node;
if (parent == null) {
if (position == -1)
@ -92,7 +212,8 @@ namespace Stetic {
parent = node;
OnWidgetAdded (new Stetic.Wrapper.WidgetEventArgs (ww));
if (!loading)
OnWidgetAdded (new Stetic.Wrapper.WidgetEventArgs (ww));
Stetic.Wrapper.Container container = Stetic.Wrapper.Container.Lookup (widget);
if (container != null) {
@ -110,14 +231,16 @@ namespace Stetic {
ww.SignalAdded -= OnSignalAdded;
ww.SignalRemoved -= OnSignalRemoved;
ww.SignalChanged -= OnSignalChanged;
((Gtk.Widget)ww.Wrapped).Destroyed -= WidgetDestroyed;
OnWidgetRemoved (new Stetic.Wrapper.WidgetEventArgs (ww));
if (!loading)
OnWidgetRemoved (new Stetic.Wrapper.WidgetEventArgs (ww));
nodes.Remove (node.Widget);
for (int i = 0; i < node.ChildCount; i++)
UnhashNodeRecursive (node[i] as ProjectNode);
}
void RemoveNode (ProjectNode node)
{
UnhashNodeRecursive (node);
@ -228,21 +351,23 @@ namespace Stetic {
Modified = true;
}
public IEnumerable Toplevels {
public Gtk.Widget[] Toplevels {
get {
ArrayList list = new ArrayList ();
foreach (Widget w in nodes.Keys) {
if (w is Gtk.Window)
Wrapper.Widget wrapper = Wrapper.Widget.Lookup (w);
if (wrapper != null && wrapper.IsTopLevel)
list.Add (w);
}
return list;
return (Gtk.Widget[]) list.ToArray (typeof(Gtk.Widget));
}
}
public void DeleteWindow (Widget window)
public void RemoveWidget (Container widget)
{
store.RemoveNode (nodes[window] as ProjectNode);
nodes.Remove (window);
ProjectNode node = nodes[widget] as ProjectNode;
store.RemoveNode (node);
UnhashNodeRecursive (node);
}
public NodeStore Store {
@ -293,7 +418,7 @@ namespace Stetic {
return tooltips;
}
}
public void PopupContextMenu (Stetic.Wrapper.Widget wrapper)
{
Gtk.Menu m = new ContextMenu (wrapper);
@ -314,16 +439,15 @@ namespace Stetic {
}
return null;
}
public event IProjectDelegate GladeImportComplete;
public void BeginGladeImport ()
{
;
loading = true;
}
public void EndGladeImport ()
{
loading = false;
if (GladeImportComplete != null)
GladeImportComplete ();
}
@ -352,10 +476,10 @@ namespace Stetic {
Widget widget;
ClassDescriptor klass;
public ProjectNode (Gtk.Widget widget)
public ProjectNode (Stetic.Wrapper.Widget wrapper)
{
this.widget = widget;
klass = Registry.LookupClass (widget.GetType ());
this.widget = (Widget) wrapper.Wrapped;
klass = wrapper.ClassDescriptor;
}
public Widget Widget {

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

@ -37,16 +37,24 @@ namespace Stetic {
public Project Project {
get { return project; }
set {
if (project != null)
if (project != null) {
project.Selected -= WidgetSelected;
project.ProjectReloaded -= OnProjectReloaded;
}
project = value;
if (project != null) {
NodeStore = project.Store;
project.Selected += WidgetSelected;
project.ProjectReloaded += OnProjectReloaded;
}
}
}
void OnProjectReloaded (object o, EventArgs a)
{
NodeStore = project.Store;
}
Stetic.Wrapper.Widget SelectedWrapper {
get {
ITreeNode[] nodes = NodeSelection.SelectedNodes;

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

@ -29,6 +29,8 @@ namespace Stetic {
lab.Markup = "<i>No selection</i>";
PackStart (lab, false, false, 0);
noSelection = lab;
Stetic.Registry.RegistryChanging += new EventHandler (OnRegistryChanging);
}
public PropertyGrid (Project project): this ()
@ -36,6 +38,20 @@ namespace Stetic {
this.Project = project;
}
public override void Dispose ()
{
base.Dispose ();
}
void OnRegistryChanging (object o, EventArgs args)
{
cachedGroups.Clear ();
Clear ();
foreach (Gtk.Widget w in Children)
if (! (w is PropertyGridHeader))
Remove (w);
}
public Project Project {
get { return project; }
set {
@ -47,7 +63,7 @@ namespace Stetic {
Selected (null, null);
}
}
void Clear ()
{
if (selection != null) {
@ -55,7 +71,6 @@ namespace Stetic {
selection = null;
}
foreach (Gtk.Widget w in Children)
// Remove (w);
w.Hide ();
}
@ -82,7 +97,7 @@ namespace Stetic {
selection = newSelection;
if (selection == null) {
if (selection == null || selection.Wrapped is ErrorWidget) {
noSelection.Show ();
return false;
}
@ -91,14 +106,14 @@ namespace Stetic {
selection.Notify += Notified;
klass = Registry.LookupClass (selection.Wrapped.GetType ());
klass = selection.ClassDescriptor;
header.AttachObject (selection.Wrapped);
AppendItemGroups (klass, selection.Wrapped);
packingSelection = Stetic.Wrapper.Container.ChildWrapper (selection);
if (packingSelection != null) {
klass = Registry.LookupClass (packingSelection.Wrapped.GetType ());
klass = packingSelection.ClassDescriptor;
if (klass.ItemGroups.Count > 0) {
AppendItemGroups (klass, packingSelection.Wrapped);
packingSelection.Notify += Notified;
@ -167,9 +182,8 @@ namespace Stetic {
{
PropertyEditor rep = new PropertyEditor (prop);
// FIXME: Make sure all notify events are based on prop names, not propspec
editors[prop.Name] = rep;
if (prop.ParamSpec != null)
editors[prop.ParamSpec.Name] = rep;
AppendPair (prop.Label, rep, prop.Description);
rep.ShowAll ();
@ -237,7 +251,7 @@ namespace Stetic {
public PropertyGridHeader ()
{
name = (PropertyDescriptor)Registry.LookupClass ("GtkWidget") ["Name"];
name = (PropertyDescriptor)Registry.LookupClassByName ("Gtk.Widget") ["Name"];
AppendProperty (name);
Gtk.HBox box = new Gtk.HBox (false, 6);
@ -253,8 +267,9 @@ namespace Stetic {
{
base.AttachObject (ob);
Gtk.Widget w = (Gtk.Widget) ob;
image.Pixbuf = Registry.LookupClass (w.GetType ()).Icon;
label.Text = w.GetType().FullName;
ObjectWrapper wrapper = ObjectWrapper.Lookup (w);
image.Pixbuf = wrapper.ClassDescriptor.Icon;
label.Text = wrapper.ClassDescriptor.WrappedTypeName;
}
}
}

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

@ -22,6 +22,8 @@ namespace Stetic
const int ColSignalObject = 6;
const int ColSignalTextWeight = 7;
public event EventHandler SignalActivated;
public SignalsEditor ()
{
tree = new Gtk.TreeView ();
@ -60,6 +62,7 @@ namespace Stetic
project.SignalAdded -= new SignalEventHandler (OnSignalAddedOrRemoved);
project.SignalRemoved -= new SignalEventHandler (OnSignalAddedOrRemoved);
project.SignalChanged -= new SignalChangedEventHandler (OnSignalChanged);
project.ProjectReloaded -= new EventHandler (OnProjectReloaded);
}
project = value;
@ -68,11 +71,27 @@ namespace Stetic
project.SignalAdded += new SignalEventHandler (OnSignalAddedOrRemoved);
project.SignalRemoved += new SignalEventHandler (OnSignalAddedOrRemoved);
project.SignalChanged += new SignalChangedEventHandler (OnSignalChanged);
project.ProjectReloaded += new EventHandler (OnProjectReloaded);
OnWidgetSelected (null, null);
}
}
void OnProjectReloaded (object s, EventArgs a)
{
OnWidgetSelected (null, null);
}
public Signal SelectedSignal {
get {
Gtk.TreeModel foo;
Gtk.TreeIter iter;
if (!tree.Selection.GetSelected (out foo, out iter))
return null;
return GetSignal (iter);
}
}
void OnWidgetSelected (Gtk.Widget widget, ProjectNode node)
{
selection = Stetic.Wrapper.Widget.Lookup (widget);
@ -99,7 +118,7 @@ namespace Stetic
if (selection == null)
return;
ClassDescriptor klass = Registry.LookupClass (selection.Wrapped.GetType ());
ClassDescriptor klass = selection.ClassDescriptor;
foreach (ItemGroup group in klass.SignalGroups) {
Gtk.TreeIter iter = store.AppendNode ();
@ -168,8 +187,12 @@ namespace Stetic
return;
SignalDescriptor sd = GetSignalDescriptor (iter);
if (sd != null)
AddHandler (iter, "On" + sd.Name);
if (sd != null) {
if (GetSignal (iter) == null)
AddHandler (iter, "On" + sd.Name);
else if (SignalActivated != null)
SignalActivated (this, EventArgs.Empty);
}
}
void OnHandlerEdited (object sender, Gtk.EditedArgs args)

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

@ -1,8 +1,7 @@
pkglib_DATA = stetic.exe
pkglib_DATA = stetic.exe stetic.exe.mdb
bin_SCRIPTS = stetic
stetic_exe_sources = \
Glade.cs \
Stetic.cs \
UIManager.cs

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

@ -1,6 +1,9 @@
using Gtk;
using System;
using System.Collections;
using System.Reflection;
using System.CodeDom;
using System.CodeDom.Compiler;
namespace Stetic {
@ -16,10 +19,73 @@ namespace Stetic {
public static Stetic.UIManager UIManager;
public static Gtk.Window MainWindow;
static string language = "C#";
static ArrayList libraries = new ArrayList ();
public static int Main (string[] args) {
public static int Main (string[] args)
{
Program = new Gnome.Program ("Stetic", "0.0", Gnome.Modules.UI, args);
int n = 0;
while (n < args.Length) {
string arg = args[n];
if (arg.StartsWith ("--language:"))
language = arg.Substring (11);
else if (arg.StartsWith ("-l:"))
language = arg.Substring (3);
else if (arg.StartsWith ("-lib:"))
libraries.Add (arg.Substring (5));
else if (arg.StartsWith ("--library:"))
libraries.Add (arg.Substring (10));
else if (arg == "--generate" || arg == "-g")
break;
n++;
}
if (args.Length - n > 2) {
if (args [n] == "--generate" || args [n] == "-g")
return GenerateCode (args [n+1], args, n+2);
}
if (args.Length == 1 && args [0] == "--help") {
Console.WriteLine ("Stetic - A GTK User Interface Builder");
Console.WriteLine ("Usage:");
Console.WriteLine ("\tstetic [<file>]");
Console.WriteLine ("\tstetic [--language:<language>] [-lib:<library>...] --generate <sourceFile> <projectFile> ...");
return 0;
}
return RunApp (args);
}
static int GenerateCode (string file, string[] args, int n)
{
foreach (string lib in libraries)
Registry.RegisterWidgetLibrary (new AssemblyWidgetLibrary (lib));
Project[] projects = new Project [args.Length - n];
for (int i=n; i<args.Length; i++) {
projects [i - n] = new Project ();
if (System.IO.Path.GetExtension (args [i]) == ".glade")
GladeFiles.Import (projects [i - n], args [i]);
else
projects [i - n].Load (args [i]);
}
CodeDomProvider provider = GetProvider (language);
CodeGenerator.GenerateProjectCode (file, "Stetic", provider, projects);
return 0;
}
static CodeDomProvider GetProvider (string language)
{
return new Microsoft.CSharp.CSharpCodeProvider ();
}
static int RunApp (string[] args)
{
Project = new Project ();
Project.WidgetAdded += OnWidgetAdded;
Project.Selected += OnSelectionChanged;

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

@ -9,6 +9,11 @@ namespace Stetic {
"<ui>" +
" <menubar>" +
" <menu action='FileMenu'>" +
" <menuitem action='Open' />" +
" <separator />" +
" <menuitem action='Save' />" +
" <menuitem action='SaveAs' />" +
" <separator />" +
" <menuitem action='ImportGlade' />" +
" <menuitem action='ExportGlade' />" +
" <separator />" +
@ -34,8 +39,11 @@ namespace Stetic {
{
ActionEntry[] entries = new ActionEntry[] {
new ActionEntry ("FileMenu", null, "_File", null, null, null),
new ActionEntry ("ImportGlade", Stock.Open, "_Import from Glade File...", null, "Import UI from a Glade file", ImportGlade),
new ActionEntry ("ExportGlade", Stock.SaveAs, "_Export to Glade File...", null, "Export UI to a Glade file", ExportGlade),
new ActionEntry ("Open", Stock.Open, null, "<control>O", "Open a file", OpenFile),
new ActionEntry ("Save", Stock.Save, null, "<control>S", "Save", SaveFile),
new ActionEntry ("SaveAs", Stock.SaveAs, null, "<control><shift>S", "Save As", SaveFileAs),
new ActionEntry ("ImportGlade", null, "_Import from Glade File...", null, "Import UI from a Glade file", ImportGlade),
new ActionEntry ("ExportGlade", null, "_Export to Glade File...", null, "Export UI to a Glade file", ExportGlade),
new ActionEntry ("Quit", Stock.Quit, null, "<control>Q", "Quit", Quit),
new ActionEntry ("EditMenu", null, "_Edit", null, null, null),
@ -93,6 +101,46 @@ namespace Stetic {
}
}
void OpenFile (object obj, EventArgs e)
{
FileChooserDialog dialog =
new FileChooserDialog ("Open Stetic File", null, FileChooserAction.Open,
Gtk.Stock.Cancel, Gtk.ResponseType.Cancel,
Gtk.Stock.Open, Gtk.ResponseType.Ok);
int response = dialog.Run ();
if (response == (int)Gtk.ResponseType.Ok)
project.Load (dialog.Filename);
dialog.Hide ();
}
void SaveFile (object obj, EventArgs e)
{
if (project.FileName == null)
SaveFileAs (obj, e);
else
project.Save (project.FileName);
}
void SaveFileAs (object obj, EventArgs e)
{
FileChooserDialog dialog =
new FileChooserDialog ("Save Stetic File As", null, FileChooserAction.Save,
Gtk.Stock.Cancel, Gtk.ResponseType.Cancel,
Gtk.Stock.Save, Gtk.ResponseType.Ok);
if (project.FileName != null)
dialog.CurrentName = project.FileName;
int response = dialog.Run ();
if (response == (int)Gtk.ResponseType.Ok) {
string name = dialog.Filename;
if (System.IO.Path.GetExtension (name) == "")
name = name + ".stetic";
project.Save (name);
}
dialog.Hide ();
}
void ImportGlade (object obj, EventArgs e)
{
FileChooserDialog dialog =
@ -250,7 +298,7 @@ namespace Stetic {
{
Stetic.Wrapper.Widget wrapper = Stetic.Wrapper.Widget.Lookup (selection);
if (wrapper != null)
UpdateEdit (wrapper.InternalChildId == null, true, false);
UpdateEdit (wrapper.InternalChildProperty == null, true, false);
else if (selection is Placeholder)
UpdateEdit (false, false, true);
else

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

@ -1,4 +1,4 @@
#!/bin/sh
export LD_LIBRARY_PATH=@pkglibdir@:$LD_LIBRARY_PATH
exec @MONO@ "$@" @pkglibdir@/stetic.exe
exec @MONO@ --debug @pkglibdir@/stetic.exe "$@"