diff options
author | Krzysztof Marecki <hippiecoder@gmail.com> | 2010-10-28 03:51:25 +0400 |
---|---|---|
committer | Michael Hutchinson <mhutchinson@novell.com> | 2010-10-28 10:03:05 +0400 |
commit | 2778758acfe2a7132b9550a5f5ffca1d1126f8c9 (patch) | |
tree | f38581ceb8f88493b6e9f754bf6e1a8850fead79 /main/src/addins/MonoDevelop.GtkCore2 | |
parent | 7b44f72cb54224ba9889720891bcf83ef09df953 (diff) |
Import MonoDevelop.GtkCore2
Diffstat (limited to 'main/src/addins/MonoDevelop.GtkCore2')
407 files changed, 77817 insertions, 0 deletions
diff --git a/main/src/addins/MonoDevelop.GtkCore2/AssemblyInfo.cs b/main/src/addins/MonoDevelop.GtkCore2/AssemblyInfo.cs new file mode 100644 index 0000000000..8769752524 --- /dev/null +++ b/main/src/addins/MonoDevelop.GtkCore2/AssemblyInfo.cs @@ -0,0 +1,9 @@ +// Autogenerated from MonoDevelop.GtkCore.addin.xml + +using System.Reflection; + +[assembly: AssemblyProduct ("MonoDevelop")] +[assembly: AssemblyTitle ("GTK# Visual Designer")] +[assembly: AssemblyDescription ("Provides support for visual design of GTK# windows, dialogs and widgets.")] +[assembly: AssemblyVersion ("2.4")] +[assembly: AssemblyCopyright ("X11")] diff --git a/main/src/addins/MonoDevelop.GtkCore2/ChangeLog b/main/src/addins/MonoDevelop.GtkCore2/ChangeLog new file mode 100644 index 0000000000..8235e70571 --- /dev/null +++ b/main/src/addins/MonoDevelop.GtkCore2/ChangeLog @@ -0,0 +1,2935 @@ +2010-10-04 Krzysztof Marecki <marecki.krzysztof@gmail.com> + + * MonoDevelop.GtkCore2.csproj: + +2010-09-30 Krzysztof Marecki <marecki.krzysztof@gmail.com> + + * gtk-gui/gui.stetic: + +2010-09-22 Krzysztof Marecki <marecki.krzysztof@gmail.com> + Implements ReloadDesigner commands. + * Makefile.am: + * MonoDevelop.GtkCore2.csproj: + * MonoDevelop.GtkCore2.addin.xml: + * MonoDevelop.GtkCore.Commands/GtkCommands.cs: + * MonoDevelop.GtkCore.Commands/GladeCommands.cs: + * MonoDevelop.GtkCore.GuiBuilder/GuiBuilderView.cs: + * MonoDevelop.GtkCore.GuiBuilder/GuiBuilderProject.cs: + * MonoDevelop.GtkCore.NodeBuilders/ProjectFileNodeBuilderExtension.cs: + * MonoDevelop.GtkCore.NodeBuilders/ProjectFolderNodeBuilderExtension.cs: + + +2010-09-21 Krzysztof Marecki <marecki.krzysztof@gmail.com> + + * MonoDevelop.GtkCore2.csproj: + +2010-09-20 Krzysztof Marecki <marecki.krzysztof@gmail.com> + + * MonoDevelop.GtkCore2.addin.xml: + +2010-09-17 Krzysztof Marecki <marecki.krzysztof@gmail.com> + + * MonoDevelop.GtkCore2.csproj: + +2010-09-17 Krzysztof Marecki <marecki.krzysztof@gmail.com> + Reorganizing project pad menu items. + * MonoDevelop.GtkCore2.csproj: + * MonoDevelop.GtkCore2.addin.xml: + +2010-09-15 Krzysztof Marecki <marecki.krzysztof@gmail.com> + + * gtk-gui/gui.stetic: + * MonoDevelop.GtkCore2.csproj: + * MonoDevelop.GtkCore2.addin.xml: + * MonoDevelop.GtkCore/GtkDesignInfo.cs: + * MonoDevelop.GtkCore/WidgetFileDescriptionTemplate.cs: + * MonoDevelop.GtkCore.NodeBuilders/ProjectNodeBuilder.cs: + * MonoDevelop.GtkCore.NodeBuilders/ProjectFolderNodeBuilderExtension.cs: + + +2010-08-30 Krzysztof Marecki <freefirma@gmail.com> + + * Makefile.am: + * MonoDevelop.GtkCore2.csproj: + +2010-08-27 Krzysztof Marecki <freefirma@gmail.com> + + * Makefile.am: + * MonoDevelop.GtkCore2.csproj: + * MonoDevelop.GtkCore2.addin.xml: + * MonoDevelop.GtkCore2.xbuild.csproj: + +2010-08-17 Krzysztof Marecki <freefirma@gmail.com> + + * Makefile.am: + * MonoDevelop.GtkCore2.csproj: + * MonoDevelop.GtkCore.addin.xml: + +2010-08-16 Krzysztof Marecki <freefirma@gmail.com> + + * MonoDevelop.GtkCore.addin.xml: + +2010-08-15 Krzysztof Marecki <freefirma@gmail.com> + + * MonoDevelop.GtkCore.addin.xml: + +2010-08-15 Krzysztof Marecki <freefirma@gmail.com> + + * Makefile.am: + * MonoDevelop.GtkCore2.csproj: + * MonoDevelop.GtkCore.addin.xml: + +2010-08-09 Krzysztof Marecki <freefirma@gmail.com> + + * Makefile.am: + * MonoDevelop.GtkCore2.csproj: + * MonoDevelop.GtkCore.addin.xml: Add GuiFolderBuilderNode extension + +2010-08-07 Krzysztof Marecki <marecki.krzysztof@gmail.com> + + * MonoDevelop.GtkCore2.csproj: + +2010-08-04 Krzysztof Marecki <freefirma@gmail.com> + + * MonoDevelop.GtkCore2.csproj: + +2010-07-27 Krzysztof Marecki <freefirma@gmail.com> + + * MonoDevelop.GtkCore.GuiBuilder/GuiBuilderView.cs: + Remove autoCommit argument + +2010-07-05 Krzysztof Marecki <marecki.krzysztof@gmail.com> + + * Makefile.am: + * MonoDevelop.GtkCore2.csproj: + * MonoDevelop.GtkCore.addin.xml: + +2010-06-28 Krzysztof Marecki <marecki.krzysztof@gmail.com> + + * MonoDevelop.GtkCore/GtkDesignInfo.cs: + * MonoDevelop.GtkCore.GuiBuilder/GuiBuilderService.cs: + * MonoDevelop.GtkCore.GuiBuilder/GuiBuilderProject.cs: + * MonoDevelop.GtkCore.NodeBuilders/ProjectNodeBuilder.cs: + * MonoDevelop.GtkCore.NodeBuilders/ProjectFileExtension.cs: + * MonoDevelop.GtkCore.NodeBuilders/ProjectFileNodeBuilderExtension.cs: + Fixes fo better file grouping in the project pad + + +2010-06-28 Krzysztof Marecki <marecki.krzysztof@gmail.com> + + * MonoDevelop.GtkCore2.csproj: + +2010-06-23 Krzysztof Marecki <marecki.krzysztof@gmail.com> + Draw action group icon + * gtk-gui/gui.stetic: + * MonoDevelop.GtkCore2.csproj: + * MonoDevelop.GtkCore/GtkDesignInfo.cs: + * MonoDevelop.GtkCore.GuiBuilder/GuiBuilderProject.cs: + * MonoDevelop.GtkCore.NodeBuilders/ProjectNodeBuilder.cs: + * MonoDevelop.GtkCore.NodeBuilders/ProjectFileExtension.cs: + * MonoDevelop.GtkCore.NodeBuilders/ProjectFileNodeBuilderExtension.cs: + +2010-06-23 Krzysztof Marecki <marecki.krzysztof@gmail.com> + + * Makefile.am: + * MonoDevelop.GtkCore2.csproj: + +2010-06-22 Krzysztof Marecki <marecki.krzysztof@gmail.com> + + * Makefile.am: + * MonoDevelop.GtkCore2.csproj: + * MonoDevelop.GtkCore.addin.xml: + * MonoDevelop.GtkCore/GtkDesignInfo.cs: + * MonoDevelop.GtkCore.NodeBuilders/ProjectNodeBuilder.cs: + * MonoDevelop.GtkCore.NodeBuilders/ProjectFileExtension.cs: + * MonoDevelop.GtkCore.NodeBuilders/ProjectFileNodeBuilderExtension.cs: + * MonoDevelop.GtkCore.NodeBuilders/ProjectFolderNodeBuilderExtension.cs: + + +2010-06-16 Krzysztof Marecki <marecki.krzysztof@gmail.com> + + * MonoDevelop.GtkCore.addin.xml: + +2010-06-15 Krzysztof Marecki <marecki.krzysztof@gmail.com> + Changes in the project pad for displaying grouped component files + + * Makefile.am: + * MonoDevelop.GtkCore2.csproj: + * MonoDevelop.GtkCore.addin.xml: + * MonoDevelop.GtkCore/GtkDesignInfo.cs: + * MonoDevelop.GtkCore.GuiBuilder/GuiBuilderService.cs: + * MonoDevelop.GtkCore.NodeBuilders/WindowsFolderNodeBuilder.cs: + * MonoDevelop.GtkCore.NodeBuilders/ProjectFileNodeBuilderExtension.cs: + + +2010-06-09 Krzysztof Marecki <marecki.krzysztof@gmail.com> + + * gtk-gui/gui.stetic: + * MonoDevelop.GtkCore2.csproj: + * MonoDevelop.GtkCore/GtkDesignInfo.cs: Add gtkx files to project + * MonoDevelop.GtkCore.GuiBuilder/GuiBuilderProject.cs: + +2010-06-07 Krzysztof Marecki <marecki.krzysztof@gmail.com> + + * gtk-gui/gui.stetic: + * MonoDevelop.GtkCore/GtkDesignInfo.cs: + * MonoDevelop.GtkCore.GuiBuilder/GuiBuilderProject.cs: + +2010-06-02 Krzysztof Marecki <marecki.krzysztof@gmail.com> + + * Makefile.am: + * MonoDevelop.GtkCore2.csproj: + * MonoDevelop.GtkCore/GtkDesignInfo.cs: + * MonoDevelop.GtkCore.GuiBuilder/GuiBuilderService.cs: + Move generated partial class for components from gtk-gui. + +2010-04-29 Michael Hutchinson <mhutchinson@novell.com> + + * MonoDevelop.GtkCore.GuiBuilder/GuiBuilderService.cs: Track + AddFilesToProject API. + +2010-04-29 Mike Krüger <mkrueger@novell.com> + + * MonoDevelop.GtkCore.GuiBuilder/CombinedDesignView.cs: + ViewContent widgets are now destroyed by the workspace + window. + + +2010-04-27 Mike Krüger <mkrueger@novell.com> + + * MonoDevelop.GtkCore.GuiBuilder/CombinedDesignView.cs: call + destroy on the container vbox during + +2010-04-26 Mike Krüger <mkrueger@novell.com> + + * MonoDevelop.GtkCore/ReferenceManager.cs: Found better work + around for the "gnome-sharp" reference issue. + +2010-04-26 Mike Krüger <mkrueger@novell.com> + + * MonoDevelop.GtkCore/ReferenceManager.cs: Fixed 'Bug 599335 - + Error CS0433: The imported type `Gtk.DeleteEventArgs' is + defined multiple times (CS0433)'. + +2010-03-30 Lluis Sanchez Gual <lluis@novell.com> + + * MonoDevelop.GtkCore.GuiBuilder/GuiBuilderProject.cs: Added + null check. + +2010-03-22 Lluis Sanchez Gual <lluis@novell.com> + + * AssemblyInfo.cs: + * MonoDevelop.GtkCore.addin.xml: Bumped MD version. + +2010-03-18 Lluis Sanchez Gual <lluis@novell.com> + + * MonoDevelop.GtkCore.GuiBuilder/GuiBuilderService.cs: Use the + stock Visual Design layout as layout for stetic. + +2010-03-18 Lluis Sanchez Gual <lluis@novell.com> + + * MonoDevelop.GtkCore.GuiBuilder/ToolboxLoader.cs: + * MonoDevelop.GtkCore.GuiBuilder/GuiBuilderService.cs: Fix + race in SteticApp initialization. + +2010-03-17 Lluis Sanchez Gual <lluis@novell.com> + + * Makefile.am: + * gtk-gui/gui.stetic: + * MonoDevelop.GtkCore.csproj: + * MonoDevelop.GtkCore.addin.xml: + * MonoDevelop.GtkCore/GtkDesignInfo.cs: + * MonoDevelop.GtkCore/ReferenceManager.cs: + * MonoDevelop.GtkCore.GuiBuilder/CodeBinder.cs: + * MonoDevelop.GtkCore/ProjectResourceProvider.cs: + * MonoDevelop.GtkCore.Dialogs/BindDesignDialog.cs: + * MonoDevelop.GtkCore.GuiBuilder/GuiBuilderView.cs: + * MonoDevelop.GtkCore.GuiBuilder/ToolboxProvider.cs: + * MonoDevelop.GtkCore.GuiBuilder/GuiBuilderWindow.cs: + * MonoDevelop.GtkCore.GuiBuilder/GuiBuilderService.cs: + * MonoDevelop.GtkCore.GuiBuilder/GuiBuilderProject.cs: + * MonoDevelop.GtkCore.GuiBuilder/CombinedDesignView.cs: + * MonoDevelop.GtkCore/WidgetFileDescriptionTemplate.cs: + * MonoDevelop.GtkCore.NodeBuilders/WidgetNodeBuilder.cs: + * MonoDevelop.GtkCore.Dialogs/WidgetBuilderOptionPanel.cs: + * MonoDevelop.GtkCore.Dialogs/SelectRenamedClassDialog.cs: + * MonoDevelop.GtkCore.Dialogs/ConfirmWindowDeleteDialog.cs: + * MonoDevelop.GtkCore.NodeBuilders/ActionGroupNodeBuilder.cs: + * MonoDevelop.GtkCore.GuiBuilder/GuiBuilderDisplayBinding.cs: + * MonoDevelop.GtkCore.GuiBuilder/ActionGroupDisplayBinding.cs: + * MonoDevelop.GtkCore.GuiBuilder/GtkProjectServiceExtension.cs: + * MonoDevelop.GtkCore.NodeBuilders/WindowsFolderNodeBuilder.cs: + * MonoDevelop.GtkCore.Dialogs/GtkDesignerOptionsPanelWidget.cs: + * MonoDevelop.GtkCore.NodeBuilders/ProjectFolderNodeBuilderExtension.cs: + Merged MD.Projects into MD.Core, and MD.Projects.Gui, + MD.Core.Gui and MD.Components into MD.Ide. + +2010-02-18 Lluis Sanchez Gual <lluis@novell.com> + + * MonoDevelop.GtkCore.Dialogs/SelectRenamedClassDialog.cs: + Track api changes. + +2010-02-09 Mike Krüger <mkrueger@novell.com> + + * MonoDevelop.GtkCore.Dialogs/SelectRenamedClassDialog.cs: + Track API changes for lazy loading images. + +2010-01-28 Lluis Sanchez Gual <lluis@novell.com> + + * MonoDevelop.GtkCore.Dialogs/GtkFeatureWidget.cs: Track api + changes. + +2010-01-28 Lluis Sanchez Gual <lluis@novell.com> + + * gtk-gui/generated.cs: + * gtk-gui/MonoDevelop.GtkCore.Dialogs.GtkDesignerOptionsPanelWidget.cs: + Flush. + +2010-01-26 Michael Hutchinson <mhutchinson@novell.com> + + * MonoDevelop.GtkCore.GuiBuilder/GuiBuilderDisplayBinding.cs: + * MonoDevelop.GtkCore.GuiBuilder/ActionGroupDisplayBinding.cs: + Track DisplayBinding API. + +2010-01-18 Lluis Sanchez Gual <lluis@novell.com> + + * Makefile.am: + * MonoDevelop.GtkCore.csproj: + * MonoDevelop.GtkCore.GuiBuilder/GuiBuilderService.cs: Format + generated files using the MD formatter to ensure that the + generated text is the same for al platforms and + environments. + + * gtk-gui/gui.stetic: Use global:: for type references in + generated code. + +2009-12-17 Lluis Sanchez Gual <lluis@novell.com> + + * MonoDevelop.GtkCore.GuiBuilder/GtkProjectServiceExtension.cs: + Implement SupportsItem. + + * MonoDevelop.GtkCore.GuiBuilder/GuiBuilderView.cs: When + adding a stock gtk widget to a window there is no need to + update the references. Fixes bug #565492. + + * gtk-gui/generated.cs: + * gtk-gui/MonoDevelop.GtkCore.Dialogs.GtkDesignerOptionsPanelWidget.cs: + Flush. + +2009-12-01 Lluis Sanchez Gual <lluis@novell.com> + + * MonoDevelop.GtkCore.GuiBuilder/GuiBuilderService.cs: + * MonoDevelop.GtkCore.GuiBuilder/GtkProjectServiceExtension.cs: + Introduced the ConfigurationSelector class to all methods + that previously took a configuration name as string. This + eliminates the ambiguity between solution configuration + names and project configuration names. + +2009-11-06 Lluis Sanchez Gual <lluis@novell.com> + + * MonoDevelop.GtkCore.NodeBuilders\WindowsFolder.cs: + Implemented Equals/GetHashCode. Fixes bug #549902 - MD + crashes when adding a new gtk form. + +2009-10-30 Lluis Sanchez Gual <lluis@novell.com> + + * AssemblyInfo.cs: + * MonoDevelop.GtkCore.addin.xml: Bump MD version. + +2009-10-21 Lluis Sanchez Gual <lluis@novell.com> + + * gtk-gui/generated.cs: + * MonoDevelop.GtkCore.csproj: + * gtk-gui/MonoDevelop.GtkCore.Dialogs.GtkDesignerOptionsPanelWidget.cs: + Flush. + + * MonoDevelop.GtkCore.GuiBuilder/GuiBuilderProject.cs: Use + typed collection instead of ArrayList. + +2009-10-16 Mike Krüger <mkrueger@novell.com> + + * MonoDevelop.GtkCore.NodeBuilders/StockIconsNodeBuilder.cs: + Handled icon loading failures. + +2009-10-07 Lluis Sanchez Gual <lluis@novell.com> + + * AssemblyInfo.cs: + * MonoDevelop.GtkCore.addin.xml: Bump MD version. + +2009-09-23 Lluis Sanchez Gual <lluis@novell.com> + + * MonoDevelop.GtkCore.GuiBuilder/CombinedDesignView.cs: Route + commands to the text editor view. Fixes bug #536740 - + Expression evaluator unnecessarily in context menu. + +2009-09-09 Christian Hergert <chris@dronelabs.com> + + * libstetic/editor/Accelerator.cs: + * libstetic/editor/GroupPicker.cs: + * libstetic/editor/TextEditor.cs: + * libstetic/editor/SelectImageDialog.cs: + * libstetic/editor/NonContainerWarningDialog.cs: + * libstetic/editor/TextEditorDialog.cs: + * libstetic/editor/EditIconDialog.cs: + * libstetic/editor/IconSelectorMenu.cs: + * libstetic/editor/Image.cs: + * libstetic/editor/ActionGroupEditor.cs: + * libstetic/editor/StringArray.cs: + * libstetic/editor/EditIconFactoryDialog.cs: + * libstetic/editor/SelectIconDialog.cs: + * MonoDevelop.GtkCore.Dialogs/SelectRenamedClassDialog.cs: + * MonoDevelop.GtkCore.Dialogs/BindDesignDialog.cs: + * MonoDevelop.GtkCore.Dialogs/ConfirmWindowDeleteDialog.cs: + * MonoDevelop.GtkCore.GuiBuilder/GuiBuilderProject.cs: Fixes to + make windows and dialogs Transient to either their parent + window/dialog or the MD root window (when applicable). + +2009-09-01 Lluis Sanchez Gual <lluis@novell.com> + + * MonoDevelop.GtkCore/ProjectResourceProvider.cs: Use real + resource Ids instead of file names. Fixes bug #528309 - + Button Icons are not displayed. + +2009-09-01 Lluis Sanchez Gual <lluis@novell.com> + + * MonoDevelop.GtkCore.NodeBuilders/WindowsFolder.cs: Store the + GuiBuilderProject on which the ChangedEvent was subscribed, + and use that reference when unsubscribing on Dispose. This + is required because the GuiBuilderProject bound to a project + may change. Fixes bug #525421 - Removing gtk-sharp reference + from a project causes it to not function properly. + +2009-08-31 Lluis Sanchez Gual <lluis@novell.com> + + * MonoDevelop.GtkCore.addin.xml: Don't use the text editor + display binding id as reference for registering the designer + view. Use DefaultDisplayBinding instead. Removed unused + supportedFormats attribute. + +2009-08-26 Lluis Sanchez Gual <lluis@novell.com> + + * gtk-gui/gui.stetic: Update gtk# dependency. + +2009-08-26 Lluis Sanchez Gual <lluis@novell.com> + + * MonoDevelop.GtkCore.csproj: Updated dependencies. We now + depend on gtk# 2.12.8, Mono 2.4, and Mono.Addins 0.4. + +2009-08-24 Lluis Sanchez Gual <lluis@novell.com> + + * MonoDevelop.GtkCore.GuiBuilder/GuiBuilderView.cs: + * MonoDevelop.GtkCore.GuiBuilder/ActionGroupView.cs: + * MonoDevelop.GtkCore.GuiBuilder/CombinedDesignView.cs: + * MonoDevelop.GtkCore.GuiBuilder/GuiBuilderDisplayBinding.cs: + Added support for saving and restoring the status of the + designer, including the undo queue. This allows implenting + ISupportsProjectReload. + +2009-08-19 Lluis Sanchez Gual <lluis@novell.com> + + * MonoDevelop.GtkCore.NodeBuilders/FolderNodeBuilder.cs: + * MonoDevelop.GtkCore.NodeBuilders/GuiBuilderProjectNodeBuilder.cs: + Remove unused files. + +2009-08-13 Lluis Sanchez Gual <lluis@novell.com> + + * MonoDevelop.GtkCore/ReferenceManager.cs: + * MonoDevelop.GtkCore.GuiBuilder/ToolboxLoader.cs: + * MonoDevelop.GtkCore.GuiBuilder/GuiBuilderView.cs: + * MonoDevelop.GtkCore.GuiBuilder/GuiBuilderService.cs: Use the + new AssemblyContext class to query and resolve assemblies. + +2009-08-06 Lluis Sanchez Gual <lluis@novell.com> + + * Makefile.am: + * MonoDevelop.GtkCore.csproj: + * MonoDevelop.GtkCore/Counters.cs: + * MonoDevelop.GtkCore.GuiBuilder/GuiBuilderProject.cs: Added + some performance counters. + +2009-07-21 Lluis Sanchez Gual <lluis@novell.com> + + * MonoDevelop.GtkCore.GuiBuilder/GuiBuilderView.cs: + * MonoDevelop.GtkCore.GuiBuilder/ActionGroupView.cs: + * MonoDevelop.GtkCore.GuiBuilder/GuiBuilderDocumentOutline.cs: + Track api changes. + +2009-07-01 Lluis Sanchez Gual <lluis@novell.com> + + * MonoDevelop.GtkCore.GuiBuilder/GuiBuilderView.cs: No more + missing IntPtr constructor exceptions. + +2009-06-23 Lluis Sanchez Gual <lluis@novell.com> + + * MonoDevelop.GtkCore/ProjectResourceProvider.cs: + * MonoDevelop.GtkCore.GuiBuilder/GuiBuilderService.cs: Use the + new DesktopService instead of PlatformService. + +2009-06-15 Michael Hutchinson <mhutchinson@novell.com> + + * MonoDevelop.GtkCore/ReferenceManager.cs: + * MonoDevelop.GtkCore.GuiBuilder/ToolboxLoader.cs: + * MonoDevelop.GtkCore.GuiBuilder/GuiBuilderView.cs: + * MonoDevelop.GtkCore.GuiBuilder/GuiBuilderService.cs: Track + assembly lookup APIs. + +2009-06-09 Lluis Sanchez Gual <lluis@novell.com> + + * MonoDevelop.GtkCore\ProjectResourceProvider.cs: + GetMimeTypeForUri doesn't really support uris. + +2009-06-03 Lluis Sanchez Gual <lluis@novell.com> + + * MonoDevelop.GtkCore/ReferenceManager.cs: + GetGtkAssemblyVersion is expected to return the version and + token, not only the version. + +2009-05-28 Lluis Sanchez Gual <lluis@novell.com> + + * MonoDevelop.GtkCore\ReferenceManager.cs: Don't get the + package version from the gtk# package. Instead, get it from + the first version numbers of the gtk-sharp assembly. That's + necessary because in windows there is no gtk# package. + +2009-05-19 Lluis Sanchez Gual <lluis@novell.com> + + * MonoDevelop.GtkCore.GuiBuilder/GuiBuilderWindow.cs: + * MonoDevelop.GtkCore.NodeBuilders/WidgetNodeBuilder.cs: + * MonoDevelop.GtkCore.NodeBuilders/ActionGroupNodeBuilder.cs: + Workaround for what seems to be a mcs bug. Looks like it + can't properly resolve the implicit conversion of null to + string. + +2009-05-19 Lluis Sanchez Gual <lluis@novell.com> + + * MonoDevelop.GtkCore\GtkDesignInfo.cs: + * MonoDevelop.GtkCore.GuiBuilder\GuiBuilderWindow.cs: + * MonoDevelop.GtkCore.GuiBuilder\GuiBuilderProject.cs: Use the + new FilePath class for handling file and directory paths. + +2009-05-07 Lluis Sanchez Gual <lluis@novell.com> + + * MonoDevelop.GtkCore.GuiBuilder/GuiBuilderView.cs: Don't + create a new drop target list. Use the one defined by + Stetic. + +2009-04-29 Lluis Sanchez Gual <lluis@novell.com> + + * MonoDevelop.GtkCore.csproj: Don't require a specific gtk# + version. + +2009-04-29 Mike Krüger <mkrueger@novell.com> + + * MonoDevelop.GtkCore.addin.xml: gui designer is now before + the text editor (wrong text editor id). + +2009-04-29 Mike Krüger <mkrueger@novell.com> + + * MonoDevelop.GtkCore.GuiBuilder/GuiBuilderDisplayBinding.cs: + * MonoDevelop.GtkCore.GuiBuilder/ActionGroupDisplayBinding.cs: + Track API changes. + +2009-04-29 Mike Krüger <mkrueger@novell.com> + + * MonoDevelop.GtkCore.GuiBuilder/GuiBuilderDisplayBinding.cs: + * MonoDevelop.GtkCore.GuiBuilder/ActionGroupDisplayBinding.cs: + Track API changes. + +2009-04-28 Lluis Sanchez Gual <lluis@novell.com> + + * MonoDevelop.GtkCore/ReferenceManager.cs: Remove vte-sharp + from the gnome libs list, since it now has its own package. + +2009-04-27 Mike Krüger <mkrueger@novell.com> + + * MonoDevelop.GtkCore/GtkDesignInfo.cs: + * MonoDevelop.GtkCore.GuiBuilder/GuiBuilderProject.cs: Track + API changes. + +2009-04-23 Mike Krüger <mkrueger@novell.com> + + * MonoDevelop.GtkCore.GuiBuilder/GuiBuilderView.cs: + * MonoDevelop.GtkCore.GuiBuilder/CombinedDesignView.cs: + Removed unused namespace. + +2009-04-20 Mike Krüger <mkrueger@novell.com> + + * MonoDevelop.GtkCore.NodeBuilders/WidgetNodeBuilder.cs: + * MonoDevelop.GtkCore.Dialogs/SelectRenamedClassDialog.cs: + * MonoDevelop.GtkCore.NodeBuilders/ActionGroupNodeBuilder.cs: + Renamed PixbufService to ImageService. + +2009-04-20 Mike Krüger <mkrueger@novell.com> + + * MonoDevelop.GtkCore.NodeBuilders/WidgetNodeBuilder.cs: + * MonoDevelop.GtkCore.Dialogs/SelectRenamedClassDialog.cs: + * MonoDevelop.GtkCore.NodeBuilders/ActionGroupNodeBuilder.cs: + Track API changes. + +2009-04-16 Lluis Sanchez Gual <lluis@novell.com> + + * MonoDevelop.GtkCore/ReferenceManager.cs: + * MonoDevelop.GtkCore.GuiBuilder/ToolboxLoader.cs: Moved + SystemAssemblyService and related classes to the namespace + MonoDevelop.Core.Assemblies. + +2009-04-15 Lluis Sanchez Gual <lluis@novell.com> + + * AssemblyInfo.cs: + * MonoDevelop.GtkCore.addin.xml: Bump MD version. + +2009-04-15 Lluis Sanchez Gual <lluis@novell.com> + + * MonoDevelop.GtkCore/GtkDesignInfo.cs: + * MonoDevelop.GtkCore/ReferenceManager.cs: + * MonoDevelop.GtkCore.Dialogs/GtkFeatureWidget.cs: + * MonoDevelop.GtkCore.GuiBuilder/ToolboxLoader.cs: + * MonoDevelop.GtkCore.GuiBuilder/GuiBuilderView.cs: + * MonoDevelop.GtkCore.GuiBuilder/GuiBuilderProject.cs: + * MonoDevelop.GtkCore.GuiBuilder/GuiBuilderService.cs: + * MonoDevelop.GtkCore/WidgetFileDescriptionTemplate.cs: + * MonoDevelop.GtkCore.Dialogs/WidgetBuilderOptionPanel.cs: Add + support for multiple target runtimes. + +2009-03-17 Mike Krüger <mkrueger@novell.com> + + * MonoDevelop.GtkCore.GuiBuilder/GuiBuilderProject.cs: + * MonoDevelop.GtkCore.GuiBuilder/GuiBuilderDisplayBinding.cs: + Track API changes. + +2009-03-10 Lluis Sanchez Gual <lluis@novell.com> + + * MonoDevelop.GtkCore/GtkDesignInfo.cs: When the stetic files + are generated for the first time, ensure that their write + date is < the write date of the .stetic file, otherwise they + won't be regenerated when building. Fixes bug #483970 - + [Regression] Default C# Gtk# app no longer builds. + +2009-03-03 Lluis Sanchez Gual <lluis@novell.com> + + * gtk-gui/gui.stetic: Flush. + +2009-03-02 Lluis Sanchez Gual <lluis@novell.com> + + * MonoDevelop.GtkCore.GuiBuilder/GtkProjectServiceExtension.cs: + Don't try to generate files when not building inside the + IDE. + +2009-02-27 Lluis Sanchez Gual <lluis@novell.com> + + * MonoDevelop.GtkCore/GtkDesignInfo.cs: In + ForceCodeGenerationOnBuild, force a rebuild of the project + too. Fixes bug #472683. + +2009-02-26 Lluis Sanchez Gual <lluis@novell.com> + + * MonoDevelop.GtkCore.csproj: Flush. + +2009-02-26 Mike Kestner <mkestner@novell.com> + + * MonoDevelop.GtkCore/ProjectResourcesProvider.cs: lookup mime + type and use more specific ResourceInfo ctor. [Fixes #475820] + +2009-02-26 Mike Kestner <mkestner@novell.com> + + * libsteticui/WidgetDesignerBackend.cs: implement Delete key + support. [Fixes #470637] + +2009-02-26 Mike Krüger <mkrueger@novell.com> + + * MonoDevelop.GtkCore.GuiBuilder/ToolboxProvider.cs: Added + explicit "Misc" category for localization. + +2009-02-26 Mike Krüger <mkrueger@novell.com> + + * MonoDevelop.GtkCore.GuiBuilder/ToolboxProvider.cs: Worked on + propertygrid localization. + +2009-02-25 Mike Kestner <mkestner@novell.com> + + * libsteticui/ApplicationBackend.cs: Reload the registry libraries + in LoadLibraries, since adding a library doesn't necessarily refresh + an out-of-date previously registered library. + * libsteticui/CecilWidgetLibrary.cs: enhance NeedsReload check to + use a cache refresh and the new change notification so that the + library stays 'dirty' until it's reloaded. + * libsteticui/LibraryCache.cs: add change notification for cache items. + * MonoDevelop.GtkCore.GuiBuilder/GuiBuilderProject.cs: do an update + of the steticapp libs even if the list hasn't changed in case the + contents of any of them have changed. + * MonoDevelop.GtkCore.GuiBuilder/GuiBuilderService.cs: check for + 'dirty' references when regenerating code. [Fixes #472683] + +2009-02-24 Mike Kestner <mkestner@novell.com> + + * MonoDevelop.GtkCore/GtkDesignInfo.cs: only touch the design file + when forcing rebuilds. + * MonoDevelop.GtkCore.GuiBuilder/GuiBuilderService.cs: don't regen + if design file and generated files have equal timestamps to avoid + regenerations on fresh checkouts. [#478894] + +2009-02-23 Lluis Sanchez Gual <lluis@novell.com> + + * MonoDevelop.GtkCore.addin.xml: + * MonoDevelop.GtkCore.NodeBuilders/WidgetNodeBuilder.cs: + * MonoDevelop.GtkCore.NodeBuilders/StockIconsNodeBuilder.cs: + * MonoDevelop.GtkCore.NodeBuilders/ActionGroupNodeBuilder.cs: + * MonoDevelop.GtkCore.NodeBuilders/WindowsFolderNodeBuilder.cs: + Track merge of the project pad context menu. + +2009-02-18 Mike Kestner <mkestner@novell.com> + + * libstetic/wrapper/ScrolledWindow.cs: when the child viewport itself + is being replaced, don't try to remove the viewport from itself. + * libstetic/wrapper/Viewport.cs: add case for when placeholders are + being replaced by scrollable widgets to insert the new child directly + into the parent scrolled window. [Fixes #404861] + +2009-02-18 Lluis Sanchez Gual <lluis@novell.com> + + * MonoDevelop.GtkCore.Dialogs/WidgetBuilderOptionPanel.cs: Fix + crash when the project's gtk# is not installed. + +2009-02-17 Michael Hutchinson <mhutchinson@novell.com> + + * MonoDevelop.GtkCore.csproj: Set correct resource name for + DrawingArea template. + +2009-02-17 Lluis Sanchez Gual <lluis@novell.com> + + * MonoDevelop.GtkCore/ReferenceManager.cs: + * MonoDevelop.GtkCore.GuiBuilder/GuiBuilderView.cs: Track api + changes. + +2009-02-13 Michael Hutchinson <mhutchinson@novell.com> + + * Makefile.am: Fix build. Looks like the makefiles can't cope + with resources with IDs. + +2009-02-13 Mike Kestner <mkestner@novell.com> + + * Makefile.am: add template resource + * MonoDevelop.GtkCore.addin.xml: ditto. + * templates/DrawingArea.xft.xml: new DrawingArea subclass template + with stubs for OnExposeEvent, OnButtonPressEvent, OnSizeRequested, + OnSizeAllocated, and ctor. Helps speed up the development of custom + drawn widgets. [Fixes #472665] + +2009-02-11 Mike Kestner <mkestner@novell.com> + + * libstetic/Registry.cs: account for reloading of the coreLib, + since this can happen when dogfooding MD. [Fixes #365983] + +2009-02-07 Michael Hutchinson <mhutchinson@novell.com> + + * MonoDevelop.GtkCore.csproj: Remove a local-copy ref. + +2009-02-06 Lluis Sanchez Gual <lluis@novell.com> + + * MonoDevelop.GtkCore.mds: + * MonoDevelop.GtkCore.mdp: + * MonoDevelop.GtkCore.csproj: Migrated to MSBuild file format. + +2009-02-05 Lluis Sanchez Gual <lluis@novell.com> + + * Makefile.am: + * gtk-gui/gui.stetic: + * gtk-gui/generated.cs: + * MonoDevelop.GtkCore.mdp: + * MonoDevelop.GtkCore.addin.xml: + * MonoDevelop.GtkCore.GuiBuilder/GuiBuilderService.cs: + * MonoDevelop.GtkCore.Dialogs/GtkDesignerOptionsPanelWidget.cs: + * gtk-gui/MonoDevelop.GtkCore.Dialogs.GtkDesignerOptionsPanelWidget.cs: + Added option for enabling/disabling auto-switch of the GUI + builder layout. Disabled from now on by default. + +2009-02-04 Mike Kestner <mkestner@novell.com> + + * libstetic/wrapper/objects.xml: explicit default values for Table + NRows and NCols values so they don't default to 1. Fixes #471242. + +2009-02-03 Lluis Sanchez Gual <lluis@novell.com> + + * AssemblyInfo.cs: + * MonoDevelop.GtkCore.addin.xml: Bump MD version. + +2009-02-02 Mike Kestner <mkestner@novell.com> + + * libstetic/PropertyDescriptor.cs: null guard the ValueToString + formatting for string arrays. + +2009-02-02 Mike Kestner <mkestner@novell.com> + + * libstetic/PropertyDescriptor.cs: handle empty string lists + * libstetic/wrapper/ComboBox.cs: some more null guarding for Items. + [Fixes #471244] + +2009-01-30 Michael Hutchinson <mhutchinson@novell.com> + + * MonoDevelop.GtkCore/WidgetFileDescriptionTemplate.cs: Propagate a + policy parent SolutionItem through project/file creation so that + policies can always be resolved correctly. + +2009-01-26 Michael Hutchinson <mhutchinson@novell.com> + + * MonoDevelop.GtkCore.mdp: + * libsteticui/libsteticui.mdp: Flush project format changes. + +2009-01-26 Mike Kestner <mkestner@novell.com> + + * libstetic/wrapper/ActionTree.cs: guard against removing unsaved + actions. [Fixes #443472] + +2009-01-22 Mike Kestner <mkestner@novell.com> + + * libstetic/editor/StringArray.cs: display "(Collection)" in the + label instead of a joined list on \n which displays garbage chars. + This approach is consistent with another very popular IDE. ;-) + * libstetic/wrapper/objects.xml: use Editor.StringArray for the Items + property of ComboBox. + * libstetic/wrapper/ComboBox.cs: switch Items to a string[]. Luckily + this is backwards compat since we currently saved string[] as a newline + join of the member strings. [Fixes #405396] + +2009-01-22 Lluis Sanchez Gual <lluis@novell.com> + + * MonoDevelop.GtkCore.addin.xml: Don't serialize the GtkDesignInfo + element when it is empty. + +2009-01-14 Lluis Sanchez Gual <lluis@novell.com> + + * MonoDevelop.GtkCore.GuiBuilder/GuiBuilderProject.cs: Added missing + nullref check. + +2009-01-13 Mike Kestner <mkestner@novell.com> + + * MonoDevelop.GtkCore.GuiBuilder/GuiBuilderProject.cs: adds a + FileAddedToProject handler which scans the file for classes and + checks the deleted-designs cache for matches to restore to the + project. + +2009-01-13 Mike Kestner <mkestner@novell.com> + + * libsteticui/ProjectBackend.cs (RemoveWidget): export the widget + to a deleted-designs dir for later recovery if necessary. Should + also decide on some cleanup mechanism to remove old designs and + automate recovery in the move case if possible. Or we can wait for + 1wpf which should solve the move case more cleanly. + * MonoDevelop.GtkCore.GuiBuilder/GuiBuilderProject.cs: reenable + OnFileRemovedFromProject handler. Revamp to use a ParseDocument of + the removed file to scan for removed classes to kill. + [Fixes #366392] + +2009-01-09 Mike Kestner <mkestner@novell.com> + + * libsteticui/Project.cs: forward isInternal to the backend in + AddWidgetLibrary. + +2009-01-08 Lluis Sanchez Gual <lluis@novell.com> + + * libsteticui/LibraryCache.cs: Don't ignore internal classes when + looking for widgets. If a widget is internal, set the "internal" flag + to true. Don't abort AddObjects if there is an assembly resolution + error. + +2009-01-08 Mike Kestner <mkestner@novell.com> + + * libsteticui/LibraryCache.cs : delay cache directory creation until + files are going to be written to it. + +2009-01-08 Lluis Sanchez Gual <lluis@novell.com> + + * libsteticui/CecilWidgetLibrary.cs: Don't try to resolve full assembly + paths. + +2008-12-18 Mike Kestner <mkestner@novell.com> + + * libstetic/editor/Flags.cs : fix cs0030 under new mcs. + * libstetic/editor/FlagsSelectionDialog.cs : fix cs0030 under new mcs. + * libstetic/editor/ResponseId.cs : fix cs0030 under new mcs. + +2008-12-13 Mike Kestner <mkestner@novell.com> + + * libstetic/wrapper/Container.cs: generate tooltips based on the target + version, using the new Tooltip API for >= 2.12. Fixes #372015. + +2008-12-12 Lluis Sanchez Gual <lluis@novell.com> + + * MonoDevelop.GtkCore/WidgetParser.cs: Properly search for subclasses of + Gtk.Widget. + +2008-12-12 Lluis Sanchez Gual <lluis@novell.com> + + * MonoDevelop.GtkCore.mdp: + * libsteticui/libsteticui.mdp: All projects now require fx 3.5. + +2008-12-11 Lluis Sanchez Gual <lluis@novell.com> + + * MonoDevelop.GtkCore.GuiBuilder/GuiBuilderService.cs: Remove the mono + version number comment from the generated files. + +2008-12-11 Lluis Sanchez Gual <lluis@novell.com> + + * MonoDevelop.GtkCore/ReferenceManager.cs: Track API changes. + +2008-12-09 Michael Hutchinson <mhutchinson@novell.com> + + * MonoDevelop.GtkCore.GuiBuilder/GuiBuilderDocumentOutline.cs: Use an + Alignment as the concrete Bin instead of custom InvisibleFrame. + +2008-12-09 Lluis Sanchez Gual <lluis@novell.com> + + * MonoDevelop.GtkCore.mdp: Don't require a specific version of + Mono.Addins. + +2008-12-07 Lluis Sanchez Gual <lluis@novell.com> + + * MonoDevelop.GtkCore/WidgetParser.cs: Optimized GetToolboxItems. + +2008-12-07 Lluis Sanchez Gual <lluis@novell.com> + + * MonoDevelop.GtkCore/WidgetParser.cs: + * MonoDevelop.GtkCore/ObjectsDocument.cs: Getting the list of widgets is + an expensive operation. It shouldn't be a property. + +2008-12-02 Michael Hutchinson <mhutchinson@novell.com> + + * Makefile.am: + * AssemblyInfo.cs: + * MonoDevelop.GtkCore.mdp: Add AssemblyInfo.cs files that are + autogenerated from the addin manifests. + +2008-12-01 Mike Kestner <mkestner@novell.com> + + * libstetic/wrapper/objects.xml: move ToggleButton ahead of CheckButton + and add ToggleButton signal item group to CheckButton. Remove toggled + signal from RadioButton since it inherits it from CheckButton. + [Fixes #450237] + +2008-11-25 Mike Kestner <mkestner@novell.com> + + * MonoDevelop.GtkCore/GtkCoreService.cs: refactor the default and + supported version checks into the ReferenceManager, with all the other + package and assembly code. + * MonoDevelop.GtkCore/ReferenceManager.cs: refactored default and + supported version properties. + * MonoDevelop.GtkCore/WidgetFileDescriptionTemplate.cs: use new api. + * MonoDevelop.GtkCore.Dialogs/GtkFeatureWidget.cs: use new api. + * MonoDevelop.GtkCore.Dialogs/WidgetBuilderOptionPanel.cs: use new api. + +2008-11-23 Mike Kestner <mkestner@novell.com> + + * *: I've typed lib/stetic/libstetic(ui) a few too many times. + +2008-11-18 Mike Kestner <mkestner@novell.com> + + * */Makefile.am: break the gnome/gconf-sharp dependencies. + * MonoDevelop.GtkCore.GuiBuilder/GuiBuilderService.cs: set up + callbacks to the PlatformService for MIME resolution and showing + urls. + +2008-11-11 Mike Kestner <mkestner@novell.com> + + * MonoDevelop.GtkCore.GuiBuilder/GuiBuilderProject.cs: use the + new ForceUpdate method on the ProjectDom returned by GetParserContext + to ensure a fully updated database. + +2008-11-11 Mike Kestner <mkestner@novell.com> + + * MonoDevelop.GtkCore.GuiBuilder/CodeBinder.cs: null guarding for + all the things that can possibly go wrong with the parse in + GetClass. + +2008-11-10 Lluis Sanchez Gual <lluis@novell.com> + + * MonoDevelop.GtkCore.GuiBuilder/GuiBuilderProject.cs: Create the + formInfos list when the project is loaded. This is necessary since + the list is destroyed when the project is unloaded. Fixes bug #Bug + 431723 - Cannot build GTK applications with sln format. + +2008-11-06 Mike Kestner <mkestner@novell.com> + + * MonoDevelop.GtkCore.NodeBuilders/ProjectFolderNodeBuilderExtension.cs: + revert the context menu changes. Don't show them if the project has no + gtk-sharp ref, only add the templates to the dialog, per Lluis. + +2008-11-06 Mike Kestner <mkestner@novell.com> + + * MonoDevelop.GtkCore/WidgetFileDescriptionTemplate.cs: + * MonoDevelop.GtkCore.NodeBuilders/ProjectFolderNodeBuilderExtension.cs: + show Add Widget|Window|Dialog|ActionGroup template items in the context + menu and Add File dialog even when the project has no Gtk# reference. + +2008-11-05 Mike Kestner <mkestner@novell.com> + + * MonoDevelop.GtkCore.GuiBuilder/GuiBuilderView.cs: needed to revert + the >= to <= change from the 440435 fix since the refmgr is now + reporting TargetGtkVersion without Version=. oops. + +2008-11-05 Mike Kestner <mkestner@novell.com> + + * MonoDevelop.GtkCore/ReferenceManager.cs: strip Version= out of + TargetGtkVersion. + +2008-11-05 Lluis Sanchez Gual <lluis@novell.com> + + * MonoDevelop.GtkCore.addin.xml: Bump MD version. + +2008-10-30 Mike Kestner <mkestner@novell.com> + + * MonoDevelop.GtkCore/ReferenceManager.cs: + * MonoDevelop.GtkCore.GuiBuilder/GuiBuilderProject.cs: + * MonoDevelop.GtkCore.GuiBuilder/GuiBuilderView.cs: + switch to a x.y TargetGtkVersion obtained by parsing the gtk-sharp + reference version. Invert the version comparison in the toolboxitem + filter. We want toolbox items that are less than the project target + version, not greater. Fixes #440435. + +2008-10-30 Lluis Sanchez Gual <lluis@novell.com> + + * MonoDevelop.GtkCore.GuiBuilder/GuiBuilderService.cs: Don't notify the + file has changed unless the changes are saved to disk. Fixes bug + #430497 - Widget names created in Stetic not available for + autocomplete. + +2008-10-29 Mike Kestner <mkestner@novell.com> + + * MonoDevelop.GtkCore.GuiBuilder/GuiBuilderView.cs (ShowPage): only + regenerate the dummy structure when switching to the source page. + +2008-10-28 Mike Kestner <mkestner@novell.com> + + * MonoDevelop.GtkCore/ReferenceManager.cs: switch default updating + to use the current assembly StoredReference version. Avoids problems + when the stored version has no corresponding installed package. + Fixes #436246. + +2008-10-27 Mike Kestner <mkestner@novell.com> + + * MonoDevelop.GtkCore.GuiBuilder/GuiBuilderProject.cs: don't store + configuration on Project Save. Avoids a crash due to file availability + when saving config while loading and it's extraneous since we store + the config on app exit and it contains no project specific props. + +2008-10-22 Mike Kestner <mkestner@novell.com> + + * MonoDevelop.GtkCore/GtkDesignInfo.cs (HasDesignedObjects): guard + against null projects. + +2008-10-21 Mike Kestner <mkestner@novell.com> + + * MonoDevelop.GtkCore/GtkDesignInfo.cs (HasDesignedObjects): don't + instantiate just to get the SteticFile. Avoids project file garbage. + [Fixes #436201] + +2008-10-21 Mike Kestner <mkestner@novell.com> + + * MonoDevelop.GtkCore.GuiBuilder/CodeBinder.cs: guard against null + documents returned from parse. I think this is related to the old + ErrorsDuringCompile check that was commented with the new parser port. + [Fixes #436998] + +2008-10-05 Mike Krüger <mkrueger@novell.com> + + * MonoDevelop.GtkCore.GuiBuilder/GuiBuilderService.cs: fixed TODO. + +2008-10-03 Mike Kestner <mkestner@novell.com> + + * MonoDevelop.GtkCore.GuiBuilder/GuiBuilderDisplayBinding: + rework GetWindow method. now uses the ParsedDocument for a requested + file to check if any of its types have a GuiBuilderWindow. + The existing method of walking the project windows list and using + the ProjectDom database to lookup their file locations is susceptible + to timing problems due to imcomplete parse databases. This method is + probably slightly more efficient as well. + +2008-10-01 Michael Hutchinson <mhutchinson@novell.com> + + * MonoDevelop.GtkCore/GtkDesignInfo.cs, + MonoDevelop.GtkCore/ProjectResourceProvider.cs, + MonoDevelop.GtkCore.GuiBuilder/GuiBuilderService.cs: Track API. + +2008-09-23 Mike Kestner <mkestner@novell.com> + + * MonoDevelop.GtkCore.GuiBuilder/CombinedDesignView.cs: bandaid to + avoid exceptions when removing non-existent buttons. Fixes #377414. + +2008-09-23 Mike Kestner <mkestner@novell.com> + + * lib/stetic/libsteticui/CecilWidgetLibrary.cs: don't hold assembly + reference beyond load operation. Recreate it on each load so we are + always accessing the current assembly instance. Only access cache + using filename. Ensure Class description lookups cause spew to + console. + * lib/stetic/libsteticui/LibraryCache.cs: enhance the path lookup + logic in Refresh to avoid some churn on named lookups. + * lib/stetic/libsteticui/ProjectBackend.cs: reload library if + necessary before getting component types. Fixes #427334. + +2008-09-17 Lluis Sanchez Gual <lluis@novell.com> + + * MonoDevelop.GtkCore.mdp: Updated projects. + +2008-09-15 Mike Kestner <mkestner@novell.com> + + * MonoDevelop.GtkCode.GuiBuilder/GtkProjectServiceExtension.cs: + add the project stetic file to any generation warnings produced. + Fixes #373244. + +2008-09-12 Lluis Sanchez Gual <lluis@novell.com> + + * lib/libsteticui.mdp, lib/libstetic.mdp, lib/gtk-gui/generated.cs, + gtk-gui/generated.cs: Updated generated code. + +2008-09-12 Lluis Sanchez Gual <lluis@novell.com> + + * MonoDevelop.GtkCore.GuiBuilder/ActionGroupDisplayBinding.cs, + MonoDevelop.GtkCore.GuiBuilder/CodeBinder.cs, + MonoDevelop.GtkCore.GuiBuilder/GuiBuilderProject.cs, + MonoDevelop.GtkCore.GuiBuilder/GuiBuilderService.cs, + MonoDevelop.GtkCore.GuiBuilder/GuiBuilderWindow.cs, + MonoDevelop.GtkCore/WidgetFileDescriptionTemplate.cs, + MonoDevelop.GtkCore/WidgetParser.cs: Track api changes. + +2008-09-11 Mike Krüger <mkrueger@novell.com> + + * MonoDevelop.GtkCore.GuiBuilder/CodeBinder.cs: Changes caused by + interface changes. + +2008-09-04 Lluis Sanchez Gual <lluis@novell.com> + + * MonoDevelop.GtkCore.NodeBuilders/ProjectFolderNodeBuilderExtension.cs, + MonoDevelop.GtkCore.NodeBuilders/StockIconsNodeBuilder.cs, + MonoDevelop.GtkCore.NodeBuilders/WidgetNodeBuilder.cs, + MonoDevelop.GtkCore.NodeBuilders/ProjectNodeBuilder.cs, + MonoDevelop.GtkCore.NodeBuilders/WindowsFolderNodeBuilder.cs, + MonoDevelop.GtkCore.NodeBuilders/ActionGroupNodeBuilder.cs: Moved + the extensible tree view to its own directory. + +2008-08-27 Mike Kestner <mkestner@novell.com> + + * MonoDevelop.GtkCore/WidgetFileDesciptionTemplate.cs: perform a + project save after the file insertions and updates. This seems + suboptimal, since it would probably be better to mark the project + dirty and let the user save the project, but until we switch to + one-widget-per-design-file, we probably need to save the project + automatically to avoid problems. + Fixes #385712. + +2008-08-27 Mike Kestner <mkestner@novell.com> + + * MonoDevelop.GtkCore.NodeBuilders/ProjectFolderNodeBuilderExtension.cs: + Restrict to DotNetProjects and verify ProjectFolders are for DNPs. + Fixes #412448. + +2008-08-22 Mike Kestner <mkestner@novell.com> + + Fixes bug #413275 and delays more GtkDesignInfo-related project file + churn. + * MonoDevelop.GtkCore/GtkCoreService.cs: init the refmgr on startup. + * MonoDevelop.GtkCore/GtkDesignInfo.cs: Remove targetVersion field and + associated prop. Move reference updating logic to Ref Manager. Target + Version is now exclusively tracked via reference version by the + ReferenceManager. + * MonoDevelop.GtkCore/ReferenceManager.cs: new class to encapsulate all + reference management behaviors, from responding to user add removes to + automated updates for designer projects. + * MonoDevelop.GtkCore.Dialogs/GtkFeatureWidget.cs: only show feature + for projects which support refactoring, since it advertises designer + support and that's not available without refactoring yet. Use refmgr + for version updates. + * MonoDevelop.GtkCore.Dialogs/WidgetBuilderOptionsPanel.cs: use refmgr + for version info and suppress gettext options if no designed objects + exist. + * MonoDevelop.GtkCore.GuiBuilder/GuiBuilderProject.cs: use refmgr for + target version. + +2008-08-20 Michael Hutchinson <mhutchinson@novell.com> + + * MonoDevelop.GtkCore.NodeBuilders/WindowsFolderNodeBuilder.cs: Remove + the "resources folder" feature. Resources are now shown in the + solution tree like any other files. For a detailed explanation see + "Bug 381430 - [PATCH] Display resource files in main project tree". + +2008-08-19 Mike Kestner <mkestner@novell.com> + + * MonoDevelop.GtkCore.GuiBuilder/GuiBuilderProject.cs: revert a silly + change that was causing explicit paths to be inserted into gui.stetic + files for gac references. [Fixes #412960] + +2008-08-19 Mike Krüger <mkrueger@novell.com> + + * MonoDevelop.GtkCore.GuiBuilder/GuiBuilderProject.cs: fixed issue in + GetSourceCodeFile. + +2008-08-19 Mike Krüger <mkrueger@novell.com> + + * MonoDevelop.GtkCore.GuiBuilder/GuiBuilderProject.cs: fixed some + possible nullrefs. + +2008-08-19 Mike Krüger <mkrueger@novell.com> + + * MonoDevelop.GtkCore.mdp, lib/libsteticui.mdp: re-set project + references (fix some libstetic.dll not found issue, localcopy == + true was missing). + +2008-08-18 Mike Kestner <mkestner@novell.com> + + * MonoDevelop.GtkCore/GtkDesignInfo.cs: make HasDesignedObjects + and SupportsDesigner static so that we can defer a few more instance + creation scenarios. + * MonoDevelop.GtkCore/WidgetFileDescriptionTemplate.cs: + * MonoDevelop.GtkCore.Dialogs/GtkFeatureWidget.cs: + * MonoDevelop.GtkCore.Dialogs/WidgetBuilderOptionPanel.cs: + * MonoDevelop.GtkCore.GuiBuilder/ActionGroupDisplayBinding.cs: + * MonoDevelop.GtkCore.GuiBuilder/GtkProjectServiceExtension.cs: + * MonoDevelop.GtkCore.GuiBuilder/GuiBuilderDisplayBinding.cs: + * MonoDevelop.GtkCore.GuiBuilder/GuiBuilderService.cs: + * MonoDevelop.GtkCore.NodeBuilders/ProjectFolderNodeBuilderExtension.cs: + * MonoDevelop.GtkCore.NodeBuilders/ProjectNodeBuilder.cs: + Update to new static API. + +2008-08-08 Michael Hutchinson <mhutchinson@novell.com> + + * MonoDevelop.GtkCore.GuiBuilder/CombinedDesignView.cs: Add a null + check. + +2008-08-04 Mike Krüger <mkrueger@novell.com> + + * MonoDevelop.GtkCore.GuiBuilder/GuiBuilderProject.cs: fixed possible + null references in the unload method. + +2008-08-01 Lluis Sanchez Gual <lluis@novell.com> + + * MonoDevelop.GtkCore/GtkDesignInfo.cs: Fix crash when looking for + designed objects in a project that doesn't support it. + +2008-07-31 Mike Krüger <mkrueger@novell.com> + + * MonoDevelop.GtkCore.GuiBuilder/GuiBuilderProject.cs: Fixed some + issues. + +2008-07-29 Mike Krüger <mkrueger@novell.com> + + * MonoDevelop.GtkCore/WidgetFileDescriptionTemplate.cs, + MonoDevelop.GtkCore.Dialogs/WidgetBuilderOptionPanel.cs, + MonoDevelop.GtkCore.GuiBuilder/ActionGroupDisplayBinding.cs, + MonoDevelop.GtkCore.GuiBuilder/GuiBuilderService.cs, + MonoDevelop.GtkCore.GuiBuilder/GuiBuilderWindow.cs, + MonoDevelop.GtkCore.GuiBuilder/CombinedDesignView.cs: Translated + old code to new dom. + +2008-07-29 Mike Krüger <mkrueger@novell.com> + + * MonoDevelop.GtkCore/GtkDesignInfo.cs, + MonoDevelop.GtkCore/ObjectsDocument.cs, + MonoDevelop.GtkCore.GuiBuilder/ActionGroupDisplayBinding.cs, + MonoDevelop.GtkCore.GuiBuilder/GuiBuilderWindow.cs, + MonoDevelop.GtkCore.GuiBuilder/CodeBinder.cs: Changes for converted + refactoring infrastructure. + +2008-07-27 Mike Krüger <mkrueger@novell.com> + + * MonoDevelop.GtkCore/GtkDesignInfo.cs, + MonoDevelop.GtkCore/WidgetParser.cs, + MonoDevelop.GtkCore/ObjectsDocument.cs, + MonoDevelop.GtkCore.Dialogs/SelectRenamedClassDialog.cs, + MonoDevelop.GtkCore.GuiBuilder/ActionGroupDisplayBinding.cs, + MonoDevelop.GtkCore.GuiBuilder/GuiBuilderProject.cs, + MonoDevelop.GtkCore.GuiBuilder/GuiBuilderWindow.cs, + MonoDevelop.GtkCore.GuiBuilder/ActionGroupView.cs, + MonoDevelop.GtkCore.GuiBuilder/GuiBuilderView.cs, + MonoDevelop.GtkCore.GuiBuilder/ClassUtils.cs, + MonoDevelop.GtkCore.GuiBuilder/CodeBinder.cs: Worked on code + completion/new dom. + +2008-07-24 Mike Kestner <mkestner@novell.com> + + * MonoDevelop.GtkCore.GuiBuilder/GuiBuilderProject.cs: get paths + for gac references to simplify the lookup in stetic. + +2008-07-23 Mike Kestner <mkestner@novell.com> + + * MonoDevelop.GtkCore.GuiBuilder/ActionGroupDisplayBinding.cs: + * MonoDevelop.GtkCore.GuiBuilder/GuiBuilderDisplayBinding.cs: + Use HasDesignedObjects not SupportsDesigner. + +2008-07-23 Mike Kestner <mkestner@novell.com> + + * MonoDevelop.GtkCore/GtkDesignInfo.cs: delay creation of guifolder + until GuiBuilderProject is accessed. Refactor Bind into a Project + property to gather all the connect/disconnects together. Add new + HasDesignedObjects prop for when SupportsDesigner doesn't cut it. + * MonoDevelop.GtkCore.NodeBuilders/ProjectNodeBuilder.cs: use new + HasDesignedObjects prop. + * MonoDevelop.GtkCore.Dialogs/WidgetBuilderOptionPanel.cs: + * MonoDevelop.GtkCore.Dialogs/GtkFeatureWidget.cs: don't + need to update the folder for these options any more. + * MonoDevelop.GtkCore.GuiBuilder/ActionGroupDisplayBinding.cs: get + GuiBuilderProject from design info directly. + * MonoDevelop.GtkCore.GuiBuilder/GuiBuilderService.cs: kill + BeforeCompile handler and GetGuiBuilderProject method. Use new + HasDesignedObjects to control code generation. + * MonoDevelop.GtkCore.GuiBuilder/GtkProjectServiceExtension.cs: kill + GenerateSteticCode field. It was always set to true. Use new + HasDesignedObjects prop to control generation. + +2008-07-22 Mike Kestner <mkestner@novell.com> + + * MonoDevelop.GtkCore/GtkDesignInfo.cs: Connect to project file + events and trigger objects.xml updates. Translate a confirm button + label. Require AddAttribute refactoring. + * MonoDevelop.GtkCore/ObjectsDocument.cs: new class reinstating some + old document updating code and adding some new. Inserts ToolBoxItem + and Category attrs into sources for a first-time "upgrade" to enable + the attr-sync feature now controlled by a root attribute on the + document. + * MonoDevelop.GtkCore/WidgetParser.cs: new class reinstating some + old parsing code and adding some new. This will become the home + for all source parsing in the addin. Refactoring to come... + * MonoDevelop.GtkCore.GuiBuilder/GuiBuilderProject.cs: Add WidgetParser + prop. Remove Debug spew. + +2008-07-21 Lluis Sanchez Gual <lluis@novell.com> + + * MonoDevelop.GtkCore.GuiBuilder/ToolboxProvider.cs, + MonoDevelop.GtkCore/GtkDesignInfo.cs: Moved serialization engine to + MonoDevelop.Core. Use new syntax for specifying attribute scope. + +2008-07-15 Mike Kestner <mkestner@novell.com> + + * MonoDevelop.GtkCore/GtkDesignInfo.cs: add an updatingVersion + state to prevent warning when we are adjusting reference versions. + +2008-07-15 Mike Kestner <mkestner@novell.com> + + * MonoDevelop.GtkCore/GtkDesignInfo.cs: add a user confirmation for + disabling the designer on reference removal. Leave the stetic.gui + and objects.xml files on disk, though we still remove them from the + project. + +2008-07-14 Mike Krüger <mkrueger@novell.com> + + * MonoDevelop.GtkCore.GuiBuilder/GuiBuilderProject.cs: Fixed possible + null reference. + +2008-07-10 Mike Kestner <mkestner@novell.com> + + * MonoDevelop.GtkCore/GtkDesignInfo.cs (FromProject): return an + empty instance for non-DotNetProjects which will report false + on SupportsDesigner. + +2008-07-10 Mike Kestner <mkestner@novell.com> + + * MonoDevelop.GtkCore/GtkCoreService.cs: Gutted. Moved everything + that took a Project parameter to GtkDesignInfo. Removed all the + enable/disable/get info methods replaced by GtkDesignInfo.FromProject. + Killed all the objects file updating. Moved designer support checks + to DesignInfo. + * MonoDevelop.GtkCore/GtkDesignInfo.cs: Add FromProject static + method to replace GtkCoreService.GetGtkInfo. Remove ExportedWidgets + and IsWidgetLibrary functionality. Enable and disable designer based + on presence of gtk-sharp reference on projects. Refactor/move code + generation to GuiBuilderProject from UpdateGtkFolder. Kill + GeneratePartialClasses since it's a simple project property access + and all users of GtkDesignInfo access it via the project. Moved + Refactory checks from GtkCoreService to encapsulate SupportsDesigner. + Fix Reference updating checks for Mono.Posix, since the + StoredReference returns a simple name for it. + * MonoDevelop.GtkCore/WidgetFileDescriptionTemplate.cs: switched to + FromProject api. Killed ExportedWidget handling. + * MonoDevelop.GtkCore.Dialogs/GtkFeatureWidget.cs: removed widget + library checkbox. s/Gtk#/GTK# for consistency. Updated to new + DesignInfo API. + * MonoDevelop.GtkCore.Dialogs/WidgetBuilderOptionPanel.cs: removed + all the Exported Widgets and WidgetLibrary tab stuff, simplified to + a vbox and hand-written to remove glade taint. + * MonoDevelop.GtkCore.GuiBuilder/ActionGroupDisplayBinding.cs: + * MonoDevelop.GtkCore.GuiBuilder/ActionGroupView.cs: + * MonoDevelop.GtkCore.GuiBuilder/CodeBinder.cs: + * MonoDevelop.GtkCore.GuiBuilder/GtkProjectServiceExtension.cs: + * MonoDevelop.GtkCore.GuiBuilder/GuiBuilderDisplayBinding.cs: + * MonoDevelop.GtkCore.GuiBuilder/GuiBuilderService.cs: + * MonoDevelop.GtkCore.GuiBuilder/GuiBuilderView.cs: + * MonoDevelop.GtkCore.GuiBuilder/GuiBuilderWindow.cs: + switched to new DesignInfo API. + * MonoDevelop.GtkCore.GuiBuilder/GuiBuilderProject.cs: + switched to new DesignInfo API. moved gui folder file generation + here instead of DesignInfo iterating over builder properties. + * MonoDevelop.GtkCore.GuiBuilder/ToolboxProvider.cs: + Added category mangling for ToolboxItems so that they are placed + by project. + * MonoDevelop.GtkCore.NodeBuilders/ActionGroupNodeBuilder.cs: + * MonoDevelop.GtkCore.NodeBuilders/ProjectFolderNodeBuilderExtension.cs: + * MonoDevelop.GtkCore.NodeBuilders/ProjectNodeBuilder.cs: + * MonoDevelop.GtkCore.NodeBuilders/StockIconsNodeBuilder.cs: + * MonoDevelop.GtkCore.NodeBuilders/WindowsFolder.cs: + * MonoDevelop.GtkCore.NodeBuilders/WindowsFolderNodeBuilder.cs: + switched to new DesignInfo api. + * templates/Widget.xft.xml: add ToolboxItem attr. + * templates/WidgetPartial.xft.xml: add ToolboxItem attr. + +2008-06-04 Lluis Sanchez Gual <lluis@novell.com> + + * MonoDevelop.GtkCore.addin.xml: Bump MD version. + +2008-05-26 Lluis Sanchez Gual <lluis@novell.com> + + * MonoDevelop.GtkCore/GtkDesignInfo.cs: Explicitly set the resource ids + for gui.stetic and objects.xml, since msbuild uses different + default ids. + +2008-05-26 Lluis Sanchez Gual <lluis@novell.com> + + * MonoDevelop.GtkCore/WidgetFileDescriptionTemplate.cs: Track api + changes. + +2008-05-22 Lluis Sanchez Gual <lluis@novell.com> + + * MonoDevelop.GtkCore.addin.xml: Merged the extension points for + project and solution option panels into a single extension point. A + single extension point will now be used for all kinds of items. + Extension conditions can be used to make panels visible only for + some specific item types. + +2008-05-22 Lluis Sanchez Gual <lluis@novell.com> + + * MonoDevelop.GtkCore.GuiBuilder/GtkProjectServiceExtension.cs: + Replaced ICompilerResult/DefaultCompilerResult/CompilerResults by a + new BuildResult class, which has owner information at error level, + so it is possible to know which project generated an error when + building a solution. Updated Task and TaskService to use the new + owner information. + +2008-05-21 Lluis Sanchez Gual <lluis@novell.com> + + * MonoDevelop.GtkCore/GtkDesignInfo.cs, + MonoDevelop.GtkCore/GtkCoreService.cs, + MonoDevelop.GtkCore/WidgetFileDescriptionTemplate.cs, + MonoDevelop.GtkCore/ProjectResourceProvider.cs, + MonoDevelop.GtkCore.addin.xml, + MonoDevelop.GtkCore.NodeBuilders/ProjectFolderNodeBuilderExtension.cs, + MonoDevelop.GtkCore.NodeBuilders/WidgetNodeBuilder.cs, + MonoDevelop.GtkCore.NodeBuilders/ActionGroupNodeBuilder.cs, + MonoDevelop.GtkCore.mdp, + MonoDevelop.GtkCore.Dialogs/WidgetBuilderOptionPanel.cs, + MonoDevelop.GtkCore.Dialogs/GtkFeatureWidget.cs, + MonoDevelop.GtkCore.mds, lib/libsteticui.mdp, lib/libstetic.mdp, + Makefile.am, + MonoDevelop.GtkCore.GuiBuilder/ActionGroupDisplayBinding.cs, + MonoDevelop.GtkCore.GuiBuilder/GuiBuilderDisplayBinding.cs, + MonoDevelop.GtkCore.GuiBuilder/GuiBuilderService.cs, + MonoDevelop.GtkCore.GuiBuilder/GuiBuilderProject.cs, + MonoDevelop.GtkCore.GuiBuilder/GuiBuilderWindow.cs, + MonoDevelop.GtkCore.GuiBuilder/GuiBuilderView.cs, + MonoDevelop.GtkCore.GuiBuilder/GtkProjectServiceExtension.cs, + MonoDevelop.GtkCore.GuiBuilder/CodeBinder.cs, + MonoDevelop.GtkCore.GuiBuilder/ToolboxProvider.cs: New project + model changes. + +2008-05-20 Mike Kestner <mkestner@novell.com> + + * templates/Widget.xft.xml: + * templates/WidgetPartial.xft.xml: + Mark the custom widgets Visible=false to conform to the Gtk convention + of widgets being shown explicitly. [Fixes #364985] + +2008-05-15 Michael Hutchinson <mhutchinson@novell.com> + + * MonoDevelop.GtkCore.GuiBuilder/ToolboxProvider.cs: Track API. Mark up + for property grid. + +2008-05-13 Mike Kestner <mkestner@novell.com> + + * MonoDevelop.GtkCore.GuiBuilder/GuiBuilderService.cs: use new + Stetic.ApplicationFactory api. + +2008-05-07 Michael Hutchinson <mhutchinson@novell.com> + + * MonoDevelop.GtkCore.GuiBuilder/ToolboxProvider.cs: Track API. + +2008-04-30 Michael Hutchinson <mhutchinson@novell.com> + + * MonoDevelop.GtkCore.addin.xml, MonoDevelop.GtkCore.mdp, gtk-gui, + gtk-gui/generated.cs, gtk-gui/gui.stetic, Makefile.am, + icons/pad-widget-tree-16.png, + MonoDevelop.GtkCore.GuiBuilder/GuiBuilderService.cs, + MonoDevelop.GtkCore.GuiBuilder/GuiBuilderView.cs, + MonoDevelop.GtkCore.GuiBuilder/GuiBuilderDocumentOutline.cs, + MonoDevelop.GtkCore.GuiBuilder/GuiBuilderProjectPad.cs: Implement + IOutlinedDocument instead of custom pad. Set GTK# version to 2.8. + +2008-03-07 Lluis Sanchez Gual <lluis@novell.com> + + * MonoDevelop.GtkCore.mdp: Removed unneeded dependency. + +2008-03-04 Mike Krüger <mkrueger@novell.com> + + * MonoDevelop.GtkCore.GuiBuilder/ToolboxProvider.cs: fixed bugfix (thanks + ankit) + +2008-03-04 Mike Krüger <mkrueger@novell.com> + + * MonoDevelop.GtkCore.GuiBuilder/ToolboxProvider.cs: Fixed possible null + reference exception. + +2008-03-04 Mike Krüger <mkrueger@novell.com> + + * MonoDevelop.GtkCore.GuiBuilder/GuiBuilderService.cs, + MonoDevelop.GtkCore.GuiBuilder/GuiBuilderProject.cs, + MonoDevelop.GtkCore.GuiBuilder/GuiBuilderWindow.cs, + MonoDevelop.GtkCore.GuiBuilder/GuiBuilderView.cs, + MonoDevelop.GtkCore.GuiBuilder/CodeBinder.cs: Worked on gnome hig + compliant alerts. + +2008-03-01 Mike Krüger <mkrueger@novell.com> + + * MonoDevelop.GtkCore.GuiBuilder/GuiBuilderProject.cs: Fixed null ref. + +2008-02-29 Mike Krüger <mkrueger@novell.com> + + * MonoDevelop.GtkCore.GuiBuilder/CombinedDesignView.cs: Refactored content + interfaces + +2008-02-28 Lluis Sanchez Gual <lluis@novell.com> + + * lib/libsteticui.mdp: Set correct makefile ver for files. + +2008-02-27 Mike Krüger <mkrueger@novell.com> + + * MonoDevelop.GtkCore.GuiBuilder/ToolboxProvider.cs: Worked on category + support for the toolbox service. + +2008-02-23 Mike Krüger <mkrueger@novell.com> + + * MonoDevelop.GtkCore.mdp, lib/libsteticui.mdp: Removed some unused glade + and gnome-sharp references (only the unused). But I'll continue to + remove glade, we need to lower the dependency tree a bit. + +2008-02-22 Mike Krüger <mkrueger@novell.com> + + * MonoDevelop.GtkCore.GuiBuilder/CombinedDesignView.cs: Added IViewContent + switching logic (but should be done centrally using the secondaryview + paradigmn). + +2008-02-21 Lluis Sanchez Gual <lluis@novell.com> + + * MonoDevelop.GtkCore/GtkDesignInfo.cs: Workaround for mono bug + #350432. + +2008-02-20 Lluis Sanchez Gual <lluis@novell.com> + + * MonoDevelop.GtkCore.NodeBuilders/ActionGroupNodeBuilder.cs, + MonoDevelop.GtkCore.NodeBuilders/WidgetNodeBuilder.cs: Handle the delete + key in TreeViewPad, so it will work event if the shortcut is not + defined. + +2008-01-29 Lluis Sanchez Gual <lluis@novell.com> + + * MonoDevelop.GtkCore.addin.xml, MonoDevelop.GtkCore.mdp, Makefile.am, + icons/pad-widget-tree-16.png: Added widget tree icon. + +2008-01-25 Lluis Sanchez Gual <lluis@novell.com> + + * MonoDevelop.GtkCore.addin.xml: Update MD version. + +2008-01-23 Lluis Sanchez Gual <lluis@novell.com> + + * MonoDevelop.GtkCore.Dialogs/BindDesignDialog.cs, + MonoDevelop.GtkCore.Dialogs/ConfirmWindowDeleteDialog.cs, + MonoDevelop.GtkCore.Dialogs/WidgetBuilderOptionPanel.cs: Made internal + some classes that don't need to be public. + +2008-01-21 Lluis Sanchez Gual <lluis@novell.com> + + * MonoDevelop.GtkCore/GtkDesignInfo.cs, + MonoDevelop.GtkCore.GuiBuilder/GuiBuilderService.cs: Notify file changes + through the FileService. + +2008-01-16 Lluis Sanchez Gual <lluis@novell.com> + + * MonoDevelop.GtkCore.GuiBuilder/GuiBuilderService.cs: Stetic code must be + generated in the GUI thread. Should fix bug #349505. + +2008-01-15 Michael Hutchinson <mhutchinson@novell.com> + + * MonoDevelop.GtkCore.GuiBuilder/GuiBuilderService.cs: Feed default layout + name to Gettext for translation. + +2008-01-15 Michael Hutchinson <mhutchinson@novell.com> + + * templates/WidgetPartial.xft.xml, templates/Widget.xft.xml, + templates/WindowPartial.xft.xml, templates/ActionGroupPartial.xft.xml, + templates/Window.xft.xml, templates/ActionGroup.xft.xml, + templates/DialogPartial.xft.xml, templates/Dialog.xft.xml: Make template + categories translatable. + +2008-01-08 Lluis Sanchez Gual <lluis@novell.com> + + * MonoDevelop.GtkCore.GuiBuilder/CodeBinder.cs: Added null check on the + result of UpdateFile. Should fix bug #352194. + +2008-01-08 Lluis Sanchez Gual <lluis@novell.com> + + * MonoDevelop.GtkCore.NodeBuilders/ProjectFolderNodeBuilderExtension.cs, + MonoDevelop.GtkCore.NodeBuilders/ProjectNodeBuilder.cs, + MonoDevelop.GtkCore/GtkDesignInfo.cs, + MonoDevelop.GtkCore/GtkCoreService.cs, + MonoDevelop.GtkCore/WidgetFileDescriptionTemplate.cs, + MonoDevelop.GtkCore.Dialogs/WidgetBuilderOptionPanel.cs, + MonoDevelop.GtkCore.GuiBuilder/ActionGroupDisplayBinding.cs, + MonoDevelop.GtkCore.GuiBuilder/GuiBuilderService.cs, + MonoDevelop.GtkCore.GuiBuilder/GuiBuilderDisplayBinding.cs, + MonoDevelop.GtkCore.GuiBuilder/GuiBuilderProject.cs, + MonoDevelop.GtkCore.GuiBuilder/GtkProjectServiceExtension.cs: Handle + projects which don't support the GTK# designer. Window and widget + generation options are hidden, and code is never generated. Fixes bug + #350632. + +2007-12-14 Lluis Sanchez Gual <lluis@novell.com> + + * MonoDevelop.GtkCore.GuiBuilder/CodeBinder.cs: Don't update bindings if the + file has syntax errors. May fix bug #347590. + +2007-12-12 Lluis Sanchez Gual <lluis@novell.com> + + * MonoDevelop.GtkCore.addin.xml: Bump add-in versions. + +2007-12-12 Lluis Sanchez Gual <lluis@novell.com> + + * Makefile.am: Update after build reorg. + +2007-12-06 Geoff Norton <gnorton@novell.com> + + * Makefile.am: Only build the GtkCore addin if we have gnome-sharp + available. + +2007-12-04 Lluis Sanchez Gual <lluis@novell.com> + + * MonoDevelop.GtkCore.mdp, lib/libsteticui.mdp, lib/libstetic.mdp, + Makefile.am: Directory reorganization. + +2007-11-20 Lluis Sanchez Gual <lluis@novell.com> + + * gui.glade, MonoDevelop.GtkCore.Dialogs/BindDesignDialog.cs: Removed + Gnome.FileEntry. + +2007-11-09 Michael Hutchinson <mhutchinson@novell.com> + + * MonoDevelop.GtkCore.GuiBuilder/GuiBuilderService.cs, + MonoDevelop.GtkCore.GuiBuilder/GtkProjectServiceExtension.cs: Track + LoggingService API changes. + +2007-11-02 Lluis Sanchez Gual <lluis@novell.com> + + * MonoDevelop.GtkCore.GuiBuilder/ActionGroupDisplayBinding.cs, + MonoDevelop.GtkCore.GuiBuilder/CodeBinder.cs, + MonoDevelop.GtkCore.GuiBuilder/GuiBuilderWindow.cs: Use RootCombine + instead of CurrentOpenCombine when possible. + +2007-10-29 Lluis Sanchez Gual <lluis@novell.com> + + * MonoDevelop.GtkCore.addin.xml: Bump MD version. + +2007-10-29 Lluis Sanchez Gual <lluis@novell.com> + + * MonoDevelop.GtkCore.GuiBuilder/GuiBuilderView.cs: Fix nullref. Happens + when removing a project from a solution while one of the windows of that + project is open. + +2007-10-25 Lluis Sanchez Gual <lluis@novell.com> + + * templates/ActionGroup.xft.xml, templates/ActionGroupPartial.xft.xml, + templates/Dialog.xft.xml, templates/DialogPartial.xft.xml, + templates/Widget.xft.xml, templates/WidgetPartial.xft.xml, + templates/Window.xft.xml, templates/WindowPartial.xft.xml: Use tango + file icons. Removed obsolete icons. + +2007-10-23 Lluis Sanchez Gual <lluis@novell.com> + + * MonoDevelop.GtkCore.Dialogs/GtkFeatureWidget.cs: Track api changes. Added + Description property. + +2007-10-23 Lluis Sanchez Gual <lluis@novell.com> + + * lib/libsteticui.mdp, lib/libstetic.mdp: Project file names updated by + change in MD path functions. + +2007-10-22 Lluis Sanchez Gual <lluis@novell.com> + + * MonoDevelop.GtkCore.mds, Makefile.am: Added custom command for updating + the Stetic sources. + +2007-10-22 Lluis Sanchez Gual <lluis@novell.com> + + * MonoDevelop.GtkCore.addin.xml: Set a more meaningful category name for + addin commands. + * MonoDevelop.GtkCore.mdp, MonoDevelop.GtkCore.mds: Updated. + +2007-10-16 Lluis Sanchez Gual <lluis@novell.com> + + * MonoDevelop.GtkCore.GuiBuilder/GuiBuilderView.cs: If the current selection + can't be deleted, just ignore the delete command, so the default handler + will be executed. Fixes bug #325440. + +2007-10-16 Lluis Sanchez Gual <lluis@novell.com> + + * lib/libstetic.mdp: Fix required gtk# version. + +2007-10-12 Mike Krüger <mkrueger@novell.com> + + * MonoDevelop.GtkCore.NodeBuilders/StockIconsNodeBuilder.cs, + MonoDevelop.GtkCore.NodeBuilders/WidgetNodeBuilder.cs, + MonoDevelop.GtkCore/GtkDesignInfo.cs, + MonoDevelop.GtkCore/GtkCoreService.cs, + MonoDevelop.GtkCore.GuiBuilder/ActionGroupView.cs, + MonoDevelop.GtkCore.GuiBuilder/GuiBuilderView.cs, + MonoDevelop.GtkCore.GuiBuilder/ToolboxProvider.cs: Applied changes that + were neccassary for to the new FileService. + +2007-10-11 Mike Krüger <mkrueger@novell.com> + + * MonoDevelop.GtkCore/WidgetFileDescriptionTemplate.cs: Changed calls for + the new StringParser. + +2007-10-10 Lluis Sanchez Gual <lluis@novell.com> + + * MonoDevelop.GtkCore/GtkDesignInfo.cs: In Bind(), don't subscribe the + NameChanged event at every call. + * MonoDevelop.GtkCore.GuiBuilder/ActionGroupView.cs, + MonoDevelop.GtkCore.GuiBuilder/GuiBuilderView.cs: The designer needs to + be explicitely destroyed. + +2007-10-03 Michael Hutchinson <mhutchinson@novell.com> + + * MonoDevelop.GtkCore.GuiBuilder/ToolboxProvider.cs: No need to implement + IComparable; it's done in the base class now. + +2007-09-27 Lluis Sanchez Gual <lluis@novell.com> + + * MonoDevelop.GtkCore.Dialogs/GtkFeatureWidget.cs: Assign the selected + target gtk# version to the new project. + +2007-09-21 Michael Hutchinson <mhutchinson@novell.com> + + * MonoDevelop.GtkCore/GtkDesignInfo.cs: Use ProjectReference.StoredReference + rather than ProjectReference.Reference, in order to refer to the actual + stored reference string rather than a temporarily bumped version. + +2007-09-21 Lluis Sanchez Gual <lluis@novell.com> + + * MonoDevelop.GtkCore.addin.xml: Bump MD version. + +2007-09-20 Lluis Sanchez Gual <lluis@novell.com> + + * MonoDevelop.GtkCore.GuiBuilder/GuiBuilderService.cs, + MonoDevelop.GtkCore.GuiBuilder/GuiBuilderProject.cs: Implemented an + assembly resolver for the stetic app, so assembly widgets registered + with .pc files can be found. + * MonoDevelop.GtkCore.GuiBuilder/ToolboxLoader.cs: If a widget dll belongs + to a package, store it as a package reference in the toolbox index. + +2007-09-19 Michael Hutchinson <mhutchinson@novell.com> + + * MonoDevelop.GtkCore/GtkDesignInfo.cs: Allow setting TargetGtkVersion to + DefaultGtkVersion when current value is null. + +2007-09-19 Michael Hutchinson <mhutchinson@novell.com> + + * MonoDevelop.GtkCore/GtkDesignInfo.cs: Don't touch GTK# assembly versions + when a target version is not set. Don't use gtkVersion=null to represent + default version. + * MonoDevelop.GtkCore/GtkCoreService.cs: Set TargetGtkVersion on new + projects. Bump default version to 2.8. + +2007-09-17 Michael Hutchinson <mhutchinson@novell.com> + + * MonoDevelop.GtkCore.mdp, lib/libsteticui.mdp, lib/libstetic.mdp, + lib/Makefile.am, MonoDevelop.GtkCore.mds, Makefile.am: Use projects for + imported stetic libraries. + +2007-09-17 Lluis Sanchez Gual <lluis@novell.com> + + * MonoDevelop.GtkCore.GuiBuilder/GuiBuilderService.cs: Removed access to + Component object. + * MonoDevelop.GtkCore.GuiBuilder/GuiBuilderProject.cs: Remove unused method. + +2007-09-13 Lluis Sanchez Gual <lluis@novell.com> + + * MonoDevelop.GtkCore.Dialogs/SelectRenamedClassDialog.cs, + MonoDevelop.GtkCore.Dialogs/WidgetBuilderOptionPanel.cs, + MonoDevelop.GtkCore.Dialogs/BindDesignDialog.cs, + MonoDevelop.GtkCore.Dialogs/ConfirmWindowDeleteDialog.cs: Fix warnings. + +2007-09-13 Michael Hutchinson <mhutchinson@novell.com> + + * lib/stetic, Makefile.am, lib/Makefile.am: Build stetic from + svn:externals. + * lib/libsteticui.dll.config, lib/libstetic.dll.config, + lib/libstetic.dll, lib/libsteticui.dll: Removed. + +2007-09-10 Michael Hutchinson <mhutchinson@novell.com> + + * templates/WidgetPartial.xft.xml, templates/Widget.xft.xml, + templates/WindowPartial.xft.xml, templates/Window.xft.xml, + templates/ActionGroupPartial.xft.xml, templates/ActionGroup.xft.xml, + templates/DialogPartial.xft.xml, templates/Dialog.xft.xml: Remove + deprecated FileOptions element from templates. + +2007-09-10 Lluis Sanchez Gual <lluis@novell.com> + + * lib/libsteticui.dll, lib/libstetic.dll, + MonoDevelop.GtkCore.GuiBuilder/GuiBuilderService.cs, + MonoDevelop.GtkCore.GuiBuilder/GuiBuilderProject.cs, + MonoDevelop.GtkCore.GuiBuilder/ActionGroupView.cs, + MonoDevelop.GtkCore.GuiBuilder/GuiBuilderView.cs, + MonoDevelop.GtkCore.GuiBuilder/CombinedDesignView.cs: Changed the way to + set the active designer (the api changed). Fixed some renaming issues. + * MonoDevelop.GtkCore.GuiBuilder/GuiBuilderProjectPad.cs: Track api changes. + +2007-09-07 Michael Hutchinson <mhutchinson@novell.com> + + * templates/Window.xft.xml: Oops, PartialTypeSupport should be set to + Disabled for non-partial window. + +2007-09-07 Michael Hutchinson <mhutchinson@novell.com> + + * MonoDevelop.GtkCore.mdp, Makefile.am: Updated. + * MonoDevelop.GtkCore/GtkDesignInfo.cs, + MonoDevelop.GtkCore/GtkCoreService.cs: Use DotNetProject.UsePartialTypes + instead of custom setting. + * MonoDevelop.GtkCore/WidgetFileTemplatePartialClass.cs, + MonoDevelop.GtkCore/WidgetFileTemplateFullClass.cs: No longer needed. + * templates/WidgetPartial.xft.xml, templates/Widget.xft.xml, + templates/WindowPartial.xft.xml, templates/Window.xft.xml, + templates/ActionGroupPartial.xft.xml, templates/ActionGroup.xft.xml, + templates/DialogPartial.xft.xml, templates/Dialog.xft.xml: Use + PartialTypes condition instead of custom file template. + +2007-09-04 Lluis Sanchez Gual <lluis@novell.com> + + * lib/libsteticui.dll, lib/libstetic.dll: Updated from stetic module. + Includes fixes for bugs #82671, #82527, #82476, #81763 and #81238. + +2007-08-31 Mike Krüger <mkrueger@novell.com> + + * MonoDevelop.GtkCore.Dialogs/WidgetBuilderOptionPanel.cs, + MonoDevelop.GtkCore.GuiBuilder/GuiBuilderService.cs, + MonoDevelop.GtkCore.GuiBuilder/PropertiesWidget.cs: Changes due to new + property infrastructure. + +2007-08-16 Lluis Sanchez Gual <lluis@novell.com> + + * MonoDevelop.GtkCore/GtkDesignInfo.cs, + MonoDevelop.GtkCore/GtkCoreService.cs: By default use the project name + as category name for new custom widgets. + * lib/libsteticui.dll, lib/libstetic.dll: Updated from stetic module. + * MonoDevelop.GtkCore.GuiBuilder/ToolboxProvider.cs: Don't show the full + name of widgets in the toolbar. + +2007-08-16 Lluis Sanchez Gual <lluis@novell.com> + + * MonoDevelop.GtkCore.GuiBuilder/GuiBuilderProject.cs: In FindClass, make + sure the getUserClass parameter is taken into account when the found + class is not a multi-part class. Fixes bug #82258. + +2007-08-09 Lluis Sanchez Gual <lluis@novell.com> + + * MonoDevelop.GtkCore.addin.xml: Removed the CommandService class. + Everything is done directly with CommandManager. Moved all extension + node types to MD.Components. + +2007-08-09 Lluis Sanchez Gual <lluis@novell.com> + + * MonoDevelop.GtkCore.addin.xml, + MonoDevelop.GtkCore.NodeBuilders/StockIconsNodeBuilder.cs, + MonoDevelop.GtkCore.NodeBuilders/WidgetNodeBuilder.cs, + MonoDevelop.GtkCore.NodeBuilders/WindowsFolderNodeBuilder.cs, + MonoDevelop.GtkCore.NodeBuilders/ActionGroupNodeBuilder.cs, + MonoDevelop.GtkCore.mdp, Makefile.am: Reorganized the extension point + hierarchy. Embedded all add-in manifests as resources. + * lib/libstetic.dll: Updated from stetic module. + +2007-08-08 Lluis Sanchez Gual <lluis@novell.com> + + * MonoDevelop.GtkCore.GuiBuilder/GuiBuilderService.cs: Improved error + reporting. + +2007-08-02 Lluis Sanchez Gual <lluis@novell.com> + + * MonoDevelop.GtkCore.NodeBuilders/WindowsFolderNodeBuilder.cs, + MonoDevelop.GtkCore.GuiBuilder/GuiBuilderService.cs, + MonoDevelop.GtkCore.GuiBuilder/GuiBuilderProject.cs: Converted + DispatchService to a static class. + +2007-08-01 Lluis Sanchez Gual <lluis@novell.com> + + * lib/libstetic.dll: Updated. + +2007-07-31 Lluis Sanchez Gual <lluis@novell.com> + + * lib/libsteticui.dll, lib/libstetic.dll, + MonoDevelop.GtkCore.GuiBuilder/GuiBuilderProject.cs: Fixed some + problems with the target gtk version. It was not assigned to the + stetic project. Also fixed some stock icon rendering issues in + Stetic. + +2007-07-31 Lluis Sanchez Gual <lluis@novell.com> + + * lib/libsteticui.dll, lib/libstetic.dll: Updated from stetic module. + Includes a nullref fix. + +2007-07-30 Lluis Sanchez Gual <lluis@novell.com> + + * lib/libsteticui.dll, lib/libstetic.dll: Updated. + * MonoDevelop.GtkCore.GuiBuilder/GuiBuilderService.cs: Layout switch + delay is not needed anymore. + +2007-07-25 Lluis Sanchez Gual <lluis@novell.com> + + * MonoDevelop.GtkCore.Dialogs/WidgetBuilderOptionPanel.cs: Fix nullref + when gtk support is not enabled. Patch by Chris Howie. + +2007-07-20 Lluis Sanchez Gual <lluis@novell.com> + + * MonoDevelop.GtkCore.NodeBuilders/ProjectFolderNodeBuilderExtension.cs: + Don't try to use the CurrentNode property after adding the file, + since it may have changed. Should fix bug #82123. + * lib/libsteticui.dll, lib/libstetic.dll: Updated from Stetic module. + Fixes bugs #81846 and #82144. + * MonoDevelop.GtkCore.GuiBuilder/GuiBuilderProject.cs: Fix window + source file lookup. + * MonoDevelop.GtkCore.GuiBuilder/GuiBuilderView.cs: Use the new methods + for checking clipboard operations on the current selection. + * MonoDevelop.GtkCore.GuiBuilder/ToolboxProvider.cs: Include the + current project in the list of libraries to show in the toolbox. + Fixes bug #82125. + +2007-07-10 Lluis Sanchez Gual <lluis@novell.com> + + * lib/libsteticui.dll, lib/libstetic.dll: Updated. Fixes bugs 81977, + 81810 and 82052. + +2007-07-10 Lluis Sanchez Gual <lluis@novell.com> + + * MonoDevelop.GtkCore.GuiBuilder/GuiBuilderService.cs, + MonoDevelop.GtkCore.GuiBuilder/GuiBuilderProject.cs, + MonoDevelop.GtkCore.GuiBuilder/ActionGroupView.cs, + MonoDevelop.GtkCore.GuiBuilder/GuiBuilderView.cs, + MonoDevelop.GtkCore.GuiBuilder/CodeBinder.cs: Properly rename + fields when the widget name is changed. Fixes bug #81976. + +2007-07-09 Lluis Sanchez Gual <lluis@novell.com> + + * MonoDevelop.GtkCore.GuiBuilder/GuiBuilderProjectPad.cs: Update the + properties pad when the focus is on the widget tree pad. Fixes bug + #81971. + +2007-07-05 Lluis Sanchez Gual <lluis@novell.com> + + * lib/libsteticui.dll, lib/libstetic.dll: Updated from Stetic module. + * MonoDevelop.GtkCore.GuiBuilder/GuiBuilderService.cs: Added null + check. + * MonoDevelop.GtkCore.GuiBuilder/GuiBuilderView.cs: Track api changes + in DesignerSupport. When adding a project reference to a widget + library, take into account that widgets may be implemented in a + library different from the one providing the widget list. + * MonoDevelop.GtkCore.GuiBuilder/ToolboxProvider.cs: In + GetDynamicItems, only return widgets provided by libraries + referenced by the project. Don't return widgets from libstetic + since those are already included by default in the toolbox. + Implemented IToolboxDefaultProvider. + +2007-07-03 Mike Krüger <mkrueger@novell.com> + + * MonoDevelop.GtkCore.GuiBuilder/GuiBuilderService.cs: Changed a bit + because of the removal of custom collections in the Ide project. + +2007-06-30 Jacob Ilsø Christensen <jacobilsoe@gmail.com> + + * gui.glade: Fixed capitalization. + +2007-06-27 Lluis Sanchez Gual <lluis@novell.com> + + * MonoDevelop.GtkCore.GuiBuilder/ToolboxLoader.cs: Don't show windows + in the toolbox. + * lib/libstetic.dll, lib/libsteticui.dll: Updated from Stetic module. + +2007-06-22 Lluis Sanchez Gual <lluis@novell.com> + + * lib/libsteticui.dll, lib/libstetic.dll: Updated from Stetic module. + +2007-06-20 Lluis Sanchez Gual <lluis@novell.com> + + * gui.glade, MonoDevelop.GtkCore/GtkDesignInfo.cs, + MonoDevelop.GtkCore/GtkCoreService.cs, + MonoDevelop.GtkCore.Dialogs/WidgetBuilderOptionPanel.cs, + MonoDevelop.GtkCore.Dialogs/GtkFeatureWidget.cs: Allow selecting + the target GTK# version of the project. + * MonoDevelop.GtkCore.addin.xml, MonoDevelop.GtkCore.mdp, Makefile.am, + MonoDevelop.GtkCore.GuiBuilder/ToolboxLoader.cs, + MonoDevelop.GtkCore.GuiBuilder/GuiBuilderView.cs, + MonoDevelop.GtkCore.GuiBuilder/ToolboxProvider.cs: Implemented a + toolbox loader, which allows registering assemblies in the toolbox. + When a widget from a toolbox is dropped to a window, MD will now + add a reference to the required assembly. + * lib/libsteticui.dll, lib/libstetic.dll: Updated from stetic module. + +2007-06-11 Lluis Sanchez Gual <lluis@novell.com> + + * lib/libsteticui.dll: One last update. + +2007-06-11 Lluis Sanchez Gual <lluis@novell.com> + + * lib/libsteticui.dll, lib/libstetic.dll: Updated from Stetic module. + +2007-06-11 Lluis Sanchez Gual <lluis@novell.com> + + * MonoDevelop.GtkCore.NodeBuilders/StockIconsNodeBuilder.cs, + MonoDevelop.GtkCore.GuiBuilder/GuiBuilderService.cs, + MonoDevelop.GtkCore.GuiBuilder/GuiBuilderView.cs: Set the import + file callback when editing project stock icons. + * MonoDevelop.GtkCore/ProjectResourceProvider.cs: The GetResources + method only returns resource files now. + * lib/libsteticui.dll, lib/libstetic.dll: Updated from stetic module. + +2007-06-06 Lluis Sanchez Gual <lluis@novell.com> + + * MonoDevelop.GtkCore.addin.xml, + MonoDevelop.GtkCore.GuiBuilder/GuiBuilderProjectPad.cs: Default pad + placement is now specified in the xml file. + +2007-05-31 Lluis Sanchez Gual <lluis@novell.com> + + * MonoDevelop.GtkCore/GtkCoreService.cs: In GetBaseType, use + Project.GetWidgetTypes to get all registered wiget types, including + base widget types (which were not provided by GetComponentTypes). + * lib/libsteticui.dll, lib/libstetic.dll: Updated from stetic module. + Includes fix for bug #81785. + +2007-05-31 Lluis Sanchez Gual <lluis@novell.com> + + * MonoDevelop.GtkCore/GtkCoreService.cs: Don't include non-public + members to the objects.xml file. + +2007-05-30 Lluis Sanchez Gual <lluis@novell.com> + + * MonoDevelop.GtkCore.mdp: Updated. + * MonoDevelop.GtkCore.Dialogs/GtkFeatureWidget.cs: Fix feature message. + * lib/libsteticui.dll, lib/libstetic.dll: Updated from Stetic module. + Includes fixes for bugs #81761, #81758 and #81762. + * MonoDevelop.GtkCore.GuiBuilder/GuiBuilderProject.cs: + (UpdateLibraries) Properly check for library changes. + +2007-05-23 Lluis Sanchez Gual <lluis@novell.com> + + * lib/libsteticui.dll, lib/libstetic.dll: Updated from stetic module. + Fixes bugs #80783 and #81683. + +2007-05-19 Lluis Sanchez Gual <lluis@novell.com> + + * MonoDevelop.GtkCore.mdp, Makefile.am: Added new dependency. + * lib/libsteticui.dll, lib/libstetic.dll: Updated from svn. Fixes bug + #81590. + * MonoDevelop.GtkCore.GuiBuilder/GuiBuilderView.cs: When selecting an + image file in the widget designer, import the file into the + project. + +2007-05-18 Lluis Sanchez Gual <lluis@novell.com> + + * MonoDevelop.GtkCore.GuiBuilder/GuiBuilderService.cs: Added some delay + in the code that changes the workbench layout when selecting the + designer. Fixes bug #80963. + +2007-05-17 Lluis Sanchez Gual <lluis@novell.com> + + * MonoDevelop.GtkCore.addin.xml, MonoDevelop.GtkCore.mdp, Makefile.am, + MonoDevelop.GtkCore.GuiBuilder/GuiBuilderPalettePad.cs: Removed old + palette pad. + * MonoDevelop.GtkCore/GtkCoreService.cs: Set the 'internal' flag for + widgets implemented by private classes. + * lib/libsteticui.dll, lib/libstetic.dll: Updated from svn module. + Fixes bugs #80875, #81261, #81365. + * MonoDevelop.GtkCore.GuiBuilder/GuiBuilderProject.cs: If the project + is a library, add itself as an internal widget library, so widgets + with internal visibility will be shown. + * MonoDevelop.GtkCore.GuiBuilder/CodeBinder.cs: When saving a window, + use the visibility of the class to set the visibility of the + component. Together with all changes done in stetic, fixes bug + #80875. + +2007-05-15 Lluis Sanchez Gual <lluis@novell.com> + + * MonoDevelop.GtkCore.NodeBuilders/WidgetNodeBuilder.cs, + MonoDevelop.GtkCore.NodeBuilders/WindowsFolderNodeBuilder.cs, + MonoDevelop.GtkCore.NodeBuilders/ActionGroupNodeBuilder.cs, + MonoDevelop.GtkCore/GtkDesignInfo.cs, + MonoDevelop.GtkCore/WidgetFileDescriptionTemplate.cs, + MonoDevelop.GtkCore.Dialogs/ConfirmWindowDeleteDialog.cs, + MonoDevelop.GtkCore.GuiBuilder/ActionGroupDisplayBinding.cs, + MonoDevelop.GtkCore.GuiBuilder/GuiBuilderService.cs, + MonoDevelop.GtkCore.GuiBuilder/GuiBuilderProject.cs, + MonoDevelop.GtkCore.GuiBuilder/GuiBuilderWindow.cs, + MonoDevelop.GtkCore.GuiBuilder/ActionGroupView.cs, + MonoDevelop.GtkCore.GuiBuilder/GuiBuilderView.cs, + MonoDevelop.GtkCore.GuiBuilder/CodeBinder.cs: Track api changes in + Stetic. + * MonoDevelop.GtkCore.Dialogs/WidgetBuilderOptionPanel.cs: Delay + library updating until really necessary. + * lib/libsteticui.dll, lib/libstetic.dll: Updated from stetic module. + +2007-05-11 Lluis Sanchez Gual <lluis@novell.com> + + * MonoDevelop.GtkCore.mdp: Copy the .addins.xml file to the output dir. + +2007-05-11 Lluis Sanchez Gual <lluis@novell.com> + + * MonoDevelop.GtkCore.mdp: Copy stetic dlls together with the assembly. + * lib/libsteticui.dll, lib/libstetic.dll: Updated. + +2007-05-09 Lluis Sanchez Gual <lluis@novell.com> + + * MonoDevelop.GtkCore.mdp, Makefile.am: Reference shared assemblies + from the correct location. + +2007-05-04 Wade Berrier <wberrier@novell.com> + * lib/libstetic.dll.config: + * lib/libsteticui.dll.config: + Fix os attribute formats (mono-config.c separates oses by comma, + and ignores or includes the whole string.) + +2007-05-04 Lluis Sanchez Gual <lluis@novell.com> + + * MonoDevelop.GtkCore.addin.xml, MonoDevelop.GtkCore.mdp, Makefile.am: + Migration to Mono.Addins. + +2007-04-26 Lluis Sanchez Gual <lluis@novell.com> + + * MonoDevelop.GtkCore.addin.xml, MonoDevelop.GtkCore.mdp, + MonoDevelop.GtkCore.Dialogs/GtkFeatureWidget.cs, Makefile.am: + Implemented project feature for enabling gtk# support in new + projects. + * MonoDevelop.GtkCore.NodeBuilders/WidgetNodeBuilder.cs, + MonoDevelop.GtkCore.NodeBuilders/ActionGroupNodeBuilder.cs: Use + Menu icon size in the project pad. + * lib/libsteticui.dll, lib/libstetic.dll: Updated from stetic module. + +2007-04-18 Lluis Sanchez Gual <lluis@novell.com> + + * MonoDevelop.GtkCore.NodeBuilders/WidgetNodeBuilder.cs: Show a + relative path in the window delete confirm dialog, since the + absolute path may take too much space. + * MonoDevelop.GtkCore.mdp: Updated. + * lib/libsteticui.dll, lib/libstetic.dll: Updated from stetic module. + * templates/DialogPartial.xft.xml, templates/Dialog.xft.xml: Add + Ok/Cancel buttons by default in new dialogs. + +2007-03-28 Lluis Sanchez Gual <lluis@novell.com> + + * lib/libsteticui.dll, lib/libstetic.dll: Updated from stetic module. + Includes fixes for bugs 81033, 81086, 81239, 81143, 81014 and + 81015. + * MonoDevelop.GtkCore.GuiBuilder/GuiBuilderView.cs: Allow pasting when + a placeholder is selected. Fixes bug #81246. + +2007-03-28 Lluis Sanchez Gual <lluis@novell.com> + + * MonoDevelop.GtkCore.addin.xml, + MonoDevelop.GtkCore.NodeBuilders/StockIconsNodeBuilder.cs, + MonoDevelop.GtkCore.NodeBuilders/WindowsFolderNodeBuilder.cs, + MonoDevelop.GtkCore.mdp, Makefile.am, icons/image-x-generic.png: + Show a "Stock Icons" node in the User Interface folder. It's easier + to discover than the context menu option. + * MonoDevelop.GtkCore.NodeBuilders/ProjectFolderNodeBuilderExtension.cs, + MonoDevelop.GtkCore.Commands/GladeCommands.cs: Added menu option + for opening the gtk# settings. + * MonoDevelop.GtkCore.GuiBuilder/GuiBuilderProject.cs: Don't crash if + the gtk-gui folder doesn't exist. Fixes bug #81152. + * MonoDevelop.GtkCore.GuiBuilder/CombinedDesignView.cs: Hide the border + of the combined view notebook. + +2007-03-08 Lluis Sanchez Gual <lluis@novell.com> + + * lib/libstetic.dll: Updated from stetic module. Fixes NRE crash. + +2007-03-08 Lluis Sanchez Gual <lluis@novell.com> + + * lib/libsteticui.dll, lib/libstetic.dll: Updated from stetic module. + * MonoDevelop.GtkCore.GuiBuilder/CodeBinder.cs: Fix null ref. + +2007-03-06 Lluis Sanchez Gual <lluis@novell.com> + + * MonoDevelop.GtkCore.addin.xml: Register a new toolbox loader. Removed + old properties pads. + * MonoDevelop.GtkCore.mdp, Makefile.am: Added reference to + MonoDevelop.DesignerSupport. + * lib/libsteticui.dll, lib/libstetic.dll: Updated from svn module. + * MonoDevelop.GtkCore.GuiBuilder/GuiBuilderService.cs, + MonoDevelop.GtkCore.GuiBuilder/GuiBuilderView.cs, + MonoDevelop.GtkCore.GuiBuilder/PropertiesWidget.cs, + MonoDevelop.GtkCore.GuiBuilder/ToolboxProvider.cs: Integrate Stetic + widgets in the main toolbox. + * MonoDevelop.GtkCore.GuiBuilder/ActionGroupView.cs: Implement + ICustomPropertyPadProvider and return the Stetic property pad. + * MonoDevelop.GtkCore.GuiBuilder/GuiBuilderPropertiesPad.cs: Renamed. + * MonoDevelop.GtkCore.GuiBuilder/CombinedDesignView.cs: Fix warning. + +2007-02-20 Lluis Sanchez Gual <lluis@novell.com> + + Updated from Stetic module. Includes fix for bug #80864. + +2007-02-20 Lluis Sanchez Gual <lluis@novell.com> + + * lib/libsteticui.dll, lib/libstetic.dll: Updated from SVN. Fixes some + memory leaks and bug #79453. + * MonoDevelop.GtkCore.GuiBuilder/CombinedDesignView.cs: Explicitely + destroy notebook children, since notebook doesnt do it because of a + gtk bug. + * MonoDevelop.GtkCore.GuiBuilder/GuiBuilderView.cs: Some fixes in the + dispose code. + +2007-02-16 Lluis Sanchez Gual <lluis@novell.com> + + * MonoDevelop.GtkCore.NodeBuilders/ProjectFolderNodeBuilderExtension.cs, + MonoDevelop.GtkCore.GuiBuilder/ActionGroupDisplayBinding.cs, + MonoDevelop.GtkCore.GuiBuilder/GuiBuilderWindow.cs: Use + ProjectOperations.SaveProject to save projects. + +2007-02-16 Lluis Sanchez Gual <lluis@novell.com> + + * MonoDevelop.GtkCore.addin.xml: Change add-in versions to 0.13. + +2007-02-15 Lluis Sanchez Gual <lluis@novell.com> + + * MonoDevelop.GtkCore.GuiBuilder/GuiBuilderProject.cs: Fix nullref. + * MonoDevelop.GtkCore.GuiBuilder/GtkProjectServiceExtension.cs: Log + error message. + * Makefile.am, MonoDevelop.GtkCore.mdp: Synchronized MD project and + makefile. + +2007-02-15 Lluis Sanchez Gual <lluis@novell.com> + + * MonoDevelop.GtkCore.GuiBuilder/GuiBuilderProject.cs: Avoid throwing + delayed events after the project has been disposed. + +2007-02-14 Lluis Sanchez Gual <lluis@novell.com> + + * MonoDevelop.GtkCore.GuiBuilder/GuiBuilderProject.cs: Added missing + null check. + +2007-02-14 Lluis Sanchez Gual <lluis@novell.com> + + * MonoDevelop.GtkCore.GuiBuilder/GuiBuilderService.cs, + MonoDevelop.GtkCore.GuiBuilder/GuiBuilderProject.cs: Ask for user + confirmation when reloading a designer only when the designer has + unsaved changes. + +2007-02-14 Lluis Sanchez Gual <lluis@novell.com> + + * MonoDevelop.GtkCore.NodeBuilders/ProjectFolderNodeBuilderExtension.cs, + MonoDevelop.GtkCore.NodeBuilders/WindowsFolderNodeBuilder.cs, + MonoDevelop.GtkCore.NodeBuilders/WindowsFolder.cs, + MonoDevelop.GtkCore/GtkDesignInfo.cs, + MonoDevelop.GtkCore.GuiBuilder/GuiBuilderService.cs, + MonoDevelop.GtkCore.GuiBuilder/GuiBuilderProject.cs, + MonoDevelop.GtkCore.GuiBuilder/ActionGroupView.cs, + MonoDevelop.GtkCore.GuiBuilder/GuiBuilderView.cs: Detect external + changes in the gui.stetic files, and reload it when it changes. + Take into account that the load of gui.stetic can fail. Added + several workarounds for this case. + +2007-02-13 Lluis Sanchez Gual <lluis@novell.com> + + * lib/libsteticui.dll, lib/libstetic.dll: Updated from SVN. Includes + fixes for bugs #80722, #79427 and #80127. + * MonoDevelop.GtkCore.GuiBuilder/GuiBuilderService.cs, + MonoDevelop.GtkCore.GuiBuilder/GuiBuilderProject.cs: Store some + Stetic configuration in the MD properties. + +2007-02-09 Lluis Sanchez Gual <lluis@novell.com> + + * gui.glade, MonoDevelop.GtkCore.Dialogs/WidgetBuilderOptionPanel.cs, + MonoDevelop.GtkCore.GuiBuilder/GuiBuilderService.cs: Added options + for enabling/disabling gtk support, and for gettext support. + * MonoDevelop.GtkCore.addin.xml: Change options panel name. + * MonoDevelop.GtkCore.NodeBuilders/ProjectFolderNodeBuilderExtension.cs, + MonoDevelop.GtkCore.GuiBuilder/CodeBinder.cs, + MonoDevelop.GtkCore.GuiBuilder/GuiBuilderWindow.cs: Make sure the + MD project is saved together with the stetic project, if necessary. + * MonoDevelop.GtkCore.NodeBuilders/WidgetNodeBuilder.cs, + MonoDevelop.GtkCore.NodeBuilders/ActionGroupNodeBuilder.cs, + MonoDevelop.GtkCore/WidgetFileDescriptionTemplate.cs: Avoid saving + the MD project twice. + * MonoDevelop.GtkCore.NodeBuilders/ProjectNodeBuilder.cs: If gtk + integration status changes for a project, refresh the tree. + * MonoDevelop.GtkCore.NodeBuilders/WindowsFolder.cs: Null check. + * MonoDevelop.GtkCore/GtkDesignInfo.cs: Added support for gettext and + gettext class options for generated code. + * MonoDevelop.GtkCore/GtkCoreService.cs: Added events for notifying + when the gtk integration status changes for a project. + * lib/libsteticui.dll, lib/libstetic.dll: Updated from stetic module. + * Makefile.am: distcheck fixes + * MonoDevelop.GtkCore.GuiBuilder/GuiBuilderProject.cs, + MonoDevelop.GtkCore.GuiBuilder/ActionGroupView.cs, + MonoDevelop.GtkCore.GuiBuilder/CombinedDesignView.cs, + MonoDevelop.GtkCore.GuiBuilder/GuiBuilderView.cs: When a designer + project is disposed, hide the designer view in the editor. + * MonoDevelop.GtkCore.GuiBuilder/GtkProjectServiceExtension.cs: + Factorized some code into GtkDesignInfo. + +2007-02-07 Lluis Sanchez Gual <lluis@novell.com> + + * MonoDevelop.GtkCore.addin.xml: Make sure the code generation + extension is executed before the last step. + * MonoDevelop.GtkCore.NodeBuilders/ProjectFolderNodeBuilderExtension.cs: + Hide the add window commands when the project is not DotNet + * MonoDevelop.GtkCore.mdp, lib/libsteticui.dll, lib/libstetic.dll: + Updated. + +2007-02-02 Lluis Sanchez Gual <lluis@novell.com> + + * MonoDevelop.GtkCore.GuiBuilder/CombinedDesignView.cs: Intercept calls + to the IPositionable interface, and show the editor page when + jumping to a line. + +2007-02-02 Lluis Sanchez Gual <lluis@novell.com> + + * MonoDevelop.GtkCore.GuiBuilder/GuiBuilderProject.cs: When looking for + the window class, avoid returning the generated partial class. + * MonoDevelop.GtkCore.GuiBuilder/GuiBuilderView.cs: Show the editor + page when jumping to a signal handler. + +2007-02-02 Lluis Sanchez Gual <lluis@novell.com> + + * MonoDevelop.GtkCore.GuiBuilder/GuiBuilderService.cs: Warn the user if + the gtk-sharp-2 package can't be found. Some distros don't include + the .pc file in the gtk# package, only in the -devel package. + +2007-02-02 Lluis Sanchez Gual <lluis@novell.com> + + * lib/libsteticui.dll, lib/libstetic.dll: Updated from Stetic module. + +2007-01-31 Lluis Sanchez Gual <lluis@novell.com> + + * lib/libstetic.dll.config, lib/libsteticui.dll, lib/libstetic.dll, + lib/libsteticui.dll.config: Updated from Stetic module. + +2007-01-29 Lluis Sanchez Gual <lluis@novell.com> + + * MonoDevelop.GtkCore.NodeBuilders/WidgetNodeBuilder.cs, + MonoDevelop.GtkCore.NodeBuilders/ActionGroupNodeBuilder.cs, + MonoDevelop.GtkCore.GuiBuilder/GuiBuilderService.cs, + MonoDevelop.GtkCore.GuiBuilder/CodeBinder.cs, + MonoDevelop.GtkCore.GuiBuilder/GuiBuilderWindow.cs: Track api + changes in Document class. + * lib/libsteticui.dll, lib/libstetic.dll: Updated form Stetic module. + * MonoDevelop.GtkCore.GuiBuilder/CombinedDesignView.cs: Removed + implementation of all text editor interfaces. Now the view + overrides GetContent and calls editor.GetContent when a requested + interface is not found. + +2007-01-22 Lluis Sanchez Gual <lluis@novell.com> + + * MonoDevelop.GtkCore.mdp: Updated. + * MonoDevelop.GtkCore/GtkDesignInfo.cs: Removed unused namespace. + * MonoDevelop.GtkCore/GtkCoreService.cs: Use the new base-type property + to describe custom widgets. When looking for properties and events, + look in the base classes as well as in the widget class. + * lib/libsteticui.dll, lib/libstetic.dll: Updated from stetic module. + * Makefile.am, + MonoDevelop.GtkCore.WidgetLibrary/ProjectClassDescriptor.cs, + MonoDevelop.GtkCore.WidgetLibrary/ProjectSignalDescriptor.cs, + MonoDevelop.GtkCore.WidgetLibrary/BaseWidgetLibrary.cs, + MonoDevelop.GtkCore.WidgetLibrary/AssemblyReferenceWidgetLibrary.cs, + MonoDevelop.GtkCore.WidgetLibrary/ProjectPropertyDescriptor.cs: + Removed unused files. All widget library functionality has been + moved to stetic. + * MonoDevelop.GtkCore.GuiBuilder/GuiBuilderService.cs: Removed all + widget library management, which has been moved to Stetic. + * MonoDevelop.GtkCore.GuiBuilder/CodeBinder.cs: Added some null checks. + * MonoDevelop.GtkCore.GuiBuilder/GuiBuilderProject.cs: Use the new way + of managing dependencies in projects. + * MonoDevelop.GtkCore.GuiBuilder/GuiBuilderWindow.cs, + templates/WindowPartial.xft.xml, templates/Window.xft.xml: The + window constructor now takes the window type. + * MonoDevelop.GtkCore.GuiBuilder/GuiBuilderView.cs: Some gui + improvements and added some null checks. + +2007-01-17 Lluis Sanchez Gual <lluis@novell.com> + + * MonoDevelop.GtkCore.GuiBuilder/GuiBuilderView.cs: Don't crash if the + designer can't be loaded for some reason. + +2007-01-15 Lluis Sanchez Gual <lluis@novell.com> + + * MonoDevelop.GtkCore.addin.xml, + MonoDevelop.GtkCore.NodeBuilders/ProjectFolderNodeBuilderExtension.cs, + MonoDevelop.GtkCore/GtkCoreService.cs, + MonoDevelop.GtkCore/WidgetFileTemplatePartialClass.cs, + MonoDevelop.GtkCore/WidgetFileTemplateFullClass.cs, + MonoDevelop.GtkCore.GuiBuilder/CodeBinder.cs, + MonoDevelop.GtkCore.GuiBuilder/GuiBuilderWindow.cs, + MonoDevelop.GtkCore.GuiBuilder/CombinedDesignView.cs, + templates/WidgetPartial.xft.xml, templates/Widget.xft.xml, + templates/WindowPartial.xft.xml, templates/Window.xft.xml, + templates/ActionGroupPartial.xft.xml, + templates/ActionGroup.xft.xml, templates/DialogPartial.xft.xml, + templates/Dialog.xft.xml: Implemented support for generating code + in partial classes. + * MonoDevelop.GtkCore.NodeBuilders/WidgetNodeBuilder.cs: Use the + correct method for saving the project. + * MonoDevelop.GtkCore.NodeBuilders/WindowsFolder.cs: Refresh the user + interface folder when the gui project is reloaded. + * MonoDevelop.GtkCore.mdp: Updated. + * MonoDevelop.GtkCore/GtkDesignInfo.cs: Added support for partial + classes. In the GuiBuilderProject property, don't update the + gtk-gui folder since this call may change the contents of the + project, and weird things happen when called by the project pad to + fill the tree. + * lib/libsteticui.dll, lib/libstetic.dll: Updated from stetic module. + * Makefile.am: Added new files. + * MonoDevelop.GtkCore.WidgetLibrary/BaseWidgetLibrary.cs, + MonoDevelop.GtkCore.WidgetLibrary/AssemblyReferenceWidgetLibrary.cs: + Make it work even when the assembly it references has been deleted + (maybe as a result of cleaning a project). In this case the widget + library is shown as empty. + * MonoDevelop.GtkCore.GuiBuilder/GuiBuilderService.cs, + MonoDevelop.GtkCore.GuiBuilder/GuiBuilderProject.cs: Added support + for Loading/Unloading a project, to optimize use of memory for + solutions with many gui projects. Implemented support for + generating code in partial classes. + * MonoDevelop.GtkCore.GuiBuilder/ActionGroupView.cs, + MonoDevelop.GtkCore.GuiBuilder/GuiBuilderView.cs: Implemented + support for generating code in partial classes. Implemented support + for UNDO/REDO. + * MonoDevelop.GtkCore.GuiBuilder/GtkProjectServiceExtension.cs: + Generation of gui code is now done from the Build method of a + project service extension. Fixes some issues when building a + project which contains custom components. + +2006-12-17 Lluis Sanchez Gual <lluis@novell.com> + + * MonoDevelop.GtkCore/GtkCoreService.cs: Track API changes in + FileService. + +2006-12-13 Jacob Ilsø Christensen <jacobilsoe@gmail.com> + + * MonoDevelop.GtkCore.GuiBuilder/GuiBuilderService.cs: Don't + generate stetic code if CurrentOpenCombine is null. + +2006-12-07 Jacob Ilsø Christensen <jacobilsoe@gmail.com> + + * MonoDevelop.GtkCore.mdp: Updated to it can be + built from MonoDevelop. + +2006-11-16 Lluis Sanchez Gual <lluis@novell.com> + + * MonoDevelop.GtkCore.GuiBuilder/GuiBuilderService.cs: Simplified the + code by using global events from the Ide, instead of combine + events. + +2006-10-18 Lluis Sanchez Gual <lluis@novell.com> + + * MonoDevelop.GtkCore/GtkDesignInfo.cs: Added RemoveExportedWidget method. + * MonoDevelop.GtkCore.Dialogs/WidgetBuilderOptionPanel.cs: track + API changes. + * MonoDevelop.GtkCore.GuiBuilder/GuiBuilderView.cs: If the name of a + widget changes and it is being exported, update it in the objects.xml + file. Fixes bug #79656. + +2006-09-23 Lluis Sanchez Gual <lluis@novell.com> + + * lib/*: Updated from Stetic module. It provides a redesigned API + which will allow running designers in a separate process. + + * MonoDevelop.GtkCore/WidgetFileDescriptionTemplate.cs: + * MonoDevelop.GtkCore.NodeBuilders/WidgetNodeBuilder.cs: + * MonoDevelop.GtkCore.NodeBuilders/WindowsFolderNodeBuilder.cs: + * MonoDevelop.GtkCore.NodeBuilders/WindowsFolder.cs: + * MonoDevelop.GtkCore.NodeBuilders/ActionGroupNodeBuilder.cs: + * MonoDevelop.GtkCore.NodeBuilders/ProjectFolderNodeBuilderExtension.cs: + * MonoDevelop.GtkCore.Dialogs/WidgetBuilderOptionPanel.cs: + * MonoDevelop.GtkCore.Dialogs/ConfirmWindowDeleteDialog.cs: + * MonoDevelop.GtkCore.WidgetLibrary/AssemblyReferenceWidgetLibrary.cs: + * MonoDevelop.GtkCore.GuiBuilder/ActionGroupDisplayBinding.cs: + * MonoDevelop.GtkCore.GuiBuilder/GuiBuilderService.cs: + * MonoDevelop.GtkCore.GuiBuilder/GuiBuilderProject.cs: + * MonoDevelop.GtkCore.GuiBuilder/GuiBuilderWindow.cs: + * MonoDevelop.GtkCore.GuiBuilder/ActionGroupView.cs: + * MonoDevelop.GtkCore.GuiBuilder/GuiBuilderView.cs: + * MonoDevelop.GtkCore.GuiBuilder/GuiBuilderPropertiesPad.cs: + * MonoDevelop.GtkCore.GuiBuilder/CodeBinder.cs: + * MonoDevelop.GtkCore.GuiBuilder/GuiBuilderPalettePad.cs: + * MonoDevelop.GtkCore.GuiBuilder/GuiBuilderProjectPad.cs: + Track api changes. + + * MonoDevelop.GtkCore.WidgetLibrary/BaseWidgetLibrary.cs: Make sure + parse information is up to date before loading an assembly library. + * MonoDevelop.GtkCore/ProjectResourceProvider.cs: Make sure this object + is always alive when remoted. + * MonoDevelop.GtkCore.GuiBuilder/CombinedDesignView.cs: Added null check. + * MonoDevelop.GtkCore.GuiBuilder/GuiBuilderEditSession.cs: Not needed anymore. + * MonoDevelop.GtkCore.addin.xml: Removed build step. Code generation + is done now before compiling. + + * MonoDevelop.GtkCore.WidgetLibrary/ProjectWidgetLibrary.cs: + * MonoDevelop.GtkCore.WidgetLibrary/CachedProjectWidgetLibrary.cs: + * MonoDevelop.GtkCore/GtkDesignInfo.cs: ProjectWidgetLibrary is not used + anymore. All libraries are now handled by AssemblyReferenceWidgetLibrary. + + * MonoDevelop.GtkCore.GuiBuilder/MonoDevelopWidgetActionBar.cs: + * MonoDevelop.GtkCore.GuiBuilder/MonoDevelopActionGroupToolbar.cs: + Moved to Stetic. + + * Makefile.am: + * MonoDevelop.GtkCore.mdp: Updated. + +2006-09-23 Lluis Sanchez Gual <lluis@novell.com> + + * MonoDevelop.GtkCore.GuiBuilder/GuiBuilderService.cs: Track api changes. + +2006-09-19 Jacob Ilsø Christensen <jacobilsoe@gmail.com> + + * .: Added svn:ignore for MonoDevelop.GtkCore.pidb + +2006-09-01 Lluis Sanchez Gual <lluis@novell.com> + + * lib/*: Updated from stetic module. Includes fix for bug #79247. + +2006-09-01 Lluis Sanchez Gual <lluis@novell.com> + + * lib/*: Updated from stetic module. + * MonoDevelop.GtkCore.NodeBuilders/ProjectFolderNodeBuilderExtension.cs: + Save the project after editing the icons. + * MonoDevelop.GtkCore.GuiBuilder/GuiBuilderProject.cs: Set the + ResourceProvider for the main stetic project. Added null check. + +2006-08-30 Lluis Sanchez Gual <lluis@novell.com> + + * MonoDevelop.GtkCore.GuiBuilder/GuiBuilderView.cs: Fixed bug about + adding the wrong widget as action designer page. + +2006-08-30 Lluis Sanchez Gual <lluis@novell.com> + + * MonoDevelop.GtkCore/GtkCoreService.cs: Only export properties which + return primitive types. Fixes bug #79195. + * lib/*: Updated from stetic module. + * MonoDevelop.GtkCore.Dialogs/BindDesignDialog.cs: Unsubscribe close + event when done. + * MonoDevelop.GtkCore.GuiBuilder/GuiBuilderView.cs: Handle designer + commands in its own tab page. + + * MonoDevelop.GtkCore.GuiBuilder/CombinedDesignView.cs: + * MonoDevelop.GtkCore.GuiBuilder/GuiBuilderEditSession.cs: + * MonoDevelop.GtkCore.GuiBuilder/ActionGroupView.cs: Explicitely dispose + custom widgets to avoid memory leaks. + + * MonoDevelop.GtkCore.GuiBuilder/GuiBuilderWindow.cs: + * MonoDevelop.GtkCore.GuiBuilder/GuiBuilderProject.cs: Track api changes. + + * MonoDevelop.GtkCore.mdp: Updated. + +2006-08-18 Lluis Sanchez Gual <lluis@novell.com> + + * gui.glade: Minor fix. + * MonoDevelop.GtkCore.NodeBuilders/WidgetNodeBuilder.cs: Track api + changes. + * MonoDevelop.GtkCore/GtkDesignInfo.cs: Stetic files don't need + to be added as resource to projects. + * MonoDevelop.GtkCore.Dialogs/ConfirmWindowDeleteDialog.cs: Make it + work for action groups. + * lib/*: several fixes. + * MonoDevelop.GtkCore.GuiBuilder/GuiBuilderProject.cs: Added method + for removing an action group. + + * MonoDevelop.GtkCore.GuiBuilder/GuiBuilderEditSession.cs: + * MonoDevelop.GtkCore.GuiBuilder/ActionGroupView.cs: + * MonoDevelop.GtkCore.GuiBuilder/GuiBuilderView.cs: Track API changes + in Stetic. Properly bound edit commands from the main menu. + + * MonoDevelop.GtkCore.NodeBuilders/ActionGroupNodeBuilder.cs: + * MonoDevelop.GtkCore.addin.xml: Implemented Open and Delete + commands for global action groups. + + * MonoDevelop.GtkCore.mdp: Updated. + +2006-08-11 Lluis Sanchez Gual <lluis@novell.com> + + * lib/*: Updated from Stetic module. Includes fixes for + bugs #79043, #79044 and #79045 + * MonoDevelop.GtkCore.GuiBuilder/GuiBuilderWindow.cs: Don't + crash if something goes wrong when binding a class. + Fixed nullref. + +2006-08-04 Lluis Sanchez Gual <lluis@novell.com> + + * MonoDevelop.GtkCore.GuiBuilder/GuiBuilderDisplayBinding.cs: + * MonoDevelop.GtkCore.GuiBuilder/ActionGroupDisplayBinding.cs: + CreateContentForFile should not load the file, just create + the view. + + * MonoDevelop.GtkCore.GuiBuilder/CombinedDesignView.cs: Add + support for IEncodedTextContent. + +2006-08-01 Lluis Sanchez Gual <lluis@novell.com> + + * MonoDevelop.GtkCore.GuiBuilder/GuiBuilderEditSession.cs: + Set the resource provider before loading the project. + Fixes bug #78966. + + * libs/*: Updated from Stetic module. Fixes several bugs: + 78938, 78916, 78909, 78956, and 78867. + +2006-07-27 Lluis Sanchez Gual <lluis@novell.com> + + * MonoDevelop.GtkCore.WidgetLibrary/ProjectClassDescriptor.cs: + Added null check. + + * MonoDevelop.GtkCore.WidgetLibrary/AssemblyReferenceWidgetLibrary.cs: + Get the parser context using the assembly file name, not the full + assembly name. + +2006-07-25 Lluis Sanchez Gual <lluis@novell.com> + + * MonoDevelop.GtkCore/GtkDesignInfo.cs: + * MonoDevelop.GtkCore.GuiBuilder/ActionGroupDisplayBinding.cs: + * MonoDevelop.GtkCore.GuiBuilder/GuiBuilderService.cs: + * MonoDevelop.GtkCore.GuiBuilder/GuiBuilderDisplayBinding.cs: + * MonoDevelop.GtkCore.GuiBuilder/GuiBuilderProject.cs: + * MonoDevelop.GtkCore.GuiBuilder/GuiBuilderWindow.cs: + * MonoDevelop.GtkCore.GuiBuilder/CodeBinder.cs: Factorized several + more or less duplicate methods into GuiBuilderProject, specially + methods for locating the class bound to a window. GuiBuilderProject + now will explicitelly update the parser database the first time it + needs to locate a class, so it will work even if the parser service + is busy parsing assemblies. + +2006-07-24 Lluis Sanchez Gual <lluis@novell.com> + + * lib/libstetic.dll: Updated from stetic module. Fixes a bug + in the table wrapper which may cause an endless loop. + +2006-07-05 Matej Urbas <matej.urbas@gmail.com> + + * MonoDevelop.GtkCore/GtkCoreService.cs: + * MonoDevelop.GtkCore.GuiBuilder/ActionGroupDisplayBinding.cs: + * MonoDevelop.GtkCore.GuiBuilder/CodeBinder: + * MonoDevelop.GtkCore.GuiBuilder/GuiBuilderWindow.cs: + * MonoDevelop.GtkCore.WidgetLibrary/BaseWidgetLibrary.cs: Updated to use + ReturnType as BaseTypes in IClass instances. + +2006-07-03 Lluis Sanchez Gual <lluis@novell.com> + + * lib/*: Updated from Stetic module. + * MonoDevelop.GtkCore.GuiBuilder/GuiBuilderService.cs: Fixed automatic + layout switch policy. + * MonoDevelop.GtkCore.GuiBuilder/GuiBuilderView.cs: Fix showing of + action group view. + * MonoDevelop.GtkCore.GuiBuilder/GuiBuilderEditSession.cs: Properly + bind actions when pressing "BindToField". + + * MonoDevelop.GtkCore.addin.xml: Updated versions. + +2006-06-29 Michael Hutchinson <m.j.hutchinson@gmail.com> + + * MonoDevelop.GtkCore.addin.xml: Only display WidgetBuilderOptionPanel + for "DotNet" projects. + +2006-06-19 Lluis Sanchez Gual <lluis@novell.com> + + * lib/*: Updated from Stetic module. + * MonoDevelop.GtkCore.GuiBuilder/GuiBuilderService.cs: Switch to the + designer workbench layout when selecting an action group file. + * MonoDevelop.GtkCore.GuiBuilder/ActionGroupView.cs: Support jumping + to signal hanlder when double-clicking it in the signals editor. + * MonoDevelop.GtkCore.GuiBuilder/CodeBinder.cs: Removed debug code. + + * templates/ActionGroup.xft.xml: + * MonoDevelop.GtkCore.GuiBuilder/ActionGroupDisplayBinding.cs: + Fix code generation of action groups. + +2006-06-12 Lluis Sanchez Gual <lluis@novell.com> + + * MonoDevelop.GtkCore/GtkCoreService.cs: If a member has a [Browsable(false)] + attribute, don't add it to the objects.xml file. Also don't add + read-only properties. + * lib/*: Updated from stetic module. Fixes bugs #78622 and #78620. + Adds an icon for expander and fixes a bug in ColorButton (fix by ml) + +2006-06-11 Lluis Sanchez Gual <lluis@novell.com> + + * lib/libsteticui.dll: + * MonoDevelop.GtkCore.GuiBuilder/MonoDevelopWidgetActionBar.cs: + Track changes in the api. + +2006-06-09 Lluis Sanchez Gual <lluis@novell.com> + + * libs/*: Updated from stetic module. Several improvements. + Also fixes bug #78160. + +2006-05-30 Lluis Sanchez Gual <lluis@novell.com> + + * MonoDevelop.GtkCore.GuiBuilder/ActionGroupDisplayBinding.cs: + * MonoDevelop.GtkCore.GuiBuilder/GuiBuilderDisplayBinding.cs: + Added DisplayName property. + +2006-05-29 David Makovský (Yakeen) <yakeen@sannyas-on.net> + + * MonoDevelop.GtkCore.GuiBuilder/CombinedDesignView.cs: reverted interface changes - missing file change + +2006-05-29 David Makovský (Yakeen) <yakeen@sannyas-on.net> + + * MonoDevelop.GtkCore.GuiBuilder/CombinedDesignView.cs: reverted interface changes + +2006-05-26 Lluis Sanchez Gual <lluis@novell.com> + + * libs/*: Updated from stetic module. Adds support for toolbars. + +2006-05-23 David Makovský (Yakeen) <yakeen@sannyas-on.net> + + * MonoDevelop.GtkCore.GuiBuilder/CombinedDesignView.cs: track api changes + +2006-05-19 Lluis Sanchez Gual <lluis@novell.com> + + * MonoDevelop.GtkCore.Commands/GladeCommands.cs: + * MonoDevelop.GtkCore.NodeBuilders/ProjectFolderNodeBuilderExtension.cs: + * MonoDevelop.GtkCore.addin.xml: Added commands for creating + an action group and editing the project icons. + + * MonoDevelop.GtkCore.NodeBuilders/WidgetNodeBuilder.cs: Show local + action groups as children of the window node. + + * MonoDevelop.GtkCore.NodeBuilders/WindowsFolder.cs: + * MonoDevelop.GtkCore.NodeBuilders/WindowsFolderNodeBuilder.cs: Moved + some event subscriptions to WindowsFolder.cs + + * MonoDevelop.GtkCore.GuiBuilder/GuiBuilderService.cs: + * MonoDevelop.GtkCore.NodeBuilders/ActionGroupNodeBuilder.cs: Open the + corresponding file when clicking on local action groups. + + * Makefile.am: + * MonoDevelop.GtkCore.mdp: Added action group template. + + * MonoDevelop.GtkCore/WidgetFileDescriptionTemplate.cs: Added support for + action group file templates. + * MonoDevelop.GtkCore.GuiBuilder/GuiBuilderWindow.cs: Notify changes in + local action groups. + * MonoDevelop.GtkCore.GuiBuilder/GuiBuilderView.cs: Don't show the actions + tab until there is at least one action group. + * MonoDevelop.GtkCore.GuiBuilder/GuiBuilderPropertiesPad.cs: Don't show + properties or signals for global actions. + * MonoDevelop.GtkCore.GuiBuilder/CombinedDesignView.cs: Added virtual method + OnActiveDocumentChanged, which is called when the view is brought to front. + + * MonoDevelop.GtkCore.GuiBuilder/GuiBuilderEditSession.cs: + * MonoDevelop.GtkCore.GuiBuilder/CodeBinder.cs: Use the new MemberName + field when binding fields. + + * MonoDevelop.GtkCore.GuiBuilder/MonoDevelopActionGroupToolbar.cs: + * MonoDevelop.GtkCore.GuiBuilder/ActionGroupView.cs: Several minor fixes. + + * lib/*: Updated. + + +2006-05-12 Lluis Sanchez Gual <lluis@novell.com> + + * Initial support for the menu editor. Still very unstable!! + + * lib/*: Updated from Stetic module. + * MonoDevelop.GtkCore.addin.xml: Register a node builder and and + display binding for action groups. + * MonoDevelop.GtkCore.NodeBuilders/WindowsFolderNodeBuilder.cs: Update + the folder when action groups change. + * MonoDevelop.GtkCore/GtkCoreService.cs: Fix nullref. + + * MonoDevelop.GtkCore.GuiBuilder/GuiBuilderEditSession.cs: Factorized + some code into CodeBinder.cs + * MonoDevelop.GtkCore.GuiBuilder/GuiBuilderView.cs: Factorized some + code into CombinedDesignView.cs. + + * MonoDevelop.GtkCore.NodeBuilders/ActionGroupNodeBuilder.cs: New node + builder for action groups. + * MonoDevelop.GtkCore.GuiBuilder/ActionGroupDisplayBinding.cs: New display + binding for editing global action groups. + * MonoDevelop.GtkCore.GuiBuilder/MonoDevelopWidgetActionBar.cs: Moved from + GuiBuilderView.cs. + * MonoDevelop.GtkCore.GuiBuilder/MonoDevelopActionGroupToolbar.cs: A new + toolbar for the action group designer. + * MonoDevelop.GtkCore.GuiBuilder/ActionGroupView.cs: A view for editing + global action groups. + * MonoDevelop.GtkCore.GuiBuilder/CodeBinder.cs: Moved here some code + from GuiBuilderEditSession.cs. + * MonoDevelop.GtkCore.GuiBuilder/CombinedDesignView.cs: Moved here some + code from GuiBuilderView.cs. + + * Makefile.am: + * MonoDevelop.GtkCore.mdp: Added new files. + + * MonoDevelop.GtkCore.GuiBuilder/GuiBuilderService.cs: Track api changes. + +2006-05-05 Lluis Sanchez Gual <lluis@novell.com> + + * lib/libstetic.dll: Updated from Stetic module. Includes + a fix for bug #78307. + +2006-05-04 Lluis Sanchez Gual <lluis@novell.com> + + * MonoDevelop.GtkCore.addin.xml: Updated versions. + * MonoDevelop.GtkCore.mdp: Updated. + +2006-05-03 Lluis Sanchez Gual <lluis@novell.com> + + * lib/*: Updated from Stetic module. Includes fixes for + bugs #78266, #78240 and #78276. + + * MonoDevelop.GtkCore.GuiBuilder/GuiBuilderWindow.cs: + * MonoDevelop.GtkCore.GuiBuilder/GuiBuilderEditSession.cs: + * MonoDevelop.GtkCore.GuiBuilder/GuiBuilderView.cs: + * MonoDevelop.GtkCore.GuiBuilder/GuiBuilderService.cs: Track changes + in the Stetic API. + +2006-04-24 Lluis Sanchez Gual <lluis@novell.com> + + * MonoDevelop.GtkCore.GuiBuilder/GuiBuilderProject.cs: Don't + crash if a stetic project can't be loaded. Fixes bug #78169. + * lib/libstetic.dll: Updated from Stetic module. Fixes bug #78167. + +2006-04-18 Lluis Sanchez Gual <lluis@novell.com> + + * libs/*: Updated from stetic module. Fixed construction of + scales and scrollbars. + +2006-04-19 Lluis Sanchez Gual <lluis@novell.com> + + * MonoDevelop.GtkCore.WidgetLibrary/ProjectClassDescriptor.cs: When + creating a widget from a widget design, remove the signals since + those signals reference handlers in the widget class, not the + widget container class. + +2006-04-18 Lluis Sanchez Gual <lluis@novell.com> + + * libs/*: Fix nullref in some themes. + +2006-04-10 Lluis Sanchez Gual <lluis@novell.com> + + * MonoDevelop.GtkCore/WidgetFileDescriptionTemplate.cs: Fix typo. + * libs/*: Fix for #78111, #78092 and #78090. + +2006-04-04 Lluis Sanchez Gual <lluis@novell.com> + + * MonoDevelop.GtkCore/ProjectResourceProvider.cs: Save the project + after adding or removing a resource. + +2006-04-03 Lluis Sanchez Gual <lluis@novell.com> + + * lib/*: Updated. + +2006-03-31 Lluis Sanchez Gual <lluis@novell.com> + + * MonoDevelop.GtkCore.GuiBuilder/GuiBuilderService.cs: Get open + combine events in the GUI thread. + * MonoDevelop.GtkCore.GuiBuilder/GuiBuilderEditSession.cs: Properly + delete signals for which there isn't a handler. Half fixed field + renaming. + * lib/*: Updated. + +2006-03-31 Lluis Sanchez Gual <lluis@novell.com> + + * MonoDevelop.GtkCore/MonoDevelop.GtkCore.addin.xml: Fix ID and + description. Added stetic config files to add-in package. + +2006-03-30 Lluis Sanchez Gual <lluis@novell.com> + + * MonoDevelop.GtkCore.addin.xml: Updated references. + +2006-03-29 Lluis Sanchez Gual <lluis@novell.com> + + * MonoDevelop.GtkCore.GuiBuilder/GuiBuilderEditSession.cs: + Don't crash if no parse info is available for the file + being edited. Should fix #77885. + * MonoDevelop.GtkCore.GuiBuilder/GuiBuilderView.cs: Don't show + the bind to field button for the root container. + * lib/*: Updated. + +2006-03-24 Lluis Sanchez Gual <lluis@novell.com> + + * Makefile.am: Use an unified format. Patch by Matze Braun. + * MonoDevelop.GtkCore.addin.xml: Updated add-in versions. + +2006-03-22 Lluis Sanchez Gual <lluis@novell.com> + + * MonoDevelop.GtkCore.addin.xml: + * MonoDevelop.GtkCore.mdp: Removed GladeFileDisplayBinding. + * lib/*: Updated. + * Makefile.am: Updated. Some files have been moved to Stetic. + + * MonoDevelop.GtkCore.GuiBuilder/GuiBuilderService.cs: Fixed + layout switching. Don't show the widget tree pad by default, + since it is already available as a combo in the designer. + * MonoDevelop.GtkCore.GuiBuilder/GladeFileDisplayBinding.cs: Removed. + * MonoDevelop.GtkCore.GuiBuilder/GuiBuilderPropertiesPad.cs: use + the new property tree instead of the grid. + * MonoDevelop.GtkCore.GuiBuilder/GuiBuilderView.cs: The designer + toolbar has been moved to Stetic. + * MonoDevelop.GtkCore.GuiBuilder/GuiBuilderProjectPad.cs: Changed + default placement. + +2006-03-19 Jacob Ilsø Christensen <jacobilsoe@gmail.com> + + * .: Added Makefile.in and Makefile to svn:ignore. + +2006-03-15 Lluis Sanchez Gual <lluis@novell.com> + + * Makefile.am: + * MonoDevelop.GtkCore.mdp: Updated. + + * MonoDevelop.GtkCore.GuiBuilder/GuiBuilderEditSession.cs: + * MonoDevelop.GtkCore/GtkDesignInfo.cs: Added support for using + resource images in the designer. + + * MonoDevelop.GtkCore/GtkCoreService.cs: Check if the objects.xml + file exists before loading it. + * MonoDevelop.GtkCore/GeneratorBuildStep.cs: Don't generate code + if the stetic file has not been modified since the last + generation. + * MonoDevelop.GtkCore.Dialogs/WidgetBuilderOptionPanel.cs: If Gtk + support is not enabled, don't enable it if no widgets have + been selected. + * lib/libstetic.dll: Updated. + * MonoDevelop.GtkCore.GuiBuilder/GuiBuilderView.cs: Mapped some + commands. + * templates/Window.xft.xml: The constructor of Gtk.Window requires + the title of the window. + +2006-03-04 Lluis Sanchez Gual <lluis@novell.com> + + * MonoDevelop.GtkCore.mdp, Makefile.am: Updated. + * MonoDevelop.GtkCore/GeneratorBuildStep.cs: When generating + code for a project that exports widgets, include the own + project library to the generation, since there can be + widgets that contain other widgets defined in the project. + * MonoDevelop.GtkCore.WidgetLibrary/ProjectClassDescriptor.cs: + removed some IdeApp dependencies. + * MonoDevelop.GtkCore.WidgetLibrary/ProjectWidgetLibrary.cs: + added method for getting the class information from + a project. + * CachedProjectWidgetLibrary.cs: New widget library class + which takes class information from a collection of + ProjectClassInfo objects. + * MonoDevelop.GtkCore.WidgetLibrary/ProjectPropertyDescriptor.cs: + Consider all properties runtime-properties, since they have + been created from class properties. + * lib/*: Updated. + +2006-03-03 Lluis Sanchez Gual <lluis@novell.com> + + * Makefile.am: removed debug files. + +2006-03-02 Lluis Sanchez Gual <lluis@novell.com> + + * MonoDevelop.GtkCore.GuiBuilder/GuiBuilderView.cs: Propagate + project changes to the editor. + +2006-03-02 Lluis Sanchez Gual <lluis@novell.com> + + Initial implementation of the Stetic add-in. diff --git a/main/src/addins/MonoDevelop.GtkCore2/ChangeLog.stetic b/main/src/addins/MonoDevelop.GtkCore2/ChangeLog.stetic new file mode 100644 index 0000000000..cd6a44f1a0 --- /dev/null +++ b/main/src/addins/MonoDevelop.GtkCore2/ChangeLog.stetic @@ -0,0 +1,6477 @@ +2008-11-18 Mike Kestner <mkestner@novell.com> + + * libstetic/editor/ActionMenuItem.cs: check for whitespace only Text + values before saving actions to stop people from doing silly things. + [Fixes #446281] + +2008-11-18 Mike Kestner <mkestner@novell.com> + + * *: kill gnome dependency. Dynamically load GConf.Client object + to query for stetic theme. Dynamically load Gnome.Stock for icon + editors. Establish callbacks for MIME resolution and showing urls. + +2008-11-12 Mike Kestner <mkestner@novell.com> + + * libsteticui/PropertyTree.cs: refine store column type declarations. + * libsteticui/SignalEditorBacked.cs: eliminate multiple refreshes on + selection changes. some changes to the store, simplifying to string + and bool columns, and using AppendValues for all row insertions. I + don't think most of the model changes are necessary, but this bug + fought me so hard I was trying everything and am too tired of it to + back down to a minimal patch. + * libsteticui/WidgetPropertyEditorBacked.cs: check the selection is + really changing before refreshing. [Fixes #431751] + +2008-10-29 Mike Kestner <mkestner@novell.com> + + * libstetic/editor/ActionMenuItem.cs (Select): don't clear and reshow + parent's submenu if it's the current item's menu. Fixes #430520. + +2008-10-27 Mike Kestner <mkestner@novell.com> + + * libsteticui/AssemblyResolver.cs: use the app backend's name resolver + in the AssemblyNameRef resolve overload to avoid some dependency load + failures. I think this also fixes #436246. At least I can't repro it + with this fix in place. + +2008-09-15 Mike Kestner <mkestner@novell.com> + + * libstetic/ErrorWidget.cs: add Project filename to the generation + warning messages. Fixes #373244. + +2008-08-19 Mike Kestner <mkestner@novell.com> + + * libstetic/wrapper/ActionTree.cs: use field references for uim + access. Use Action.Name for name in ui string if name isn't set. + * libstetic/wrapper/Widget.cs: make UIManagerName fixed and dependent + on action group presence. Adjust uim generation to field references. + * libsteticui/CodeGenerator.cs (GetFieldsToBind): add uimanager + field if needed. + * libsteticui/CodeGeneratorPartialClass.cs: add uimanager field if + needed. + +2008-08-19 Mike Krüger <mkrueger@novell.com> + + * libsteticui/CecilClassDescriptor.cs: fixed some possible nullrefs. + +2008-08-18 Mike Kestner <mkestner@novell.com> + + * libstetic/wrapper/Widget.cs: null guarding for ToString(). + +2008-08-10 Mike Kestner <mkestner@novell.com> + + * libsteticui/LibraryCache.cs: add browsable properties and events + to the toolbox item entries in the objects xml doc. + +2008-07-27 Mike Krüger <mkrueger@novell.com> + + + +2008-07-24 Mike Kestner <mkestner@novell.com> + + * libsteticui/CecilWidgetLibrary.cs (Load): use Refresh to get + the cache info so it has a better resolver to work with if the + cache is dirty. + +2008-07-22 Mike Kestner <mkestner@novell.com> + + * libsteticui/LibraryCache.cs: only perform attribute parsing if + there is no objects.xml resource. If an objects.xml resource exists, + it is the definitive source of exported capabilities. + +2008-07-22 Mike Kestner <mkestner@novell.com> + + * libsteticui/CecilClassDescriptor.cs: some null guarding in prop + lookup method. + +2008-07-21 Mike Kestner <mkestner@novell.com> + + Patch from David Makovsky and Jeremie Laval. + * libstetic/PropertyDescriptor.cs: use invariant culture for doubles. + * libsteticui/GladeUtils.cs: use invariant culture for doubles. + +2008-07-16 Mike Kestner <mkestner@novell.com> + + * libsteticui/CecilWidgetLibrary.cs (LoadDependencies): always set + up dependencies to ensure we never return null. + +2008-07-16 Mike Kestner <mkestner@novell.com> + + * libsteticui/ApplicationBackend.cs (RegisterLibrary): null guarding. + +2008-07-14 Mike Krüger <mkrueger@novell.com> + + * libsteticui/CecilWidgetLibrary.cs: fixed possible null reference + exception. + +2008-07-11 Mike Kestner <mkestner@novell.com> + + * libsteticui/ApplicationBackend.cs: removed some CWL spew. This + case is apparently expected for first-time builds. + +2008-07-01 Mike Kestner <mkestner@novell.com> + + * libsteticui/AssemblyResolver.cs: make type resolver public. + * libsteticui/LibraryCache.cs: [ToolboxItem] and [Category] scanner + for identification of exported widgets from libraries. + +2008-06-25 Mike Kestner <mkestner@novell.com> + + * libsteticui/Application.cs: use resolver. + * libsteticui/ApplicationBackend.cs: use resolver. + * libsteticui/AssemblyResolver.cs: integrate ImportContext. remove + usused method and field resolution methods. + * libsteticui/AssemblyWidgetLibrary.cs: refactor ImportContext. + use cached objects doc. + * libsteticui/CecilWidgetLibrary.cs: refactor to use cached docs + and assembly resolver. + * libsteticui/LibraryCache.cs: add document props for objects/gui. + add objects and gui resource extraction and caching. Refresh using + resolver if available. + * libsteticui/ProjectBackend.cs: ImportContext refactor to resolver. + +2008-06-19 Mike Kestner <mkestner@novell.com> + + * configure.in: detect cecil and substitute the dll path. + * libsteticui/Makefile.am: build using installed dll. + * libsteticui/lib/Mono.Cecil.dll: remove + +2008-06-19 Mike Kestner <mkestner@novell.com> + + * libsteticui/AssemblyWidgetLibrary.cs: refactor to use LibraryCache. + * libsteticui/CecilWidgetLibrary.cs: use singleton Cache. Refine + NeedsReload. Call Load (XmlDocument) conditionally. + * libsteticui/LibraryCache.cs: hide Load and expose a singleton Cache + field to share between AssemblyWidgetLibrary and CecilWidgetLibrary. + Remove Gtk reference checking, we will use explicit ToolboxItem attrs + instead. Make HasWidgets a check for an objects.xml file, since we + will be constructing one for attr-only assemblies. + +2008-06-18 Mike Kestner <mkestner@novell.com> + + * libstetic/WidgetLibrary.cs: refactor class addition logic from Load + into a protected AddClass method which subclasses can use to add + classes marked with [ToolboxItem]. + +2008-06-18 Mike Kestner <mkestner@novell.com> + + * libsteticui/CecilWidgetLibrary.cs: remove timestamp code and reuse + cache currency logic. flatten out an unnecessary if branch in Load. + +2008-06-18 Mike Kestner <mkestner@novell.com> + + * libsteticui/Application.cs: remove dead code + +2008-06-02 Mike Kestner <mkestner@novell.com> + + * libstetic/wrapper/Object.cs: dispose guarding + * libstetic/wrapper/Widget.cs: dispose guarding + +2008-05-28 Mike Kestner <mkestner@novell.com> + + * libstetic/editor/ActionGroupEditor.cs: dispose guarding + * libstetic/editor/ActionMenuItem.cs: dispose guarding + * libsteticui/ActionGroupDesigner.cs: dispose guarding + * libsteticui/ActionGroupEditSession.cs: dispose guarding + * libsteticui/ActionGroupToolbar.cs: dispose guarding + * libsteticui/WidgetActionBar.cs: dispose guarding + +2008-05-21 Mike Kestner <mkestner@novell.com> + + * libstetic/wrapper/ActionToolbarWrapper.cs: call FillMenu on Wrap + so that the actionTree is populated on the editor. Otherwise we + crash when inserting items. [Fixes #377672] Also fix what looks to + be a copy/paste error on a UIManagerItemType in the ActionTree. + +2008-05-20 Mike Kestner <mkestner@novell.com> + + * libsteticui/LibraryCache.cs: do a recursive delete when revising + the cache directory. + +2008-05-15 Mike Kestner <mkestner@novell.com> + + * libsteticui/Application.cs: remove redundant cache. Destroy widgets + on Dispose instead of Disposing them. + +2008-05-13 Mike Kestner <mkestner@novell.com> + + * libsteticui/Application.cs: refactor to split out isolated backend + and inprocess backend cases. Dispose additions. Destroy handling for + the public accessors. + * libsteticui/ApplicationBackendController.cs: use IsolatedApplication. + * libsteticui/PluggableWidget.cs: IsolatedApplication handling and + dispose rework. + * libsteticui/Project.cs: ditto. + * stetic/Stetic.cs: use new ApplicationFactory. + +2008-05-13 Mike Kestner <mkestner@novell.com> + + * libsteticui/AssemblyResolver.cs: update to JBs latest Linker version. + * libsteticui/CecilWidgetLibrary.cs: use new cache API. + * libsteticui/LibraryCache.cs: rewritten to use instances, + XmlSerialization of the index and keep the index in memory, and to add + HasWidgets capability. Should be able to remove the other cache from + Application now. + +2008-05-11 Mike Kestner <mkestner@novell.com> + + * libsteticui/SignalsEditor.cs: some Disposal bulletproofing. + +2008-04-30 Mike Kestner <mkestner@novell.com> + + * libstetic/wrapper/objects.xml: clamp Gtk.Misc.(X|Y)align to values + between 0.0 and 1.0. + +2008-02-28 Lluis Sanchez Gual <lluis@novell.com> + + * libstetic/editor/ActionItem.cs: Properly handle drag event fired by + the widget selection box. Fixes bug #363865. + +2008-02-28 Lluis Sanchez Gual <lluis@novell.com> + + * libsteticui/CecilClassDescriptor.cs, + libsteticui/CecilWidgetLibrary.cs: Properly load icons from + resurces. + +2008-02-25 Lluis Sanchez Gual <lluis@novell.com> + + * libstetic/ErrorWidget.cs: Always write the ErrorWidget by reusing the + xml that generated it, unless we are exporting to another format, + in which case we can't write the same xml, and we replace it by a + label. Fixes bug #362596. + +2008-02-21 Lluis Sanchez Gual <lluis@novell.com> + + * libsteticui/CecilClassDescriptor.cs: Don't create black boxes for + custom widgets which allow children. Fixes bug #361650. + * libsteticui/ContextMenu.cs: Dont show invisible commands. + * libstetic/wrapper/Frame.cs, libstetic/wrapper/Table.cs, + libstetic/wrapper/Paned.cs, libstetic/wrapper/Box.cs, + libstetic/wrapper/ScrolledWindow.cs, libstetic/wrapper/Expander.cs, + libstetic/wrapper/Notebook.cs: Don't add placeholders if they are + not allowed. + * libstetic/wrapper/Container.cs: Don't allow placeholders if a + container can't have children. + * libstetic/wrapper/objects.xml: Hide commands not allowed when + containers does not allow children. + +2008-02-20 Lluis Sanchez Gual <lluis@novell.com> + + * libsteticui/ActionComponent.cs, libstetic/wrapper/Action.cs: Added wrapper + properties for Label and StockId, since the notify event is not being + fired for Gtk.Action. + * libstetic/editor/ActionMenuItem.cs, libstetic/editor/ActionToolItem.cs: + Use new Action wrapper properties to access to the label and stock id. + +2008-02-06 Lluis Sanchez Gual <lluis@novell.com> + + * libsteticui/SignalsEditorBackend.cs: TargetObject can't be set when no + project is selected. + +2008-01-25 Lluis Sanchez Gual <lluis@novell.com> + + * libsteticui/PropertyTree.cs: Use a theme color for the property group + headers. Fixes bug #356244. + +2008-01-25 Lluis Sanchez Gual <lluis@novell.com> + + * libstetic/wrapper/Label.cs: Fix generation of MnemonicWidget property + assignment. + * libstetic/wrapper/objects.xml: The default way of + * libstetic/editor/WidgetSelector.cs: Sort the list of widgets. Hide + unselectable widgets. + +2008-01-21 Lluis Sanchez Gual <lluis@novell.com> + + * libsteticui/GuiDispatchServerSink.cs, libsteticui/WidgetDesigner.cs, + libsteticui/Project.cs: Made events fired by the designer synchronous. + Fixes some criticals caused by events being fired in the wrong order. + * libstetic/wrapper/Frame.cs, libstetic/wrapper/CheckButton.cs, + libstetic/wrapper/Container.cs, libstetic/wrapper/ScrolledWindow.cs: Fix + some gtk warnings and criticals. + +2008-01-16 Lluis Sanchez Gual <lluis@novell.com> + + * libsteticui/WidgetDesigner.cs: Fix typo. + +2008-01-15 Lluis Sanchez Gual <lluis@novell.com> + + * libstetic/wrapper/ComboBox.cs: Fix bug #324925 - Glade import: Text combos + not correctly imported. + +2008-01-14 Lluis Sanchez Gual <lluis@novell.com> + + * libstetic/editor/Boolean.cs: Improve rendering of checkbox. + +2008-01-11 Marek Safar <marek.safar@gmail.com> + + * libstetic/editor/ActionMenu.cs, libstetic/editor/ActionMenuBar.cs, + libstetic/editor/ActionToolbar.cs, libstetic/undo/ActionDiffAdaptor.cs + libstetic/editor/ActionGroupEditor.cs: Build with the latest gmcs. + +2008-01-11 Marek Safar <marek.safar@gmail.com> + + * libsteticui/ActionGroupToolbar.cs: Build with the latest gmcs. + +2008-01-08 Lluis Sanchez Gual <lluis@novell.com> + + * libsteticui/ProjectBackend.cs: Don't fire load events when loading a + widget. Fixes part of bug #352065. + * libstetic/wrapper/Paned.cs: Fix bug in paned initialization. Fixes part of + bug #352065. + * libstetic/editor/IconSelectorItem.cs: Added null check. Fixes some + crashes. + +2007-12-13 Lluis Sanchez Gual <lluis@novell.com> + + * libstetic/wrapper/Container.cs: Call base method when attaching/detaching + designer, since Object has some logic in those methods. + +2007-12-13 Lluis Sanchez Gual <lluis@novell.com> + + * libstetic/wrapper/ScrolledWindow.cs, libstetic/wrapper/objects.xml: Set + the correct default for ScrolledWindow.XscrollbarPolicy. + +2007-12-12 Lluis Sanchez Gual <lluis@novell.com> + + * libstetic/editor/ActionMenuItem.cs: Don't try to remove the menu item + controls if they have not been added to the table. + +2007-12-12 Lluis Sanchez Gual <lluis@novell.com> + + * libsteticui/libsteticui.mdp, libstetic/libstetic.mdp, stetic/stetic.mdp, + stetic.mds: Updated. + * libstetic/wrapper/objects.xml: In ScrolledWindow, ignore the default for + scrollbar policy. The default value returned by gtk is not correct. + Fixes bug #344196. + * libstetic/ErrorWidget.cs: Allow exporting projects with unknown widgets. + * stetic/UIManager.cs: Use gtk stock icons instead of gnome's. + +2007-10-26 Lluis Sanchez Gual <lluis@novell.com> + + * libsteticui/PaletteBackend.cs: Moved defaultActionIcon to ActionComponent. + * libsteticui/ActionComponent.cs, libsteticui/ComponentType.cs, + libstetic/wrapper/Action.cs: Added a label property to the + ActionComponent. The label will be shown in the toolbox now. Also show + the default action icon if no icon is specified, instead of the missing + image icon. + +2007-10-25 Lluis Sanchez Gual <lluis@novell.com> + + * libstetic/editor/ActionItem.cs: Ignore the SelectionDisposed event if the + action item has already been disposed. + +2007-10-23 Lluis Sanchez Gual <lluis@novell.com> + + * libsteticui/ProjectBackend.cs: Remove undo annotations from the xml + document when saving. + +2007-10-22 Lluis Sanchez Gual <lluis@novell.com> + + * libstetic/wrapper/objects.xml: Set default value for ShowScrollbars + property. + +2007-10-18 Lluis Sanchez Gual <lluis@novell.com> + + * libstetic/editor/ActionItem.cs: The selected object needs to be the action + because that's what is shown in the properties pad. + +2007-10-16 Lluis Sanchez Gual <lluis@novell.com> + + * libstetic/wrapper/TextView.cs, libstetic/wrapper/TreeView.cs: By default, + show TextView and TreeView widgets wrapped in a ScrolledWindow. Fixes + bug #324439. + * libstetic/wrapper/Widget.cs, libstetic/wrapper/Container.cs, + libstetic/wrapper/ScrolledWindow.cs, libstetic/wrapper/Viewport.cs, + libstetic/wrapper/objects.xml: Implemented new ShowScrollbars + pseudo-property for widgets. When set, the widget will be wrapped inside + a ScrolledWindow. This scrolled window will be bound to the widget, so + if the widget is deleted or moved, the ScrolledWindow will also be + deleted or moved. + * libstetic/wrapper/Table.cs, libstetic/wrapper/Paned.cs, + libstetic/wrapper/Box.cs, libstetic/wrapper/Notebook.cs: Methods for + adding widgets to a container other than Add() do not fire the child + Added event, so it has to be manually called. + +2007-10-16 Lluis Sanchez Gual <lluis@novell.com> + + * libstetic/Clipboard.cs, libsteticui/Clipboard.cs: Moved to libstetic. + * libstetic/editor/ActionGroupEditor.cs, libstetic/editor/ActionItem.cs, + libstetic/editor/ActionMenuItem.cs, libstetic/editor/ActionToolItem.cs: + Factorized common code in ActionMenuItem and ActionToolItem into + ActionItem. Implemented IEditableObject. + * libstetic/editor/ActionMenu.cs: Improved support for keyboard. Return now + edits the selected item, and ctrl+right/left adds/removes submenus. + * libstetic/editor/ActionMenuBar.cs, libstetic/editor/ActionToolbar.cs: Keep + the selection when a node is deleted. Track other api changes. + * libstetic/IEditableObject.cs: New interface to be implemented by objects + which can handle clipboard operations. + * libstetic/libstetic.mdp, libstetic/Makefile.am, + libsteticui/libsteticui.mdp, libsteticui/Makefile.am: Updated. + * libstetic/Placeholder.cs, libstetic/wrapper/Widget.cs: Implemented + IEditableObject. + * libsteticui/ContextMenu.cs: Use the new IEditableObject interface to + implement the clipboard operations. + * libsteticui/ProjectBackend.cs, libsteticui/WidgetDesigner.cs, + libsteticui/WidgetEditSession.cs: Use IEditableObject to handle + clipboard operations. + +2007-10-16 Lluis Sanchez Gual <lluis@novell.com> + + * libsteticui/WidgetEditSession.cs: Removed unneeded dispose and destroy + calls. The toolbar will be destroyed together with the parent. + * libsteticui/ActionGroupEditSession.cs: If the designer has not been + requested, it means it has not been added to a container, so it has to + be explicitely destroyed. + * libsteticui/WidgetActionBar.cs: Removed unneeded Dispose and Destroy calls + (Destroy already calls dispose). + * libsteticui/WidgetDesignerBackend.cs: Make sure base.Dispose is always + called. Handle exceptions thrown by the GConf query. + * libsteticui/ActionGroupDesignerBackend.cs: Remove references on dispose. + Helps tracking down leaks. + * libsteticui/PluggableWidget.cs: Don't try to create an image of the + designer if it is not visible. Don't explicitely destroy the child + designer. It will be destroyed by the subclass. + * libstetic/editor/ActionToolbar.cs, libstetic/editor/ActionGroupEditor.cs: + Properly destroy items. + +2007-10-04 Lluis Sanchez Gual <lluis@novell.com> + + * libstetic/wrapper/Action.cs: Avoid providing a null name in the Gtk.Action + constructor. Fixes crash in gtk+ 2.12. + +2007-10-01 Lluis Sanchez Gual <lluis@novell.com> + + * libsteticui/CecilWidgetLibrary.cs: Added missing null check. + +2007-09-20 Lluis Sanchez Gual <lluis@novell.com> + + * libsteticui/ProjectBackend.cs, libsteticui/AssemblyWidgetLibrary.cs, + libsteticui/CecilWidgetLibrary.cs, libsteticui/ApplicationBackend.cs, + libsteticui/Application.cs: Added a callback for resolving assembly + names. + +2007-09-17 Lluis Sanchez Gual <lluis@novell.com> + + * libsteticui/ActionGroupDesigner.cs, libsteticui/Designer.cs, + libsteticui/WidgetDesigner.cs: Added a property for getting the project + element being edited in the designer. + * libsteticui/ComponentEventHandler.cs: Added property for getting the new + name in the args for the name change event. + +2007-09-13 Lluis Sanchez Gual <lluis@novell.com> + + * libstetic/WidgetUtils.cs: Fix version comparison logic. + +2007-09-10 Lluis Sanchez Gual <lluis@novell.com> + + * libsteticui/ProjectBackend.cs, libsteticui/WidgetEditSession.cs, + libsteticui/Project.cs: Properly propagate the widget name change event + when saving the contents of the designer. + +2007-09-06 Lluis Sanchez Gual <lluis@novell.com> + + * libsteticui/WidgetEditSession.cs: Removed unneeded code. + +2007-09-06 Lluis Sanchez Gual <lluis@novell.com> + + * libsteticui/ProjectBackend.cs, libsteticui/WidgetEditSession.cs: When + creating the designer, about creating twice the window widget (once for + the source project and once for the project being edited). Removed some + debug code. + +2007-09-06 Lluis Sanchez Gual <lluis@novell.com> + + * libsteticui/ActionGroupDesigner.cs, libsteticui/ApplicationBackend.cs, + libsteticui/Designer.cs, libsteticui/Application.cs, + libsteticui/WidgetDesigner.cs: The Application.ActiveProject has been + replaced by Application.ActiveDesigner, which coveys more information + about what to show in the designer widgets. + * libsteticui/ProjectBackend.cs, libsteticui/Project.cs, libstetic/DND.cs: + Implemented lazy loading of windows. The project now only loads the xml, + and only creates the widgets when they have to be shown in the designer. + * libsteticui/WidgetEditSession.cs, libsteticui/WidgetTree.cs, + libsteticui/ProjectView.cs, libsteticui/ProjectViewBackend.cs: Renamed + ProjectView to WidgetTree. This widget now only displays the widget tree + of the currently active designer. + * libsteticui/libsteticui.mdp, libsteticui/Makefile.am: Added new files. + * libsteticui/PaletteBackend.cs: Hide the palette if there is no active + project. + * libstetic/IProject.cs, libstetic/ObjectWrapper.cs, + libstetic/wrapper/Widget.cs: Added notification methods to IProject, in + this way some common events can be forwarded to the project without + having to subscribe them on every widget. + * libstetic/wrapper/Button.cs, libstetic/wrapper/Object.cs, + libstetic/wrapper/Container.cs, libstetic/TypedPropertyDescriptor.cs: + Make sure change events are not fired when widgets are loaded from xml. + * libstetic/WidgetUtils.cs: Removed unused code. + * stetic/Stetic.cs, stetic/DesignerView.cs, stetic/stetic.glade, + stetic/Makefile.am, stetic/stetic.mdp, stetic/WindowListWidget.cs, + stetic/UIManager.cs: Added a new widget for displaying the list of all + windows in the project, since the project view now only displays the + widget tree of the active designer. Track other api changes. + +2007-09-04 Lluis Sanchez Gual <lluis@novell.com> + + * libstetic/wrapper/objects.xml: Added support for NodeView. Fixes bug + #81238. + +2007-09-04 Lluis Sanchez Gual <lluis@novell.com> + + * libstetic/wrapper/ComboBox.cs: Comboboxes are now of type Text by default. + Fixes bug #81763. + +2007-09-04 Lluis Sanchez Gual <lluis@novell.com> + + * libstetic/wrapper/Notebook.cs: Workaround for GTK bug. ShowAll is not + propagated to tab labels. Fixes bug #82476. + +2007-09-04 Lluis Sanchez Gual <lluis@novell.com> + + * libsteticui/ProjectBackend.cs: When reloading a project, reuse the same + icon factory instance, since it may be inherited from another project. + Fixes bug #82527. + * libsteticui/WidgetEditSession.cs: Removed unneeded assignement. + * libsteticui/CodeGenerator.cs, libsteticui/CodeGeneratorInternalClass.cs, + libsteticui/CodeGeneratorPartialClass.cs, libstetic/GeneratorContext.cs: + Fix crash when generating the icon factory (the root object was not set + in the GeneratorContext). + * libsteticui/Project.cs: Special handling of IconFactory is not needed. + * libstetic/editor/ActionToolItem.cs: In CreateControls, fix crash caused by + the icon property being set too early, when it might be null. + * libstetic/editor/ActionToolbar.cs: Added missing null check. + +2007-09-03 Lluis Sanchez Gual <lluis@novell.com> + + * libstetic/wrapper/objects.xml: FileChooserButton doesn't have a default + constructor, it requires the title and the action. Fixes bug #82671. + +2007-08-16 Lluis Sanchez Gual <lluis@novell.com> + + * libsteticui/ApplicationBackend.cs, libsteticui/Application.cs, + libsteticui/ApplicationBackendController.cs: When a library is unloaded + notify the application frontend. The frontend can then clear cached data + from the library. + * libstetic/wrapper/objects.xml: Update EventBox category to 'container'. + * libstetic/ClassDescriptor.cs: When no label is set for a widget, use the + class name, without namespace. + +2007-08-08 Lluis Sanchez Gual <lluis@novell.com> + + * libstetic/wrapper/Widget.cs: Added missing null check. Don't set the Name + property to unselectable widgets. + +2007-07-31 Lluis Sanchez Gual <lluis@novell.com> + + * libstetic/wrapper/Button.cs, libstetic/wrapper/ButtonBox.cs: Don't + store the IsDialogButton property. The value can be determined on + the fly. + +2007-07-31 Lluis Sanchez Gual <lluis@novell.com> + + * libsteticui/WidgetEditSession.cs: Assign the target gtk version to + the project being edited. + * libstetic/wrapper/IconView.cs, libstetic/wrapper/objects.xml, + libstetic/libstetic.mdp, libstetic/Makefile.am: Added wrapper for + IconView. + * libstetic/TypedPropertyDescriptor.cs: Added null check. + +2007-07-31 Lluis Sanchez Gual <lluis@novell.com> + + * libstetic/ImageInfo.cs, libstetic/editor/ThemedIcon.cs, + libstetic/editor/SelectImageDialog.cs, + libstetic/editor/StockIconSelectorItem.cs, + libstetic/editor/StockIconList.cs, libstetic/editor/StockItem.cs, + libstetic/editor/SelectIconDialog.cs, + libstetic/GeneratorContext.cs, libstetic/WidgetUtils.cs: Fixed + loading of theme and gtk stock icons. + +2007-07-31 Lluis Sanchez Gual <lluis@novell.com> + + * libsteticui/WidgetPropertyTreeBackend.cs: Added missing null check. + +2007-07-27 Lluis Sanchez Gual <lluis@novell.com> + + * libsteticui/CecilWidgetLibrary.cs: Added null check. + * libsteticui/PluggableWidget.cs: When updating the child widget, do + not add it to the notebook if it is already a child of the + notebook. + * libstetic/wrapper/pixmaps/comboentry.png, + libstetic/wrapper/pixmaps/iconview.png, libstetic/libstetic.mdp, + libstetic/Makefile.am: Added some missing icons. + * libstetic/wrapper/Widget.cs, libstetic/wrapper/objects.xml: Fixed + some issues with HasDefault. It can only be assigned when the + widget already has a parent. + * libstetic/TypedClassDescriptor.cs: Report icon loading errors. + +2007-07-20 Lluis Sanchez Gual <lluis@novell.com> + + * libsteticui/ProjectBackend.cs: Make DeleteSelection work for + placeholders. + * libsteticui/WidgetEditSession.cs, libsteticui/Component.cs, + libsteticui/WidgetDesigner.cs, libsteticui/WidgetComponent.cs: + Moved all clipboard checking properties to WidgetDesigner. + +2007-07-16 Lluis Sanchez Gual <lluis@novell.com> + + * libsteticui/Project.cs: Fixes on ActionGroup management. + +2007-07-16 Lluis Sanchez Gual <lluis@novell.com> + + * libsteticui/ActionGroupToolbar.cs: Notify group changes to the + frontend. + * libsteticui/ActionGroupEditSession.cs: Don't delay the creation of + the designer because when used in combination with the widget + designer, change events are subscribed since the begining + +2007-07-10 Lluis Sanchez Gual <lluis@novell.com> + + * libsteticui/ProjectBackend.cs: Fix NRE (bug #82052). + +2007-07-09 Lluis Sanchez Gual <lluis@novell.com> + + * libstetic/editor/ActionMenuItem.cs, + libstetic/editor/ActionToolItem.cs: Show menu items and tool + buttons insensitive when bound to an insensitive action. Fixes bug + #81810. + +2007-07-09 Lluis Sanchez Gual <lluis@novell.com> + + * libsteticui/ProjectViewBackend.cs: Cosmetic fixes. + +2007-07-09 Lluis Sanchez Gual <lluis@novell.com> + + * libsteticui/CecilWidgetLibrary.cs: Return 2.4 target gtk version is + none is provided. + * libsteticui/ApplicationBackend.cs, libsteticui/Application.cs, + libsteticui/ComponentType.cs: Added Library property to + ComponentType. + * libsteticui/PluggableWidget.cs: The widget may be unrealized after + adding the notebook. Added a null check for this case. Fixes bug + #81977. + +2007-06-27 Lluis Sanchez Gual <lluis@novell.com> + + * libsteticui/CecilWidgetLibrary.cs, libsteticui/Application.cs, + libsteticui/ComponentType.cs: When reading the component list of a + library, get the target version. + * libsteticui/ApplicationBackend.cs: Properly report an error when + dropping a widget of a class that doesn't exist. + * libstetic/WidgetLibrary.cs, libstetic/DND.cs: Added null check. + +2007-06-27 Jacob Ilsø Christensen <jacobilsoe@gmail.com> + + * libstetic/WidgetLibrary.cs: Added handling of + an empty objects.xml file. + +2007-06-22 Lluis Sanchez Gual <lluis@novell.com> + + * libsteticui/CecilWidgetLibrary.cs: When looking for widgets in a + library, ignore those without a palette category. + * libsteticui/ApplicationBackend.cs: Added null check. + * libsteticui/Application.cs: Don't try to load widgets from an + assembly if we know that's not a widget library. + * libstetic/CustomWidget.cs: Add IntPtr constructor. + * libstetic/EnumDescriptor.cs: Fix problem with the enum loading code, + which was not working when loading Gtk.SelectionMode, because it + has two members with the same value. + * libstetic/wrapper/Container.cs: When dropping an object, look for + placeholders in all the child hierarchy, not only the direct + childs. + +2007-06-20 Lluis Sanchez Gual <lluis@novell.com> + + * libsteticui/WidgetEditSession.cs: Flickering fixes. + * libsteticui/WidgetDesigner.cs: In BeginComponentDrag, don't take a + callback when the component type is known. + +2007-06-20 Lluis Sanchez Gual <lluis@novell.com> + + * libsteticui/ProjectBackend.cs, libsteticui/WidgetEditSession.cs, + libsteticui/WidgetDesigner.cs, libsteticui/PluggableWidget.cs, + libsteticui/Project.cs: Fixed flickering in widget designers caused + by project reloading. The new ProjectReloading event is fired + before the whole process reloading starts, and the designer takes a + 'screenshot' of the old desiger, which is shown in place of the + real designer during the reloading process. + * libsteticui/CecilWidgetLibrary.cs, libsteticui/Application.cs: Added + GetComponentTypes method, which returns a list of widgets + implemented in a library, without having to load it. + * libsteticui/ApplicationBackend.cs, libstetic/IProject.cs, + libstetic/ObjectWriter.cs, libstetic/ObjectWrapper.cs, + libstetic/wrapper/Container.cs, libstetic/DND.cs: Added support for + dragging widgets from a palette before loading the widget library + that implements them. When the widget is dropped, a callback is + called (which is supposed to load the library) and the new widget + is created. + * libstetic/wrapper/pixmaps/widget.png, libstetic/libstetic.mdp, + libstetic/Makefile.am: Added new image. + +2007-06-19 Lluis Sanchez Gual <lluis@novell.com> + + * libstetic/wrapper/objects.xml: Added some missing gtk 2.8 properties. + +2007-06-18 Lluis Sanchez Gual <lluis@novell.com> + + * libsteticui/ProjectBackend.cs, libsteticui/SignalsEditorBackend.cs, + libsteticui/WidgetPropertyTreeBackend.cs, + libsteticui/WidgetEditSession.cs, libsteticui/PropertyTree.cs, + libsteticui/WidgetActionBar.cs, libsteticui/ApplicationBackend.cs, + libsteticui/PaletteBackend.cs, libsteticui/Project.cs, + libstetic/IProject.cs, libstetic/ItemDescriptor.cs, + libstetic/ObjectWrapper.cs, libstetic/WidgetLibrary.cs, + libstetic/ErrorWidget.cs, libstetic/WidgetUtils.cs, + libstetic/ClassDescriptor.cs: Allow selecting the target the gtk# + version of a project. + * libstetic/wrapper/objects.xml: Added new widgets, properties and + events for gtk# 2.6. + +2007-06-12 Lluis Sanchez Gual <lluis@novell.com> + + * libsteticui/lib/Mono.Cecil.dll: Updated from SVN, to keep in sync + with MD. + +2007-06-11 Lluis Sanchez Gual <lluis@novell.com> + + * libsteticui/Project.cs: Make sure the project backend is loaded when + checking the CanGenerateCode property. + +2007-06-11 Lluis Sanchez Gual <lluis@novell.com> + + * libstetic/ImageInfo.cs: Load images from a path relative to the entry + assembly location. + +2007-06-11 Lluis Sanchez Gual <lluis@novell.com> + + * libsteticui/Project.cs: Fix problem with reading empty action groups. + +2007-06-04 Lluis Sanchez Gual <lluis@novell.com> + + * libstetic/GeneratorContext.cs: IconLoader must be an internal class. + +2007-05-31 Lluis Sanchez Gual <lluis@novell.com> + + * libstetic/wrapper/Action.cs: Generate initialization of the Active + and DrawAsRadio properties. They are not generated by default + because they belong to a Gtk.Action subclass. Fixes bug #81785. + +2007-05-31 Lluis Sanchez Gual <lluis@novell.com> + + * libsteticui/ProjectBackend.cs, libsteticui/Project.cs: Added method + for getting all widget types included in a project. + * libstetic/wrapper/objects.xml: Gtk.Bin now inherits the properties of + Gtk.Container. + +2007-05-31 Lluis Sanchez Gual <lluis@novell.com> + + * libsteticui/CecilClassDescriptor.cs: Added missing null check when + checking for base classes in FindEvent. + +2007-05-30 Lluis Sanchez Gual <lluis@novell.com> + + * libsteticui/libsteticui.mdp, libsteticui/Makefile.am: Added reference + to glib. + * libsteticui/WidgetActionBar.cs, libstetic/CommandDescriptor.cs: Use + Menu size for command icons. + * libsteticui/WidgetTreeCombo.cs: Replaced the popup widget menu by a + popup widget tree view. Fixes bug #81762. + +2007-05-30 Lluis Sanchez Gual <lluis@novell.com> + + * libstetic/wrapper/Window.cs: Store the WindowPosition property in the + Window wrapper, since it may sometimes be changed by the embedder + widget. + * libstetic/wrapper/objects.xml: Added default value for Widget.Events + property. + * libstetic/wrapper/Dialog.cs: (Wrap) Don't initialize the HasSeparator + property if the provided instance is already initialized. + +2007-05-30 Lluis Sanchez Gual <lluis@novell.com> + + * libstetic/editor/ActionMenuBar.cs, libstetic/editor/ActionMenu.cs: + When a menu bar loses the focus, reset the menu item selection + before hiding the submenus. Fixes bug #81761. + +2007-05-23 Lluis Sanchez Gual <lluis@novell.com> + + * libstetic/editor/StockIconSelectorItem.cs, + libstetic/editor/IconSelectorItem.cs: Added IntPtr constructors. It + seems to crash without them in some contexts. + +2007-05-21 Lluis Sanchez Gual <lluis@novell.com> + + * libsteticui/ProjectBackend.cs: When saving write to a temporary file + first, just in case something fails. + +2007-05-21 Lluis Sanchez Gual <lluis@novell.com> + + * libsteticui/CecilSignalDescriptor.cs, + libsteticui/CecilWidgetLibrary.cs: Properly handle generic event + handler types. Fixes bug #80783. + +2007-05-19 Lluis Sanchez Gual <lluis@novell.com> + + * libsteticui/ProjectBackend.cs, libsteticui/WidgetEditSession.cs, + libsteticui/WidgetDesigner.cs, libsteticui/Project.cs, + libstetic/IProject.cs: Added ImagesRootPath, which is the root path + where to start looking for images. Added the ImportFileCallback + callback, called when an image file is referenced from the stetic + project. + * libstetic/ImageInfo.cs: Image files are now relative to + ImagesRootPath. + * libstetic/stetic.glade, libstetic/editor/SelectImageDialog.cs: Use + the new root image path to create relative paths to images. + * libstetic/editor/ImageSelector.cs: Make the clean button smaller. + * libstetic/WidgetUtils.cs: Added AbsoluteToRelative function. + +2007-05-17 Lluis Sanchez Gual <lluis@novell.com> + + * libstetic/wrapper/Notebook.cs, libstetic/wrapper/objects.xml: Added + CurrentPage property to Notebook. + +2007-05-17 Lluis Sanchez Gual <lluis@novell.com> + + * libsteticui/CecilSignalDescriptor.cs: Added missing null check. + * libsteticui/ProjectBackend.cs: Remove debug cwl. + * libstetic/wrapper/Container.cs: Don't show the main window if the + visible flag is not set. Fixes bug #81365. + +2007-05-17 Lluis Sanchez Gual <lluis@novell.com> + + * libsteticui/WidgetActionBar.cs, libstetic/CommandDescriptor.cs: Fix + bug about widget commands without an icon not being properly shown. + * libstetic/wrapper/Notebook.cs: Implemented Swap methods. + * libstetic/libstetic.mdp: Updated. + +2007-05-16 Lluis Sanchez Gual <lluis@novell.com> + + * libsteticui/ProjectBackend.cs, libsteticui/WidgetEditSession.cs, + libsteticui/PaletteBackend.cs, libsteticui/Project.cs: Added + support for internal widgets and internal widget libraries. + Internal widgets won't be shown in the palette unless the library + to which they belong is internal to the project. + * libsteticui/Component.cs, libsteticui/ActionGroupComponent.cs, + libsteticui/WidgetComponent.cs: Added properties for changing the + GeneratePublic flag. + * libstetic/ImageInfo.cs, libstetic/ProjectIconFactory.cs, + libstetic/GeneratorContext.cs: Added a GenerateLoadPixbuf method + which creates a pixbuf from a stock image name in safe way (it + won't crash if the image doesn't exist, but it will return a + 'missing image' icon). + * libstetic/wrapper/ActionGroup.cs: Allow generatic private action + groups. + * libstetic/ClassDescriptor.cs: Added support for internal widgets. + +2007-05-15 Lluis Sanchez Gual <lluis@novell.com> + + * libsteticui/ActionGroupDesigner.cs, libsteticui/ProjectBackend.cs, + libsteticui/WidgetInfoEventHandler.cs, libsteticui/Application.cs, + libsteticui/Project.cs, libsteticui/PluggableWidget.cs, + stetic/Stetic.cs, stetic/DesignerView.cs, stetic/UIManager.cs: + Implemented lazy loading of projects. Project widgets won't be + instantiated until necessary. The new WidgetInfo class allows + getting the list of toplevels in a project without having to + completely load it. + * libsteticui/CecilSignalDescriptor.cs, + libsteticui/CecilPropertyDescriptor.cs, + libsteticui/LibraryCache.cs, libsteticui/CecilClassDescriptor.cs, + libsteticui/CecilWidgetLibrary.cs: Store parsed information in a + cache file. When loading the library again stetic will check if the + library has changed, and it if has not it will load widget info + from the cache file. + * libsteticui/libsteticui.mdp, libsteticui/Makefile.am: Updated. + * libsteticui/ProjectView.cs, libsteticui/ProjectViewBackend.cs: Added + SelectionChanged event. Moved from the Project class, since project + doesn't have the concept of Selection anymore. + * libsteticui/WidgetDesigner.cs: Added clipboard check operations from + the Project class. + * libstetic/wrapper/Widget.cs: After reading the info of a widget, + store the oldName field, so it can properly track name changes. + * stetic/Makefile.am, stetic/stetic.mdp: Added new files. + +2007-05-08 Lluis Sanchez Gual <lluis@novell.com> + + * libstetic/wrapper/ScrolledWindow.cs: Manually notify that a child has + been added, since the child added event is not being fired. + * libstetic/GladeUtils.cs: Normalize glade field names when loading. + +2007-05-02 Mike Kestner <mkestner@novell.com> + + * libsteticui/WidgetFactory.cs: don't Destroy from Dispose override + since the circular ref GC mechanism can get to the child before the + parent. + +2007-05-01 Mike Kestner <mkestner@novell.com> + + * libstetic/wrapper/MenuBar.cs: + * libstetic/wrapper/ActionToolbarWrapper.cs: + * libstetic/editor/ActionMenuItem.cs: + * libstetic/editor/IconSelectorMenuItem.cs: + * libstetic/editor/ActionMenu.cs: Call base.Dispose on GLib.Objects + after all other dispose actions are performed. + +2007-05-01 Mike Kestner <mkestner@novell.com> + + * libsteticui/WidgetFactory.cs: + * libsteticui/ProjectView.cs: + * libsteticui/PaletteBackend.cs: + * libsteticui/SignalsEditor.cs: + * libsteticui/ActionGroupToolbar.cs: + * libsteticui/WidgetDesigner.cs: + * libsteticui/PluggableWidget.cs: + * stetic/DesignerView.cs: Call base.Dispose on GLib.Objects after + all other dispose actions are performed. + +2007-04-27 Mike Kestner <mkestner@novell.com> + + * libstetic/editor/ActionToolbar.cs (FillMenu): can't Destroy + after Disposing the widgets. Just Destroy, as it disposes. + +2007-04-27 Mike Kestner <mkestner@novell.com> + + * libsteticui/ObjectWrapper.cs: ContainerChildHashItem.Equals needs + to return avoid cast and return false if comparing to another type. + +2007-04-26 Mike Kestner <mkestner@novell.com> + + * libsteticui/PaletteBackend.cs: ActionGroupBox.Dispose needs to + do its cleanup before invoking base.Dispose. + +2007-04-18 Lluis Sanchez Gual <lluis@novell.com> + + * libsteticui/libsteticui.mdp, libstetic/libstetic.mdp: Updated. + * libstetic/wrapper/Box.cs, libstetic/wrapper/Table.cs: Set spacing to + 6 by default. + * libstetic/wrapper/ScrolledWindow.cs: Set scrolling to automatic by + default. + * libstetic/WidgetUtils.cs, libstetic/ClassDescriptor.cs, + libstetic/TypedClassDescriptor.cs: When looking for default values, + avoid initializing the test instance, make sure the get an instance + with all default values. + +2007-04-10 Lluis Sanchez Gual <lluis@novell.com> + + * libsteticui/CecilWidgetLibrary.cs: Performance improvements in the + method that resolves widget types. + * libstetic/wrapper/ButtonBox.cs: Don't automatically bind dialog + buttons with response type set to None. + * libstetic/PropertyDescriptor.cs: Set the hasDefault flag when a + default is explicitely set in the objects.xml file. + * libstetic/Makefile.am: Updated. + +2007-03-28 Lluis Sanchez Gual <lluis@novell.com> + + * libsteticui/ApplicationBackend.cs: Don't allow cutting/copying top + level widgets. Fixes bug #81015. + +2007-03-28 Lluis Sanchez Gual <lluis@novell.com> + + * libstetic/wrapper/Container.cs, libstetic/wrapper/Widget.cs: When + selecting a widget, avoid setting the focus to the parent + container, since it may end changing the selection. Fixes bug + #81014. + +2007-03-28 Lluis Sanchez Gual <lluis@novell.com> + + * libstetic/wrapper/objects.xml: Removed properties already inherited + from Gtk.Button. + +2007-03-28 Lluis Sanchez Gual <lluis@novell.com> + + * libstetic/undo/XmlDiffAdaptor.cs: Don't crash if a child element + doesn't exist. + * libstetic/editor/StockItem.cs: Fix warning. + +2007-03-28 Lluis Sanchez Gual <lluis@novell.com> + + * libstetic/wrapper/ScrolledWindow.cs: Don't generate the viewport if + there isn't any child. Make scrollbars always visible in the + designer. + * libstetic/wrapper/objects.xml: Ignore the default for DrawIndicator, + since the default is 'false', but a default CheckButton has 'true' + as value. + +2007-03-26 Lluis Sanchez Gual <lluis@novell.com> + + * libsteticui/WidgetEditSession.cs, + libsteticui/CodeGeneratorPartialClass.cs, + libstetic/wrapper/Widget.cs, libstetic/wrapper/objects.xml: Support + generating private classes. + * libsteticui/ComponentType.cs, libstetic/ImageInfo.cs, + libstetic/wrapper/Action.cs, libstetic/wrapper/ImageMenuItem.cs, + libstetic/editor/StockItem.cs, libstetic/WidgetUtils.cs: Use the + new MissingIcon constant. + * libstetic/wrapper/ComboBox.cs: Made combo values translatable. Fixes + bug #81033. + * libstetic/HandleWindow.cs: Removed unused file. + +2007-03-08 Lluis Sanchez Gual <lluis@novell.com> + + * libstetic/wrapper/Container.cs: Fix null ref. + * libstetic/wrapper/Widget.cs: Use a wrapper property for CanFocus + since it may be changed by the designer. + +2007-03-08 Lluis Sanchez Gual <lluis@novell.com> + + * libsteticui/WidgetDesignerBackend.cs: ResetSelection now sets the + focus to the fixed container. + * libsteticui/PropertyTree.cs: Dispose the edit session of a cell when + losing the focus. + * libsteticui/PaletteBackend.cs: Don't call SetActionGroups when + disposing, since it ends calling show(). + * libstetic/wrapper/Container.cs: Use ResetSelection to remove the + focus from the current widget. + * libstetic/editor/TextEditor.cs: Don't fire the changed event at every + key press, only when pressing enter or losing the focus. + * libstetic/PropertyEditorCell.cs: When losing the focus, update the + property value. + * libstetic/wrapper/Widget.cs: Don't try to change widget event flags + if the widget is already realized. + +2007-03-06 Lluis Sanchez Gual <lluis@novell.com> + + * libsteticui/ApplicationBackend.cs: Added some null checks. Added + BeginComponentDrag, to allow using an external toolbox. + * libsteticui/ProjectBackend.cs, libsteticui/WidgetDesigner.cs, + libsteticui/Project.cs: Added method for getting all component + types accessible from a project. Added some null checks. + * libsteticui/WidgetEditSession.cs: Reload the project when the widget + libraries change. + * libsteticui/Application.cs: Fill ComponentType with category + information. + * libsteticui/PropertyTree.cs: Removed the horizontall scrollbar. Cell + size will always fit the available space. Allow changing the column + width by dragging the divider. + * libsteticui/PaletteBackend.cs: The library list of a project now + includes the core library. + * libsteticui/ActionGroupComponent.cs: Added null check. + * libsteticui/ComponentType.cs: Added category information. Allow + creating a ComponentType from an action. + * libsteticui/WidgetComponent.cs: Added some null checks. + * libstetic/editor/Enumeration.cs: Use a combo box entry with no frame + as selector. It takes less space. + * libstetic/editor/TextEditor.cs, libstetic/editor/Flags.cs, + libstetic/editor/String.cs, libstetic/editor/IntRange.cs, + libstetic/editor/Identifier.cs, libstetic/editor/OptIntRange.cs, + libstetic/editor/StringArray.cs: Removed frames from all editors. + Take less space. + + + +2007-02-24 Zach Lute <zach.lute@gmail.com> + + * libstetic/ImageInfo.cs: Fixed an issue in which an image thumbnail + wouldn't be scaled if width and height were equal. Fixes bug #80927. + +2007-03-02 Lluis Sanchez Gual <lluis@novell.com> + + * libstetic/ObjectReader.cs, libstetic/wrapper/Container.cs: Fixed + issues with internal children when importing a glade file. + * libstetic/GladeUtils.cs: Use invariant culture to parse floats. + +2007-02-20 Lluis Sanchez Gual <lluis@novell.com> + + * libsteticui/ActionGroupEditSession.cs: Added null check. + * libstetic/wrapper/Action.cs: Don't set the type to Radio unless a + real group name is provided. + * libstetic/editor/ActionMenu.cs: Set AppPaintable, since we do some + custom painting in the Expose event. Also call the base + OnExposeEvent after painting the background. Fixes bug #80864. + + + +2007-02-19 Nate Hancock <nchancock@yahoo.com> + + * libstetic/wrapper/object.xml: Gtk.ToggleButton now has base class + Gtk.Button instead of Gtk.Container. + +2007-02-19 Lluis Sanchez Gual <lluis@novell.com> + + * libsteticui/WidgetFactory.cs, libsteticui/WidgetEditSession.cs: + Several fixes in the disposing code. + * libsteticui/ActionGroupToolbar.cs: Unsubscribe all events, since gtk# + seems to leak if not done. Replaced all anonymous methods, since + keep to many references in memory. + * libsteticui/ActionGroupDesignerBackend.cs: Removed the Dispose + method, since everything will be disposed when the backend is + destroyed. + * libsteticui/libsteticui.mdp, libstetic/libstetic.mdp, + stetic/stetic.mdp: Updated. + * libsteticui/WidgetDesigner.cs: Added some checks to avoid operating + on disposed designers. + * libsteticui/ActionGroupEditSession.cs: Delay the creation of the + action group designer until it is really required. + * libsteticui/PluggableWidget.cs: Explicitely destroy replaced + children. + * libstetic/undo/UndoManager.cs: Don't use an anonymous method since it + will hold a reference to the object to which the event is being + added, and we don't want this. + * libstetic/wrapper/Container.cs, libstetic/wrapper/Widget.cs: Moved + tooltip generation code from Widget to Container. Reset the + generated widget code when starting code generation. + * libstetic/wrapper/MenuBar.cs: Dispose the attached ActionTreeNode + object when the palette item is disposed. + * libstetic/wrapper/ActionTree.cs: Recursively dispose node children. + * libstetic/editor/ActionGroupEditor.cs: Unsubscribe events when + disposing. + +2007-02-13 Lluis Sanchez Gual <lluis@novell.com> + + * libstetic/wrapper/Container.cs: Emit the content changed event when a + new child is added. + * libstetic/wrapper/Paned.cs: Add1 and Add2 does not fire the child + added event, so the parent has to be manually notified. + +2007-02-13 Lluis Sanchez Gual <lluis@novell.com> + + * libstetic/RadioGroupManager.cs: Implement the IRadioGroupManager + interface. + * libstetic/wrapper/Action.cs, libstetic/wrapper/objects.xml, + libstetic/wrapper/RadioActionGroupManager.cs: Implemented support + for radio groups in RadioAction objects. + * libstetic/wrapper/RadioToolButton.cs, + libstetic/wrapper/RadioButton.cs, + libstetic/wrapper/RadioMenuItem.cs: Implement the new + IRadioGroupManagerProvider interface. + * libstetic/IRadioGroupManager.cs: Added new interface for wrapping + group managers. + * libstetic/editor/GroupPicker.cs: Get the group manager from the + manager provider, instead of looking for a static method. + * libstetic/libstetic.mdp, libstetic/Makefile.am: Updated. + +2007-02-12 Lluis Sanchez Gual <lluis@novell.com> + + * libsteticui/ApplicationBackend.cs, libsteticui/Application.cs, + libstetic/stetic.glade, libstetic/wrapper/Container.cs, + libstetic/editor/NonContainerWarningDialog.cs, + libstetic/libstetic.mdp, libstetic/Makefile.am, stetic/Stetic.cs, + stetic/Configuration.cs: When dropping a non-container into a main + window, warn the user whether they really wanted that, or if they + instead wanted a container to be in place. Make this warning dialog + configurable. + * libsteticui/PropertyTree.cs: Removed unused code. + +2007-02-12 Lluis Sanchez Gual <lluis@novell.com> + + * libsteticui/PropertyTree.cs: Refiltering the tree while it is being + edited has lots of issues, so filtering has been completely + removed. Now, the label of hidden properties are shown as disabled, + and the content blank. + * stetic/Makefile.am, stetic/stetic.mdp: Added missing resource. + +2007-02-12 Lluis Sanchez Gual <lluis@novell.com> + + * libsteticui/libsteticui.mdp, libsteticui/Makefile.am, + libstetic/Makefile.am, stetic/Makefile.am: Flush. + * libsteticui/WidgetDesigner.cs: When disposing the active project, + reset the active project property. + * libstetic/GeneratorContext.cs: Added a code generation option for + specifying the Gettext class to use. + +2007-02-08 Lluis Sanchez Gual <lluis@novell.com> + + * libsteticui/libsteticui.mdp, libsteticui/Makefile.am: Fixed + references. + * configure.in: Added missing modules. + +2007-02-08 Lluis Sanchez Gual <lluis@novell.com> + + * libsteticui/Makefile.am, libstetic/Makefile.am, stetic/Makefile.am: + Distcheck fixes. + * libstetic/GeneratorContext.cs: Don't generate gettext for empty + strings. + * configure.in: Add missing package. + * stetic/stetic.mdp, libsteticui/libsteticui.mdp, + libstetic/libstetic.mdp, stetic.mds: Added MonoDevelop projects. + +2007-02-05 Lluis Sanchez Gual <lluis@novell.com> + + * libsteticui/WidgetEditSession.cs: Clone the widget library list from + the master project since the list is cleared when the copy project + is closed. + * libstetic/ObjectWrapper.cs, libstetic/wrapper/Button.cs, + libstetic/PropertyDescriptor.cs, libstetic/WidgetUtils.cs: Properly + generate translatable properties. + +2007-02-02 Lluis Sanchez Gual <lluis@novell.com> + + * libstetic/editor/SelectImageDialog.cs, + libstetic/editor/StockIconSelectorItem.cs, + libstetic/editor/SelectIconDialog.cs, libstetic/WidgetUtils.cs, + libstetic/TypedClassDescriptor.cs, + libstetic/wrapper/pixmaps/missing.png: Looks like some themes don't + have icon for gtk-missing-image. Added a fallback to avoid crashes. + * stetic/UIManager.cs: Action fixes. + +2007-02-01 Lluis Sanchez Gual <lluis@novell.com> + + * configure.in: More dependency removal. + +2007-02-01 Lluis Sanchez Gual <lluis@novell.com> + + * autogen.sh: Removed gnome-common dependency. + +2007-01-31 Lluis Sanchez Gual <lluis@novell.com> + + * libsteticui/Clipboard.cs: Use the new PasteChild method, since + ReplaceChild is now protected. + * libsteticui/Glade.cs: Don't try to resolve references when loading a + glade file. + * libsteticui/libsteticui.dll.config, libstetic/libstetic.dll.config: + Added dlls maps for MacOSX + * libstetic/wrapper/Button.cs, libstetic/wrapper/CheckButton.cs: Set + UseUnderline = true by default. + * libstetic/wrapper/Container.cs: Made ReplaceChild protected. Make + sure widgets copied from clipboard are properly registered in the + undo system. + * libstetic/wrapper/Paned.cs, libstetic/wrapper/Box.cs, + libstetic/wrapper/Frame.cs, libstetic/wrapper/Fixed.cs, + libstetic/wrapper/ScrolledWindow.cs, libstetic/wrapper/Toolbar.cs, + libstetic/wrapper/Notebook.cs, libstetic/wrapper/Expander.cs: Made + ReplaceChild protected. + * libstetic/wrapper/ComboBoxEntry.cs: Fix code generation issue for + text combo box. + * libstetic/wrapper/objects.xml: Added UseUnderline property to + CheckButton. + * libstetic/DND.cs: Use the native format for copy/paste widgets. + +2007-01-25 Lluis Sanchez Gual <lluis@novell.com> + + * libsteticui/CodeGenerator.cs, + libsteticui/CodeGeneratorInternalClass.cs, + libsteticui/CodeGeneratorPartialClass.cs: Make sure the globla + Initialization is called from internal and partial classes. + * libstetic/editor/ActionMenuItem.cs, + libstetic/editor/ActionToolItem.cs: Fix compilation conflict with + recent gtk# versions. + +2007-01-22 Lluis Sanchez Gual <lluis@novell.com> + + * libsteticui/WidgetDesigner.cs: Avoid disposing twice the designer. + +2007-01-22 Lluis Sanchez Gual <lluis@novell.com> + + * libsteticui/ApplicationBackend.cs, libsteticui/ProjectBackend.cs, + libsteticui/Application.cs: Fixed problem when updating project + libraries. Make sure referenced libraries are not unloaded when + they are still needed. + * libsteticui/CecilWidgetLibrary.cs: Null check. + +2007-01-22 Lluis Sanchez Gual <lluis@novell.com> + + * libsteticui/ActionGroupDesigner.cs, libsteticui/ProjectView.cs, + libsteticui/SignalsEditor.cs, libsteticui/PluggableWidget.cs: Some + protection to avoid dispatching some events after the object has + been disposed. + * libsteticui/ApplicationBackend.cs: Changed the way libraries are + loaded. If a library has dependencies, the dependencies are loaded + first. + * libsteticui/CecilSignalDescriptor.cs, + libsteticui/CecilPropertyDescriptor.cs, + libsteticui/AssemblyResolver.cs, + libsteticui/CecilClassDescriptor.cs, + libsteticui/CecilWidgetLibrary.cs: New classes which allow loading + a widget library using cecil. + * libsteticui/ProjectBackend.cs, libsteticui/Project.cs: Project + libraries are now stored in the project file. In this way it is + possible to generate code for projects which depend on other + libraries using the command line tool. + * libsteticui/GuiDispatchServerSink.cs: Removed debug message. + * libsteticui/CodeGenerator.cs: Avoid dependency on + TypeSignalDescriptor. + * libsteticui/WidgetTreeCombo.cs, stetic/Stetic.cs: Misc fixes. + * libsteticui/WidgetEditSession.cs, libsteticui/WidgetDesigner.cs: Some + protection to avoid dispatching some events after the object has + been disposed. Some fixes for the out-of-process mode. + * libsteticui/Application.cs: Implemented method which determines if an + assembly is a widget library or not. Other misc fixes. + * libsteticui/PaletteBackend.cs: Update the widget list when the + registry changes. + * libsteticui/Makefile.am: Updated. Added Cecil dependency. + * libsteticui/AssemblyWidgetLibrary.cs, libstetic/WidgetLibrary.cs: + Added GetLibraryDependencies method, which returns widget libraries + needed by the widgets of this library. + * libstetic/ItemGroup.cs, libstetic/Registry.cs: When looking for an + item group of a class, avoid returning a group which has not been + declared in the class, but inherited by a base class. + * libstetic/NoGuiDispatchAttribute.cs: Moved from libsteticui to + libstetic. + * libstetic/ObjectWrapper.cs: Added an extended data property where + class descriptors can store random information. + * libstetic/wrapper/Container.cs: Removed dependency on + TypeClassDescriptor. + * libstetic/wrapper/FontSelectionDialog.cs, + libstetic/wrapper/ComboBox.cs, libstetic/wrapper/ColorButton.cs: + Set the correct base class. + * libstetic/wrapper/ScrolledWindow.cs: Destory viewport after replacing + it. + * libstetic/wrapper/objects.xml, libstetic/ClassDescriptor.cs, + libstetic/TypedClassDescriptor.cs: Implemented support for + 'base-type' attribute, which means that a widget class inherits all + properties and events of the referenced type. + * libstetic/wrapper/TreeView.cs: New wrapper for TreeView. + * libstetic/Makefile.am: Updated. + * libstetic/AssemblyWidgetLibrary.cs: Moved to libsteticui. + +2007-01-17 Lluis Sanchez Gual <lluis@novell.com> + + * libstetic/EnumDescriptor.cs: Avoid importing enum values which have + not been declared in the xml file. Shoud fix bugs 80007 and 80471. + * libstetic/wrapper/objects.xml: Removed missing property. + +2007-01-17 Lluis Sanchez Gual <lluis@novell.com> + + * libsteticui/ApplicationBackend.cs: Fixed some warnings. + * libsteticui/WidgetDesignerBackend.cs, + libsteticui/WidgetEditSession.cs, libstetic/IDesignArea.cs, + libstetic/editor/ActionMenuItem.cs, + libstetic/editor/ActionToolItem.cs: Provide information about the + drag hot point when firing the drag event. Allow enabling/disabling + drag support. + * libsteticui/ProjectBackend.cs: Fix cast exception when changing + signals in actions. + * libsteticui/Clipboard.cs, libstetic/wrapper/Button.cs, + libstetic/wrapper/Frame.cs, libstetic/wrapper/ButtonBox.cs: User + the new ReplaceChild overload. + * libsteticui/WidgetDesigner.cs: Improve error message when the + designet can't be loaded. + * libsteticui/Makefile.am, configure.in, stetic/Makefile.am: Build + libstetic with mcs instead of gmcs, since that assembly may need to + be linked with widget libraries based on .net 1.1. + * libstetic/wrapper/pixmaps/fixed.png: New bitmap for Gtk.Fixed. + * libstetic/wrapper/Container.cs: Added protected methods for notifying + the add/remove child event, since some containers don't fire them. + Added ReplaceChild overload which will explicitely destroy the + replaced widget. Don't allow dragging top level widgets. + * libstetic/wrapper/Fixed.cs, libstetic/Makefile.am: Implemented + support for Gtk.Fixed. + * libstetic/wrapper/Window.cs: Don't generate code for the Type + property, since it's read-only. + * libstetic/wrapper/objects.xml: Implemented support for Gtk.Fixed. + Hide the Type property, since code for that property can't be + generated (it must be provided by the user in the window + constructor. + * libstetic/DND.cs: Added properties for getting the hot drag point + when dragging a widget. + +2007-01-15 Lluis Sanchez Gual <lluis@novell.com> + + * libsteticui/UndoQueue.cs: Removed debug messages. + +2007-01-15 Lluis Sanchez Gual <lluis@novell.com> + + * libsteticui/ApplicationBackend.cs, libstetic/Registry.cs: Allow + grouping several changes in the registry in a single transaction. + * libsteticui/CodeGenerator.cs, libsteticui/Application.cs, + libsteticui/CodeGeneratorInternalClass.cs, + libsteticui/CodeGeneratorPartialClass.cs, + libsteticui/CodeGenerationResult.cs, libstetic/ObjectWrapper.cs, + libstetic/GeneratorContext.cs, libstetic/ErrorWidget.cs, + stetic/Stetic.cs: Added an option to allow generating code even + when not all referenced widgets are available. Added support for + warnings in the code generation methods, so the caller can get + information about what went wrong during the generation process. + * libsteticui/Makefile.am: Added CodeGenerationResult. + * libstetic/wrapper/Widget.cs: Clear the signal list when reloading a + widget. Fixed action group read code. + * libstetic/wrapper/Table.cs: Always return the children of the table + in the same order, to avoid unneeded changes in the diff files. + +2007-01-12 Lluis Sanchez Gual <lluis@novell.com> + + * libsteticui/ContainerUndoRedoManager.cs: Added missing file. + +2007-01-12 Lluis Sanchez Gual <lluis@novell.com> + + * libsteticui/WidgetEditSession.cs: When saving the designer session, + instead of deleting the old widget and adding the new one, update + the existing widget. + * libsteticui/Application.cs: Added some thread locking. + * libsteticui/Project.cs: When a widget name changed event is received, + update the corresponding component from the current thread, there + is no need to do it in the gui thread. + * libstetic/wrapper/Container.cs: Added null check for container child. + +2007-01-11 Lluis Sanchez Gual <lluis@novell.com> + + * libsteticui/ActionGroupDesigner.cs, libsteticui/WidgetDesigner.cs, + libsteticui/ActionGroupEditSession.cs: Added undo support for the + global action group designer. + * libsteticui/ApplicationBackend.cs: Catch errors when loading a + library to avoid aborting the whole update operation. + * libsteticui/ProjectBackend.cs, + libsteticui/CodeGeneratorInternalClass.cs, + libsteticui/PaletteBackend.cs, libsteticui/PropertyGrid.cs, + libstetic/undo/ActionDiffAdaptor.cs, stetic/Stetic.cs, + stetic/DesignerView.cs: Track api changes. + * libsteticui/CodeGenerator.cs: Include actions in the bind field list. + * libsteticui/ComponentEventHandler.cs, libsteticui/Project.cs: The + component removed event now provides the name of the removed + component, no the component reference. Needed since the component + is already removed, and providing an instance in this case is + problematic. + * libsteticui/ActionComponent.cs: Added property for gettion the group + of an action. + * libsteticui/Makefile.am: Added new file. + * libsteticui/UndoQueue.cs: Generalized the undo manager, so it can be + used for the action group editor. + * libstetic/undo/DiffGenerator.cs: Improved error message. + * libstetic/undo/UndoManager.cs: Make sure the UndoWriter works for + wrappers other than widgets. Don't include disposed or unregistered + wrappers into the undo event. + * libstetic/ObjectWrapper.cs: Factorized some undo properties and + methods into ObjectWrapper. + * libstetic/wrapper/Action.cs: More undo support. + * libstetic/wrapper/Container.cs, libstetic/wrapper/Widget.cs: Removed + some methods and properties now implemented in ObjectWrapper. + * libstetic/wrapper/ActionGroup.cs: ActionGroup is now an ObjectWrapper + subclass. Added better support for Undo. + * libstetic/editor/ActionGroupEditor.cs: Use new new ObjectChanged + event. + * libstetic/GeneratorContext.cs: Made GenerateInstanceExpression + public. + * stetic/LibraryManagerDialog.cs: Fixed warning. + +2007-01-09 Lluis Sanchez Gual <lluis@novell.com> + + * libsteticui/CodeGenerator.cs: Don't generate variables for + unselectable widgets. Use CodeDom expressions instead of variable + names when possible. When using partial classes, avoid creating + unneeded local variables, use field references instead. + * libsteticui/WidgetTreeCombo.cs: Don't show unselectable widgets, but + show its children if they are selectable. + * libsteticui/CodeGeneratorInternalClass.cs: Use CodeDom expressions + instead of variable names when possible. Fixed some incorrect + variable names. Make sure the generated class names are valid. + * libsteticui/CodeGeneratorPartialClass.cs: Use CodeDom expressions + instead of variable names when possible. + * libstetic/RadioGroupManager.cs, libstetic/ObjectWrapper.cs, + libstetic/wrapper/Button.cs, libstetic/wrapper/Label.cs, + libstetic/wrapper/TextView.cs, + libstetic/wrapper/RadioToolButton.cs, + libstetic/wrapper/RadioButton.cs, libstetic/wrapper/Frame.cs, + libstetic/wrapper/ActionGroup.cs, libstetic/wrapper/Window.cs, + libstetic/wrapper/ComboBox.cs, libstetic/wrapper/ColorButton.cs, + libstetic/wrapper/Notebook.cs, libstetic/wrapper/ButtonBox.cs, + libstetic/wrapper/MenuBar.cs, + libstetic/wrapper/ActionToolbarWrapper.cs, + libstetic/wrapper/RadioMenuItem.cs, libstetic/wrapper/Expander.cs, + libstetic/wrapper/Bin.cs, libstetic/wrapper/CheckButton.cs, + libstetic/ErrorWidget.cs: Track api changes. Variable name in code + generation methods has been replaced by a CodeDom expression. + * libstetic/wrapper/Container.cs, libstetic/wrapper/Widget.cs: Instead + of calling Show for each visible widget, call ShowAll on the top + level container child, and hide all invisible widgets. Track api + changes. + * libstetic/GeneratorContext.cs: Don't use variable names to reference + widget instances anymore, use CodeDom expressions instead. Needed + since widgets can be stored in variables and in fields. + +2006-12-17 Lluis Sanchez Gual <lluis@novell.com> + + * libsteticui/ProjectBackend.cs, libsteticui/WidgetEditSession.cs, + libsteticui/WidgetDesigner.cs, libsteticui/Project.cs: Added new + Changed event. + * libsteticui/PaletteBackend.cs, libsteticui/UndoQueue.cs, + libstetic/undo/DiffGenerator.cs, + libstetic/undo/ActionDiffAdaptor.cs, libstetic/wrapper/Action.cs, + libstetic/wrapper/Container.cs, libstetic/wrapper/Widget.cs, + libstetic/wrapper/ActionGroup.cs, libstetic/wrapper/MenuBar.cs, + libstetic/wrapper/ActionTree.cs, + libstetic/editor/ActionMenuItem.cs, + libstetic/editor/ActionMenuBar.cs, libstetic/editor/ActionMenu.cs, + libstetic/editor/ActionToolItem.cs, + libstetic/editor/ActionToolbar.cs: Improved support for Undo. + * libstetic/undo/UndoManager.cs: Removed debug code. + * libstetic/undo/XmlDiffAdaptor.cs: Fix support for name and id + properties when diffing. + * libstetic/wrapper/objects.xml: HasFocus property doesn't need to be + available at design time. + * libstetic/wrapper/ActionToolbarWrapper.cs: Implemented support for + Undo. + +2006-12-17 Lluis Sanchez Gual <lluis@novell.com> + + * libsteticui/ProjectBackend.cs, libsteticui/WidgetEditSession.cs, + libsteticui/WidgetDesigner.cs, libsteticui/Project.cs: Added new + Changed event. + * libsteticui/PaletteBackend.cs, libsteticui/UndoQueue.cs, + libstetic/undo/DiffGenerator.cs, + libstetic/undo/ActionDiffAdaptor.cs, libstetic/wrapper/Action.cs, + libstetic/wrapper/Container.cs, libstetic/wrapper/Widget.cs, + libstetic/wrapper/ActionGroup.cs, libstetic/wrapper/MenuBar.cs, + libstetic/wrapper/ActionTree.cs, + libstetic/editor/ActionMenuItem.cs, + libstetic/editor/ActionMenuBar.cs, libstetic/editor/ActionMenu.cs, + libstetic/editor/ActionToolItem.cs, + libstetic/editor/ActionToolbar.cs: Improved support for Undo. + * libstetic/undo/UndoManager.cs: Removed debug code. + * libstetic/undo/XmlDiffAdaptor.cs: Fix support for name and id + properties when diffing. + * libstetic/wrapper/objects.xml: HasFocus property doesn't need to be + available at design time. + * libstetic/wrapper/ActionToolbarWrapper.cs: Implemented support for + Undo. + +2006-12-05 Lluis Sanchez Gual <lluis@novell.com> + + * libsteticui/UndoQueue.cs: Added debug method. + * libstetic/UndoManager.cs: Moved to undo dir. + * libstetic/undo, libstetic/undo/IDiffAdaptor.cs, + libstetic/undo/DiffGenerator.cs, libstetic/undo/UndoManager.cs, + libstetic/undo/ActionDiffAdaptor.cs, + libstetic/undo/XmlDiffAdaptor.cs: Moved here UndoManager and added + some classes to generate undo diffs between objects and xml + representations. + * libstetic/wrapper/Button.cs, libstetic/wrapper/RadioToolButton.cs, + libstetic/wrapper/RadioButton.cs, libstetic/wrapper/OptionMenu.cs, + libstetic/wrapper/Image.cs, libstetic/wrapper/ImageMenuItem.cs, + libstetic/wrapper/RadioMenuItem.cs, + libstetic/wrapper/ToolButton.cs: Track api changes. + * libstetic/wrapper/Action.cs, libstetic/wrapper/ActionGroup.cs, + libstetic/wrapper/MenuBar.cs, + libstetic/wrapper/ActionToolbarWrapper.cs: Added support for + Undo/Redo. + * libstetic/wrapper/Container.cs, libstetic/wrapper/Widget.cs: Moved + all diffing code to the DiffGenerator class. + * libstetic/Placeholder.cs: Changed the name of the undo id property. + * libstetic/editor/ActionMenuItem.cs: Made atomic some action property + changes. + * libstetic/editor/ActionMenuBar.cs, libstetic/editor/ActionMenu.cs: + Added methods for saving/restoring the selection of a menu and + toolbar. + * libstetic/TypedPropertyDescriptor.cs: Added null check. + * libstetic/Makefile.am: Updated. + +2006-12-01 Lluis Sanchez Gual <lluis@novell.com> + + * libsteticui/ActionGroupDesigner.cs: Added null check. + * libsteticui/ProjectBackend.cs: Always return the top level widgets in + the same order they were stored in the project file. + * libsteticui/WidgetEditSession.cs, libsteticui/Clipboard.cs, + libsteticui/WidgetDesigner.cs, libsteticui/UndoQueue.cs, + libstetic/UndoManager.cs, libstetic/ObjectWrapper.cs, + libstetic/Placeholder.cs, stetic/Stetic.cs, stetic/DesignerView.cs, + stetic/UIManager.cs: Added support for undo/redo. + * libsteticui/Application.cs: Minor fix. + * libsteticui/Glade.cs, libsteticui/ActionGroupEditSession.cs, + libstetic/wrapper/Button.cs, libstetic/wrapper/Action.cs, + libstetic/wrapper/Container.cs, libstetic/wrapper/Widget.cs, + libstetic/wrapper/RadioToolButton.cs, + libstetic/wrapper/RadioButton.cs, libstetic/wrapper/Frame.cs, + libstetic/wrapper/ActionGroup.cs, libstetic/wrapper/OptionMenu.cs, + libstetic/wrapper/Notebook.cs, libstetic/wrapper/Image.cs, + libstetic/wrapper/MenuItem.cs, libstetic/wrapper/ButtonBox.cs, + libstetic/wrapper/ImageMenuItem.cs, libstetic/wrapper/Table.cs, + libstetic/wrapper/MenuBar.cs, libstetic/wrapper/Dialog.cs, + libstetic/wrapper/ActionToolbarWrapper.cs, + libstetic/wrapper/RadioMenuItem.cs, libstetic/wrapper/Expander.cs, + libstetic/wrapper/CheckButton.cs, libstetic/wrapper/ToolButton.cs, + libstetic/GladeUtils.cs, libstetic/ErrorWidget.cs, + libstetic/WidgetUtils.cs: Track api changes. + * libsteticui/Makefile.am, libstetic/Makefile.am: Updated. + * libsteticui/Project.cs: Update the app library list after removing a + project. + * libstetic/ItemGroup.cs: Use an ordered dictionary to store + properties, so we always get them in the correct order. + * libstetic/CommandDescriptor.cs: Make sure the changes done by + commands are atomic. + * libstetic/ObjectReader.cs, libstetic/ObjectWriter.cs: New clases for + reading/writing objects + * libstetic/PropertyDescriptor.cs, + libstetic/TypedPropertyDescriptor.cs, libstetic/ClassDescriptor.cs, + libstetic/TypedClassDescriptor.cs: Added new method for + initializing and instance to its default values. + +2006-11-13 Lluis Sanchez Gual <lluis@novell.com> + + * libstetic/editor/Flags.cs: + * libstetic/editor/ActionToolItem.cs: + Fix build. Patch by Michael Schurter. + +2006-09-22 Lluis Sanchez Gual <lluis@novell.com> + + * libsteticui/WidgetEditSession.cs: + * libsteticui/Palette.cs: + * libsteticui/ProjectView.cs: + * libsteticui/SignalsEditor.cs: + * libsteticui/ApplicationBackend.cs: Reconnect the plug when the socket + is unrealized. + + * libsteticui/WidgetDesignerBackend.cs: Added null check. + + * libsteticui/WidgetDesigner.cs: + * libsteticui/ActionGroupEditSession.cs: + * libsteticui/PluggableWidget.cs: + * libsteticui/WidgetPropertyTree.cs: + * libsteticui/ActionGroupDesigner.cs: + * libstetic/Registry.cs: + * stetic/Stetic.cs: + * libsteticui/Application.cs: Fixed process restart workflow, to make + the process switch faster. + + * libsteticui/GuiDispatchServerSink.cs: + * libsteticui/Component.cs: + * libsteticui/ApplicationBackendController.cs: + * libsteticui/Project.cs: + * libsteticui/ProjectBackend.cs: Misc bug fixes. + + * libstetic/ItemDescriptor.cs: Made it serializable. + * libstetic/wrapper/Action.cs (CopyFrom): Clear the signals list before + adding the new signals. + * stetic/DesignerView.cs: Added getter for the root component. + +2006-09-21 Lluis Sanchez Gual <lluis@novell.com> + + * stetic/UIManager.cs: + * stetic/Stetic.cs: Use the new API. + + * stetic/stetic.glade: + * stetic/Configuration.cs: + * stetic/LibraryManagerDialog.cs: Implemented dialog for selecting + widget libraries. + + * stetic/Makefile.am: Updated. + +2006-09-21 Lluis Sanchez Gual <lluis@novell.com> + + * libsteticui/ActionGroupDesigner.cs: + * libsteticui/ApplicationBackend.cs: + * libsteticui/WidgetDesignerBackend.cs: + * libsteticui/ProjectBackend.cs: + * libsteticui/SignalsEditorBackend.cs: + * libsteticui/WidgetPropertyTreeBackend.cs: + * libsteticui/WidgetEditSession.cs: + * libsteticui/Palette.cs: + * libsteticui/ComponentSignalEventHandler.cs: + * libsteticui/ProjectView.cs: + * libsteticui/ComponentEventHandler.cs: + * libsteticui/Component.cs: + * libsteticui/Application.cs: + * libsteticui/EmbedWindow.cs: + * libsteticui/PaletteBackend.cs: + * libsteticui/SignalsEditor.cs: + * libsteticui/ActionGroupComponent.cs: + * libsteticui/ApplicationBackendController.cs: + * libsteticui/ActionGroupDesignerBackend.cs: + * libsteticui/ActionComponent.cs: + * libsteticui/WidgetDesigner.cs: + * libsteticui/ActionGroupEditSession.cs: + * libsteticui/ComponentType.cs: + * libsteticui/Project.cs: + * libsteticui/WidgetComponent.cs: + * libsteticui/PluggableWidget.cs: + * libsteticui/WidgetPropertyTree.cs: + * libsteticui/ProjectViewBackend.cs: + * libstetic/IResourceProvider.cs: + Redesigned the API so it allows running the designer in a separate + process. This running mode is optional and not enabled by default + until all stability problems have been fixed. + + * libsteticui/NoGuiDispatchAttribute.cs: + * libsteticui/GuiDispatchServerSinkProvider.cs: + * libsteticui/GuiDispatchServerSink.cs: A channel sink which ensures that + all incoming calls al dispatched in the GUI thread. + + * libsteticui/ActionGroupToolbar.cs: + * libsteticui/WidgetActionBar.cs: Added the Bind to Field button + (moved from MD). + + * libsteticui/CodeGenerator.cs: Added optional Gettext support. + + * libsteticui/WidgetTreeCombo.cs: + * libsteticui/Clipboard.cs: + * libsteticui/Glade.cs: + * libsteticui/PropertyGrid.cs: + * libsteticui/UserInterface.cs: + * libsteticui/WidgetFactory.cs: Make classes internal. + + * libsteticui/Makefile.am: Updated. + +2006-09-21 Lluis Sanchez Gual <lluis@novell.com> + + * libstetic/IProject.cs: Removed unused method. + * libstetic/ItemDescriptor.cs: Made some fields not serializable. + * libstetic/ObjectWrapper.cs: Allow binding a wrapper to a remote + frontend running in another process. + + * libstetic/Registry.cs: + * libstetic/WidgetLibrary.cs: Implemented better support for library + reloading. + + * libstetic/wrapper/Container.cs: + * libstetic/wrapper/Widget.cs: + * libstetic/wrapper/Action.cs: Track api changes, added some null checks. + + * libstetic/wrapper/Signal.cs: + * libstetic/SignalDescriptor.cs: + * libstetic/TypedSignalDescriptor.cs: + * libstetic/wrapper/SignalCollection.cs: Made it serializable. + + * libstetic/wrapper/ActionGroup.cs: Made it sealed. Added some helper + methods. + * libstetic/wrapper/objects.xml: Action properties are translatable. + * libstetic/editor/ThemedIcon.cs, ImageSelector.cs: Don't use + stock_symbol-selection stock + icon since it is not available in all themes. + * libstetic/editor/Identifier.cs: Fix warning. + * libstetic/TypedPropertyDescriptor.cs: Improved error reporting. + * libstetic/GeneratorContext.cs: Added support for Gettext. + +2006-09-01 Lluis Sanchez Gual <lluis@novell.com> + + * libstetic/wrapper/Container.cs: When changing the selected item, + disable the focus event for the correct widget. Fixes bug #79247. + + * libstetic/editor/ThemedIcon.cs: + * libstetic/editor/ImageSelector.cs: Use "..." as label for the selector + button since the icon stock_symbol-selection is not present in some + themes. + +2006-09-01 Lluis Sanchez Gual <lluis@novell.com> + + * libsteticui/Project.cs: Avoid the normal widget clearing callback + when closing a project. It may avoid a crash seen by some users + but which is hard to reproduce. Initialize the icon factory + when closing the project. + * libstetic/CommandDescriptor.cs: Added null check. + * libstetic/wrapper/Widget.cs: Clear the selection if the selected + widget is destroyed. + * libstetic/wrapper/WidgetEventHandler.cs: Set the wrapper property + in the args constructor. + * libstetic/wrapper/Viewport.cs: Wrapper properties can't be initialized + in the constructor. + * libstetic/wrapper/objects.xml: Set the default value for Visible to + 'true' (in gtk, the default is false, but for stetic it is true). + * libstetic/editor/ActionMenuItem.cs: Added null check. + * libstetic/editor/SelectImageDialog.cs: Don't allow addin/removing + resources if there is no resource manager. + +2006-08-30 Lluis Sanchez Gual <lluis@novell.com> + + * libsteticui/ActionGroupDesigner.cs: Use Dispose instead of destroy + since it was generating some warnings. + * libsteticui/WidgetDesigner.cs: Dispose is enough. + * libsteticui/Project.cs: Don't add unselectable widgets to the tree. + Moved here some selection code from Widget.cs. + * libstetic/ItemGroup.cs: Make sure properties are returned in the + same order they are declared in objects.xml. + * libstetic/ObjectWrapper.cs: Don't nullify proj and signals on dispose, + it is causing some nullrefs. + * libstetic/wrapper/Container.cs: Changed a bit how selection works. + Everything is now controled by the project. + * libstetic/wrapper/Widget.cs: Make sure clicks for unselectable widgets + are intercepted. + * libstetic/wrapper/Notebook.cs: Track api changes. + * libstetic/wrapper/Table.cs: Destroy widgets removed from the table. + * libstetic/editor/ActionGroupEditor.cs: Implemented public Cut, Copy, + Paste and Delete methods. + * stetic/Stetic.cs: + * libstetic/TypedPropertyDescriptor.cs: Improved some error messages. + +2006-08-29 Lluis Sanchez Gual <lluis@novell.com> + + * libsteticui/ActionGroupDesigner.cs: + * libsteticui/ActionGroupToolbar.cs: + * libsteticui/Palette.cs: + * libsteticui/WidgetDesigner.cs: + * libsteticui/Project.cs: + * libsteticui/WidgetActionBar.cs: + * libstetic/ObjectWrapper.cs: + * libstetic/editor/ActionMenuBar.cs: + * libstetic/editor/ActionMenu.cs: + * libstetic/editor/ActionGroupEditor.cs: + * stetic/Stetic.cs: Explicitely destroy custom widgets to avoid memory + leaks. + +2006-08-26 Lluis Sanchez Gual <lluis@novell.com> + + * libstetic/wrapper/WidgetEventHandler.cs: Added WidgetWrapper property. + + * libsteticui/PropertyGrid.cs: + * libsteticui/Palette.cs: + * libsteticui/ProjectView.cs: + * libsteticui/WidgetActionBar.cs: + * libsteticui/SignalsEditor.cs: + * stetic/Stetic.cs: + * stetic/UIManager.cs: + * libsteticui/WidgetPropertyTree.cs: Track changes in WidgetEventHandler. + + * libsteticui/Project.cs: Factorized cleanup methods into Close(). + Properly dispose actions. + * libstetic/wrapper/Action.cs: Properly read the action id. + * libstetic/wrapper/Container.cs: Disconnect container events when + disposing. Sync the table after reading it. + * libstetic/wrapper/Widget.cs: Properly track unwrapped children + and intercept clicks for them. + * libstetic/wrapper/Box.cs: Don't create drop faults if the widget is + not selectable. + * libstetic/wrapper/ActionGroup.cs: Implemented IDisposable. + * libstetic/wrapper/ButtonBox.cs: Destroy buttons being removed (this will + dispose the wrapper). + * libstetic/wrapper/objects.xml: Inherit IsTextCombo property. + * libstetic/editor/ActionMenuBar.cs: Show an "Empty" message when the widget + is not selected. + * libstetic/editor/StockIconSelectorItem.cs: Removed gnome stock icons since + they need some special initialization code. Still available in the stock + icon selection box. + * libstetic/editor/ActionToolItem.cs: Propagate to menu popup the key used + to show the menu. + * libstetic/PropertyDescriptor.cs: Store translation info in the object wrapper, + instead of a global hashtable. This avoids keeping a reference to the object + forever in the translation info hashtable. + + * libstetic/wrapper/TextView.cs: + * libstetic/wrapper/Window.cs: + * libstetic/wrapper/Scale.cs: + * libstetic/wrapper/Range.cs: + * libstetic/wrapper/Dialog.cs: + * libstetic/wrapper/Toolbar.cs: Unsubscribe events on dispose. + + * libstetic/editor/SelectIconDialog.cs: + * libstetic/stetic.glade: Added warning to stock selection icon, shown when + the selected icon needs special icon factories. + +2006-08-18 Lluis Sanchez Gual <lluis@novell.com> + + * libsteticui/ActionGroupToolbar.cs: Fix exception. + * libsteticui/CodeGenerator.cs: Use CodeArgumentReferenceExpression + instead of CodeVariableReferenceExpression to reference parameters. + * libsteticui/WidgetDesigner.cs: Update the widget design size when + it changes. + * libstetic/ObjectWrapper.cs: Added setter for Loading. + * libstetic/wrapper/Container.cs: Don't fire ChildRemoved event + when loading. + * libstetic/wrapper/ActionGroup.cs: Added Remove method. + + * libstetic/wrapper/ActionTree.cs: + * libstetic/wrapper/ActionToolbarWrapper.cs: + * libstetic/wrapper/MenuBar.cs: Don't fire change events when + creating the menu and toolbar. + + * libstetic/wrapper/Widget.cs: + * libstetic/wrapper/Bin.cs: Implemented support for UIManagers + in custom widgets. + + * libstetic/editor/Accelerator.cs: Fire change event when the + accelerator is set. + * stetic/UIManager.cs: Some UI improvements. + +2006-08-17 Lluis Sanchez Gual <lluis@novell.com> + + * libsteticui/PropertyEditor.cs: Made the class internal. + * libsteticui/UserInterface.cs: Added new overload for + CreateActionGroupDesigner. + * stetic/Stetic.cs: Close the project before opening a new one. + * stetic/UIManager.cs: Fixed bug when opening recent files. + * libsteticui/ActionGroupDesigner.cs: New file. + * libsteticui/Project.cs: Set the modified flag when a widget + is added or removed from the project. + * stetic/Stetic.cs: Moved page creation code to DesignerView.cs. + * DesignerView.cs: New file. + + * libstetic/wrapper/Custom.cs: + * libstetic/CustomWidget.cs: Make public again, since it is + being used by the MD addin. + + * libsteticui/Makefile.am: Updated. + +2006-08-16 Lluis Sanchez Gual <lluis@novell.com> + + * libsteticui/*: + * libstetic/* + * stetic/*: Added Catalog.GetString to all translatable strings. + +2006-08-16 Lluis Sanchez Gual <lluis@novell.com> + + * stetic/Stetic.cs: If a file name is specified when starting + Stetic, load it. Warn the user when closing an unsaved project. + Implemented Close command. Read and save the main window position. + * stetic/stetic.glade: Added an status bar. + * stetic/UIManager.cs: Implemented "Recent Files" submenu. + + * stetic/RecentFiles.cs: + * stetic/Configuration.cs: New files. + + * stetic/Makefile.am: Updated. + +2006-08-16 Lluis Sanchez Gual <lluis@novell.com> + + * libsteticui/Shadow.cs: + * libsteticui/EmbedWindow.cs: + * libsteticui/Metacity: Moved from libstetic. + + * libsteticui/WidgetFactory.cs: Don't allow dragging window + items. + * libsteticui/Glade.cs: Removed unused BeginGladeImport method. + * libsteticui/CodeGenerator.cs: Use GenerateCreationCode instead + of GenerateBuildCode to generate the code for the root window, + since it includes initialization code for properties which are + usually provided as constructor parameters. + * libsteticui/WidgetTreeCombo.cs: Fix warning. + * libsteticui/Project.cs: Added Close method. Removed some unused + code. + * libsteticui/PropertyTree.cs: Made CellRendererPropertyGroup internal. + + * libsteticui/UserInterface.cs: Added method overload. + CreateActionGroupDesigner now creates the toolbar. + + * libsteticui/ContextMenu.cs: + * libsteticui/Grid.cs: Made the class internal. + + * libsteticui/WidgetDesigner.cs: Moved from libstetic. Renamed from + PreviewBox to WidgetDesigner. + + * libsteticui/WidgetPropertyTree.cs: + * libsteticui/SignalsEditor.cs: Track api changes. + + * libsteticui/Makefile.am: Updated. + +2006-08-16 Lluis Sanchez Gual <lluis@novell.com> + + * libstetic/CustomWidget.cs: + * libstetic/wrapper/Custom.cs: Made the class internal. + + * libstetic/wrapper/Frame.cs: + * libstetic/wrapper/Notebook.cs: + * libstetic/wrapper/ButtonBox.cs: + * libstetic/wrapper/Expander.cs: + * libstetic/HandleWindow.cs: + * libstetic/editor/Translatable.cs: Track api changes. + + * libstetic/PreviewBox.cs: + * libstetic/EmbedWindow.cs: + * libstetic/Shadow.cs: + * libstetic/Metacity: Moved to libsteticui. + + * libstetic/IDesignArea.cs: Moved here a delegate previously declared + in PreviewBox. + * libstetic/IProject.cs: Removed unused event. + * libstetic/ObjectWrapper.cs: Added public methods for attaching/detaching + designers. + * libstetic/wrapper/Container.cs: Removed unused code. + * libstetic/editor/TextBox.cs: Moved to Editors directory. + * libstetic/PropertyDescriptor.cs: Made TranslationInfo internal. + * libstetic/GeneratorContext.cs: Added initialization code for + top level widgets. + + * libstetic/wrapper/ActionToolbarWrapper.cs: + * libstetic/wrapper/objects.xml: Support specifying a "Default" style for + the toolbar, which will cause the toolbar to take the style from the + gnome preferences. + + * libstetic/Makefile.am: Updated. + +2006-08-11 Lluis Sanchez Gual <lluis@novell.com> + + * libstetic/editor/DateTimeEditor.cs: + * libstetic/editor/TimeSpanEditor.cs: + * libstetic/PropertyEditorCell.cs: + * libstetic/Makefile.am: Added editors for DateTime and TimeSpan. + +2006-08-11 Lluis Sanchez Gual <lluis@novell.com> + + * libsteticui/WidgetTreeCombo.cs: Don't show unselectable + widgets in the combo. + + * libstetic/IProject.cs: + * libsteticui/Project.cs: Removed tooltips property. They are + now handlerd in a different way. + + * libstetic/ObjectWrapper.cs: + * libstetic/wrapper/Container.cs: + * libstetic/wrapper/Frame.cs: + * libstetic/wrapper/Button.cs: Fixed some issues when reading + and writing buttons. + + * libstetic/wrapper/Notebook.cs: + * libstetic/wrapper/MenuItem.cs: + * libstetic/wrapper/OptionMenu.cs: + * libstetic/wrapper/Expander.cs: + * libstetic/wrapper/CheckButton.cs: + * libstetic/wrapper/Object.cs: Track api changes. + + * libstetic/wrapper/objects.xml: Added initialization property + for windows. Use Entry.IsEditable instead of Editable, which is + obsolete. + + * libstetic/editor/Flags.cs: Fix warnings. + * libstetic/wrapper/Widget.cs: Generate code for displaying + tooltips. + + * libstetic/GeneratorContext.cs: + * libstetic/PropertyDescriptor.cs: Support code generation of + DateTime and TimeSpan. + + * libstetic/DND.cs: Fixed several issues with insert bars in + boxes. + + * libstetic/Makefile.am: Updated. + +2006-08-01 Lluis Sanchez Gual <lluis@novell.com> + + * libstetic/ItemGroup.cs: Use a hashtable to store the items. + + * libstetic/wrapper/Button.cs: + * libstetic/wrapper/Object.cs: + * libstetic/wrapper/Table.cs: + * libstetic/ObjectWrapper.cs: Avoid firing events while the objects + are loading. + + * libstetic/wrapper/Container.cs: Don't validate names while the object + is being loaded. + * libstetic/ItemGroupCollection.cs: Added helper method for getting + an item. + + * libstetic/WidgetUtils.cs: Avoid using SelectSingleNode since it's very + slow. Use the ChildNodes property instead. Merged ReadProperties and + ReadSignals in a single ReadMembers method, which is more efficient. + +2006-08-01 Lluis Sanchez Gual <lluis@novell.com> + + * libsteticui/Clipboard.cs: When copying a widget, store it as + xml, so if the widget is deleted the clipboard will still + have the data. Fixes bug #78938. + + * libstetic/PreviewBox.cs: + * libstetic/EmbedWindow.cs: Avoid a crash when metacity is not + installed. Fixes bug #78916. + + * libstetic/wrapper/Container.cs: Properly read internal children + when using Glade format. + * libstetic/wrapper/RadioButton.cs: Fix read code for radio buttons. + Fixes bug #78909. + + * libstetic/wrapper/Dialog.cs: + * libstetic/wrapper/ButtonBox.cs: Added special code generation case + when the button box is the action area of a dialog. In this case + widgets are added using dialog.AddActionWidget(). Fixes bug #78956. + + * libstetic/editor/Accelerator.cs: Capture the key combination using + a modal dialog, to avoid messing with the container accelerators. + Fixes bug #78867. + +2006-07-24 Lluis Sanchez Gual <lluis@novell.com> + + * libstetic/EnumDescriptor.cs: Don't throw an exception if the + CLR enum has more members than the enum declared in objects.xml. + A new backward compatible version of a library may introduce new + members which Stetic is unaware of. + +2006-07-24 Lluis Sanchez Gual <lluis@novell.com> + + * libstetic/wrapper/Table.cs: Don't try to automatically set + the horizontal expansion property of widgets which expand + more than one column, since we may have a different expand + value for each column, and changing it for every column may + end up in an infinite loop when syncing the table. The + same for rows and vertical expansion. + +2006-07-21 Alp Toker <alp@atoker.com> + + * libsteticui/CodeGenerator.cs: + * libsteticui/PropertyTree.cs: + * libstetic/TypedPropertyDescriptor.cs: + * libstetic/WidgetUtils.cs: Trivial comment typofixes. + +2006-07-04 Lluis Sanchez Gual <lluis@novell.com> + + * libsteticui/WidgetActionBar.cs: Assign the label of the command + to the button. + * libstetic/PreviewBox.cs: Added property for getting the current + selection. + * libstetic/wrapper/Action.cs: Use IconSet.RenderIcon to render + action icons. + + * libstetic/wrapper/Image.cs: + * libstetic/wrapper/Label.cs: Changed base wrapper to Misc. + + * libstetic/wrapper/objects.xml: Use the new identifier editor + for the widget name. Added alignment commands for Label and + for table child. + * libstetic/wrapper/Table.cs: Implemented Fill/Expand commands. + * libstetic/editor/ImageSelector.cs: Use a default size of 16 + for thumbnail icons. + * libstetic/editor/StockItem.cs: Render icons using the icon set, + not the theme. + * libstetic/WidgetUtils.cs: In ParseWidgetName, limit numeric suffix + to 4 digits. + * libstetic/Makefile.am: Added Identifier.cs and Misc.cs. + * libstetic/TypedClassDescriptor.cs: If a wrapper is inherited + from a base class, ignore the CreateInstance method since it + is going to create an instance of the base class. + + +2006-06-12 Lluis Sanchez Gual <lluis@novell.com> + + * libstetic/ItemDescriptor.cs: Properly invoke method based checks + for item descriptors. + * libstetic/wrapper/Action.cs: Copy signals when cloning actions. + * libstetic/ErrorWidget.cs: Improve error message when generating code. + + * libstetic/GeneratorContext.cs: + * libstetic/PropertyDescriptor.cs: Add support for string arrays. + + * libstetic/wrapper/objects.xml: + * libstetic/wrapper/ComboBox.cs: Added property which when set generates + a text based combobox. + + * libstetic/wrapper/Notebook.cs: + * libstetic/RadioGroupManager.cs: Fix bug when accessing to widget + variable names. Patch by Jasiu. + +2006-06-12 Lluis Sanchez Gual <lluis@novell.com> + + * libsteticui/PropertyTree.cs: Don't show empty item groups. + * libsteticui/WidgetActionBar.cs: Call the virtual AddWidgetCommands + only once per widget. + * libstetic/editor/ActionToolbar.cs: Remove debug code. + * libstetic/wrapper/Widget.cs: When deleting a widget unselect it if + it is the current selection. Fixes bugs #78620 and 78622. + * libstetic/wrapper/ColorButton.cs: Don't generate the Alpha property + if the value is -1 (not set). + + * libstetic/wrapper/objects.xml: + * libstetic/wrapper/pixmaps/expander.png: Added icon for the expander + widget by ml. + + +2006-06-09 Lluis Sanchez Gual <lluis@novell.com> + + * libstetic/CommandDescriptor.cs: + * libsteticui/WidgetActionBar.cs: Add support for icon based + commands and for toogle commands. + + * libstetic/ItemDescriptor.cs: invisible-if and disable-if elements + now support calling a method to get the check value. + * libstetic/WidgetLibrary.cs: Assign the widget library to + class descriptors. + * libstetic/wrapper/Container.cs: Implemented IncBorder and DecBorder + commands. + * libstetic/wrapper/Box.cs: Implemented BoxExpand and BoxFill toggle + commands. + * libstetic/wrapper/objects.xml: Added IncBorder and DecBorder commands + to containers. Added BoxExpand and BoxFill to box child. + * libstetic/editor/Accelerator.cs: Fixed. Added button for clearing + the accelerator. + + * libstetic/editor/ActionToolbar.cs: + * libstetic/editor/ActionMenuBar.cs: Make sure the menu has some height + when there are no items, so it can be easily selected. + + * libstetic/editor/ActionToolItem.cs: Don't allow editing separators. + * libstetic/PropertyEditorCell.cs: Paint text, not markup. + * libstetic/ClassDescriptor.cs: Added property which returns the widget + library that implements the class descriptor. + * libstetic/AssemblyWidgetLibrary.cs: Implemented GetResource method. + +2006-06-08 Lluis Sanchez Gual <lluis@novell.com> + + * libstetic/wrapper/Box.cs: In GladeChildren return children + based on the order of their positions. Fixes bug #78160. + +2006-05-26 Lluis Sanchez Gual <lluis@novell.com> + + * libsteticui/Palette.cs: Don't show the toolitems section, + since it's not being used right now. Show a default icon + for actions which don't have an icon. + * libsteticui/PropertyTree.cs: If the property tree only + has one group, allways expand it. + * libsteticui/Makefile.am: Added resource. + * libsteticui/WidgetPropertyTree.cs: There is no need to delay + the tree filling when the selection is null. + * libstetic/PreviewBox.cs: Minor fixes. + * libstetic/ImageInfo.cs: Added some image scaling methods. + * libstetic/ProjectIconFactory.cs: Added RenderIcon method. + * libstetic/wrapper/Action.cs: Added Accelerator property. + Other minor fixes. + * libstetic/wrapper/Widget.cs: Notify changes in the local + action groups. Register the accel group of the generated + UIManager. + * libstetic/wrapper/objects.xml: Disabled the old toolbar + model. Use the action based toolbar instead. + * libstetic/wrapper/ActionTree.cs: Added Changed event. + * libstetic/editor/ActionMenuItem.cs: Use the new icon + selection menu. + * libstetic/editor/StockItem.cs: Implemented a new editor + which uses the new icon selector menu. + * libstetic/PropertyDescriptor.cs: Added support for + specifying a default value for a property in the xml file. + * libstetic/Makefile.am: Updated. + + * wrapper/ActionToolbarWrapper.cs: + * editor/ActionToolbar.cs: + * editor/ActionToolItem.cs: New toolbar designer. + + * editor/IconSelectorItem.cs: + * editor/IconSelectorMenu.cs: + * editor/IconSelectorMenuItem.cs: + * editor/ProjectIconSelectorItem.cs: + * editor/StockIconSelectorItem.cs: New menu for selecting icons. + + * libstetic/wrapper/MenuBar.cs: + * libstetic/editor/ActionMenu.cs: + * libstetic/editor/ActionGroupEditor.cs: + * libstetic/editor/ActionMenuBar.cs: + * libstetic/wrapper/ActionGroup.cs: Several fixes. + + * stetic/stetic.glade: + * stetic/UIManager.cs: + * stetic/Stetic.cs: Added a toolbar to the UI. + + +2006-05-19 Lluis Sanchez Gual <lluis@novell.com> + + * libsteticui/WidgetFactory.cs: Highlight the item on mouse over. + * libsteticui/ActionGroupToolbar.cs: Implemente a single group + mode, to be used when editing global action groups. + * libsteticui/CodeGenerator.cs: Generate code for actions and + icon factories. + * libsteticui/Palette.cs: Adjusted some margins. Update actions + when they change. + * libsteticui/ProjectView.cs: Clean the tree when no project + is selected. + * libsteticui/Makefile.am: Added UserInterface.cs. + * libsteticui/Project.cs: Added IconFactory property. + * libsteticui/SignalsEditor.cs: Added missing null check. + * libstetic/Metacity/ButtonLayout.cs: + * libsteticui/WidgetPropertyTree.cs: Minor fix. + + * libstetic/IProject.cs: Added Modified and IconFactory properties. + * libstetic/PreviewBox.cs: Implemented UpdateObjectViewers. + * libstetic/stetic.glade: Added icon selector and icon factory editor. + * libstetic/RadioGroupManager.cs: + + * libstetic/wrapper/MenuBar.cs: + * libstetic/wrapper/ActionTree.cs: + * libstetic/wrapper/ActionGroup.cs: + * libstetic/wrapper/Action.cs: Implemented code generation. Avoid name + duplication inside action groups. + * libstetic/wrapper/Container.cs: Moved method ParseWidgetName into + WidgetUtils. + * libstetic/wrapper/Widget.cs: Added some methods for supporting code + action generation. + * libstetic/wrapper/ActionGroup.cs: Added memberName property. + + * libstetic/editor/ImageSelector.cs: + * libstetic/editor/StockItem.cs: + * libstetic/GladeUtils.cs: + * libstetic/editor/TextEditorDialog.cs: Fix warning. + + * libstetic/editor/ThemedIconList.cs: Factorized some code into the + new base class IconList. + * libstetic/editor/ActionMenuItem.cs: Added context menu. Added support + for separators. Use the new icon selector for selecting action items. + * libstetic/editor/SelectImageDialog.cs: Improved disabling of OK button when + nothing is selected. + + * libstetic/editor/ActionGroupEditor.cs: + * libstetic/editor/ActionMenu.cs: + * libstetic/editor/ActionMenuBar.cs: Implemented some context menu commands. + + * libstetic/GeneratorContext.cs: Support generating code for ActionGroups. + Make WidgetMap work for non-widget objects (e.g. Action). + * libstetic/WidgetUtils.cs: Moved from Container.cs. + + * libstetic/Makefile.am: Updated. Added Mono.Unix reference. + + * libstetic/editor/IconList.cs: Base class for two-column icon lists. + * libstetic/ProjectIconFactory.cs: Holds information about icons defined + in a project. + * libstetic/editor/ProjectIconList.cs: IconList subclass that shows + icons from a project icon factory. + * libstetic/editor/EditIconDialog.cs: Dialog for editing icons. + * libstetic/editor/StockIconList.cs: IconList subclass that shows + stock icons only. + * libstetic/editor/EditIconFactoryDialog.cs: Dialog for editing an + icon factory. + * libstetic/editor/SelectIconDialog.cs: Dialog for selecting an icon. + + * libstetic/editor/TreeViewCellContainer.cs: Bridge widget to be used for + cell rederers with custom editors. + * libstetic/editor/CellRendererComboBox.cs: A combo cell renderer. + + * stetic/Stetic.cs: Make sure Gtk is properly initialized before trying + to generate code. + * stetic/UIManager.cs: Added EditProjectIcons command. + + +2006-05-12 Lluis Sanchez Gual <lluis@novell.com> + + * libsteticui/ActionGroupToolbar.cs: Initialize the action group + editor after binding it. + * libstetic/PreviewBox.cs: Call OnDesignerAttach when attaching + a widget for editing. + * libstetic/wrapper/Widget.cs: + * libstetic/ObjectWrapper.cs: Moved basic code generation methods + here from Widget.cs, since generic objects may also need to + support it (for example, Gtk.Action). + Added OnDesignerAttach, which is called when a widget is attached + to a designer. + * libstetic/wrapper/Container.cs: Implement OnDesignerAttach. + * libstetic/wrapper/Action.cs: Implemented CopyTo in ActionCollection. + * libstetic/wrapper/Box.cs: Use Add insted of PackStart to add a widget + from drag-drop. Looks like PackStart does not fire the ChildAdded + event? + * libstetic/editor/ActionMenuItem.cs: Grab the keyboard focus after editing + is done. + * libstetic/editor/ActionMenuBar.cs: Show a dummy menu item when none is + defined, so the menubar has a proper height. Unselec any selected + item when the bar is unselected. Allow dropping actions from the + palette. + * libstetic/editor/ActionGroupEditor.cs: Sort action alphabetically. + * libstetic/editor/ActionMenu.cs: Destroy menu items when the menu + is disposed. + * libstetic/GeneratorContext.cs: In GenerateCreationCode, added the variable + for the new object to the statements collections after calling + GenerateObjectCreation, so statements needed for the object creation + are added before the declaration. + * libstetic/TypedClassDescriptor.cs: Lazily initialize the missingIcon + static variable. + * stetic/Stetic.cs: Show stetic help before standard gnome app help. + + * libstetic/wrapper/ActionTree.cs: + * libstetic/wrapper/MenuBar.cs: + * libstetic/wrapper/ActionGroup.cs: Added code generation support. + + * libstetic/wrapper/HScale.cs: + * libstetic/wrapper/Expander.cs: + * libstetic/wrapper/ToolButton.cs: + * libstetic/wrapper/VScrollbar.cs: + * libstetic/wrapper/ComboBoxEntry.cs: + * libstetic/wrapper/ComboBox.cs: + * libstetic/wrapper/HScrollbar.cs: + * libstetic/wrapper/VScale.cs: Renamed GenerateWidgetCreation to + a more generic GenerateObjectCreation. + + * libstetic/wrapper/objects.xml: Defined some initialization properties. + +2006-05-11 Lluis Sanchez Gual <lluis@novell.com> + + * libstetic/wrapper/ActionMenuItem.cs: + * libstetic/wrapper/ActionMenu.cs: Moved to /editor + * libstetic/Makefile.am: Updated. + +2006-05-11 Lluis Sanchez Gual <lluis@novell.com> + + * libsteticui/Palette.cs: Show all action groups inside + an "Actions" section. + * libsteticui/Makefile.am: Updated. + * libsteticui/ActionGroupToolbar.cs: Toolbar for the ActionGroup + designer. + * libsteticui/Project.cs: Forwards events fired when changing action + signals. + * libsteticui/SignalsEditor.cs: Include the action name in generated + handlers. + + * libstetic/IDesignArea.cs: Added some methods for getting the + current selection. + * libstetic/PreviewBox.cs: Implemented the new IDesignArea methods. + * libstetic/wrapper/Action.cs: Implemented clone and copy methods. + * libstetic/wrapper/ActionMenuItem.cs: Many fixes. + * libstetic/wrapper/Widget.cs: Allow more than one local action group. + Forward signal change events from the action groups. + * libstetic/wrapper/ActionGroup.cs: Added several events. + * libstetic/wrapper/ActionMenu.cs: Implemented keyboard support. + * libstetic/wrapper/objects.xml: Added name property to gtk.Action. + * libstetic/wrapper/MenuBar.cs: Moved ActionMenuBar to its own file. + * libstetic/WidgetUtils.cs: Added common GetDesignArea method. + * libstetic/Makefile.am: Updated. + * libstetic/editor/ActionGroupEditor.cs: Implemented an editor for + action groups. + + * stetic/Stetic.cs: Added some support for the new action group editor. + +2006-05-05 Lluis Sanchez Gual <lluis@novell.com> + + * libstetic/wrapper/objects.xml: Ignore the default for the + Position property of BoxChild. The position always needs to + be set, even if it's 0. Fixes bug #78307. + +2006-05-03 Lluis Sanchez Gual <lluis@novell.com> + + * libsteticui/Palette.cs: Added support for drag&drop between + action groups. Temporarily disabled action group support. + * libsteticui/Project.cs: Create a global action group by + default. + * libstetic/IDesignArea.cs: Added MoveWidget method. + * libstetic/IProject.cs: Added ActionGroups property. + * libstetic/PreviewBox.cs: Update the preview window title when + the wrapped window title changes. Implemented IDesignArea.MoveWidget. + * libstetic/ObjectWrapper.cs: For Gtk.Container.ContainerChild objects, + store the object in the wrapper hashtable using a special container + objects which properly implements the GetHashCode and Equals methods. + This is needed since every call to the Gtk.Container indexer returns + a new instance of the container child. + * libstetic/wrapper/Action.cs: Implemented Read/Write methods. Added + some missing events. Improved ActionCollection. + * libstetic/wrapper/Container.cs: Fixed some issues with name conflict + checking. Checks can't be done in the ParentSet event, since when + it is fired the child is not yet shown as a child of the container. + Properly dispose container child wrappers. + * libstetic/wrapper/Widget.cs: Same as before. Implemented read/write + support for action groups, but it is disabled for now. + * libstetic/wrapper/Box.cs: In the ChildContentsChanged method, avoid + setting Expand and Fill properties if the values don't change. + This avoids firing some unneeded change events. + * libstetic/wrapper/ActionGroup.cs: Implemented. + * libstetic/wrapper/objects.xml: Added some 'min' values to properties. + * libstetic/wrapper/ActionTree.cs: Implemented read/write methods. Added + some events. + * libstetic/WidgetUtils.cs: Added support for reading/writing properties + of arbitrary objects, not only widgets. + + * libstetic/wrapper/MenuBar.cs: + * libstetic/wrapper/ActionMenu.cs: + * libstetic/wrapper/ActionMenuItem.cs: Support editing of menu items in + a menu bar. Bug fixes and improvements. + +2006-04-28 Lluis Sanchez Gual <lluis@novell.com> + + * libsteticui/WidgetFactory.cs: Added PaletteItemFactory class, + as a base class for palette factories. Added InstanceWidgetFactory, + to support Action palette items. + + * libsteticui/SignalsEditor.cs: + * libsteticui/CodeGenerator.cs: Track api changes in signal handling. + + * libsteticui/Palette.cs: Add action groups to the palette. + * libsteticui/PropertyTree.cs: After editing a property, + notify the change to the wrapper. + + * libsteticui/Project.cs: Added action group collection. + Track api changes in signal handling. + * libsteticui/WidgetPropertyTree.cs: Allow showing properties of any + kind of wrapper, not only widgets. + * libstetic/PreviewBox.cs: Implemented IDesignArea. Implemented a new + way of drawing the widget selection box. + + * libstetic/wrapper/Widget.cs: + * libstetic/ObjectWrapper.cs: Moved signal properties and the notify + event from Widget to ObjectWrapper. + + * libstetic/wrapper/SignalCollection.cs: + * libstetic/wrapper/Signal.cs: + * libstetic/wrapper/SignalEventHandler.cs: + * libstetic/wrapper/SignalChangedEventHandler.cs: + * libstetic/wrapper/Container.cs: Use the new selection box system, + based in IDesignArea. + + * libstetic/wrapper/objects.xml: Added Action class. + + * libstetic/DND.cs: Some minor changes to allow dragging widgets which + don't have a wrapper. + + * libstetic/Makefile.am: Updated. + + * libstetic/IDesignArea.cs: New class for providing some designer + services to widget wrappers. + * libstetic/ObjectWrapperEventHandler.cs: New handler for + ObjectWrapper events. + * libstetic/wrapper/Action.cs: Wrapper for Gtk.Action. + * libstetic/wrapper/ActionMenu.cs: Widget for editing a Menu. + * libstetic/wrapper/ActionMenuItem.cs: An action menu item editor. + * libstetic/wrapper/ActionGroup.cs: Wrapper for Gtk.ActionGruoup. + * libstetic/wrapper/ActionTree.cs: An action tree structure (menu or + toolbar). + * libstetic/wrapper/MenuBar.cs: Wrapper for Gtk.MenuBar. + +2006-04-24 Lluis Sanchez Gual <lluis@novell.com> + + * libstetic/PreviewBox.cs: When handling the case of metacity + not being installed, don't specifically check for + a DllNotFoundException, since the exception may be wrapped + in another exception. + * libstetic/EmbedWindow.cs: Don't crash if the metacity + libs can't be found. + * libstetic/wrapper/Table.cs: Fix hang when loading project + which contains a table (bug #78167). + +2006-04-21 Lluis Sanchez Gual <lluis@novell.com> + + * libstetic/wrapper/VScale.cs: + * libstetic/wrapper/HScrollbar.cs: + * libstetic/wrapper/HScale.cs: + * libstetic/wrapper/VScrollbar.cs: Generate valid construction + expressions. + +2006-04-18 Lluis Sanchez Gual <lluis@novell.com> + + * libstetic/wrapper/objects.xml: + * libstetic/wrapper/Notebook.cs: Disable "Insert Before" and + "Delete Page" commands when there are no pages in the notebook. + * stetic/Stetic.cs: Fix crash when deleting a widget. + +2006-04-18 Lluis Sanchez Gual <lluis@novell.com> + + * libstetic/wrapper/Widget.cs: + * libstetic/wrapper/Container.cs: When adding a widget to a container, + make sure the identifiers are not duplicated. + * libstetic/wrapper/Frame.cs: Fixed code generation for + the label widget. + * libstetic/wrapper/Expander.cs: Fix code generation. Fixes bug #78090. + +2006-04-10 Lluis Sanchez Gual <lluis@novell.com> + + * libstetic/editor/Boolean.cs: Fix nullref in some themes. + +2006-04-03 Lluis Sanchez Gual <lluis@novell.com> + + * libsteticui/WidgetTreeCombo.cs: Don't show children + for widgets which don't allow children. + * libsteticui/ProjectView.cs: Allow deleting top level + widgets from the project view. + * libsteticui/ContextMenu.cs: Don't allow deleting or + cutting top level widgets. + * libstetic/CustomWidget.cs: Use EventBox as base class. + A gdk window is required to make child widgets selectable. + * libstetic/wrapper/Container.cs: Minor change in focus + handling. Don't allow deleting the only placeholder of a + top level container. + * libstetic/wrapper/Widget.cs: Avoid handling the FocusIn + event fired by an internal Select call. + * libstetic/wrapper/objects.xml: Removed some read-only + properties. + * libstetic/TypedPropertyDescriptor.cs: Provide defaults only + for primitive type properties. + * stetic/Stetic.cs: When deleting a top level widget, hide the + corresponding tab. + +2006-03-31 Lluis Sanchez Gual <lluis@novell.com> + + * libsteticui/PropertyTree.cs: Changed the way instance + information is stored. The value is now stored in + the tree store instead of a hashtable. + * libstetic/wrapper/Table.cs: Added a flag to avoid + recursively notifying changes in properties. + +2006-03-29 Lluis Sanchez Gual <lluis@novell.com> + + * libstetic/ImageInfo.cs: Don't crash if an icon is not + found in the current theme. + +2006-03-22 Lluis Sanchez Gual <lluis@novell.com> + + * libsteticui/WidgetTreeCombo.cs: A combo that shows the + tree of widgets of a window. + * libsteticui/WidgetPropertyTree.cs: + * libsteticui/PropertyTree.cs: A TreeView based property + editor. + * libsteticui/WidgetActionBar.cs: A toolbar that shows + the tree of widgets on a combo and some commands + available for the selected widget. + * libsteticui/Project.cs: Replaced the Selected event by + SelectionChanged, which uses a standard signature + for event handlers. + * libsteticui/PropertyGrid.cs: + Track changes in the widget selected event. + * libsteticui/PropertyEditor.cs: Moved most of code to + PropertyEditorCell. + * libsteticui/Palette.cs: Show windows before widgets, since + windows are the first thing an user is going to create. + * libsteticui/ProjectView.cs: Track changes in the widget + selected event. Added WidgetActivated event. + * libsteticui/SignalsEditor.cs: Make columns resizable. + Track changes in the widget selected event. + + * libsteticui/ContextMenu.cs: Show the Delete command for + placeholders. Delete placeholders through their container. + + * libsteticui/Makefile.am: Updated. + + * libstetic/PropertyEditorCell.cs: New file. Implements the base + class for property editors that need custom rendering. + * libstetic/IProject.cs: Added SelectionChanged event. + * libstetic/ItemDescriptor.cs: HasDependencies now returns true + if there are visibility dependencies, not only sensitivity. + * libstetic/stetic.glade: Added text editor dialog. + + * libstetic/wrapper/Button.cs: Added null check. + * libstetic/wrapper/Container.cs: When the last placeholder of + a container is delete, delete the container. + * libstetic/wrapper/Paned.cs: Don't allow deleting placeholders. + * libstetic/wrapper/Box.cs: Removed AllowPlaceholders override, + now will always return true. Why was this override needed? + * libstetic/wrapper/Window.cs: Store the window icon in an ImageInfo + instance. + * libstetic/wrapper/objects.xml: Fixed some editor references. + Removed icons that don't exist. Moved scrollbar and separator + widgets to the "widget" palette category. + * libstetic/wrapper/Table.cs: Make sure placeholders can only be + deleted using the delete row/column commands. + + * libstetic/editor/Color.cs: + * libstetic/editor/Boolean.cs: + * libstetic/editor/ImageSelector.cs: + * libstetic/editor/Enumeration.cs: + * libstetic/editor/Flags.cs: + * libstetic/editor/StockItem.cs: + * libstetic/editor/IntRange.cs: + * libstetic/editor/ResponseId.cs: Implemented as a PropertyEditorCell, + since it needs custom rendering. + + * libstetic/editor/Text.cs: Implemented as a subclass of TextEditor. + * libstetic/editor/Image.cs: Make the editor visible. + * libstetic/editor/StringArray.cs: New implementation based on the + TextEditor dialog. + + * libstetic/editor/TextEditorDialog.cs: + * libstetic/editor/TextEditor.cs: A new editor for strings. + + * libstetic/DND.cs: + * libstetic/WidgetUtils.cs: Added some null checks. + + * libstetic/TypedClassDescriptor.cs: Properly handle errors while + loading widget icons. + * libstetic/Makefile.am: Updated. + + * stetic/stetic.glade: + * stetic/UIManager.cs: + * stetic/Stetic.cs: Implemented a new interface model. Design windows are + now embedded, instead of floating around. Using the new property tree. + +2006-03-14 Lluis Sanchez Gual <lluis@novell.com> + + * libsteticui/CodeGenerator.cs: Moved statements collection into + the GeneratorContext class. + * libsteticui/PropertyEditor.cs: Register new image editor. + + * libstetic/IProject.cs: + * libsteticui/Project.cs: Added property for IResourceProvider. + + * libstetic/ObjectWrapper.cs: Generate an error widget if something + fails while loading the project. + * libstetic/Registry.cs: In LookupItem, throw an exception if the + item can't be found. + * libstetic/wrapper/Button.cs: Use the new ImageInfo class for + storing the pixbuf. + * libstetic/wrapper/Label.cs: Generate specific code for setting + the MnemonicWidget property. + * libstetic/wrapper/TextView.cs: Don't allow placeholders in a + text view. Generate code for setting the text of the buffer. + + * libstetic/wrapper/Widget.cs: The Visible property is the last + one to be set, in this way nothing is shown until everything + is built. + * libstetic/wrapper/Toolbar.cs: Put placeholders inside a ToolItem. + * libstetic/wrapper/Image.cs: Simplified the code by using an ImageInfo + object for storing the pixbuf. + + * libstetic/wrapper/ComboBox.cs: + * libstetic/wrapper/ComboBoxEntry.cs: If some items have been + added at design time, generate a text combo box. + + * libstetic/wrapper/RadioToolButton.cs: + * libstetic/wrapper/RadioButton.cs: + * libstetic/wrapper/Window.cs: + * libstetic/wrapper/Notebook.cs: + * libstetic/wrapper/RadioMenuItem.cs: + * libstetic/wrapper/Bin.cs: + * libstetic/wrapper/Container.cs: Moved statements collection into + the GeneratorContext class. + + * libstetic/wrapper/objects.xml: Added some min values. Removed the + Bin control from the palette. Track changes in Image and Button + image properties. + * libstetic/wrapper/CheckButton.cs: In the generated code, remove + the default label child widget if not needed. + * libstetic/wrapper/ToolButton.cs: Simplified the code by using a n + ImageInfo object for storing the pixbuf. + * libstetic/editor/ThemedIcon.cs: Fixed some compilation problems. + Moved ThemedIconList to its own file. + * libstetic/PropertyDescriptor.cs: Added support for type converters. + * libstetic/TypedPropertyDescriptor.cs: Implemented RuntimePropertyType. + + * libstetic/GeneratorContext.cs: Added the statements collection that + will contain all generated code. Added EndGeneration, which + runs all post build generation methods. + * libstetic/ErrorWidget.cs: Added support for reporting load errors. + + * libstetic/editor/FlagsSelectorDialog.cs: + * libstetic/editor/Flags.cs: When there are more than 5 flag values, + use a dialog to select them, since the checkbox list takes too + much space. + + * libstetic/Makefile.am: Updated. + +2006-03-03 Lluis Sanchez Gual <lluis@novell.com> + + * libstetic/WidgetLibrary.cs: Made Dispose virtual. + * libstetic/wrapper/objects.xml: Declared initializer properties. + * libstetic/wrapper/Container.cs: Don't generate code for building + children if children are not allowed. + * libstetic/wrapper/Widget.cs: Support generating code for untyped + class descriptors. + * libstetic/TypedClassDescriptor.cs: When looking for a static + CreateInstance method, look for an overload that takes + a ClassDescriptor as parameter. + * libstetic/wrapper/Bin.cs: In CreateInstance, return the + CustomWidget instance only if the class is a Gtk.Bin. + Don't do it for subclasses of Bin. + + * libstetic/wrapper/RadioButton.cs: + * libstetic/wrapper/RadioMenuItem.cs: + * libstetic/wrapper/RadioToolButton.cs: Track api changes. + +2006-03-03 Lluis Sanchez Gual <lluis@novell.com> + + * libsteticui/SignalsEditor.cs: Add the name of the widget + to the handler name, to avoid collisions when mapping + the same event from different widgets. + * libstetic/wrapper/Notebook.cs: Added some specific generation + code. + +2006-03-02 Lluis Sanchez Gual <lluis@novell.com> + + * libsteticui/CodeGenerator.cs: Generated class is not internal. + Generate a new Build overload, which takes a type instead of + an id as parameter. Other minor fixes. + * libsteticui/Palette.cs: Added methods for showing/hiding groups. + Added property for setting the widget libraries to show in + the palette. + * libsteticui/Clipboard.cs: Use the native format to make copies + of widgets. + * libsteticui/ProjectView.cs: Redraw the tree when widget names + change. + * libsteticui/Project.cs: Added method for getting a node. + * libstetic/PreviewBox.cs: Added some null checks. + + * libstetic/wrapper/RadioToolButton.cs: + * libstetic/wrapper/RadioButton.cs: + * libstetic/wrapper/RadioMenuItem.cs: + * libstetic/RadioGroupManager.cs: Added support for code generation. + + * libstetic/Registry.cs: Added getter for the core widget library. + * libstetic/wrapper/Container.cs: Generate code only for properties + available at run time. + * libstetic/wrapper/Widget.cs: Same as previous. Also use the wrapped + type name specified by the class descriptor, instead of using the + real type of the object, since it may be a design-time only object. + * libstetic/wrapper/Object.cs: Translate gtk property names to managed + names when firing the notify event. + * libstetic/wrapper/Custom.cs: Don't use GdkWindow.SetBackPixmap since + it seems to fail for some widget sizes. + * libstetic/wrapper/objects.xml: Specified a custom wrapper for Bin. + Added references to Gtk.Widget properties and signals. + + * libstetic/PropertyDescriptor.cs: Added some methods for handling + property values at run-time. + * libstetic/TypedPropertyDescriptor.cs: Added support for run-time + properties. + * libstetic/GeneratorContext.cs: Added CodeNamespace property. + + * libstetic/WidgetUtils.cs: Use XmlElement instead of XmlDocument + for exporting/importing widgets (its more generic). Implemented + Copy/Paste methods based on native format serialization. + Added some BuildWidget methods (which are not used right now). + + * libstetic/ClassDescriptor.cs: Properly initialize the name of the + widget. + * libstetic/TypedClassDescriptor.cs: Moved name initialization to + base class. + * libstetic/Makefile.am: Updated. + +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. + * configure.in, Makefile.am: Add libsteticui dir. + + * stetic/WidgetFactory.cs: + * stetic/Grid.cs: + * stetic/missing.png: + * stetic/PropertyGrid.cs: + * stetic/PropertyEditor.cs: + * stetic/Palette.cs: + * stetic/Clipboard.cs: + * stetic/ProjectView.cs: + * stetic/Makefile.am: + * stetic/Project.cs: + * stetic/SignalsEditor.cs: + * stetic/ContextMenu.cs: + Moved files to libsteticui. + +2006-02-07 Lluis Sanchez Gual <lluis@novell.com> + + * libstetic/ItemGroup.cs: Converted to class. Added support for + Signal items. + + * libstetic/wrapper/Container.cs: Added properties for storing + the width and height of the container (at design time). + + * libstetic/wrapper/Widget.cs: Added support for signals. + Added some new events: NameChanged, WidgetChanged, SignalAdded, + SignalRemoved, SignalChanged. + + * libstetic/wrapper/Window.cs: Don't show the window when it's + selected. That's something that the hosting application has to + decide. The selection change event in Project can be used for this. + + * libstetic/wrapper/objects.xml: Added signals. + + * libstetic/editor/ResponseId.cs: + * libstetic/editor/Translatable.cs: + * libstetic/editor/Char.cs: + * libstetic/editor/Color.cs: + * libstetic/editor/ThemedIcon.cs: + * libstetic/editor/Boolean.cs: + * libstetic/editor/Image.cs: + * libstetic/editor/FloatRange.cs: + * libstetic/editor/Text.cs: + * libstetic/editor/Accelerator.cs: + * libstetic/editor/Enumeration.cs: + * libstetic/editor/GroupPicker.cs: + * libstetic/editor/OptIntRange.cs: + * libstetic/editor/Flags.cs: + * libstetic/editor/StringArray.cs: + * libstetic/editor/String.cs: + * libstetic/editor/IntRange.cs: + Implement the new IPropertyEditor interface. + + * libstetic/HandleWindow.cs: Use a wider focus rectangle. + Get the correct top level window when it's embedded in another window. + + * libstetic/GladeUtils.cs: Added helper methods for exporting and + importing widgets. Read/Write signal information. + + * libstetic/ClassDescriptor.cs: Added support for signals. + + * stetic/Makefile.am: + * libstetic/Makefile.am: Updated. + + * libstetic/Registry.cs: Added some helper methods for locating + groups. + + * Makefile.am: + * configure.in: Set version to 0.1.0. Added .pc file. + + * stetic/WidgetFactory.cs: Don't show the window when it's + created. The hosting app can do it by subscribing the + Project.WidgetAdded event. + + * stetic/Glade.cs: Top level widgets don't need to be windows, + they can be containers. + + * stetic/PropertyGrid.cs: Some big changes. This widget is not a Grid + anymore, but a VBox of grids. There is a grid for every ItemGroup, and + they are reused for all widgets that share the same ItemGroup. The + property grid is now much faster. + + * stetic/Stetic.cs: Added the signals editor. Handle some events + previously handled in the widget code, but which I moved here to + make the code more generic. + + * libstetic/IPropertyEditor.cs: New interface to be implemented + by all property editors. + + * stetic/PropertyEditor.cs: Replaced all code that relied on reflection + to create and initialize property editors. All this is now done through + the new IPropertyEditor interface. Now it is also possible to reuse + the same PropertyEditor for different objects that share the same + property. + + * stetic/Palette.cs: + * stetic/ProjectView.cs: Added support for changing the project to + which those widgets are bound. + + * stetic/stetic.glade: Added the signals editor. + + * stetic/Project.cs: Added several events which are needed to + integrate Stetic in an IDE. + + * stetic.pc.in: Added. + + * libstetic/SignalDescriptor.cs: New descriptor for signals. + + * libstetic/wrapper/WidgetEventHandler.cs: + * libstetic/wrapper/WidgetNameChangedHandler.cs: + * libstetic/wrapper/SignalEventHandler.cs: + * libstetic/wrapper/SignalChangedEventHandler.cs + + * libstetic/wrapper/SignalCollection.cs: + * libstetic/wrapper/Signal.cs: New class. Holds information + about signal handlers bound to a widgets. + + * libstetic/ItemGroupCollection.cs: New collection class. + + * stetic/SignalsEditor.cs: The new signals editor. + +2005-09-27 Dan Winship <danw@novell.com> + + * libstetic/HandleWindow.cs (HandleEvent): hack around bgo 316871 + (shaped windows block update events in gtk+ 2.8.0 - 2.8.3). + +2005-09-26 Dan Winship <danw@novell.com> + + * libstetic/wrapper/objects.xml: bring back ThemedIcon images and + buttons. Add <itemgroup ref="Gtk.Widget"> to a few classes that + were missing it. + + * libstetic/editor/ThemedIcon.cs: Fix to work under Gtk# 2.4 + + * libstetic/wrapper/Button.cs: bring back ThemedIcon buttons + + * libstetic/wrapper/Image.cs: bring back ThemedIcon images. + + * libstetic/wrapper/Frame.cs: don't crash when importing a frame + with no label widget. If the LabelWidget changes, create a new + wrapper for it. + + * libstetic/wrapper/Container.cs (GladeImport): don't crash when + importing a placeholder into a !AllowPlacerholders container. + +2005-09-26 Dan Winship <danw@novell.com> + + * libstetic/wrapper/Dialog.cs (Buttons): make this a number rather + than having an enum of standard button choices; the HIG prefers + stronger labels than "OK"/"Yes", so we shouldn't be making it + easier to use bad labels than good ones. + (HelpButton): reorder the help button to be the first child so + that it won't ever get deleted when you decrement Buttons + (ButtonsChanged): keep the Buttons and HelpButton properties in + sync if the user manipulates the buttonbox contents by hand + + * libstetic/wrapper/Button.cs (StockId): if the button's ReponseId + matches its old StockId (or is unset), update it to match it's new + StockId. + (IsDialogButton): replaces HasResponseId and is now settable + rather than being figured out automatically. Also, set + button.CanDefault when turning on IsDialogButton. + (ResponseIdForStockId): maps Gtk.Stock values to Gtk.ResponseType + values. + + * libstetic/wrapper/ButtonBox.cs (NewButton): if the buttonbox is + a dialog's action_area, set IsDialogButton on new child buttons. + (AllowPlaceholders): false + (InsertBefore, InsertAfter): Reimplement using Secondary/non- + Secondary rather than PackType. + (ButtonBoxChild): add InDialog property + + * libstetic/wrapper/Container.cs (ContextChildProps): for use in + context-menu ops; gets the child properties corresponding to the + ancestor of the widget that is a child of the container. + + * libstetic/wrapper/Box.cs (AllowPlaceholders): only return false + if InternalChildId is unset. (Eg, we definitely want to allow + placeholders in a dialog box's internal vbox). + (InsertBefore, InsertAfter): use Container.ContextChildProps so + that this works regardless of what descendant widget was clicked + on. + + * libstetic/wrapper/objects.xml (Gtk.ButtonBox): Change the + command labels to "Insert Button Before" and "Insert Button + After". + (Gtk.ButtonBox+ButtonBoxChild): Remove PackType, since the + interaction of PackType and Secondary is unnecessarily annoying. + Also add a new internal InDialog property and hide Secondary if + that's true (since we handle Help buttons specially and nothing + else should be secondary). + (Gtk.Button): s/HasResponseId/IsDialogButton/ + (Gtk.Dialog): change the description of Buttons since it's now a + number, and give it a minimum value of "1". + (Gtk.ResponseType): add labels/descriptions for this enum + (Stetic.Wrapper.Dialog+StandardButtons): and kill this one + + * libstetic/editor/ResponseId.cs: update this to use + EnumDescriptor + +2005-09-22 Dan Winship <danw@novell.com> + + * libstetic/ClassDescriptor.cs: Handle <contextmenu ref="..." /> + + * libstetic/DND.cs (Cancel): fix a crash + + * libstetic/Registry.cs (LookupContextMenu): look up a context + menu by class name. + (NewInstance): Look up a class and invoke NewInstance on it + + * libstetic/wrapper/ButtonBox.cs: Wrapper for ButtonBox, that + automatically fills in dummy buttons as needed. + + * libstetic/wrapper/objects.xml (Gtk.ButtonBox): use the new + ButtonBox wrapper. Add a "Size" property and a context menu. + + * libstetic/wrapper/Container.cs (AllowPlaceholders): new virtual + property saying whether or not to allow arbitrary placeholders in + the container. + (Wrap, GladeImport, Delete): Don't add placeholders if + !AllowPlaceholders + (DragEnd): Remove the dragSource placeholder after a successful + drag if !AllowPlaceholders + + * libstetic/wrapper/Box.cs (AllowPlaceholders): false + (InsertBefore, InsertAfter): If invoked on the box directly + (rather than via the submenu from one of its children), insert + before the first / after the last child. + + * libstetic/wrapper/Button.cs: Remove CreateInstance method; + default to text-only buttons like Glade does. + + * libstetic/wrapper/Dialog.cs (AddButton): Use + Registry.NewInstance. + + * libstetic/wrapper/Notebook.cs (InsertPage): Use + Registry.NewInstance + + * stetic/ContextMenu.cs: Fix up for bxc 75689 again, since it was + still broken before. + +2005-09-20 Dan Winship <danw@novell.com> + + * libstetic/EnumDescriptor.cs: New descriptor class for English + (and later localized) enum value names and descriptions. + + * libstetic/Registry.cs (Registry): Create EnumDescriptors before + ClassDescriptors. + (LookupEnum): return EnumDescriptors. + + * libstetic/PropertyDescriptor.cs: throw an exception if an + enum-valued property has no EnumDescriptor in the registry. + + * libstetic/editor/Enumeration.cs: simplify using EnumDescriptor. + Also set the combobox's tooltip to the description of the selected + enum value. + + * libstetic/editor/Flags.cs: editor for flags values (vbox full of + checkbuttons, with tooltips). + + * libstetic/wrapper/Widget.cs (Events): proxy this property, since + it can't be changed after the widget is realized. + + * libstetic/wrapper/objects.xml: add <enum> nodes for all enum + types we use. + + * stetic/PropertyEditor.cs (PropertyEditor): Use the Flags editor + for flags-valued enums + +2005-09-16 Dan Winship <danw@novell.com> + + * libstetic/wrapper/Container.cs (ReplaceChild): + EmitContentsChanged() at the end, to fix a bug with the + Project tree being out of sync. + + * configure.in: bump gtk-sharp dependency back up to 2.3.91. There + are too many post-1.9.5 fixes we need. + + * libstetic/DND.cs: + * libstetic/HandleWindow.cs: + * libstetic/editor/Accelerator.cs: + * libstetic/editor/Translatable.cs: Revert 1.9.5 reversions + +2005-09-15 Dan Winship <danw@novell.com> + + * libstetic/wrapper/Label.cs: remove the custom ctor + + * libstetic/wrapper/Notebook.cs (InsertPage): use the Gtk.Label + ClassDescriptor's NewInstace to create labels, so they end up + fully-constructed. + +2005-09-14 Dan Winship <danw@novell.com> + + * configure.in: drop gtk# dependency down to 1.9.5 + + * libstetic/Makefile.am (libstetic_dll_sources): remove + editor/ThemedIcon.cs and wrapper/AboutDialog.cs + + * libstetic/DND.cs: + * libstetic/HandleWindow.cs: use gtk# 1.9.5-compatible + Gdk.WindowAttr fields + + * libstetic/ItemGroup.cs (ItemGroup): deal with comment nodes in + objects.xml + + * libstetic/editor/GroupPicker.cs: comment out use of + ComboBox.RowSeparatorFunc. + + * libstetic/editor/Translatable.cs (ButtonPressed): use gtk# + 1.9.5-compatible Gtk.Menu.Popup call. + + * libstetic/wrapper/objects.xml: comment out all 2.6 widgets and + properties + + * libstetic/wrapper/Image.cs: comment out "themed icon" support + + * libstetic/wrapper/Button.cs: comment out "themed icon" buttons + and the use of Button.Image + + * stetic/UIManager.cs: Comment out Gtk.AboutDialog usage, use + Gnome.About instead. + + * stetic/Clipboard.cs: Comment out support for plaintext cut+paste. + + * stetic/Stetic.cs: Comment out Gtk.AboutDialog-related stuff. + +2005-08-18 Dan Winship <danw@novell.com> + + * libstetic/Tooltips.cs: Hashtable/Gtk.Tooltips mix. (Gtk.Tooltips + is write-only, so we can't use it by itself.) + + * libstetic/IProject.cs (Tooltips): new tooltips field + + * stetic/Project.cs (Tooltips): implement + + * libstetic/wrapper/objects.xml (Gtk.Widget): add Tooltip + property. + + * libstetic/wrapper/Widget.cs (Tooltip): implement, using + proj.Tooltips. + +2005-08-17 Dan Winship <danw@novell.com> + + * libstetic/wrapper/objects.xml (Expander): Remove "Label", + "UseMarkup", and "UseUnderline" properties; we'll treat the label + as a child widget now, like Glade does. Also fix palette-category + to be "container". + (Frame): Remove the Label property, as with Expander. Also remove + the redundant and deprecated "Shadow" property. + (Notebook): Remove some deprecated properties + + * libstetic/wrapper/Expander.cs (Wrap): create an ObjectWrapper + for the expander's LabelWidget + (ReplaceChild): deal with LabelWidget + + * libstetic/wrapper/Frame.cs: Likewise + + * libstetic/wrapper/Notebook.cs (Wrap): remove the dummy page that + will have been added by Container.Wrap. + (Select): don't crash if the passed-in wrapper is null + +2005-08-04 Dan Winship <danw@novell.com> + + Support cut+paste of widgets, including interprocess cut+paste and + drag+drop. (For some reason, it is very slow when going + cross-process...) + + * libstetic/GladeUtils.cs (ApplicationXGladeAtom): Gdk.Atom for + glade selections. + (XslImportTransform, XslExportTransform): do the import/export xsl + fixups. + (Copy): copy a glade representation of a widget into a + Gtk.SelectionData (in the same format that glade uses for its own + internal clipboard). + (Paste): generate a widget from a glade representation in a + Gtk.SelectionData. + + * libstetic/DND.cs (targetList): add application/x-glade to the + supported target types. + (Drag): connect to the source's DragDataGet signal + (Drop): if asked to drop an out-of-proc widget, call + Gtk.Drag.GetData and return null. + (DragDataGet): Respond by calling GladeUtils.Copy + (FaultDragDrop, FaultDragDataReceived): update to be able to deal + with receiving an out-of-proc widget + + * libstetic/ObjectWrapper.cs (Project): new public property to get + the wrapper's Project + + * libstetic/wrapper/Container.cs (GladeExport): create + <placeholder> elements as appropriate. + (CreatePlaceholder): connect to DragDataReceived. + (PlaceholderDragDataReceived): Paste the received widget data into + place. + (GladeChildren): return AllChildren, not RealChildren, because we + want to include placeholders. + (ReplaceChild): make this public + + * libstetic/wrapper/Button.cs (UseUnderline): wrap this; we can't + set it directly on the button when we have a special icon set. + (GladeImport): Remove a useless special case. + (GladeExport): Set the "label" property when the button has a + stock id. + (GladeChildren): return base.GladeChildren, not base.RealChildren. + + * libstetic/wrapper/ScrolledWindow.cs (GladeChildren): don't need + to override any more. + + * libstetic/wrapper/objects.xml (Gtk.Button): add UseStock as an + internal property. + (Gtk.ColorButton): Remove the "Color" property, since we have no + way to serialize it. + (Gtk.ColorSelection): Likewise for CurrentColor here. + + * stetic/Clipboard.cs: new static class with some cut/paste helper + routines. + + * stetic/ContextMenu.cs (DoCut, DoCopy, DoPaste, DoDelete): update + to use Clipboard + + * stetic/Glade.cs: use GladeUtils.XslImportTransform and + XslExportTransform. + + * stetic/Project.cs (Selection): don't crash when clearing the + selection + + * stetic/UIManager.cs (Cut, Copy, Paste): Implement these for + widgets as well as text. + +2005-08-02 Dan Winship <danw@novell.com> + + * libstetic/GladeUtils.cs (ParseEnum, ParseFlags, PropToString): + use Enum rather than obsolete EnumWrapper + + * libstetic/editor/Translatable.cs (ButtonPressed): Use + non-obsolete Gtk.Menu.Popup(). + + * libstetic/wrapper/objects.xml: add "Stock" internal property to + Image so that stock images load correctly again. Fix + Gtk.Notebook's InsertBefore and InsertAfter commands. + + * stetic/ContextMenu.cs (ContextMenu): work around another + anonymous delegates bug (75689) + +2005-07-21 Dan Winship <danw@novell.com> + + * libstetic/wrapper/*.cs: add a bunch of missing EmitNotify() + calls. + +2005-07-19 Dan Winship <danw@novell.com> + + * stetic/UIManager.cs: subclass of Gtk.UIManager for Stetic. Not + horribly functional yet, though it does track Edit menu + sensitivity, for both widgets and text, and implements + Cut/Copy/Paste for text (but not widgets). + + * stetic/stetic.glade: Replace the menubar with another Custom. + + * stetic/Stetic.cs (Main): create a Stetic.UIManager. Set + SteticMain.MainWindow (to the window containing the PropertyGrid). + Move menu command implementations to UIManager.cs + + * stetic/ContextMenu.cs: use ImageMenuItems for Cut/Copy/Paste. + Use the UIManager to implement them. + + * stetic/Project.cs (SelectedHandler, Selection): pass the + Gtk.Widget, not its wrapper, since there won't be a wrapper in the + Placeholder case. + + * stetic/ProjectView.cs (WidgetSelected): + * stetic/PropertyGrid.cs (Selected): update for prototype change + +2005-07-19 Dan Winship <danw@novell.com> + + * libstetic/IProject.cs: rename IStetic to IProject + + * libstetic/*.cs: + * libstetic/wrapper/*.cs: + * stetic/Project.cs: update + +2005-07-15 Dan Winship <danw@novell.com> + + * libstetic/PropertyDescriptor.cs (Translatable, IsTranslated, + SetTranslated, TranslationContext, SetTranslationContext, + TranslationComment, SetTranslationComment): support for + translatable properties. + + * libstetic/GladeUtils.cs: Reorg a bunch to handle + translatable-string-related attributes on import/export. + (SetPacking): do GladeOverride packing properties correctly. + + * libstetic/EditorAttribute.cs: gone. We weren't really using it + anyway, and editors can get data from the PropertyDescriptor now. + + * libstetic/TextBox.cs: a vertically-scrolling + fixed-number-of-lines TextView. Stolen from Stetic.Editor.Text, + now also used by Stetic.Editor.Translatable. + + * libstetic/editor/Translatable.cs: base class for translatable + property editors. Adds an icon indicating whether or not the + property is marked for translation, with a pop-up menu allowing + you to toggle that and set a context or comment (which appear + inline in the property grid rather than only in a separate + window). + + * libstetic/editor/String.cs: inherit from Translatable + + * libstetic/editor/Text.cs: inherit from Translatable and use + TextBox. + + * libstetic/editor/Enumeration.cs: + * libstetic/editor/GroupPicker.cs: + * libstetic/editor/StringArray.cs: update protytype to take a + PropertyDescriptor rather than a PropertyInfo. + + * libstetic/wrapper/objects.xml: Mark all translatable string + properties with translatable="true". Also make more use of + <property ref=...> to simplify/correctify things. + + * libstetic/wrapper/Container.cs (GladeSetInternalChild): Make + this look up the internal child using the properties on the + ClassDescriptor, since the "child" might really be a grandchild or + deeper descendant. + (GladeImportChild, GladeSetInternalChild): Update for + GladeUtils.SetPacking change. + + * libstetic/wrapper/pixmaps/globe.png: + * libstetic/wrapper/pixmaps/globe-not.png: translated/not + translated icon + + * stetic/stetic.glade: Remove the height_request and + width_request, because we only wanted to set initial defaults and + let it resize itself appropriately after that. + + * stetic/PropertyEditor.cs (PropertyEditor): Pass + PropertyDescriptors, not PropertyInfos to editor constructors, and + add another new type (PropertyDescriptor, object). + + * stetic/Glade.cs (Export): set the DOCTYPE after the xsl + transform, or else XslTransform will insist on adding lots of + redundant attributes we don't want. + +2005-07-13 Dan Winship <danw@novell.com> + + * libstetic/ClassDescriptor.cs (ClassDescriptor) parse the + internal-children node of a class as an ItemGroup. + (InternalChildren): return it + + * libstetic/wrapper/objects.xml: Add internal-children nodes to + Dialog and OptionMenu. Add info for AboutDialog, ColorSelection, + ColorSelectionDialog, FileChooserWidget, FileChooserButton, + FileChooserDialog, FontSelection, and FontSelectionDialog (several + of which also have internal-children). Move AutoSize from + ContainerChild to BoxChild and TableChild for now at least. + + * libstetic/wrapper/Container.cs (Wrap): get the ClassDescriptor's + InternalChildren list and set InternalChildId and Name on the + container's internal children. + + * libstetic/wrapper/Dialog.cs (Wrap): + * libstetic/wrapper/OptionMenu.cs (Wrap): Remove internal child + handling; it's done by Container now. + + * libstetic/wrapper/AboutDialog.cs: wrap this, to make the + Website/WebsiteLabel behavior more interactively-sane, and to make + it not default to putting "Stetic" as the application name :). + + * libstetic/wrapper/FontSelectionDialog.cs: wrapper to expose the + internal FontSelection widget. + + * libstetic/editor/StringArray.cs: editor for string[] (for + AboutDialog) + + * stetic/PropertyEditor.cs: add Stetic.Editor.StringArray to the + editors hashtable. + + * stetic/Grid.cs (SizeAllocate): don't vertically center the label + wrt the editor if the editor is more than twice the line height + (eg, a multiline text box). + + * stetic/Stetic.cs (Main): call Gtk.AboutDialog.SetUrlHook() here + rather than in About(), so that the UrlHook is set for + user-created about dialogs too. + +2005-07-12 Dan Winship <danw@novell.com> + + * libstetic/ClassDescriptor.cs: fix some names with underscores to + use camelCase instead. + (ClassDescriptor): If a class has no wrapper typed specified, use + its parent's wrapper type. Allow a "cname" attribute, to override + the CName property, so we can use a different class at design time + than we do at runtime (eg, for MessageDialog). Remove the + never-necessary "commands" node and no-longer-necessary + "internal-properties" node. Count the number of "important" + itemgroups. + (NewInstance): move the widget-name-generation code here from + Widget, and apply it to every property on the object with the + init-with-name attribute. + (ImportantGroups): return the number of "important" itemgroups + + * libstetic/GladeUtils.cs (ExtractWrapperProperties, GetProps): + update for ItemGroup being enumerable. + (ExportWidget): use the ClassDescriptor's CName, not the wrapped + type's name. + + * libstetic/ItemDescriptor.cs (ItemDescriptor, IsInternal): note + when properties are internal. + + * libstetic/ItemGroup.cs: make this IEnumerable, clean up a bit + + * libstetic/PropertyDescriptor.cs (PropertyDescriptor, + InitWithName): note when properties have the init-with-name + attribute set. + + * libstetic/wrapper/objects.xml: Move all internal-properties + properties to internal="true" properties in itemgroups. Set + init-with-name where appropriate. Remove now-redundant + wrapper="..." attributes. Remove <commands> node from Gtk.Label. + Fix Custom and GtkMessageDialog with cname attributes. + + * libstetic/wrapper/Bin.cs: gone; Container can handle all of + this now. + + * libstetic/wrapper/Expander.cs: + * libstetic/wrapper/Frame.cs: + * libstetic/wrapper/ScrolledWindow.cs: + * libstetic/wrapper/Viewport.cs: inherit from Container now, since + Bin is gone + + * libstetic/wrapper/CheckButton.cs (Wrap): Remove Label setting, + which now happens via init-with-name. + + * libstetic/wrapper/Container.cs (Wrap): when initializing a + container, if it has no children, add a placeholder. + + * libstetic/wrapper/Custom.cs: Remove references to C glue since + we can now do this entirely in C# via the "cname" property. Move + all of the properties into Stetic.Custom and remove + Stetic.Wrapper.Custom. + + * libstetic/wrapper/Label.cs (Wrap): remove; LabelProp gets + initialized via init-with-name now + + * libstetic/wrapper/MessageDialog.cs: create a new class + Stetic.MessageDialog that subclasses Gtk.Dialog (and update the + objects.xml entry to use that). The old solution of just creating + a special Gtk.Dialog in CreateInstance() doesn't work any more. + + * libstetic/wrapper/RadioButton.cs (Wrap): remove the Label + setting, which now happens via init-with-name + + * libstetic/wrapper/Widget.cs (Wrap): remove the Name setting, + which now happens in ClassDescriptor. + + * libstetic/wrapper/Window.cs: inherit from Container, since Bin + is now gone, and remove Title setting, which now happens via + init-with-name + + * stetic/PropertyEditor.cs: fix a bug in int properties with + neither a min nor a max specified. + + * stetic/PropertyGrid.cs (AppendItemGroups): use + ClassDescriptor.ImportantGroups rather than assuming the first + ItemGroup should be expanded and the later ones shouldn't. + + * glue/custom.c: no longer needed + +2005-07-11 Dan Winship <danw@novell.com> + + * libstetic/wrapper/objects.xml: add some missing properties + +2005-07-08 Dan Winship <danw@novell.com> + + * libstetic/wrapper/Widget.cs (InsensitiveManager): track + realize/unrealize events and only create the intercepting window + when the underlying widget is realized, or else it will end up as + a child of the root window and we'll totally lose. + +2005-07-08 Dan Winship <danw@novell.com> + + * libstetic/wrapper/objects.xml: add <glade-transform> nodes with + XSL transformations to fix some oddities in the glade file format. + (GtkHButtonBox): set the "secondary" property on a Help button + child. Use Gtk.Box as a wrapper now, since we don't need a + ButtonBox wrapper any more. + (GtkButtonBox, GtkVButtonBox): use Gtk.Box as a wrapper. + (GtkMenuItem): a menuitem with no label should be a + SeparatorMenuItem. + (GtkTable): fix/break the non-standard "x_options" and "y_options" + (GtkWidget): remove/add the extraneous spaces in "events" + + * libstetic/wrapper/ButtonBox.cs: gone + + * libstetic/wrapper/Container.cs (GladeImport): Sync() at the end. + + * libstetic/wrapper/Table.cs (GladeImportChild, GladeExportChild): + gone, handled by xsl now. + (GladeImport): gone, Container does the Sync() for us now. + + * libstetic/GladeUtils.cs (ParseFlags): remove special case for + Widget.Events + + * libstetic/Registry.cs: handle the <glade-transform> nodes. + (GladeImportXsl, GladeExportXsl): properties to return + XslTransforms for glade import and export. + + * stetic/Glade.cs: use Registry.GladeImportXsl and GladeExportXsl. + +2005-07-08 Dan Winship <danw@novell.com> + + Rework the glade import/export framework to pass XmlElements + directly to the wrapper import/export methods, rather than trying + to parse out the "relevant" parts into Hashtables, etc. This makes + it easier to handle a lot of the things that need special + handling now, and will make it easier to handle signal, + accelerator, and a11y import/export stuff later. + + * libstetic/GladePropertyAttribute.cs: gone, entirely replaced by + XML attributes now + + * libstetic/GladeUtils.cs: update to use XML. + (ParseProperty): handle gunichar properties. + (Wrap): don't need the LateImportHelper stuff now + + * libstetic/ObjectWrapper.cs (GladeImport): update to use XML + + * libstetic/PropertyDescriptor.cs: Update for removal of + GladePropertyAttribute. Handle glade-name and glade-override xml + attributes. + + * libstetic/wrapper/objects.xml: Add glade-override="true" to + properties that should be read from/written to the wrapper rather + than the object during glade import/export. Move AutoSize from + Container to ContainerChild, where it belonged. Fix + Button.ResponseId to invisiblify correctly. Remove + palette-category="internal" since the Palette will now ignore + objects with no palette-category. Make Menu be wrapped by + Container rather than Widget, so its MenuItems will be added + correctly. + + * libstetic/wrapper/Button.cs (GladeImport, GladeExport): update + (GladeImportChild): update, and remove the GladeImportComplete + stuff, since we can do it immediately after + base.GladeImportChild() now. + (StockId): Fix so this actually works :) + + * libstetic/wrapper/ButtonBox.cs (GladeImportChild): update, + remove redundant setting of button.ResponseId. + + * libstetic/wrapper/Container.cs: make non-abstract, since Menu + uses this as its wrapper now. + (GladeImport, GladeImportChild, GladeSetInternalChild, + GladeExport, GladeExportChild): Update. In particular, Container + now handles recursing into child widgets itself, which is nice + because it means all of a widget's children are imported when its + base.GladeImport() call returns, which lets us simplify a few + places that used to need the GladeImportComplete event. + + * libstetic/wrapper/Image.cs (Wrap): Fix the case of wrapping a + Gtk.Image with no image specified + (IconSize): Remove GladePropertyAttribute + + * libstetic/wrapper/Label.cs (MnemonicWidget): make this a string, + for now at least. + + * libstetic/wrapper/OptionMenu.cs (GladeImport, etc): + * libstetic/wrapper/Table.cs (GladeImport, etc): update. Remove + GladeImportComplete hacks. + + * libstetic/wrapper/Widget.cs (GladeImport, GladeExport): Make + these work with XML. + (Visible, HasDefault, Sensitive): Remove the + GladePropertyAttribute. + + * libstetic/wrapper/Window.cs (Modal, TypeHint, Type): Remove + GladePropertyAttribute. + + * libstetic/wrapper/Bin.cs (GladeImport): + * libstetic/wrapper/ComboBox.cs (GladeImport): + * libstetic/wrapper/CheckButton.cs (GladeImportChild): + * libstetic/wrapper/Expander.cs (GladeImportChild, GladeExportChild): + * libstetic/wrapper/Frame.cs (GladeImportChild, GladeExportChild): + * libstetic/wrapper/ImageMenuItem.cs (GladeImport): + * libstetic/wrapper/Notebook.cs (GladeImportChild, GladeExportChild): + * libstetic/wrapper/MenuItem.cs (GladeImportChild): + * libstetic/wrapper/RadioButton.cs (GladeImport, GladeExport): + * libstetic/wrapper/RadioMenuItem.cs (GladeImport, GladeExport): + * libstetic/wrapper/RadioToolButton.cs (GladeImport, GladeExport): + * libstetic/wrapper/ToolButton.cs (GladeImport): update + + * libstetic/editor/FloatRange.cs: + * libstetic/editor/IntRange.cs: + * libstetic/editor/OptIntRange.cs: Make these take object args, + and substitute in a default min/max value if either is null. + + * libstetic/ClassDescriptor.cs: + * libstetic/ItemDescriptor.cs: Use SelectNodes, not + GetElementsByTagName, which is recursive. (Oops.) + + * libstetic/ParamSpec.cs (IsUnichar): add this, to test + G_IS_PARAM_SPEC_UNICHAR, since you can't otherwise distinguish + them from uint paramspecs. + + * stetic/Glade.cs: update to pass XML to libstetic, and to not + recurse (since the wrappers do it themselves now). + + * stetic/Palette.cs: ignore classes with no palette category + specified. + + * stetic/PropertyEditor.cs: merge BasicEditor and RangeEditor + together, and update for the range editor changes to handle + implicit min/max. + + * glue/paramspec.c (stetic_param_spec_is_unichar): glue for + ParamSpec.IsUnichar. + +2005-07-06 Dan Winship <danw@novell.com> + + * libstetic/DND.cs (NewWindow): + * libstetic/HandleWindow.cs (HandleWindow): update for new + studlynamed WindowAttr fields. + +2005-07-01 Dan Winship <danw@novell.com> + + * libstetic/wrapper/objects.xml: new XML description of widgets, + replacing the Register() methods and a lot of miscellaneous + property attributes. + + * libstetic/CommandAttribute.cs: + * libstetic/DescriptionAttribute.cs: + * libstetic/ObjectWrapperAttribute.cs: + * libstetic/ObjectWrapperType.cs: + * libstetic/RangeAttribute.cs: gone (replaced by XML attributes) + + * libstetic/ItemGroup.cs: construct from XML + + * libstetic/ItemDescriptor.cs: construct from XML + (EnabledFor, VisibleFor): take the widget as an argument rather + than the wrapper + + * libstetic/PropertyDescriptor.cs: construct from XML, remove + slashed property names + (GetValue, SetValue): take the widget rather than the wrapper + + * libstetic/CommandDescriptor.cs: construct from XML + (Enabled, Run): take the widget rather than the wrapper + + * libstetic/Registry.cs: New static class that handles keeping + track of ObjectWrappers and ClassDescriptors. + + * libstetic/ClassDescriptor.cs: new, describes a class. Takes on a + lot of functionality that used to be in static ObjectWrapper + methods. Also, having ItemGroups, etc stored on a ClassDescriptor + object means we don't need a ObjectWrapper subclass for each + wrapped class (unless the wrapper implements some special + functionality). + + * libstetic/ObjectWrapper.cs: Remove a lot of static methods, + which are now handled by Registry and ClassDescriptor. + + * libstetic/GladeUtils.cs: Misc updates for Registry/ObjectWrapper + changes + + * libstetic/wrapper/*.cs: remove Register() and various other + no-longer-needed things + + * libstetic/wrapper/Alignment.cs: + * libstetic/wrapper/Arrow.cs: + * libstetic/wrapper/Calendar.cs: + * libstetic/wrapper/CheckMenuItem.cs: + * libstetic/wrapper/DrawingArea.cs: + * libstetic/wrapper/Entry.cs: + * libstetic/wrapper/EventBox.cs: + * libstetic/wrapper/HBox.cs: + * libstetic/wrapper/HButtonBox.cs: + * libstetic/wrapper/HPaned.cs: + * libstetic/wrapper/HSeparator.cs: + * libstetic/wrapper/Menu.cs: + * libstetic/wrapper/MenuBar.cs: + * libstetic/wrapper/Misc.cs: + * libstetic/wrapper/ProgressBar.cs: + * libstetic/wrapper/SeparatorMenuItem.cs: + * libstetic/wrapper/SeparatorToolItem.cs: + * libstetic/wrapper/Statusbar.cs: + * libstetic/wrapper/ToggleButton.cs: + * libstetic/wrapper/TreeView.cs: + * libstetic/wrapper/VBox.cs: + * libstetic/wrapper/VButtonBox.cs: + * libstetic/wrapper/VPaned.cs: + * libstetic/wrapper/VSeparator.cs: gone; these classes don't + need any special functionality beyond what can be specified in + objects.xml. + + * stetic/Palette.cs: Use Registry.AllClasses to get the palette + contents. + + * stetic/PropertyEditor.cs: use objects directly rather than via + their wrappers (particularly since PropertyDescriptor.Get/SetValue + now work directly on the objects). + + * stetic/WidgetFactory.cs: take a ClassDescriptor instead of name, + icon, and wrapperType. + + * stetic/ContextMenu.cs: + * stetic/Project.cs: + * stetic/PropertyGrid.cs: misc updates for other changes + +2005-06-28 Raja R Harinath <rharinath@novell.com> + + Fix 'make distcheck'. + * stetic/Makefile.am (RESOURCE_FILES): Pick stetic.glade from + $(srcdir). + (stetic.exe): Prepend $(srcdir)/ to all source filenames. + (EXTRA_DIST): Add stetic.glade. Don't use $(RESOURCE_FILES). + Automake doesn't grok $(wildcard ..). + (dist-hook): New. Copy the png files here. + * libstetic/Makefile.am (libstetic.dll): Prepend $(srcdir)/ to all + source filenames. + (EXTRA_DIST): Don't list wrapper/pixmaps/*.png. + (dist-hook): New. Copy the png files here. + +2005-06-23 Dan Winship <danw@novell.com> + + * libstetic/ItemDescriptor.cs (DisabledIf): Replaces DependsOn and + DependsInverselyOn; specifies that a property is disabled if + another property has any of the listed values. (Rather than only + being able to depend on boolean values like before). + (InvisibleIf): Likewise replaces VisibleIf and InvisibleIf. + (HasVisibility): Tests if an item has any visibility constraints, + a la HasDependencies. + + * libstetic/editor/ThemedIcon.cs: new editor for selecting a + themed icon (which can be either a registered stock icon or one of + the broader set of theme-based icons). + + * libstetic/wrapper/Button.cs: Redo this using an enum to select + the type of button (Stock, Text-only, Themed icon + Label, + Icon-from-file + Label, or Custom contents). Use + ItemDescriptor.InvisibleIf to cause irrelevant fields to be + hidden. + (Register): Rework for the above, plus for the + ToggleButton/CheckButton inheritance changes below. + (ThemedIcon): Use the ThemedIcon editor to select this. + + * libstetic/wrapper/Image.cs: Handle the themed icon vs + icon-from-file distinction the same way Button does. + + * libstetic/wrapper/CheckButton.cs: inherit from Container rather + than Button, since we're mostly not like Button. + + * libstetic/wrapper/RadioButton.cs: inherit from CheckButton, not + Button. + + * libstetic/wrapper/ToggleButton.cs: Simplify because it can + inherit more behavior from Button, now that CheckButton doesn't. + + * libstetic/wrapper/Dialog.cs (AddButton): update for Button + changes + + * libstetic/wrapper/ScrolledWindow.cs (AddWithViewport): Set the + ShadowType on the Viewport to None. + + * libstetic/wrapper/Box.cs (BoxChild.Register): + * libstetic/wrapper/ButtonBox.cs (ButtonBoxChild.Register): + * libstetic/wrapper/FontButton.cs (Register): + * libstetic/wrapper/Scale.cs (Register): + * libstetic/wrapper/Table.cs (TableChild.Register): Update for + ItemDescriptor changes. + + * stetic/PropertyGrid.cs: Add logic to allow property visibility + to change on the fly, rather than being assumed to be constant for + a given object. + + * stetic/Grid.cs (OnSizeAllocated): if a widget is invisible, + don't allocate space for it. If an editor is invisible, hide its + label too. + +2005-06-12 Todd Berman <tberman@off.net> + + * libstetic/wrapper/Frame.cs: Make the frame HIG-ified by default. + * TODO: Update TODO. + +2005-06-10 Dan Winship <danw@novell.com> + + * libstetic/wrapper/Widget.cs (InsensitiveManager): new static + class to manage insensitive widgets (using a Gtk.Invisible and + InputOnly Gdk.Windows to intercept clicks on them). + (Sensitive): Inform the InsensitiveManager about the widget's + state. + + * libstetic/HandleWindow.cs: Likewise, attach the HandleWindow to + a Gtk.Invisible, so we still get events on it even if the selected + widget is insensitive. + + * TODO: Sensitive is handled properly now. + +2005-06-01 Dan Winship <danw@novell.com> + + * libstetic/wrapper/ScrolledWindow.cs (AddWithViewport): Create + and wrap the viewport first, rather than trying to wrap it after + adding it to the window, which may cause a warning trying to set + its .Events in Widget.Wrap(). + (ReplaceChild): If oldChild is in a Viewport, remove it from that + as well as removing the viewport from the scrolled window. + + * libstetic/wrapper/Container.cs (Select): connect to the + selection's "Destroyed" event (and disconnect from the old + selection's) + (SelectionDestroyed): Unselect the selection + (Delete): No longer need to do it here. (Now destroyed widgets get + properly unselected whether you delete them directly or delete one + of their ancestors.) + + * stetic/Palette.cs: Fix this to not be a subclass of + ScrolledWindow; the caller can put it in a ScrolledWindow itself + if it wants to. + + * stetic/Project.cs (Selection): don't try to unselect the + previous selection if it's been destroyed, or we'll get a warning. + + * stetic/stetic.glade: Fill in the menu contents here, set up some + signal handlers. + + * stetic/stetic-multi.glade: An alternate UI file, with multiple + windows like glade. + + * stetic/Stetic.cs (Main): update for the .glade file changes. + (Cut, Copy, Paste, Delete): currently dummy methods + (Quit): implement + (About): implement + +2005-05-27 Dan Winship <danw@novell.com> + + * libstetic/wrapper/Box.cs (DoSync, Drop): Properly handle + PackStart vs PackEnd (particularly in terms of creating all the + right drag faults). + + * libstetic/DND.cs (AddFault): add some new overloads + + * TODO: remove comments about PackStart/PackEnd + +2005-05-26 Dan Winship <danw@novell.com> + + * stetic/Stetic.cs (Main): Load the UI from a glade file rather + than hardcoding it. + + * stetic/stetic.glade: the UI, now editable in itself + + * stetic/Glade.cs: Rename this class to GladeFiles, because C#'s + namespacing rules suck. + + * stetic/Makefile.am: add stetic.glade as a resource + + * libstetic/wrapper/Container.cs (LookupParent): don't return + Unselectable wrappers + + * libstetic/wrapper/Custom.cs (Int1, Int2): Add RangeAttributes + to these so the property grid doesn't crash + + * libstetic/wrapper/Paned.cs (ReplaceChild): Make this actually + work. + + * libstetic/wrapper/ScrolledWindow.cs (ReplaceChild, + AddPlaceholder): when using a Viewport, create an (unselectable) + ObjectWrapper for it. + (RealChildren, GladeChildren): override to make the viewport show + up when glade-exporting, but not otherwise. + + * libstetic/wrapper/Viewport.cs: new, wrapper for Gtk.Viewport. + +2005-05-26 Dan Winship <danw@novell.com> + + * libstetic/GladeUtils.cs (ParseFlags, PropToString): Remove + special cases for TableChild options (now handled in Table.cs). + Use PropertyDescriptor.HasDefault. + + * libstetic/IStetic.cs (Selection): Make this a Gtk.Widget, not a + Stetic.Wrapper.Widget, so we can keep more careful track of + Placeholder selections. + + * libstetic/PropertyDescriptor.cs (HasDefault): new settable + property to say whether or not the property has a default value. + (See Scale.cs below). + + * libstetic/wrapper/Bin.cs (GladeImport): at GladeImportComplete + time, if the bin is empty, add a Placeholder. + + * libstetic/wrapper/Button.cs (GladeImport, GladeChildren): dtrt + with buttons that contain placeholders. + (FixupGladeChildren): set UseUnderline correctly. + (GladeExport): handle stock buttons correctly + + * libstetic/wrapper/ButtonBox.cs (GladeImportChild): fix the + "Help" button case. + + * libstetic/wrapper/Container.cs (LookupParent): was + Widget.ParentWrapper, but now can be used for Placeholders as + well. + (Select, UnSelect): update for selection changes + + * libstetic/wrapper/Image.cs (GladeExport): don't export the + "filename" property when it's a stock image, or the "stock" + property when it's an image file. + (UseStock, Stock, Filename): misc other fixes + + * libstetic/wrapper/OptionMenu.cs (GladeImport): juggle the Menu + at GladeImportComplete time to force a proper size request + (GladeImportChild): allow the menu to be specified as an internal + or non-internal child, since different versions of glade + apparently do different things. + + * libstetic/wrapper/Scale.cs (Register): clear HasDefault on the + DrawValue and ValuePos properties, since the ParamSpecs are + registered with the wrong default values. + + * libstetic/wrapper/Table.cs (GladeImportChild, GladeExportChild): + translate between the "normal" flag value representation + ("GTK_EXPAND|GTK_FILL") and TableChild's special representation + ("expand|fill") here rather than in GladeUtils. + + * libstetic/wrapper/Widget.cs (ParentWrapper): use + Container.LookupParent(). + (WidgetEvent): update for selection changes + (UnSelect): gone, handled by other things now + + * stetic/ContextMenu.cs: Fix (again) so that only the top level + menu has submenus. Add icons to the widget labels. + + * stetic/Glade.cs (Export): close the file when we're done. + (ExportWidget): Remove a no-longer-relevant FIXME about + Placeholders + + * stetic/Project.cs (Selection, etc): update for IStetic change to + make Selection a Gtk.Widget. Unselect the previous selection + always. (Previously Placeholders weren't unselected properly.) + + * stetic/PropertyGrid.cs: Add a "Widget Class" line (with icon) + +2005-05-24 Dan Winship <danw@novell.com> + + * libstetic/GladeUtils.cs: Fix up the parsing/unparsing to be + based on C# types rather than ParamSpec GTypes, so that it can be + used for C# wrapper properties. Update for PropertyDescriptor + GladeProperty changes. + + * libstetic/PropertyDescriptor.cs (PropertyDescriptor): Allow the + "Foo" in a "Foo/Bar" property to be a wrapper property. Copy the + ParamSpec and GladeAttribute from a property to its glade proxy. + (GladeProperty): don't return null; if the property has no + GladeProperty proxy, return the property itself. + (GladeName): don't peek into GladeProperty. (Make the caller do + it). + (GladeGetValue, GladeSetValue): gone; just use GetValue/SetValue + on the GladeProperty. + + * libstetic/RadioGroupManager.cs (GladeGroupName): return the + glade "group" property value for a radio group item. + + * libstetic/editor/GroupPicker.cs (Dispose): Changed from + OnDestroyed() to work around a gtk# refcounting bug at the moment. + + * libstetic/wrapper/Button.cs (ConstructChild): build Unselectable + wrappers for the contents, so they can be glade-serialized + correctly. + (GladeChildren): include or skip the child wrappers as + appropriate. + (HasResponseId): fix + + * libstetic/wrapper/Calendar.cs (DisplayOptions): proxies + Gtk.Calendar.DisplayOptions, with a GladeProperty attribute. + (Register): Change properties to, "DisplayOptions/ShowHeading", + etc, so that DisplayOptions is treated as the glade property. + (GladeImport): no longer needed + + * libstetic/wrapper/Container.cs (GladeChildren): new virtual + property to get a list of children for glade export purposes + + * libstetic/wrapper/Custom.cs: + s/ObjectManager.RegisterType/GType.Register/ + (Int1, Int2): make these ints now that GladeUtils can deal with + that. + + * libstetic/wrapper/MenuItem.cs (Label): store the label text + separately from the Label itself, since OptionMenu will steal the + Label of the selected MenuItem, so our Label will sometimes be + unexpectedly null. + (UseUnderline): remove glade proxy now that GladeUtils can + directly deal with the property being a bool. + + * libstetic/wrapper/OptionMenu.cs (Items, FlattenMenu): Remove. + Make the contents be a menu, not just a list of labels. + (Wrap): mark the menu wrapper with the InternalChildId "menu" + (GladeImport): don't need FlattenMenu any more, but have to set + Active property after the menu is built. + (GladeChildren): return the menu. + + * libstetic/wrapper/RadioButton.cs: + * libstetic/wrapper/RadioMenuItem.cs: + * libstetic/wrapper/RadioToolButton.cs (GladeImport): Re-set + "Active" after setting the group. + (GladeExport): Use GroupManager.GladeGroupName() to get the right + group + + * libstetic/wrapper/Widget.cs (Unselectable): new property. + (FindWrapper): skip wrappers marked Unselectable. + + * stetic/Glade.cs (ExportWidget): use GladeChildren rather than + RealChildren. + +2005-05-04 Dan Winship <danw@novell.com> + + * configure.in: require gtk-sharp 2.5 + + * libstetic/editor/GroupPicker.cs: use ComboBox.RowSeparatorFunc + to add a separator to the menu + + * libstetic/wrapper/Toolbar.cs (Tooltips): Remove; this is a real + property in gtk 2.6 + + * libstetic/wrapper/ToggleToolButton.cs (Active): Likewise + +2005-04-28 Dan Winship <danw@novell.com> + + * libstetic/GladeUtils.cs (PropToString): switch based on the type + of value, not on prop.PropertyType, since they might not match + (eg, if UseUnderlying is set). + (GetProps): skip props that aren't visible on a given wrapper + + * glue/custom.c: define the last_modification_time property to + avoid warnings on glade import + + * libstetic/wrapper/Expander.cs: + * libstetic/wrapper/Frame.cs (GladeExportChild): implement + + * libstetic/wrapper/Paned.cs: Remove MaxPosition/MinPosition from + the Pane Properties; they're not writable. + +2005-04-26 Dan Winship <danw@novell.com> + + * glue/Makefile.am (pkglib_LTLIBRARIES): install libsteticglue.la + + * libstetic/Makefile.am (pkglib_DATA): install libstetic.dll and + libstetic.dll.config + (libstetic.dll): update to non-warned-about mcs option syntax + (CLEANFILES, EXTRA_DIST): update + + * libstetic/libstetic.dll.config: remove unused mapping + + * libstetic/wrapper/pixmaps/Makefile.am: remove unused Makefile + + * stetic/Makefile.am (pkglib_DATA, bin_DATA): install stetic and + stetic.exe + (stetic.exe): update to non-warned-about mcs option syntax + (CLEANFILES, EXTRA_DIST): update + (run, trace, mdb, gdb): targets to run the uninstalled stetic.exe + + * stetic/stetic.in: redo this for installation + + * stetic/stetic.exe.config: remove this; stetic.exe doesn't + DllImport anything of its own + + * configure.in: remove unused GACUTIL checks + +2005-04-20 Dan Winship <danw@novell.com> + + * libstetic/wrapper/CheckMenuItem.cs: + * libstetic/wrapper/ImageMenuItem.cs: + * libstetic/wrapper/MenuBar.cs: + * libstetic/wrapper/MenuItem.cs: + * libstetic/wrapper/RadioMenuItem.cs: + * libstetic/wrapper/SeparatorMenuItem.cs: wrap these enough to be + able to glade-import menus, but not really well enough to be able + to edit them happily. + + * libstetic/Makefile.am (libstetic.dll): Change the rule to write + all the args out to a response file and then use that. + + * libstetic/editor/Accelerator.cs: PropertyGrid editor for + accelerators. Loosely based on EggCellRendererKeys. + + * glue/misc.c (stetic_keycode_is_modifier): for + Stetic.Editor.Accelerator + + * glue/Makefile.am (libsteticglue_la_SOURCES): add misc.c + +2005-04-19 Dan Winship <danw@novell.com> + + * libstetic/GladeUtils.cs (ParseProperty, PropToString): do the + value<->string conversion here rather than calling out to C glue. + Later on, this will let us get rid of some per-widget hacks, but + for now it just does exactly what the C code did. + + * libstetic/wrapper/Container.cs (GladeExportChild): fix the + tagging of internal-children, which has apparently been broken for + a while. + + * glue/value.c: gone + +2005-04-13 Dan Winship <danw@novell.com> + + * libstetic/wrapper/*.cs: change a bunch of fields that are only + used via reflection to be "internal" rather than "private", so + that mcs won't warn about their apparent unusedness. + + * libstetic/PropertyDescriptor.cs: remove an unused field + + * stetic/Glade.cs: remove an unused DllImport + +2005-04-11 Dan Winship <danw@novell.com> + + * libstetic/wrapper/HBox.cs: + * libstetic/wrapper/HPaned.cs: + * libstetic/wrapper/Notebook.cs: + * libstetic/wrapper/OptionMenu.cs: + * libstetic/wrapper/VBox.cs: + * libstetic/wrapper/VPaned.cs: s/.Children// + + * libstetic/wrapper/Container.cs (FindInternalChild): use + AllChildren + (RealChildren): use AllChildren. kill RealChildEnumerator. + + * libstetic/wrapper/Widget.cs (InterceptClicks, FindWrapper): use + AllChildren, kill ChildEnumerator + + * stetic/Grid.cs (ForAll): use new signature + +2005-04-11 Dan Winship <danw@novell.com> + + * glue/custom.c (custom_new): new method + + * libstetic/RadioGroupManager.cs (this[Gtk.Widget]): track the + Destroyed event on radio widgets and update everything + appropriately when a radio widget is destroyed. + + * libstetic/wrapper/Widget.cs (Delete): UnSelect when Deleting. + + * libstetic/wrapper/Container.cs (UnSelect): clear the Project + selection when unselecting. + + * libstetic/wrapper/Custom.cs (Stetic.Custom.ctor()): call + custom_new() + + * TODO: misc updates + +2005-04-07 Dan Winship <danw@novell.com> + + * glue/custom.c: + * libstetic/wrapper/Custom.cs: + * libstetic/wrapper/pixmaps/custom.png: Add custom widgets (a bit + kludgy at the moment). + + * libstetic/wrapper/Calendar.cs (GladeImport): handle "display_options" + + * libstetic/wrapper/ComboBox.cs (Items): tag this properly for + glade import/export + + * libstetic/wrapper/ScrolledWindow.cs (AddPlaceholder): override + this to add the placeholder in a viewport + + * libstetic/wrapper/Widget.cs (ParentWrapper): fix to not get into + an infinite loop on toplevel windows. + +2005-04-07 Dan Winship <danw@novell.com> + + Add Toolbar and its children, plus a bunch of things I had to fix + to get there. + + * libstetic/DND.cs (Cancel): Returns the widget that was being + dragged, after removing it from the DragWindow, so we don't get + errors when you cancel a drag. + + * libstetic/HandleWindow.cs (Dispose): disconnect from + selection.WidgetEvent. + (SelectionEvent): if the event occurred in the handle window, + always return true. Fixes the bug where widgets sometimes undrew + themselves when they were selected. + + * libstetic/ObjectWrapperAttribute.cs (ObjectWrapperType): kill + this enum + (Type): make this a string + + * libstetic/ObjectWrapperType.cs: new static class containing + constant strings for the predefined wrapper types (including the + new ToolbarItem type). + + * libstetic/Placeholder.cs (OnDragDrop): remove this; Container + can handle the event itself. + + * libstetic/PropertyDescriptor.cs: Fix this to be able to handle + the case of a subproperty of a wrapper type (eg, + ToolItem.IsImportant in Wrapper.Toolbar.ToolbarChild) + + * libstetic/RadioGroupManager.cs: Move the group-handling code + from Wrapper.RadioButton here, and genericize it to be able to + work with RadioToolButtons and RadioMenuItems as well. + + * libstetic/editor/GroupPicker.cs: update to use RadioGroupManager. + + * libstetic/wrapper/Container.cs (PlaceholderDragDrop): connect to + this directly rather than having the Placeholder proxy it to us. + (CreateDragSource): new virtual method to create a Placeholder (or + not) specifically for when dragging something out of a container + (CreatePlaceholder): update signal-handling here + (RealChildren): make this virtual + + * libstetic/wrapper/Toolbar.cs: Wrap this. + (RealChildren, ReplaceChild): Override these to handle "invisible" + ToolItem wrappers around non-ToolItem objects stuck into the + toolbar. + (DoSync, Drop): do DND autoexpanding. (At some point, we should + use the actual toolbar DND editing methods.) + (CreateDragSource, DragEnd): return a Gtk.Invisible rather than + adding a placeholder to the toolbar. + (ToolbarChild): wrap this, putting the three ToolItem properties + here, since it's where they really belong. + + * libstetic/wrapper/RadioButton.cs: port to use RadioGroupManager + + * libstetic/wrapper/Widget.cs (Wrap, InterceptClicks): recursively + set up event interception, so that widgets with internal embedded + widgets work correctly. + (ParentWrapper): Make this able to cope with non-wrapped widgets + in the hierarchy. + + * libstetic/wrapper/RadioToolButton.cs: + * libstetic/wrapper/SeparatorToolItem.cs: + * libstetic/wrapper/ToggleToolButton.cs: + * libstetic/wrapper/ToolButton.cs: Wrap + + * stetic/Palette.cs: update for ObjectWrapperType changes + +2005-04-05 Dan Winship <danw@novell.com> + + * libstetic/wrapper/Widget.cs (ToString): override + + * stetic/ContextMenu.cs (ContextMenu): Update for WidgetSite + removal; use the right context widget. Also, only include the + insensitive "name" label on the top-level menu. + +2005-04-04 Dan Winship <danw@novell.com> + + * libstetic/PropertyDescriptor.cs (GladeName): fix for proxied + properties so that MnemonicWidget works right. + + * libstetic/wrapper/Button.cs (ConstructChild): Fix so that stock + icons always UseUnderline + + * libstetic/wrapper/Container.cs (FindInternalChild): No need to + recurse upward here any more. Also, return the wrapper rather than + the child. + (GladeSetInternalChild): don't create a wrapper here, since the + widget must already have one. + (Select): add a workaround for when you select a widget that isn't + mapped. + + * libstetic/wrapper/OptionMenu.cs (Wrap): create a wrapper for the + menu. + (GladeSetInternalChild): override this, since the menu (which + glade considers to be an internal child of the optionmenu) is not + actually a real child. + + * libstetic/wrapper/Widget.cs (FindWrapper): don't find widgets + that aren't mapped. + (HasDefault, HierarchyChanged): Fix the logic here; a widget + always has a "Toplevel", it's just that the Toplevel is not always + actually a toplevel widget. + + * libstetic/wrapper/Window.cs (Select): Show() the window when it + is selected. + +2005-03-29 Dan Winship <danw@novell.com> + + * libstetic/HandleWindow.cs (SelectionEvent): simplify for gdk# + changes + + * libstetic/editor/Image.cs: Use reflection to get the list of + stock IDs rather than Gtk.Stock.ListIds, since the latter will + return 2.6-specific IDs if you have libgtk 2.6. + (Image): pack the combobox into a vbox so it won't expand + incorrectly. + + * libstetic/wrapper/ButtonBox.cs (GladeImportChild): fix + ResponseId handling. + + * libstetic/wrapper/Container.cs (Select, UnSelect): virtualize + (Delete): new method to delete a widget and replace it with a + Placeholder. + + * libstetic/wrapper/Label.cs (Label (string)): pass "true" to Wrap + so it doesn't bash the passed-in label string + + * libstetic/wrapper/Notebook.cs (GladeImportChild, InsertPage): + Remove FIXMEs. + (GladeExportChild): fix a leftover WidgetSiteism. + (Select): override this; if a tab is selected, switch to its page. + (ReplaceChild): allow tabs to be replaced, and don't muck things + up when pages get replaced + + * libstetic/wrapper/Table.cs (Sync): fix to not get caught in + infinite loops again. + + * libstetic/wrapper/Widget.cs (WidgetEvent): simply for gdk# + changes. + (FindWrapper): search all children (not just non-internal ones) + (Delete): new method to delete a widget (by calling + ParentWrapper.Delete) + + * stetic/ContextMenu.cs (DoDelete): use Wrapper.Widget.Delete() + +2005-03-29 Dan Winship <danw@novell.com> + + * libstetic/WidgetBox.cs: + * libstetic/WidgetSite.cs: GONE! + + * libstetic/Placeholder.cs: inherit from DrawingArea rather than + WidgetBox now. + (NewWindow): Gone. The DrawingArea creates the window for us now. + (Mimic, UnMimic): kill; Wrapper.Container watches out for this now + + * libstetic/HandleWindow.cs (SelectionEvent): intercept + ButtonPress and Motion events and signal to the parent container + when to start dragging. + + * libstetic/DND.cs (SourceSet, SourceUnset, SourceButtonPress, + CanDrag): Remove "non-automatic" drag sources; HandleWindow + handles that now. + (AddFault, etc): update/rename stuff for WidgetSite removal + + * libstetic/IStetic.cs (CreateWidgetSite, CreatePlaceholder): gone + (PopupContextMenu): new, to make the app pop up a context menu + (Selection): new read/write property to replace old Select() method + + * libstetic/wrapper/Widget.cs (Wrap): add ButtonPressMask to the + widget eventmask, and connect to WidgetEvent and PopupMenu + (ParentWrapper): simplify for lack of WidgetSites + (WidgetEvent): intercept button presses and walk through the + widget's children to find the deepest wrapped widget that the + click was inside (since NoWindow widgets will no longer be able to + report their own clicks). Handle selection and context menus. + + * libstetic/wrapper/Container.cs (GladeImportChild, + GladeExportChild): remove WidgetSite handling + (Add): replaces AddWidgetSite + (CreateWidgetSite, SiteButtonPress, SiteMotionNotify): gone + (CreatePlaceholder): create the Placeholder directly rather than + needing stetic.CreatePlaceholder. + (PlaceholderDrop, PlaceholderDragEnd): don't create a WidgetSite + (RealChildren): replaces Sites + (HandleWindowDrag): initiate drag and drop from here. + (ChildHExpandable, ChildVExpandable): checks the expandability of + a child (which might be a Placeholder, or not) + + * libstetic/wrapper/*.cs: Update for WidgetSite removal, and + ChildHExpandable/ChildVExpandable. + + * stetic/ContextMenu.cs (OnSelectionDone): be self-destroying + + * stetic/Glade.cs (ExportWidget): no more WidgetSites + + * stetic/Project.cs (Selection): change from method to property + (CreateWidgetSite, CreatePlaceholder): Kill + (PopupContextMenu): Implement + (AddWidget, ContentsChanged): s/foo.Sites/foo.RealChildren/ + +2005-03-28 Dan Winship <danw@novell.com> + + * libstetic/HandleWindow.cs: new class to implement selection handles. + + * libstetic/WidgetBox.cs: Remove all handle-related code + + * libstetic/IStetic.cs (Select): new, to tell the main program to + select a widget (rather than having the it listen for an event on + all toplevel windows). + + * libstetic/wrapper/Widget.cs (Select, UnSelect): tell the parent + container (if any) to select this widget + (CreateWidgetSite, CreatePlaceholder): remove these; anything that + is a container needs to be subclassing Container, not Widget. + + * libstetic/wrapper/Container.cs (CreateWidgetSite, + CreatePlaceholder): catch ButtonPressEvents + (SiteButtonPress, PlaceholderButtonPress): handle + selection/context menus + (Select, UnSelect): update handles, call stetic.Select() + + * libstetic/wrapper/Notebook.cs: FIXME out a few bits for now... + + * libstetic/wrapper/Table.cs (OnButtonPressEvent): remove this + code, which has been commented-out forever. + + * libstetic/wrapper/Window.cs (SetFocus, Select): gone; selection + is handled at the Container level now. + + * stetic/Project.cs (WindowFocusChanged): gone + (IStetic.Select): handle selection here + (SelectedHandler): change the WidgetBox arg to a Wrapper.Widget + + * stetic/ProjectView.cs (WidgetSelected): + * stetic/PropertyGrid.cs (Selected): update signature + +2005-03-24 Dan Winship <danw@novell.com> + + * libstetic/DND.cs: move the drag-and-drop "fault" code from + WidgetSite to here. Remove the DragBegin and DragEnd events since + nothing needs them any more. + + * libstetic/WidgetSite.cs (AddFault, AddVFault, AddHFault, + ClearFaults, ShowFaults, HideFaults, OnDragMotion, OnDragLeave, + OnDragDrop): all moved into DND now. + (Internal): gone; does nothing WidgetBox.Internal doesn't do now + + * libstetic/wrapper/Widget.cs (Drop): dummy virtual implementation + that just destroys the dropped widget + + * libstetic/wrapper/Box.cs (Sync): s/site/DND/ for all the fault + stuff + (Drop): override to dtrt + +2005-03-24 Dan Winship <danw@novell.com> + + More code migration out of WidgetSite + + * libstetic/DND.cs (DragWidget): public accessor for dragWidget + + * libstetic/Placeholder.cs (Mimic, UnMimic): makes a Placeholder + mimic the size and expandability of a given WidgetSite. (Replaces + the old "PseudoOccupied" mode of WidgetSite). + + * libstetic/WidgetSite.cs (Contents): killed, was redundant with + "Child". + (ShapeChanged): gone, replaced by ChildContentsChanged on + Wrapper.Container. + (Occupancy, Empty): gone. pseudo-occupancy is now handled by + Placeholder; all WidgetSites are now always actually occupied. + (OnMotionNotifyEvent, OnDragDataDelete, OnDragEnd): handled by + Wrapper.Container now + + * libstetic/wrapper/Button.cs: s/site.Contents/site.Child/ + + * libstetic/wrapper/Box.cs (DoSync): do autosizing here + (ReplaceChild): kill off the empty-placeholder-killing code for now + + * libstetic/wrapper/Container.cs (Freeze, Thaw, Sync, DoSync): + move Freeze/Thaw here from Table, change the overridable method to + "DoSync" and make Sync check frozenness and then call DoSync. + (CreateWidgetSite): Set up DND on the site and if it contains a + container, connect to its ContentsChanged method (to replace the + old WidgetSite.ShapeChanged method). + (SiteMotionNotify, PlaceholderDragEnd): handle DND. + (ChildContentsChanged): Replaces SiteShapeChanged; + + * stetic/Glade.cs: + * stetic/Project.cs: + * stetic/PropertyGrid.cs: s/site.Contents/site.Child/ + +2005-03-23 Dan Winship <danw@novell.com> + + Move IWidgetSite and WindowSite interfaces to + Stetic.Wrapper.Widget and Stetic.Wrapper.Window. + + * libstetic/wrapper/Widget.cs (Wrapped): override to return a + Gtk.Widget, to get rid of lots of typecasting + (ParentWrapper): replacement for WidgetSite.ParentSite; returns + the wrapper for the wrapped widget's parent + (InternalChildId, Select): Moved here from WidgetSite. + + * libstetic/wrapper/Window.cs (FocusChanged): moved here from + WindowSite. + (Select): override + + * libstetic/WidgetSite.cs (ParentSite): gone; replaced by + Wrapper.Widget.ParentWrapper. + (Internal): replaces InternalChildId. + (Drop): call Select on the wrapper, not the site. + (Select, UnSelect, Delete): gone + + * libstetic/IWidgetSite.cs: + * libstetic/WindowSite.cs: gone + + * libstetic/wrapper/Button.cs (HasResponseId): use ParentWrapper + rather than ParentSite. + + * libstetic/wrapper/Container.cs (GladeExportChild, + FindInternalChild): update for InternalChildId move from + WidgetSite to Wrapper.Widget. + (ChildWrapper): take a Wrapper.Widget instead of an IWidgetSite. + (PlaceholderDrop): call Select on the wrapper, not the site. + + * libstetic/wrapper/Dialog.cs (Wrap): set InternalChildId on the + wrapper, not the site. + + * stetic/ContextMenu.cs: Change all IWidgetSites to + Stetic.Wrapper.Widgets + + * stetic/Project.cs (AddWindow): take a Stetic.Wrapper.Window + rather than a WindowSite. + (ProjectNode): add a "Wrapper" field + + * stetic/ProjectView.cs (RowSelected, WidgetSelected): update to + use wrappers intead of sites. + + * stetic/Glade.cs (Import): + * stetic/WidgetFactory.cs (WindowFactory.OnButtonPressEvent): + don't need to create a WindowSite for top-level windows any more. + Just pass the wrapper to Project.AddWindow instead. + +2005-03-23 Dan Winship <danw@novell.com> + + Split apart placeholders and WidgetSites. This is an intermediate + step on the road to killing off WidgetSite, and several wrappers + are broken in this check-in because it doesn't make much sense to + fix them twice. + + * libstetic/Placeholder.cs: New subclass of WidgetBox to represent + a placeholder (which can accept drops, but can't actually hold + widgets). + + * libstetic/WidgetSite.cs: Mostly remove support for empty + WidgetSites (though not pseudo-occupied ones). + + * libstetic/WidgetBox.cs: Move some stuff here from WidgetSite + that both WidgetSite and Placeholder will need. Move out some (but + not all) stuff that they don't both need. + + * libstetic/WindowSite.cs (FocusChangedHandler, FocusChanged): + make the focus be a WidgetBox rather than an IWidgetSite + + * libstetic/CommandDescriptor.cs: + * libstetic/ItemDescriptor.cs: Update commands to take a Widget + context rather than an IWidgetSite. + + * libstetic/wrapper/Bin.cs: + * libstetic/wrapper/Box.cs: + * libstetic/wrapper/Dialog.cs: + * libstetic/wrapper/Expander.cs: + * libstetic/wrapper/Frame.cs: + * libstetic/wrapper/Notebook.cs: + * libstetic/wrapper/Paned.cs: + * libstetic/wrapper/ScrolledWindow.cs: + * libstetic/wrapper/Table.cs: + * libstetic/wrapper/Window.cs: update for site/placeholder changes + + * libstetic/wrapper/Widget.cs (CreateWidgetSite): Make this take a + widget to put in the WidgetSite. + (CreatePlaceholder): like the old CreateWidgetSite, but creates a + Placeholder. + + * libstetic/wrapper/Container.cs: update for site/placeholder + changes + (ReplaceChild): new virtual method to replace one child widget + with another + (SiteEmpty): replace the site with a placeholder + (PlaceholderDrop): replace the placeholder with a WidgetSite + containing the dropped widget. + + * libstetic/wrapper/Button.cs: update for site/placeholder changes + (Wrap): fix this so we don't get blank buttons + (ConstructChild): fix this to work around a maybe-bug in gtk + 2.4.12 and earlier. + + * stetic/*.cs: Misc updates for WidgetSite/Placeholder changes + +2005-03-21 Dan Winship <danw@novell.com> + + * libstetic/wrapper/Button.cs: Remove "UseStock" property and just + use a Stetic.Editor.Image to select either a stock icon or a file. + Also allow stock icon (or file) with non-stock label. + (GladeImportChild, FixupGladeChildren): import correctly + + * libstetic/wrapper/ToggleButton.cs: likewise + + * libstetic/wrapper/Dialog.cs (AddButton): update for Button changes + + * libstetic/wrapper/Image.cs (File): This is equivalent to the + GladeProperty "pixbuf". + + * libstetic/editor/Image.cs: fixes + + * libstetic/GladeUtils.cs (ParseGladeProperty): don't try to parse + string properties, since they don't need to be (and might not + correspond to underlying properties anyway). + +2005-03-21 Dan Winship <danw@novell.com> + + * glue/paramspec.c: + * libstetic/ParamSpec.cs: Simplify based on the latest version of + the patch in #70061. + + * libstetic/ParamFlags.cs: gone; we never used this + + * libstetic/libstetic.dll.config: add libgtk to the map + +2005-03-18 Dan Winship <danw@novell.com> + + * libstetic/editor/Image.cs: editor that allows selecting a stock + image or a file + + * libstetic/editor/ImageFile.cs: subclass of Stetic.Editor.Image + that only allows picking a file + + * libstetic/editor/StockItem.cs: now a subclass of Image + + * libstetic/editor/File.cs: gone + + * libstetic/wrapper/Image.cs: Use ImageFile editor and fix things + up a bit. + + * libstetic/wrapper/Window.cs (Icon): wrap, using the ImageFile editor + +2005-03-17 Dan Winship <danw@novell.com> + + * libstetic/WidgetBox.cs (Internal): new property saying that the + box represents an internal object. + (ShapeHandles): if the box is Internal, don't add corner handles. + + * libstetic/WidgetSite.cs (InternalChildId): set the "Internal" + property according to whether or not the child id is null, and + call DND.SourceUnset if marking something internal, so it can't be + dragged anywhere. + + * libstetic/DND.cs (SourceUnset): new. + (SourceButtonPress, CanDrag): make sure that CanDrag always + returns false if the widget isn't a source. + + * stetic/ContextMenu.cs (ContextMenu): disable Cut and Delete on + "Internal" widgetsites. + + * libstetic/ItemDescriptor.cs (VisibleIf, InvisibleIf): mark a + property visible if/unless another property is set + (VisibleFor): Check if the property should be visible on a given + object. + + * stetic/PropertyGrid.cs (AppendProperty): skip properties that + shouldn't be visible on this wrapper. + + * libstetic/wrapper/Button.cs (Register): add a "ResponseId" + property, and a "HasResponseId" property saying whether or not it + should be visible. + (HasResponseId): Check if the button's site's parentsite has an + InternalChildId of "action_area" + + * libstetic/editor/ResponseId.cs: ComboBoxEntry for dialog button + Response IDs. + + * libstetic/wrapper/Dialog.cs (Register): add Buttons and + HelpButton properties. + (Wrap): set HasSeparator false. Give the internal children sane + names. Create a button by default. + (Buttons): Allow the user to pick default buttons via a menu + (HelpButton): Toggle a "Help" button on/off. + + * libstetic/wrapper/Box.cs: Fix some minor autoexpand problems, + make it work right with buttonboxes. + + * libstetic/wrapper/Widget.cs (HasDefault): instead of marking + this "LateImport", if it's set when the widget doesn't have a + Toplevel, connect to "HierarchyChanged". (That way things other + than glade import can set it at inappropriate times as well.) + +2005-03-15 Dan Winship <danw@novell.com> + + * libstetic/editor/StockItem.cs: fix sorting again. (ignore "_") + + * libstetic/wrapper/CheckButton.cs: + * libstetic/wrapper/Entry.cs: + * libstetic/wrapper/ProgressBar.cs: + * libstetic/wrapper/RadioButton.cs: + * libstetic/wrapper/Statusbar.cs: mark HExpandable + + * libstetic/wrapper/DrawingArea.cs: + * libstetic/wrapper/TextView.cs: + * libstetic/wrapper/TreeView.cs: mark HExpandable and VExpandable + +2005-03-15 Dan Winship <danw@novell.com> + + * libstetic/WidgetSite.cs (AddFault, AddHFault, AddVFault): Make + AddHFault and AddVFault take WidgetSites rather than coordinates, + and provide AddFault for fully-generic fault adding. For AddHFault + and AddVFault, make the fault windows fill the entire space + between the two widgets (or from the widget to the edge of its + parent) if the widgets are spread apart. + (OnDragMotion): Center the splitter inside its fault since the + fault may be very large now. + + * libstetic/wrapper/Box.cs (Sync): update for that + + * stetic/Project.cs (ContentsChanged): fix a crash when dragging a + widget from one position to another within the same container + +2005-03-14 Dan Winship <danw@novell.com> + + * libstetic/WidgetSite.cs (FindFault): fix another autoexpand + buglet + (Drop): fix the focus in the autoexpand case + + * libstetic/editor/StockItem.cs: sort the buttons by their Label, + not their StockId + + * libstetic/wrapper/Box.cs (Wrap): Add 2 children to start out, + rather than 3. + (SiteOccupancyChanged): If a site is emptied, destroy it rather + than leaving an empty site behind (since you can still drag a new + widget there even without the empty site). + +2005-03-14 Dan Winship <danw@novell.com> + + * libstetic/WidgetSite.cs: Make OccupancyChanged mean only + "Occupancy changed", and add a new ShapeChanged event for when + something else happens that may affect AutoSizing in its parent. + (ToString): override this for debug purposes + + * libstetic/wrapper/Container.cs (CreateWidgetSite, SiteRemoved): + connect to/disconnect from ShapeChanged + (SiteShapeChanged): new virtual method + (SiteRemoved): call EmitContentsChanged() + + * libstetic/wrapper/Box.cs (InsertBefore, InsertAfter, DropOn): + call EmitContentsChanged() + (SiteShapeChanged): connect to this, not OccupancyChanged + + * libstetic/wrapper/Expander.cs: don't EmitContentsChanged when + toggling the expander, make HExpandable/VExpandable not depend on + whether or not the expander is expanded. + + * libstetic/wrapper/Table.cs (Sync): EmitContentsChanged() iff we + added sites. + (SiteShapeChanged): connect to this, not OccupancyChanged + + * stetic/Project.cs (AddWindow): take a WindowSite rather than a + Window, and connect to its FocusChanged event + (AddWidget): connect to the widget's Destroyed event + (WidgetDestroyed): remove the widget from the tree + (ContentsChanged): simplify using new gtk# api + (Selected): new event, emitted from the WindowSite.FocusChanged + handler + + * stetic/ProjectView.cs (ProjectView): connect to the project's + "Selected" event. + (RowSelected): if not already syncing, grab the selection on the + widget corresponding to the row. + (WidgetSelected): if not already syncing, move the table selection + to the selected widget. + + * stetic/Stetic.cs: pass Project to the PropertyGrid. + (Select, NoSelection): gone; the PropertyGrid snoops the Project + directly now. + + * stetic/Glade.cs (Import): + * stetic/WidgetFactory.cs (WindowFactory): remove focus-handling + code; Project.AddWindow will deal with it now + + * stetic/PropertyGrid.cs (PropertyGrid): take a Project and + connect to its Selected event and set the selection directly from + that. + +2005-03-11 Dan Winship <danw@novell.com> + + First draft of Glade export. + + * libstetic/GladeException.cs: simplify/fix + + * libstetic/GladePropertyAttribute.cs: add "UseUnderlying", to + specify that export should use the underlying GObject property + rather than the stetic wrapper's version. + + * libstetic/GladeUtils.cs (ExtractWrapperProperty): don't extract + properties with the "UseUnderlying" flag set. + (ParseGladeProperty): deal with the various new kinds of + PropertyDescriptor confusion. + (ExportWidget): base glade export method + (GetProps): utility method to fill in a Hashtable from a wrapper + + * libstetic/ItemGroup.cs (ItemGroup): deal with '/'s in property + names. + + * libstetic/ObjectWrapper.cs (WrappedType, NativeTypeName): make + these public so GladeUtils can use them. + + * libstetic/ParamSpec.cs (ValueType, OwnerType): fix the return + type + + * libstetic/PropertyDescriptor.cs (PropertyDescriptor): Allow + property names to have '/'s like "XOptions/XExpand", meaning that + the real property is XOptions, but it's being split up into other + properties (including XExpand) in stetic. For split properties + like that, and sub-properties like "Adjustment.Value", create a + PropertyDescriptor representing the intermediate property too. + (GladeProperty): returns the PropertyDescriptor to use for glade + export (when that's not the same as the PropertyDescriptor itself) + (GladeGetValue, GladeSetValue): renamed to not have "proxy" in the + name. Handle all getting/setting of properties for glade. + + * libstetic/SiteContentEnumerator.cs: gone; + Stetic.Wrapper.Container.Sites handles this by itself now. + + * libstetic/WidgetSite.cs (InternalChildId): property to mark a + WidgetSite as containing an "internal child" of the widget. + + * glue/value.c: reorg a bunch + (stetic_g_value_child_property_to_string, + stetic_g_value_property_to_string, stetic_g_value_to_string): new + functions for glade export + + * libstetic/wrapper/Widget.cs (GladeExport): implement + + * libstetic/wrapper/Container.cs (GladeExportChild): implement + (FindInternalChild): make this less gross by expecting the + container's wrapper class to have set the InternalChildId on the + relevant WidgetSite. + (Sites): use Gtk.Container.Forall so that internal sites get + returned too. + + * libstetic/wrapper/Button.cs (Label): set UseUnderlying + + * libstetic/wrapper/Dialog.cs (Wrap): set InternalChildId on the + internal children. + + * libstetic/wrapper/Image.cs (IconSize): set UseUnderlying + + * libstetic/wrapper/Notebook.cs (GladeExportChild): do the inverse + of the GladeImportChild hackery to represent notebook tabs + correctly. + + * libstetic/wrapper/RadioButton.cs (GladeExport): fake the "group" + property. + + * libstetic/wrapper/Table.cs (TableChild): rewrite the property + names as, eg, "XOptions/XExpand", so they will be exported + correctly. + + * stetic/Glade.cs (Export): Implement + + * stetic/Project.cs (AddWidget, ContentsChanged): Use + Stetic.Wrapper.Container.Sites directly rather than using + SiteContentEnumerator. + (Toplevels): add an enumerator exposing this, for Glade.Export + + * stetic/PropertyEditor.cs: Fix for PropertyDescriptor changes + + * stetic/Stetic.cs: add an "Export" command to the menu. + +2005-03-11 Dan Winship <danw@novell.com> + + * libstetic/ObjectWrapper.cs (Register, Create): if the wrapper + type doesn't have a CreateInstance method and the wrapped type + doesn't have a no-arg constructor, use g_object_new and the IntPtr + constructor. + + * libstetic/wrapper/Alignment.cs: + * libstetic/wrapper/Arrow.cs: + * libstetic/wrapper/HBox.cs: + * libstetic/wrapper/RadioButton.cs: + * libstetic/wrapper/VBox.cs: + * libstetic/wrapper/Window.cs: remove no-longer-necessary + CreateInstance methods + +2005-03-08 Dan Winship <danw@novell.com> + + * libstetic/GladePropertyAttribute.cs: new attribute to mark + properties that need special treatment for glade import/export (to + allow us to do the special treatment automatically rather than + needing custom GladeImport/GladeExport routines). + (GladeProperty): flags type for GladePropertyAttribute. Currently + defines Proxied (meaning that an alternate property is actually + used for glade import/export) and LateImport (meaning that on + import, the property shouldn't be set until the import has + completed). + + * libstetic/PropertyDescriptor.cs: track glade-related info + (GladeFlags, GladeName): new accessors + (GladeProxyGetValue, GladeProxySetValue): getter/setter for glade + proxy properties + + * libstetic/GladeUtils.cs (ImportWidget): replace CreateWidget and + SetProps with two new ImportWidget methods that also handle + [GladeProperty] properties. + + * libstetic/ObjectWrapper.cs (GladeImport): if the GladeImport + invocation throws a TargetInvocationException, throw its + InnerException (presumably a GladeException) up to the caller. + + * libstetic/wrapper/ComboBox.cs (Items): add + GladePropertyAttribute noting that this is glade's "items" + property. + (GladeImport): simplify + + * libstetic/wrapper/Container.cs (GladeSetInternalChild): update. + + * libstetic/wrapper/Entry.cs (InvisibleChar): add this, with a + GladePropertyAttribute marking GladeInvisibleChar as its proxy + (GladeInvisibleChar): get/set InvisibleChar as a string + (GladeImport): gone + + * libstetic/wrapper/Label.cs (MnemonicWidget): add this, with a + GladePropertyAttribute marking GladeMnemonicWidget as its + LateImport proxy + (GladeMnemonicWidget): get/set MnemonicWidget as a string + (GladeImport): gone + + * libstetic/wrapper/TextView.cs (Text): add a + GladePropertyAttribute noting that this is glade's "text" + property. + (GladeImport): gone + + * libstetic/wrapper/Widget.cs (Visible, HasDefault): add + GladePropertyAttributes. (HasDefault is LateImport) + (GladeImport): simplified + + * libstetic/wrapper/Window.cs (Modal, TypeHint, Type): add + GladePropertyAttributes + (GladeImport): gone + +2005-03-08 Dan Winship <danw@novell.com> + + * libstetic/WidgetSite.cs (SetupFaults): Pass "false" to DND.DestSet, + not true, so that the whole widget isn't drop-on-able. + (AddHFault, AddVFault): don't create windows if we're not realized. + + * libstetic/wrapper/Box.cs (Wrap): call box_ParentSet from here so + that the DropOn handler will be set up if the Parent is already + set when it's wrapped (ie, if it's an internal child) + +2005-03-08 Dan Winship <danw@novell.com> + + * libstetic/GladeException.cs: exception class for Glade import problems + + * libstetic/GladeUtils.cs: + * libstetic/ObjectWrapper.cs: + * libstetic/wrapper/Container.cs: use GladeException + + * libstetic/GladeUtils.cs (Hydrate): Call g_type_class_ref() and + pass the GObjectClass* to the glue methods rather than the GType* + (to save a bunch of lookups). + + * glue/value.c (stetic_g_value_init_for_property, + stetic_g_value_init_for_child_property): Update for that + + * stetic/Glade.cs: renamed from GladeImport.cs + (Import): renamed from Load. Use GladeException. + + * libstetic/wrapper/Box.cs (Sync): Fix to not crash on empty boxes + +2005-03-08 Dan Winship <danw@novell.com> + + * libstetic/GladeUtils.cs (ExtractProperty, CreateWidget, + SetProps, SetPacking): Make these all take a Hashtable of + propname->value rather than a pair of ArrayLists. + + * libstetic/ObjectWrapper.cs (Wrap): make this public + (GladeImport): take a Hashtable rather than ArrayLists + + * libstetic/wrapper/*.cs: + * stetic/GladeImport.cs: update for those + +2005-03-03 Todd Berman <tberman@off.net> + + * stetic/Stetic.cs: Add a ShadowType.In to the widget TreeView. + +2005-03-03 Dan Winship <danw@novell.com> + + * libstetic/DND.cs: static class to handle various + drag-and-drop-related stuff, so WidgetFactory doesn't need to + subclass WidgetSite, which is nice since they're not really very + related. + (SourceSet): wrapper for Gtk.Drag.SourceSet that can also set up + drag tracking for widgets that can't use SourceSet. + (DestSet, DestUnset): more wrappers + (CanDrag): for non automatic sources, checks if a + MotionNotifyEvent counts as a drag start + (Drag): starts a drag + (Drop): receives the dropped widget + (DragBegin, DragEnd): moved here from IStetic + + * libstetic/WidgetSite.cs: remove static DND-related fields + (various): use DND methods rather than Gtk.Drag or IStetic ones + (OnButtonPressEvent): don't need to track click locations any + more; DND does it. + (OnMotionNotify): use DND.CanDrag and DND.Drag + (OnDragDrop): use DND.Drop + (OnDropEnd): don't need to call DragEnded() from here any more; + DND does it. + + * libstetic/IStetic.cs: + * stetic/Project.cs: kill off the dnd-related events; they're on + DND now. + + * stetic/WidgetFactory.cs: now a subclass of EventBox + (ctor): set AboveChild, call DND.SourceSet + (OnDragBegin): Call DND.Drag + (Drop): dead code since WidgetFactory isn't a drag destination any more. + +2005-03-02 Dan Winship <danw@novell.com> + + "Autoexpand" for boxes (but not yet tables, and not 100% right + yet.) + + * libstetic/WidgetSite.cs (AddHFault, AddVFault): allow the site + occupant to add "fault lines" inside the widget where it can split + apart to fit additional widgets + (ShowFaults, HideFaults): connected to the IStetic's DragBegin and + DragEnd signals, to show/hide the (invisible) fault line windows + as needed. + (OnDragMotion): if the user drags into a fault line, draw a + splitter. + (OnDragDrop): if the user dropped onto a fault line, emit the + "DropOn" event to let the child handle placing the widget. + + * libstetic/WidgetBox.cs (NewWindow): make this protected so + WidgetSite can use it + + * libstetic/IStetic.cs (DragBegin, DragEnd): new events, to + indicate that something somewhere is being dragged + + * libstetic/wrapper/Container.cs (Sync): make this a virtual + method on Container + (ContainerChild.EmitNotify): Sync the parent + + * libstetic/wrapper/Box.cs (Wrap): connect to the box's + SizeAllocated and ParentSet handlers + (Sync): add fault lines + (box_ParentSet): connect to the parent site's DropOn event + (box_SizeAllocated): Sync() + (DropOn): Insert the child in the right place + + * libstetic/wrapper/Table.cs (Sync): add "override" + (TableChild.EmitNotify): don't need to call Sync from here; + Container does it + + * stetic/Project.cs: implement the new IStetic bits + + * stetic/WidgetFactory.cs (ctor): pass the project (IStetic) to + the WidgetSite ctor + (Drop): override this to get rid of the warning message when you + drag something from the palette but then cancel the drag + + * TODO: update + +2005-02-28 Dan Winship <danw@novell.com> + + * libstetic/GladeUtils.cs (HydrateProperties): Handle "adjustment" + properties, which glade serializes as 6 doubles separated by + spaces. + + * libstetic/WidgetSite.cs (Selected): new event + (Focus): emit it + + * libstetic/wrapper/ComboBox.cs (GladeImport): use CreateInstance + rather than calling down to base.GladeImport, so that we end up + with a text-only combobox. Handle the "items" property. + (Items): ignore trailing newlines + + * libstetic/wrapper/Dialog.cs (Wrap): Put WidgetSites around the + VBox and ActionArea. + + * libstetic/wrapper/Container.cs (FindInternalChild): make this a + little more complicated (read: grosser) to deal with the extra + WidgetSites inside a Dialog now. + + * libstetic/wrapper/Expander.cs (GladeImport): Do the same label + widget hack as in Notebook and Frame + + * libstetic/wrapper/Image.cs: if filename is "", use a "broken + image" image. + + * libstetic/wrapper/Label.cs: add a new ctor that takes a string + and constructs a label with that string, and a wrapper around the + label. + + * libstetic/wrapper/Notebook.cs: connect to the Selected event + on the label WidgetSites, and switch pages when a label is + selected. + (InsertPage): use the new Stetic.Wrapper.Label ctor + + * libstetic/wrapper/OptionMenu.cs (Wrap): if the optionmenu has no + Menu, create one here rather than in FlattenMenu. + + * libstetic/wrapper/Table.cs (GladeImportChild): if x_options or + y_options is unspecified, consider it to be "expand|fill", which + is glade's default value. + (SiteOccupancyChanged): don't adjust the cell's packing unless it + is set to AutoSize. + + * libstetic/wrapper/Window.cs (Type): make this a shadow prop too + +2005-02-28 Dan Winship <danw@novell.com> + + * libstetic/ObjectWrapperAttribute.cs: add a "Deprecated" flag + + * libstetic/wrapper/OptionMenu.cs: New, wrap Gtk.OptionMenu, but + mark it with the "Deprecated" ObjectWrapperAttribute flag. Also, + since we don't have a menu editor yet, we just wrap it the same + way as ComboBox, with a multiline text entry to specify the menu + items. + + * libstetic/wrapper/Menu.cs: + * libstetic/wrapper/MenuItem.cs: Wrap these just enough for + importing OptionMenus from glade + + * libstetic/wrapper/Container.cs (GladeImportChild): if the + container does not accept arbitrary GtkWidget children (according + to Gtk.Container.ChildType()), then don't interpose a WidgetSite + between parent and child. + + * stetic/Palette.cs (AddWidget): skip widgets with "Deprecated" + set on their ObjectWrapperAttribute. (Meaning that for now, they + can be imported, but not created by hand.) + +2005-02-27 Dan Winship <danw@novell.com> + + * libstetic/GladeUtils.cs (ExtractProperty): utility to remove a + property from the propNames/propVals lists. + (HydrateProperties): add some debug messages here + + * libstetic/wrapper/Label.cs (GladeImport): simplify using + ExtractProperty + + * libstetic/wrapper/RadioButton.cs (GladeImport): handle "group" + + * libstetic/wrapper/Table.cs (GladeImport): force a Sync after + import + (Sync): don't knock out conflicting sites if they're full (which + will happen temporarily during glade import, since table.Add(foo) + will always put it at 0,0). + + * libstetic/wrapper/TextView.cs (GladeImport): handle "text" + + * libstetic/wrapper/Widget.cs (GladeImport): extract "visible" and + "has_default"; fake out "visible", hold off on setting + "has_default" until the import is complete (since it requires a + parent window). + + * libstetic/wrapper/Window.cs (Wrap): force TypeHint to "Normal" + so the WM doesn't do annoying things to us + (GladeImport): extract "modal" and "type_hint" + (TypeHint): add a shadow property for this + + * stetic/GladeImport.cs (CreateWidget, AddChildren): merge these + together and reduce redundant code. + +2005-02-25 Dan Winship <danw@novell.com> + + Reorganize the glade import code; put all the wacky exceptions + into the wrapper classes rather than adding more and more to + GladeImport itself. + + * libstetic/ObjectWrapper.cs (GladeImport): static method to find + the wrapper type for a given class name and create a wrapper and + object based on glade data. + (Create): add a new overload using a className rather than a Type. + + * libstetic/IStetic.cs: add GladeImportComplete event and + LookupWidgetById method. + + * libstetic/GladeUtils.cs: utilities for GladeImport, etc + + * libstetic/wrapper/Widget.cs (GladeImport): virtual method to + create widget from a glade description. + + * libstetic/wrapper/Container.cs (GladeImportChild): virtual + method to add and pack a child widget from a glade file. + (AddPlaceholder): virtual method to add a placeholder + (GladeSetInternalChild): virtual method to set properties on an + internal child + + * libstetic/wrapper/ButtonBox.cs (GladeImportChild): remove + "response_id" from the child's properties, and set the "secondary" + packing flag if the response_id is ResponseType.Help. This is not + a complete fix; we need to get the response_id back to the parent + Dialog somehow. + + * libstetic/wrapper/Entry.cs (GladeImport): Handle the + "invisible_char" property. + + * libstetic/wrapper/Frame.cs (GladeImportChild): handle the + special "label_item" child. + + * libstetic/wrapper/Label.cs (GladeImport): Handle the + "mnemonic_widget" property. + + * libstetic/wrapper/Notebook.cs (GladeImportChild): handle the + special "tab" child. (This is the only "new" exception so far; all + the others were previously handled in GladeImport.) + + * stetic/Project.cs (LookupWidgetById, GladeImportComplete): + implement. + + * stetic/GladeImport.cs: lots of code moved from here into + GladeUtils, ObjectWrapper, and various wrapper classes. + +2005-02-25 Dan Winship <danw@novell.com> + + * libstetic/wrapper/Table.cs: + * libstetic/wrapper/Container.cs: move the "AutoSize" child + property from Table/TableChild to Container/ContainerChild. Also, + fix the previous fix. + + * libstetic/wrapper/Box.cs: Add AutoSize child property and update + the SiteOccupancyChanged logic accordingly. Also remove the weird + code with the FIXME there, since I can't reproduce the bug anyway, + so either it's fixed or Todd's going to have to debug it himself. + +2005-02-25 Dan Winship <danw@novell.com> + + * libstetic/ObjectWrapper.cs (Register): Fix the no-CreateInstance + case to use the *wrapped* type's ctor, not the wrapper type. + + * libstetic/wrapper/Container.cs (Register): Make types whose + containerchild types are declared by a superclass work again. + +2005-02-25 Dan Winship <danw@novell.com> + + * libstetic/wrapper/Icon.cs: + * libstetic/wrapper/Image.cs: Merge these two together, with a + bool property to switch between stock icon and pixmap behavior. + It's too messy to have two GtkImage wrappers. + + * libstetic/ObjectWrapper.cs (Register, WrapperType): Simplify the + logic here for 1-1 mapping between gtk and stetic types. + + * stetic/GladeImport.cs: Likewise + +2005-02-25 Dan Winship <danw@novell.com> + + * stetic/Project.cs: implement IStetic + + * stetic/GladeImport.cs: pass the Project down into CreateWidget + and AddChildren so they can eventually pass it to + ObjectWrapper.Create as an IStetic. One more FIXME down. + + * stetic/Palette.cs: take a Project at construct time and pass it + on to WidgetFactories + + * stetic/WidgetFactory.cs: take a Project at construct time and + pass that to new wrappers rather than implementing IStetic here. + + * stetic/Stetic.cs: pass Project to the Palette + + * libstetic/ObjectWrapper.cs (Create): swap the order of the + arguments + + * libstetic/wrapper/Container.cs (ChildWrapper): update for + ObjectWrapper.Create change + +2005-02-24 Dan Winship <danw@novell.com> + + * libstetic/ObjectWrapper.cs: remove the protected (IStetic, + object) constructor and replace it with a virtual Wrap method. + (Register): new method to register a wrapper type + (Create): new method to create a wrapper of a given type (with + either a provided widget or a fresh one). + (AddItemGroup): replaces RegisterWrapper. Adds a single ItemGroup + to the type. + (AddContextMenuItems): replaces RegisterContextMenu + + * libstetic/ObjectWrapperAttribute.cs: remove the WrappedType + again; it's now a static property on the wrapper. + + * libstetic/ItemGroup.cs (ItemGroup): fix this to not lose if + passed a wrapperType and a dotted property + + * libstetic/wrapper/*.cs: update for the NWO: + * ObjectWrapperAttribute only takes 3 args again + * Add static WrappedType property to all wrappers + * Add static CreateInstance method to all wrappers that + need to do more than just "new Gtk.Foo ()" + * Replace static ctor with static Register method + using AddItemGroup/AddContextMenuItems + * Replace instance ctors with a Wrap override + + * stetic/GladeImport.cs: + * stetic/Palette.cs: + * stetic/PropertyGrid.cs: + * stetic/WidgetFactory.cs: Update to match ObjectWrapper changes + +2005-02-24 Dan Winship <danw@novell.com> + + * libstetic/wrapper/Dialog.cs: + * libstetic/wrapper/Window.cs (Modal): wrap this and don't set the + underlying window property + + * libstetic/wrapper/Widget.cs (Visible): wrap this property and + don't set the underlying widget property for Window subclasses. + + * stetic/GladeImport.cs (Load): set doc.PreserveWhitespace so that + things like '<property name="label"> </property>' (which is + used to indent HIG-style frames) import correctly. Don't crash if + CreateWidget returns null. + (CreateWidget): Add some debug messages, prevent a g_warning if + the glade file uses types we don't wrap. + (AddChildren): Add a hack to make "Help" buttons be packed with + the "secondary" property in ButtonBoxes, the same as glade does. + (HydrateProperties): Don't need to filter out Window.Visible any + more. + +2005-02-22 Dan Winship <danw@novell.com> + + * stetic/PropertyGrid.cs: Kill ChildPropertyGrid and make the + child properties appear as just another property group in the main + Properties window. + + * stetic/Stetic.cs (Main): clean this up a little, and reorganize + (palette on the left, project + properties on the right). Also + update for PropertyGrid changes. + + * stetic/Palette.cs: fix up code style, make "Widgets" appear + before "Containers", remove some commented out code + +2005-02-22 Everaldo Canuto <everaldo_canuto@yahoo.com.br> + + * stetic/Palette.cs: New palette GUI. + +2005-02-22 Todd Berman <tberman@off.net> + + * libstetic/wrapper/Button.cs: + * libstetic/wrapper/ToggleButton.cs: + * libstetic/wrapper/VScale.cs: + * libstetic/wrapper/Label.cs: + * libstetic/wrapper/TextView.cs: + * libstetic/wrapper/Container.cs: + * libstetic/wrapper/Widget.cs: + * libstetic/wrapper/VSeparator.cs: + * libstetic/wrapper/Paned.cs: + * libstetic/wrapper/Icon.cs: + * libstetic/wrapper/Box.cs: + * libstetic/wrapper/ProgressBar.cs: + * libstetic/wrapper/RadioButton.cs: + * libstetic/wrapper/ComboBoxEntry.cs: + * libstetic/wrapper/EventBox.cs: + * libstetic/wrapper/Frame.cs: + * libstetic/wrapper/HPaned.cs: + * libstetic/wrapper/ScrolledWindow.cs: + * libstetic/wrapper/HBox.cs: + * libstetic/wrapper/SpinButton.cs: + * libstetic/wrapper/Window.cs: + * libstetic/wrapper/ComboBox.cs: + * libstetic/wrapper/ColorButton.cs: + * libstetic/wrapper/VPaned.cs: + * libstetic/wrapper/Alignment.cs: + * libstetic/wrapper/VBox.cs: + * libstetic/wrapper/Notebook.cs: + * libstetic/wrapper/Image.cs: + * libstetic/wrapper/ButtonBox.cs: + * libstetic/wrapper/DrawingArea.cs: + * libstetic/wrapper/Scale.cs: + * libstetic/wrapper/Table.cs: + * libstetic/wrapper/Arrow.cs: + * libstetic/wrapper/TreeView.cs: + * libstetic/wrapper/Misc.cs: + * libstetic/wrapper/HScrollbar.cs: + * libstetic/wrapper/HButtonBox.cs: + * libstetic/wrapper/Range.cs: + * libstetic/wrapper/HScale.cs: + * libstetic/wrapper/Dialog.cs: + * libstetic/wrapper/Entry.cs: + * libstetic/wrapper/FontButton.cs: + * libstetic/wrapper/MessageDialog.cs: + * libstetic/wrapper/Expander.cs: + * libstetic/wrapper/HSeparator.cs: + * libstetic/wrapper/Bin.cs: + * libstetic/wrapper/Statusbar.cs: + * libstetic/wrapper/Calendar.cs: + * libstetic/wrapper/CheckButton.cs: + * libstetic/wrapper/VScrollbar.cs: + * libstetic/wrapper/VButtonBox.cs: + + Move to a 3 param'd ctor, to provide initialized information + Add a Site property in Bin. + Add a 4th parameter to the ObjectWrapperAttributes to show which + gtk# type is wrapped. + Dummy TreeView wrapper. + + * libstetic/ObjectWrapperAttribute.cs: New parameter to show which + gtk# type is wrapped. + + * libstetic/Makefile.am: Add wrapper/TreeView.cs + + * libstetic/ObjectWrapper.cs: Add LookupWrappedTypes, to return a + Type[] of the Stetic.Wrapper.* classes that wrap a given gtk# type. + + * TODO: Update. + + * stetic/WidgetFactory.cs: Make sure to hit wrappedObject.GType so + that GObject stuff is properly initialized. + + * stetic/Stetic.cs: Change the GUI around a bit. + + * stetic/Palette.cs: New palette GUI. + + * stetic/Makefile.am: Add GladeImport.cs. + + * stetic/Project.cs: Add Project.Clear (); + + * stetic/GladeImport.cs: New file, used to provide glade file + importation. + + * glue/Makefile.am: Add value.c + * glue/value.c: New glue file to help with interacting with GValues, + and used in the GladeImport process. + +2005-02-22 Dan Winship <danw@novell.com> + + * TODO: New + +2005-02-22 Everaldo Canuto <everaldo_canuto@yahoo.com.br> + + * libstetic/wrapper/pixmaps/alignment.png: new icon converted fron xpm. + * libstetic/wrapper/pixmaps/eventbox.png: new icon converted fron xpm. + * libstetic/wrapper/pixmaps/progressbar.png: new icon converted fron xpm. + * libstetic/wrapper/pixmaps/statusbar.png: new icon converted fron xpm. + +2005-02-19 Dan Winship <danw@novell.com> + + * libstetic/WidgetBox.cs (PopupContextMenu): new event to mean + "pop up a context menu for some reason", which could be because of + a keypress or button press in either the widgetbox itself or its + child. + (InterceptButtonPress, OnButtonPressEvent): Handle this stuff here + rather than passing it off to WidgetSite. + + * stetic/WidgetSite.cs: + * libstetic/WidgetSite.cs: move stetic/WidgetSite.cs to libstetic, + minus the very very small amount that depended on other things in + stetic/. + + * libstetic/WindowSite.cs: split this out of WidgetSite.cs + + * stetic/WidgetFactory.cs (CreateWidgetSite): connect to the + site's PopupContextMenu event. + +2005-02-18 Dan Winship <danw@novell.com> + + * libstetic/TranslatableAttribute.cs: new attribute to mark a + string property of an attribute as being translatable. + + * libstetic/ObjectWrapperAttribute.cs (Name): add + TranslatableAttribute to this property + + * libstetic/CommandAttribute.cs: add a Description field, and mark + the Label and Description as Translatable. + + * libstetic/CommandDescriptor.cs: extract description from + CommandAttribute and make it available via the Description field + + * libstetic/DescriptionAttribute.cs: new attribute to give a + translatable label and description for a property. + + * libstetic/PropertyDescriptor.cs: extract label and description + info from ParamSpecs or DescriptionAttributes, and make them + available via the Label and Description fields + + * libstetic/wrapper/Box.cs: + * libstetic/wrapper/Button.cs: + * libstetic/wrapper/ComboBox.cs: + * libstetic/wrapper/Icon.cs: + * libstetic/wrapper/MessageDialog.cs: + * libstetic/wrapper/Notebook.cs: + * libstetic/wrapper/RadioButton.cs: + * libstetic/wrapper/Table.cs: + * libstetic/wrapper/TextView.cs: add descriptions to commands and + properties + + * stetic/Grid.cs (AppendPair, Append): add overloads that take a + "description" arg, and set up tooltips. + + * stetic/PropertyGrid.cs (AppendProperty, AppendCommand): Pass the + descriptions from the ItemDescriptors to the underlying Grid + methods + +2005-02-17 Dan Winship <danw@novell.com> + + * libstetic/wrapper/Container.cs (RegisterWrapper): override the + base RegisterWrapper method and scan the type for a + Stetic.Wrapper.Container.ContainerChild subclass, and if found, + remember it as the class's child wrapper class. + (RegisterChildItems, ChildItemGroups): Gone now + (ChildWrapper): Creates a child property wrapper for a WidgetSite + (class ContainerChild): ObjectWrapper implementation for wrapping + Gtk.Container.ContainerChild + (CreateWidgetSite): Now an override of Widget's + (HExpandable, VExpandable): moved to Widget + + * libstetic/wrapper/Widget.cs (CreateWidgetSite, HExpandable, + VExpandable): moved here from Container, with non-Container base + implementations. + + * libstetic/wrapper/Table.cs: implement a ContainerChild subclass + and use it to implement AutoSize again. Also, split XOptions and + YOptions into multiple bools. + + * libstetic/wrapper/Box.cs: implement a ContainerChild subclass. + (SiteOccupancyChanged): when adding a new widget, set Expand and + Fill correctly according to its expandability + + * libstetic/wrapper/ButtonBox.cs: + * libstetic/wrapper/Notebook.cs: + * libstetic/wrapper/Paned.cs: implement a ContainerChild subclass. + + * libstetic/wrapper/Bin.cs: + * libstetic/wrapper/Dialog.cs: + * libstetic/wrapper/ScrolledWindow.cs: + * libstetic/wrapper/Window.cs: make Bin better able to deal with + subclasses that create their own WidgetSites. + + * libstetic/wrapper/Scrollbar.cs: kill this. HScrollbar and + VScrollbar can inherit directly from Range. + + * libstetic/wrapper/HScale.cs (HExpandable): + * libstetic/wrapper/HScrollbar.cs (HExpandable): + * libstetic/wrapper/HSeparator.cs (HExpandable): + * libstetic/wrapper/VScale.cs (VExpandable): + * libstetic/wrapper/VScrollbar.cs (VExpandable): + * libstetic/wrapper/VSeparator.cs (VExpandable): return true + + * libstetic/CommandDescriptor.cs: + * libstetic/ItemDescriptor.cs: + * libstetic/PropertyDescriptor.cs: s/object/ObjectWrapper/ in + several parts of the API now that ContainerChildren have + ObjectWrappers. + + * stetic/ContextMenu.cs + * stetic/PropertyGrid.cs: + * stetic/PropertyEditor.cs: update for that + + * libstetic/IStetic.cs: + * libstetic/WidgetSite.cs: remove the 2-arg CreateWidgetSite + method from IStetic and add an "EmptySize" property to WidgetSite + instead. + + * stetic/WidgetFactory.cs: + * stetic/WidgetSite.cs: update for CreateWidgetSite/EmptySize + changes + + * libstetic/Set.cs: convenience class used by Table. + +2005-02-17 Dan Winship <danw@novell.com> + + * libstetic/ObjectWrapper.cs (RegisterWrapper): Renamed from + RegisterItems. + + * libstetic/wrapper/*.cs: update for that + + * stetic/Stetic.cs: Put all of the windows into a single notebook. + Probably not the best layout, but I'm getting sick of the multiple + windows... + +2005-02-16 Dan Winship <danw@novell.com> + + * stetic/Grid.cs (Connect): static method to connect multiple + grids so they have the same column widths. + (OnSizeRequested, OnSizeAllocated): update for that + + * stetic/Stetic.cs (Main): Connect the Properties and + ChildProperties grids. + +2005-02-15 Dan Winship <danw@novell.com> + + * libstetic/ObjectWrapper.cs: split out parts of + libstetic/wrapper/Object.cs into this. + (RegisterItems, RegisterContextMenu): static methods to register + property grid and context menu items for a wrapper type. + (ItemGroups, ContextMenuItems): these can be implemented here now + rather than needing to be abstract and then reimplemented by each + class. + + * libstetic/wrapper/Object.cs: simplified since most of it is in + ObjectWrapper.cs now. + + * libstetic/wrapper/Container.cs: parallel some of the + ObjectWrapper stuff for child properties + + * libstetic/wrapper/*: update for new (simplified) itemgroup + handling. + + * stetic/PropertyGrid.cs (Notified): update prototype + +2005-02-14 Dan Winship <danw@novell.com> + + * libstetic/editor/GroupPicker.cs: property editor for a + user-extensible list of strings + + * libstetic/wrapper/RadioButton.cs: use GroupPicker for the Group, + and translate that into Gtk's terms. + +2005-02-14 Dan Winship <danw@novell.com> + + * libstetic/wrapper/Widget.cs (Widget): Set the Name property + (based on the class name and a per-class counter). + + * libstetic/wrapper/Button.cs: + * libstetic/wrapper/CheckButton.cs: + * libstetic/wrapper/Expander.cs: + * libstetic/wrapper/Frame.cs: + * libstetic/wrapper/Label.cs: + * libstetic/wrapper/RadioButton.cs: + * libstetic/wrapper/ToggleButton.cs: + * libstetic/wrapper/Window.cs: use the widget name for the default + label/title + + * libstetic/wrapper/Notebook.cs: Use real + wrapped-labels-in-WidgetSites for the notebook tabs. + + * stetic/WidgetFactory.cs: remove widget naming stuff from here + + * stetic/Grid.cs (OnSizeRequested, OnSizeAllocated): fix layout of + misc widgets (ie, command buttons) + +2005-02-14 Dan Winship <danw@novell.com> + + * libstetic/wrapper/Range.cs: + * libstetic/wrapper/Scale.cs: proxy notifications from the + Adjustment so that the PropertyGrid will reflect manual changes to + the widget's value + +2005-02-14 Dan Winship <danw@novell.com> + + * libstetic/RangeAttribute.cs: new attribute for specifying the + range of a property. + + * libstetic/EditorAttribute.cs: local replacement for + System.ComponentModel.EditorAttribute + + * libstetic/PropertyDescriptor.cs: update to look for + Stetic.EditorAttribute rather than + System.ComponentModel.EditorAttribute, and handle + Stetic.RangeAttribute too. + (PropertyInfo): property to return the underlying PropertyInfo + (Minimum, Maximum): new, set from RangeAttribute + (CanRead): Gone. We never really supported write-only properties. + + * stetic/PropertyEditor.cs (MakeEditor): use the + PropertyDescriptor's Minimum and Maximum if available. + (BasicEditor.BasicEditor): Use the property's PropertyInfo rather + than its type as the "special" constructor used for enumerations, + etc. This will let us have a few more special editor types. Don't + bother trying to find a ctor that takes an initial value; it's + easy enough to just set it post-construction. + + * libstetic/editor/Enumeration.cs: Change the Type ctor to take a + PropertyInfo instead. + + * libstetic/editor/Text.cs: Use a PropertyInfo ctor, and check if + there's an EditorAttribute with an EditorSize specified, and use + that to set the textview's size if so. + + * libstetic/editor/Boolean.cs: + * libstetic/editor/Char.cs: + * libstetic/editor/Color.cs: + * libstetic/editor/File.cs: + * libstetic/editor/FloatRange.cs: + * libstetic/editor/IntRange.cs: + * libstetic/editor/OptIntRange.cs: + * libstetic/editor/StockItem.cs: + * libstetic/editor/String.cs: Remove "initial" arg from ctor. + + * libstetic/wrapper/ComboBox.cs (Items): + * libstetic/wrapper/Icon.cs (Stock): + * libstetic/wrapper/Image.cs (File): + * libstetic/wrapper/TextView.cs (Text): use new EditorAttribute + + * libstetic/wrapper/Button.cs (StockId): use new EditorAttribute. + Remove unused DefaultValueAttribute. + + * libstetic/wrapper/ColorButton.cs (Alpha): Use RangeAttribute to + create a new Alpha property that combines the underlying UseAlpha + and Alpha properties into a single "optional int range". + +2005-02-13 Dan Winship <danw@novell.com> + + * libstetic/CommandDescriptor.cs: like PropertyDescriptor, but + describes commands implemented by the widget wrapper (which, like + properties, can become sensitive and insensitive depending on + other properties) + + * libstetic/CommandAttribute.cs: attribute for marking methods + that will be referred to via CommandDescriptors + + * libstetic/IContextMenuProvider.cs: Gone, this functionality is + part of CommandDescriptor now. + + * libstetic/ItemDescriptor.cs: abstract subclass for + PropertyDescriptor and CommandDescriptor + + * libstetic/PropertyDescriptor.cs: make this a subclass of + ItemDescriptor + + * libstetic/ItemGroup.cs: formerly PropertyGroup, but now can hold + any ItemDescriptor. + + * libstetic/wrapper/Object.cs: add a ContextMenuItems property, + empty by default. + + * libstetic/wrapper/*.cs: update for Item changes + + * libstetic/wrapper/Button.cs: implement "Remove Button Contents" + and "Restore Button Label" as Commands. Add dummy properties + HasLabel and HasContents for them to depend on. + + * libstetic/wrapper/Box.cs: + * libstetic/wrapper/Notebook.cs: + * libstetic/wrapper/Table.cs: change IContextMenuItemProvider + stuff to use the new Command stuff + + * libstetic/wrapper/ComboBox.cs: replace Model property with a + multi-line-text Items property + + * libstetic/wrapper/ComboBoxEntry.cs: new wrapper + + * libstetic/wrapper/Window.cs: on a DeleteEvent, just hide the window + + * stetic/Grid.cs: Allow adding of arbitrary widgets in addition to + the property name/editor pairs. + + * stetic/PropertyGrid.cs: Implement CommandDescriptors by adding + buttons to the Grid. + + * stetic/ContextMenu.cs: update for CommandDescriptor stuff + + * stetic/PropertyEditor.cs (EditorValueChanged, Update): Fix this + again to avoid updating loops + + * stetic/WidgetSite.cs (WindowSite.Select): Show() the window, in + case it was hidden + +2005-02-13 Dan Winship <danw@novell.com> + + * libstetic/ParamSpec.cs (gtksharp_get_type_id): Fix the library + name in the DllImport attribute + +2005-02-11 Dan Winship <danw@novell.com> + + * stetic/Grid.cs: new base class for PropertyGrid. Instead of + being a VBox of Expanders, its now a subclass of Container which + lays out its contents by hand; this makes it much easier to make + everything end up with the size and location we want (particularly + in the presence of multi-line editors). + + * stetic/PropertyGrid.cs: Update to be a subclass of Grid + + * libstetic/editor/Text.cs: TextView-based multi-line text editor + + * libstetic/wrapper/TextView.cs: mark the "Text" property as + wanting the "Text" editor type. Proxy the TextView's Buffer's + "Changed" event so that the property editor will track typing in + the widget. + + * stetic/WidgetSite.cs (OnMotionNotifyEvent): force the dragWindow + to be at least 20x20, so that widgets that make very small + requests expecting to be allocated much more space (eg, TextView) + aren't invisible when dragged. + +2005-02-09 Dan Winship <danw@novell.com> + + * libstetic/editor/Color.cs: add an editor for Gdk.Color-valued + properties + + * stetic/PropertyEditor.cs: Use it + + * stetic/PropertyGrid.cs: + * stetic/Stetic.cs: re-enable child packing property page + +2005-02-09 Dan Winship <danw@novell.com> + + * Major reorg again... Now instead of having the widget wrappers + be subclasses of the types they wrap, they are a parallel set of + classes. This lets them share code between each other more easily + than before. Touches nearly every file. Also, update to use + GLib.Object.AddNotification rather than our own notify hack. + +2005-01-27 Dan Winship <danw@novell.com> + + * stetic/ProjectView.cs: TreeView subclass for displaying the + widget tree. + + * stetic/Project.cs: model for ProjectView + + * stetic/Palette.cs (IconForType): Split this code out so the + Project window can make use of it too. + + * stetic/Stetic.cs (Main): Create a "Project" window. Some day + there will be windows whose names don't start with "P". + + * stetic/WidgetSite.cs: s/ExpandabilityChanged/ContentsChanged/ + + * stetic/WidgetFactory.cs (WidgetFactory, Create): set the widget + Name property, a la glade + (WindowFactory.OnButtonPressEvent): call + SteticMain.Project.AddWindow() + + * libstetic/IContainerWrapper.cs: subclass IWidgetWrapper, not + IObjectWrapper. + (ContentsChanged): new event that replaces ExpandabilityChanged + + * libstetic/IWindowWrapper.cs: subclass IContainerWrapper, not + IObjectWrapper + + * libstetic/SiteContentEnumerator.cs: IEnumerator to enumerate the + real widget children of a container (rather than its WidgetSites) + + * widgets/*.cs: s/ExpandabilityChanged/ContentsChanged/ + + * widgets/Dialog.cs: + * widgets/MessageDialog.cs: + * widgets/Window.cs: Implement ContentsChanged + + * widgets/Paned.cs (Paned): fix a bug in the shared Paned + properties + + * widgets/ToggleButton.cs (ToggleButton): Initialize "label" + +2005-01-25 Dan Winship <danw@novell.com> + + * libstetic/IWidgetWrapper.cs: New dummy subclass of + IObjectWrapper + + * libstetic/WidgetBox.cs: Implement OnSetScrollAdjustments (by + passing them on to the child). Needed for ScrolledWindow. + + * widgets/Alignment.cs: + * widgets/EventBox.cs: + * widgets/Expander.cs: + * widgets/ScrolledWindow.cs: Wrap these + + * widgets/*.cs: s/IObjectWrapper/IWidgetWrapper/ + + * stetic/WidgetSite.cs (ParentSite): Deal with the fact that the + immediate parent won't be a WidgetSite in a few cases. + + * stetic/Palette.cs (AddWidgets): Look for IWidgetWrapper, not + IObjectWrapper. + +2005-01-20 Dan Winship <danw@novell.com> + + * libstetic/IWindowWrapper.cs: new (empty) interface + + * libstetic/WidgetWrapperAttribute.cs (WidgetType): gone; we can + distinguish widget wrappers based on whether they implement + IWindowWrapper, IContainerWrapper, or just IObjectWrapper. + + * widgets/*.cs: remove WidgetType declarations from containers and + windows. + + * widgets/Dialog.cs: + * widgets/Window.cs: Remove IContainerWrapper junk that wasn't + being used anyway. + + * widgets/Calendar.cs: + * widgets/FontButton.cs: + * widgets/MessageDialog.cs: new wrappers + + * widgets/pixmaps/curve.png: + * widgets/pixmaps/gammacurve.png: + * widgets/pixmaps/hruler.png: + * widgets/pixmaps/inputdialog.png: + * widgets/pixmaps/selector.png: + * widgets/pixmaps/vruler.png: Kill off some glade icons we won't + be using + + * stetic/Palette.cs: Update for WidgetType going away, and + reorganize into two columns + +2005-01-20 Dan Winship <danw@novell.com> + + * Move 90% of the files in the repository somewhere else. + + * libstetic/: classes needed by both Stetic itself and widget + wrapper implementations + + * libstetic/editor/: moved from stetic/editor + + * widgets/: moved from stetic/wrapper and modified a bit to only + require libstetic. (In particular, all the wrappers now have + constructors that take an IStetic object which can be used to + create new WidgetSites) + + * widgets/pixmaps: moved from pixmaps/ + + * stetic/: now just the app itself, which links to libstetic and + dynamically loads libsteticwidgets. + +2005-01-20 Dan Winship <danw@novell.com> + + * stetic/IObjectWrapper.cs (PropertyGroup): Make this take a + varargs list of property names and build the PropertyDescriptors + itself, to cut down on the amount of work the wrappers need to do. + Also add an indexer to retrieve a PropertyDescriptor by name. + (IPropertySensitizer): Gone + + * stetic/PropertyDescriptor.cs: Update the ctor for how + PropertyGroup uses it now. + (DependsOn, DependsInverselyOn, Dependencies, + InverseDependencies): stuff to specify/probe inter-property + dependencies, to replace the old IPropertySensitizer stuff more + simply. + + * stetic/PropertyGrid.cs: Replace IPropertySensitizer stuff with + PropertyDescriptor.Dependencies, etc + + * stetic/Palette.cs (AddWidgets): Catch exceptions from the + Gdk.Pixbuf ctor and use the "broken image" image instead if it + can't load the wrapper's specified image. + + * stetic/wrapper/*.cs: Update for new, simpler PropertyGroup + creation and inter-property sensitivity settings. + + * stetic/wrapper/ColorButton.cs: + * stetic/wrapper/HScale.cs: + * stetic/wrapper/ProgressBar.cs: + * stetic/wrapper/Scale.cs: + * stetic/wrapper/Statusbar.cs: + * stetic/wrapper/VScale.cs: New wrappers + + * pixmaps/missing.png: "missing image" pixmap to use for now for + widgets I don't have an icon for. + +2005-01-14 Dan Winship <danw@novell.com> + + * stetic/PropertyEditor.cs (BasicEditor.EditorValueChanged, + BasicEditor.Update, RangeEditor.EditorValueChanged, + RangeEditor.Update): Ignore EditorValueChanged if we're inside an + Update, since it's just reflecting the change we're already + making. Indirectly fixes a problem with deleting characters in an + Entry. + + * stetic/wrapper/Arrow.cs: Add Misc.MiscProperties + + * stetic/wrapper/Button.cs: Implement IContextMenuProvider. + (ContextMenuItems): Return a context menu with "Remove Button + Contents" and "Restore Button Label" items, properly sensitized. + (RemoveContents, RestoreLabel): Implement those. + (InsensitiveProperties): Update to deal with RemoveContents + + * stetic/wrapper/CheckButton.cs: + * stetic/wrapper/RadioButton.cs: Add missing "Label" property plus + Button.ButtonExtraProperties + + * stetic/editor/Enumeration.cs: Don't show the enumeration values + in the menu. + + * stetic/editor/FloatRange.cs: Show 2 decimal digits + +2005-01-14 Dan Winship <danw@novell.com> + + * stetic/WidgetBox.cs: Remove InterceptEvents property and + EventWindow. Instead, ConnectBefore to the child's + ButtonPressEvent. (This should help to deal with + non-container-like containers. Eg, GtkButton if you replace the + label widget with something else.) + (OnChildButtonPress): called when a button press is intercepted on + the child widget + + * stetic/WidgetSite.cs: Update for WidgetBox changes. + (OnChildButtonPress): Handle context menu or focus grabbing as + needed + (StartDrag): Change this to take an EventMotion arg. Return false + if the event window isn't the WidgetBox's HandleWindow. (ie, don't + allow drags from the widget itself any more, only from its + handles). + + * stetic/WidgetFactory.cs (StartDrag): add evt arg + +2005-01-13 Dan Winship <danw@novell.com> + + * stetic/ContextMenu.cs (ContextMenuItem): add an "Enabled" field + and a ctor to set it + (ContextMenu): obey the "Enabled" field on IContextMenuProvider + items + (IContextMenuProvider): Turn ContextMenuItems from a property to a + procedure, so we can pass the context item to it + + * stetic/wrapper/Notebook.cs: update for IContextMenuProvider + change. Disable items (eg, "Go To Previous Page") as appropriate. + + * stetic/wrapper/HBox.cs: + * stetic/wrapper/VBox.cs: + * stetic/wrapper/Table.cs: update for IContextMenuProvider change + +2005-01-13 Dan Winship <danw@novell.com> + + * stetic/WidgetSite.cs (EmptySize): new property to set the site's + size when empty + (set_Occupancy): Use that rather than hardcoding 10x10 + (WidgetSite): New ctor to set EmptySize + + * stetic/wrapper/Window.cs: Use the new WidgetSite ctor rather + than overriding OnSizeRequested + + * stetic/wrapper/Dialog.cs: Use the new WidgetSite ctor + +2005-01-13 Dan Winship <danw@novell.com> + + * stetic/Stetic.cs: Rename the main class from "Stetic" to + "SteticMain", to work around really annoying C# semantics + + * stetic/WidgetFactory.cs (WindowFactory.OnButtonPressEvent): + update for that + +2005-01-13 Dan Winship <danw@novell.com> + + * stetic/WidgetFactory.cs (WidgetFactoryAttribute): gone, turned + into WidgetWrapperAttribute + (WidgetFactory, WindowFactory): Take a Type directly rather than a + WidgetFactoryDelegate. + + * stetic/WidgetWrapperAttribute.cs: replaces + WidgetFactoryAttribute, but basically the same thing + + * stetic/Palette.cs (AddWidgets): Take an Assembly rather than a + Type, and search for all Types in that Assembly with a + WidgetWrapperAttribute. + + * stetic/Stetic.cs (Main): Update call to Palette.AddWidgets + + * stetic/wrapper/DefaultWidgets.cs: Gone + + * stetic/wrapper/Dialog.cs: + * stetic/wrapper/Notebook.cs: + * stetic/wrapper/TextView.cs: + * stetic/wrapper/ToggleButton.cs: wrap these + + * stetic/wrapper/*.cs: add WidgetWrapper attributes, make sure + every class has a no-arg constructor + +2005-01-13 Dan Winship <danw@novell.com> + + * stetic/ContextMenu.cs (IContextMenuProvider): New interface for + widget wrappers that want to add items to their context menus. + (ContextMenu): support IContextMenuProvider. + + * stetic/IObjectWrapper.cs (IPropertySensitizer): Make + InsensitiveProperties a property rather than a method + + * stetic/PropertyDescriptor.cs (PropertyDescriptor): Add a new + constructor for "proxy" descriptors, which get a ParamSpec from + the base class, but use the property on the derived class. Also, + if the passed-in propertyName is invalid, throw an + ArgumentException with a useful message rather than causing a + NullArgumentException later. + + * stetic/PropertyGrid.cs (SetupSensitivity): Update for + InsensitiveProperties change + + * stetic/WidgetSite.cs: Update for ContextMenu ctor change + + * stetic/wrapper/Button.cs: Use a proxy PropertyDescriptor for + "Label", update InsensitiveProperties. + + * stetic/wrapper/ComboBox.cs: Fix a crasher typo noted by Peter + Williams. + + * stetic/wrapper/Icon.cs: Use proxy PropertyDescriptors for Stock + and IconSize. + + * stetic/wrapper/HBox.cs: + * stetic/wrapper/VBox.cs: Implement IContextMenuProvider, adding + "Insert Before" and "Insert After" commands. + + * stetic/wrapper/Table.cs: Implement IContextMenuProvider, adding + "Insert Row/Column Before/After" and "Delete Row/Column". Use + proxy PropertyDescriptors for NRows and NColumns since the base + properties won't let you remove non-empty rows/columns. Update + InsensitiveProperties. + + * stetic/stetic.in: If command-line args are passed, pass them to + mono (since stetic doesn't take any arguments at the moment, and I + use mono --trace a lot). + +2005-01-12 Dan Winship <danw@novell.com> + + * stetic/PropertyGrid.cs: Reorganize stuff so that ContainerChild + classes can override properties and implement IPropertySensitizer + as well. + + * stetic/IDesignTimeContainer.cs: + * stetic/IObjectWrapper.cs (IContainerWrapper): Move the things + that used to be in IDesignTimeContainer to IContainerWrapper. Kill + IDesignTimeContainer. + + * stetic/WidgetSite.cs: Update for that + + * stetic/wrapper/Frame.cs: + * stetic/wrapper/HBox.cs: + * stetic/wrapper/HButtonBox.cs: + * stetic/wrapper/HPaned.cs: + * stetic/wrapper/VBox.cs: + * stetic/wrapper/VButtonBox.cs: + * stetic/wrapper/VPaned.cs: + * stetic/wrapper/Window.cs: Update + + * stetic/wrapper/Table.cs: Update. + (TableChild) Subclass Gtk.Table.TableChild with an "AutoSize" + property saying whether or not to automatically adjust the packing + of child widgets (defaults to on). Also implement + IPropertySensitizer. + (Sync): Update for that. + +2005-01-12 Dan Winship <danw@novell.com> + + * stetic/IObjectWrapper.cs (IContainerWrapper): new interface a la + IObjectWrapper, but including child properties as well. + + * stetic/PropertyGrid.cs (ChildPropertyGrid): Use IContainerWrapper + + * stetic/wrapper/Box.cs: + * stetic/wrapper/ButtonBox.cs: + * stetic/wrapper/Paned.cs: add static child PropertyGroups + + * stetic/wrapper/HBox.cs: + * stetic/wrapper/HButtonBox.cs: + * stetic/wrapper/HPaned.cs: + * stetic/wrapper/Table.cs: + * stetic/wrapper/VBox.cs: + * stetic/wrapper/VButtonBox.cs: + * stetic/wrapper/VPaned.cs: Implement IContainerWrapper, add child + PropertyGroups + + * stetic/wrapper/Frame.cs: + * stetic/wrapper/Window.cs: Implement IContainerWrapper, but + return an empty ChildPropertyGroups + +2005-01-11 Dan Winship <danw@novell.com> + + * stetic/WidgetBox.cs (WidgetBox, OnRealized): Use WidgetFlags + property instead of Obsolete Flags. + (ShowHandles, OnRealized, OnExposeEvent): Set the Background of + the HandleWindow to black when creating it, rather than filling in + the foreground in OnExposeEvent. + (OnSizeAllocated): Don't set HandleAllocation here, since the + window may not have been realized yet, which would make + TranslateCoordinates not work. + (ShapeHandles): Figure out HandleAllocation here. + +2005-01-07 Dan Winship <danw@novell.com> + + * stetic/wrapper/Image.cs: wrapper for Gtk.Images that show files + + * stetic/wrapper/Icon.cs: wrapper for Gtk.Images that show stock icons + + * stetic/wrapper/SpinButton.cs: wrapper for Gtk.SpinButton + + * stetic/wrapper/Frame.cs: + * stetic/wrapper/HBox.cs: + * stetic/wrapper/HButtonBox.cs: + * stetic/wrapper/HPaned.cs: + * stetic/wrapper/VBox.cs: + * stetic/wrapper/VButtonBox.cs: + * stetic/wrapper/VPaned.cs: + * stetic/wrapper/Table.cs: + * stetic/wrapper/Window.cs: Implement IObjectWrapper on these + (previously they just implemented IDesignTimeContainer) + + * stetic/wrapper/Box.cs: + * stetic/wrapper/ButtonBox.cs: + * stetic/wrapper/Paned.cs: static classes that define + PropertyDescriptors used by their subclasses + + * stetic/wrapper/DefaultWidgets.cs: Update for new wrappers + + * stetic/editor/File.cs: editor for strings that represent filenames + + * stetic/Stetic.cs: Use Gnome.Program rather than Gtk.Application + now, since we're using Gnome.FileEntry. + +2005-01-06 Dan Winship <danw@novell.com> + + * stetic/IDesignTimeContainer.cs: New name for the old + IWidgetSite. + + * stetic/WidgetSite.cs (IWidgetSite): Now a "parent" for + WidgetSite and WindowSite. + (WidgetSite): Implement IWidgetSite and IDesignTimeContainer. + (WindowSite): IWidgetSite implementation for toplevel windows. + Includes the focus-tracking code formerly in + Stetic.Wrapper.Window. + + * stetic/ContextMenu.cs (ContextMenu): + * stetic/Stetic.cs (Select): + * stetic/PropertyGrid.cs (PropertyGrid.Select, + ChildPropertyGrid.Select): Change WidgetBox and WidgetSite params + to IWidgetSite. This lets us select and show properties for toplevels. + + * stetic/WidgetFactory.cs (WindowFactory.OnButtonPressEvent): + Create a WindowSite for the new window and connect to its + FocusChanged event. + + * stetic/wrapper/*.cs: s/IWidgetSite/IDesignTimeContainer/ + + * stetic/wrapper/Window.cs (OnSetFocus): Gone. Handled by + WindowSite now. + +2005-01-05 Dan Winship <danw@novell.com> + + * stetic/ContextMenu.cs: Menu subclass to use as a WidgetSite's + context menu. Currently a clone of Glade's context menu, but with + no widget-specific content, and it doesn't actually implement Cut, + Copy, or Paste. (Meaning you can do Select or Delete.) + + * stetic/WidgetSite.cs (OnPopupMenu): create a ContextMenu and pop + it up. + (OnButtonPressEvent): Call OnPopupMenu() on a right-click. + (OnKeyReleaseEvent): hand off Delete key handling to Delete() + (Delete): new public method to delete the site's child. + + * stetic/PropertyDescriptor.cs (PropertyDescriptor): fix a bug in + the sub-property case + +2005-01-05 Dan Winship <danw@novell.com> + + * stetic/IObjectWrapper.cs (IPropertySensitizer): interface for + wrapper classes that want to be able to tweak the sensitivity of + their editors. + + * stetic/Notify.cs: static helper class for the GObject "notify" + signal, which isn't currently bound by glib-sharp. + + * stetic/PropertyDescriptor.cs (EventInfo, ParamSpec, EditorType): + Make these be properties of the PropertyDescriptor rather than + being figured out in PropertyEditors. + + * stetic/PropertyEditor.cs: Renamed from PropertyEditors.cs and + made into an abstract widget class rather than a static class. + (MakeEditor): Now returns a PropertyEditor rather than just a + Widget. + (BasicEditor, RangeEditor, NoEditor): Now subclasses of + PropertyEditor, and they implement an Update() method to force the + editor to sync with the underlying property. + + * stetic/PropertyGrid.cs: Tweak for PropertyDescriptor and + PropertyEditor changes. Use IPropertySensitizer if the displayed + widget supports it. Use Stetic.Notify to notice when the user + interacts with the displayed widget (eg, toggling a checkbox) and + force the relevant property editor to update itself. + + * stetic/ParamSpec.cs (ParamSpecTypeHack): add an unused private + subclass of GLib.Object so we can access the static protected + LookupGType method. (This wouldn't be needed if ParamSpec was in + glib-sharp, because there's an internal method we could use.) + (LookupObjectProperty, LookupChildProperty): Take a Type rather + than a GLib.Object, so we can look up a type's properties without + needing an instatiated object. + + * stetic/wrapper/Button.cs: Make the UI for the "Stock ID" and + "Label" properties work more nicely by wrapping both of them at + the Stetic.Wrapper.Button level, and watching for notifications on + the UseStock property, and setting the wrapper Label to the stock + item's Label rather than its Name when setting a stock item (eg, + "_OK" rather than "gtk-ok"). Also add the UseStock property, and + implement the IPropertySensitizer interface so that only one of + Stock ID and Label is sensitive at any time. + + * stetic/editor/StockItem.cs: Remove the "None" option; the editor + should be desensitized if no stock item is being used. + + * glue/notify.c: glue for Stetic.Notify + + * glue/paramspec.c (stetic_param_spec_for_property, + stetic_param_spec_for_child_property): Take a GType rather than a + GObject. + +2004-12-20 Dan Winship <danw@novell.com> + + * stetic/IObjectWrapper.cs: interface for Stetic.Wrapper objects + to use to allow them to define their properties + + * stetic/PropertyDescriptor.cs: a class describing an editable + object property + + * stetic/PropertyGrid.cs: Reimplement this using + PropertyDescriptors and PropertyGroups for the model, and + Gtk.Expanders for the view. + + * stetic/PropertyEditorAttribute.cs: for Stetic.Editors to use to + specify the property and/or event to use to interact with them + + * stetic/PropertyEditors.cs: Updated for PropertyDescriptor, the + Stetic.Editor namespace, etc + + * stetic/ParamSpec.cs: make Minimum, Maximum, Default virtual + methods on ParamSpec itself, overridden by subclasses. + + * stetic/editor/Boolean.cs: + * stetic/editor/Char.cs: + * stetic/editor/Enumeration.cs: + * stetic/editor/FloatRange.cs: + * stetic/editor/IntRange.cs: + * stetic/editor/OptIntRange.cs: + * stetic/editor/StockItem.cs: + * stetic/editor/String.cs: Editors for properties of various types + + * stetic/wrapper/Arrow.cs: + * stetic/wrapper/Button.cs: + * stetic/wrapper/CheckButton.cs: + * stetic/wrapper/ComboBox.cs: + * stetic/wrapper/DrawingArea.cs: + * stetic/wrapper/Entry.cs: + * stetic/wrapper/HScrollbar.cs: + * stetic/wrapper/HSeparator.cs: + * stetic/wrapper/Label.cs: + * stetic/wrapper/RadioButton.cs: + * stetic/wrapper/VScrollbar.cs: + * stetic/wrapper/VSeparator.cs: IObjectWrapper implementations + + * stetic/wrapper/Misc.cs: + * stetic/wrapper/Range.cs: + * stetic/wrapper/Widget.cs: static classes defining certain + PropertyGroups + + * stetic/wrapper/HBox.cs: + * stetic/wrapper/HPaned.cs: + * stetic/wrapper/Table.cs: + * stetic/wrapper/VBox.cs: + * stetic/wrapper/VPaned.cs: + * stetic/wrapper/Window.cs: s/Widget/Gtk.Widget/ since there is + now a Stetic.Wrapper.Widget + + * stetic/wrapper/DefaultWidgets.cs: use the new wrappers + + * stetic/Makefile.am (stetic_exe_SOURCES): update + + * stetic/stetic.in: pass --debug to mono + +2004-12-20 Dan Winship <danw@novell.com> + + * stetic/wrapper: Rename "wrappers" dir to "wrapper", to match the + namespace + + * stetic/Makefile.am (stetic_exe_SOURCES): update for that + +2004-12-15 Dan Winship <danw@novell.com> + + * stetic/Stetic.cs: + * stetic/WidgetSite.cs: + * stetic/wrappers/Table.cs: Clean up new mcs warnings + + * stetic/PropertyEditors.cs (Enum): Redo this using ComboBox to + avoid the warning about OptionMenu being deprecated + (Flags): Make this a no-op for now. The OptionMenu-based + implementation wasn't very useful anyway. + +2004-12-14 Dan Winship <danw@novell.com> + + * stetic/*Wrapper.cs: Move these all to stetic/wrappers and rename + + * stetic/DefaultWidgets.cs: Moved out of stetic/WidgetFactory.cs + + * stetic/Makefile.am (stetic_exe_SOURCES): Update + +2004-12-13 Dan Winship <danw@novell.com> + + * stetic/PropertyEditors.cs (Enum, Flags): implement these by + using private classes rather than anonymous delegates, to work + around 69614. + + * stetic/TableWrapper.cs: fix a search-and-replace-o ("placesite" + instead of "placeholder") + (Sync): Don't adjust expand/fill settings of occupied sites. + (ChildOccupancyChanged): When a site becomes occupied, reset its + attach options. + +2004-12-10 Dan Winship <danw@novell.com> + + * stetic/WidgetBox.cs: Always have a GdkWindow, so that the + background of a container can be clicked on to select it (if any + background is visible). Fix up coordinate handling accordingly. + + * stetic/WidgetFactory.cs (DefaultWidgets): add VButtonBox and + HButtonBox. + + * stetic/Makefile.am (stetic_exe_SOURCES): add + HButtonBoxWrapper.cs, VButtonBoxWrapper.cs + (stetic.exe): Use -pkg:gtk-sharp-2.0 rather than the output we + already cached in configure.in, because Miggie says so. :) + +2004-12-08 Dan Winship <danw@novell.com> + + * Initial commit + diff --git a/main/src/addins/MonoDevelop.GtkCore2/Makefile.am b/main/src/addins/MonoDevelop.GtkCore2/Makefile.am new file mode 100644 index 0000000000..9648571c49 --- /dev/null +++ b/main/src/addins/MonoDevelop.GtkCore2/Makefile.am @@ -0,0 +1,112 @@ +SUBDIRS = libstetic libsteticui + +ADDIN_BUILD = $(top_builddir)/build/AddIns/MonoDevelop.GtkCore2 +ASSEMBLY = $(ADDIN_BUILD)/MonoDevelop.GtkCore2.dll + +DEPS = \ + $(top_builddir)/build/AddIns/MonoDevelop.Deployment/MonoDevelop.Deployment.dll \ + $(top_builddir)/build/AddIns/MonoDevelop.DesignerSupport/MonoDevelop.DesignerSupport.dll \ + $(top_builddir)/build/AddIns/MonoDevelop.GtkCore2/libstetic2.dll \ + $(top_builddir)/build/AddIns/MonoDevelop.GtkCore2/libsteticui2.dll \ + $(top_builddir)/build/bin/Mono.TextEditor.dll \ + $(top_builddir)/build/bin/MonoDevelop.Core.dll \ + $(top_builddir)/build/bin/MonoDevelop.Ide.dll + +REFS = \ + $(GLADE_SHARP_LIBS) \ + $(GLIB_SHARP_LIBS) \ + $(GTK_SHARP_LIBS) \ + $(MONO_ADDINS_LIBS) \ + -pkg:monodevelop \ + -r:Mono.Posix \ + -r:System \ + -r:System.Core \ + -r:System.Xml + +FILES = \ + AssemblyInfo.cs \ + gtk-gui/generated.cs \ + gtk-gui/MonoDevelop.GtkCore.Dialogs.GtkDesignerOptionsPanelWidget.cs \ + gtk-gui/MonoDevelop.GtkCore.Dialogs.ProjectConversionDialog.cs \ + MonoDevelop.GtkCore.Commands/GtkCommands.cs \ + MonoDevelop.GtkCore.Dialogs/BindDesignDialog.cs \ + MonoDevelop.GtkCore.Dialogs/ConfirmWindowDeleteDialog.cs \ + MonoDevelop.GtkCore.Dialogs/GtkDesignerOptionsPanelWidget.cs \ + MonoDevelop.GtkCore.Dialogs/GtkFeatureWidget.cs \ + MonoDevelop.GtkCore.Dialogs/ProjectConversionDialog.cs \ + MonoDevelop.GtkCore.Dialogs/SelectRenamedClassDialog.cs \ + MonoDevelop.GtkCore.Dialogs/WidgetBuilderOptionPanel.cs \ + MonoDevelop.GtkCore.GuiBuilder/ActionGroupDisplayBinding.cs \ + MonoDevelop.GtkCore.GuiBuilder/ActionGroupView.cs \ + MonoDevelop.GtkCore.GuiBuilder/ClassUtils.cs \ + MonoDevelop.GtkCore.GuiBuilder/CodeBinder.cs \ + MonoDevelop.GtkCore.GuiBuilder/CombinedDesignView.cs \ + MonoDevelop.GtkCore.GuiBuilder/GtkProjectServiceExtension.cs \ + MonoDevelop.GtkCore.GuiBuilder/GuiBuilderDisplayBinding.cs \ + MonoDevelop.GtkCore.GuiBuilder/GuiBuilderDocumentOutline.cs \ + MonoDevelop.GtkCore.GuiBuilder/GuiBuilderProject.cs \ + MonoDevelop.GtkCore.GuiBuilder/GuiBuilderService.cs \ + MonoDevelop.GtkCore.GuiBuilder/GuiBuilderView.cs \ + MonoDevelop.GtkCore.GuiBuilder/GuiBuilderWindow.cs \ + MonoDevelop.GtkCore.GuiBuilder/PropertiesWidget.cs \ + MonoDevelop.GtkCore.GuiBuilder/ToolboxLoader.cs \ + MonoDevelop.GtkCore.GuiBuilder/ToolboxProvider.cs \ + MonoDevelop.GtkCore.NodeBuilders/GuiProjectFolder.cs \ + MonoDevelop.GtkCore.NodeBuilders/GuiProjectFolderNodeBuilder.cs \ + MonoDevelop.GtkCore.NodeBuilders/ProjectFileExtension.cs \ + MonoDevelop.GtkCore.NodeBuilders/ProjectFileNodeBuilderExtension.cs \ + MonoDevelop.GtkCore.NodeBuilders/ProjectFolderNodeBuilderExtension.cs \ + MonoDevelop.GtkCore.NodeBuilders/ProjectNodeBuilder.cs \ + MonoDevelop.GtkCore.NodeBuilders/StockIconsNodeBuilder.cs \ + MonoDevelop.GtkCore/Counters.cs \ + MonoDevelop.GtkCore/GtkCoreService.cs \ + MonoDevelop.GtkCore/GtkDesignInfo.cs \ + MonoDevelop.GtkCore/ObjectsDocument.cs \ + MonoDevelop.GtkCore/ProjectResourceProvider.cs \ + MonoDevelop.GtkCore/ReferenceManager.cs \ + MonoDevelop.GtkCore/WidgetFileDescriptionTemplate.cs \ + MonoDevelop.GtkCore/WidgetParser.cs + +RES = \ + gtk-gui/gui.stetic \ + gui.glade \ + icons/actiongroup.png \ + icons/gtk-logo.png \ + icons/gtkx.png \ + icons/image-x-generic.png \ + icons/widget.png \ + MonoDevelop.GtkCore2.addin.xml,MonoDevelop.GtkCore.addin.xml \ + templates/ActionGroup.xft.xml \ + templates/ActionGroupPartial.xft.xml \ + templates/Dialog.xft.xml \ + templates/DialogPartial.xft.xml \ + templates/DrawingArea.xft.xml \ + templates/Widget.xft.xml \ + templates/WidgetPartial.xft.xml \ + templates/Window.xft.xml \ + templates/WindowPartial.xft.xml + + +EXTRA_DIST = $(FILES) $(RES) + +update-stetic: + svn rm -m "Update Stetic sources" svn+ssh://mono-cvs.ximian.com/source/trunk/monodevelop/main/src/addins/MonoDevelop.GtkCore/lib/stetic && \ + svn cp -m "Update Stetic sources" svn+ssh://mono-cvs.ximian.com/source/trunk/stetic svn+ssh://mono-cvs.ximian.com/source/trunk/monodevelop/main/src/addins/MonoDevelop.GtkCore/lib/stetic + +all: $(ASSEMBLY) + +$(ADDIN_BUILD)/%: $(srcdir)/lib/% + mkdir -p $(ADDIN_BUILD) + cp $< $@ + +$(ASSEMBLY): $(build_sources) $(build_resources) $(DEPS) + mkdir -p $(ADDIN_BUILD) + $(CSC) $(CSC_FLAGS) -debug -out:$@ -target:library \ + $(build_resources:%=/resource:%) $(build_sources) $(REFS) $(build_deps) + +assemblydir = $(MD_ADDIN_DIR)/MonoDevelop.GtkCore2 +assembly_DATA = $(ASSEMBLY) $(ASSEMBLY).mdb + +CLEANFILES = $(ASSEMBLY) $(ASSEMBLY).mdb + +include $(top_srcdir)/Makefile.include diff --git a/main/src/addins/MonoDevelop.GtkCore2/MonoDevelop.GtkCore.Commands/ChangeLog b/main/src/addins/MonoDevelop.GtkCore2/MonoDevelop.GtkCore.Commands/ChangeLog new file mode 100644 index 0000000000..b2765325e1 --- /dev/null +++ b/main/src/addins/MonoDevelop.GtkCore2/MonoDevelop.GtkCore.Commands/ChangeLog @@ -0,0 +1,4 @@ +2010-08-15 Krzysztof Marecki <freefirma@gmail.com> + + * GladeCommands.cs: + diff --git a/main/src/addins/MonoDevelop.GtkCore2/MonoDevelop.GtkCore.Commands/GtkCommands.cs b/main/src/addins/MonoDevelop.GtkCore2/MonoDevelop.GtkCore.Commands/GtkCommands.cs new file mode 100644 index 0000000000..e8772a0680 --- /dev/null +++ b/main/src/addins/MonoDevelop.GtkCore2/MonoDevelop.GtkCore.Commands/GtkCommands.cs @@ -0,0 +1,45 @@ +// +// GtkCommands.cs +// +// Author: +// Lluis Sanchez Gual +// Krzysztof Marecki +// +// Copyright (C) 2006 Novell, Inc (http://www.novell.com) +// Copyright (C) 2010 Krzysztof Marecki +// +// Permission is hereby granted, free of charge, to any person obtaining +// a copy of this software and associated documentation files (the +// "Software"), to deal in the Software without restriction, including +// without limitation the rights to use, copy, modify, merge, publish, +// distribute, sublicense, and/or sell copies of the Software, and to +// permit persons to whom the Software is furnished to do so, subject to +// the following conditions: +// +// The above copyright notice and this permission notice shall be +// included in all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, +// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND +// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE +// LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION +// OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION +// WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. +// + +namespace MonoDevelop.GtkCore +{ + public enum GtkCommands + { + AddNewDialog, + AddNewWindow, + AddNewWidget, + AddNewActionGroup, + ImportGladeFile, + EditIcons, + GtkSettings, + GenerateCode, + ReloadDesigner + } +} diff --git a/main/src/addins/MonoDevelop.GtkCore2/MonoDevelop.GtkCore.Dialogs/BindDesignDialog.cs b/main/src/addins/MonoDevelop.GtkCore2/MonoDevelop.GtkCore.Dialogs/BindDesignDialog.cs new file mode 100644 index 0000000000..04bd159640 --- /dev/null +++ b/main/src/addins/MonoDevelop.GtkCore2/MonoDevelop.GtkCore.Dialogs/BindDesignDialog.cs @@ -0,0 +1,186 @@ +// +// BindDesignDialog.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 System.Collections; + +using Glade; +using Gtk; +using MonoDevelop.Core; +using MonoDevelop.Components; +using MonoDevelop.Ide; + +namespace MonoDevelop.GtkCore.Dialogs +{ + class BindDesignDialog: IDisposable + { + [Glade.Widget ("BindDesignDialog")] protected Gtk.Dialog dialog; + [Glade.Widget] protected Gtk.Label labelMessage; + [Glade.Widget] protected Gtk.ComboBox comboClasses; + [Glade.Widget] protected Gtk.Entry entryClassName; + [Glade.Widget] protected Gtk.Entry entryNamespace; + [Glade.Widget] protected Gtk.RadioButton radioSelect; + [Glade.Widget] protected Gtk.RadioButton radioCreate; + [Glade.Widget] protected Gtk.Table tableNewClass; + [Glade.Widget] protected Gtk.Button okButton; + [Glade.Widget] protected Gtk.EventBox fileEntryBox; + + FolderEntry fileEntry; + + ListStore store; + static string lastNamespace = ""; + + public BindDesignDialog (string id, ArrayList validClasses, string baseFolder) + { + XML glade = new XML (null, "gui.glade", "BindDesignDialog", null); + glade.Autoconnect (this); + labelMessage.Text = GettextCatalog.GetString ("The widget design {0} is not currently bound to a class.", id); + + fileEntry = new FolderEntry (); + fileEntryBox.Add (fileEntry); + fileEntry.ShowAll (); + + if (validClasses.Count > 0) { + + store = new ListStore (typeof (string));
+ foreach (string cname in validClasses) + store.AppendValues (cname); + comboClasses.Model = store; + CellRendererText cr = new CellRendererText (); + comboClasses.PackStart (cr, true); + comboClasses.AddAttribute (cr, "text", 0); + comboClasses.Active = 0; + + } else { + radioSelect.Sensitive = false; + radioCreate.Active = true; + } + + fileEntry.Path = baseFolder; + + // Initialize the class name using the widget name + int i = id.IndexOf ('.'); + if (i != -1) { + entryClassName.Text = id.Substring (i+1); + entryNamespace.Text = id.Substring (0,i); + } else { + entryClassName.Text = id; + entryNamespace.Text = lastNamespace; + } + + dialog.Response += new Gtk.ResponseHandler (OnResponse); + UpdateStatus (); + } + + void OnResponse (object ob, Gtk.ResponseArgs args) + { + dialog.Response -= new Gtk.ResponseHandler (OnResponse); + if (args.ResponseId == ResponseType.Ok && radioCreate.Active) + lastNamespace = Namespace; + } + + public bool Run () + { + dialog.TransientFor = IdeApp.Workbench.RootWindow; + return dialog.Run () == (int) ResponseType.Ok; + } + + public bool CreateNew { + get { return radioCreate.Active; } + } + + public string ClassName { + get { + if (radioCreate.Active) { + return entryClassName.Text; + } else { + Gtk.TreeIter it; + if (!comboClasses.GetActiveIter (out it)) + return ""; + string s = (string) store.GetValue (it, 0); + int i = s.IndexOf ('.'); + if (i != -1) + return s.Substring (i+1); + else + return s; + } + } + } + + public string Namespace { + get { + if (radioCreate.Active) { + return entryNamespace.Text; + } else { + Gtk.TreeIter it; + if (!comboClasses.GetActiveIter (out it)) + return ""; + string s = (string) store.GetValue (it, 0); + int i = s.IndexOf ('.'); + if (i != -1) + return s.Substring (0, i); + else + return ""; + } + } + } + + public string Folder { + get { return fileEntry.Path; } + } + + protected void OnSelectToggled (object ob, EventArgs args) + { + UpdateStatus (); + } + + protected void OnEntryChanged (object ob, EventArgs a) + { + UpdateStatus (); + } + + void UpdateStatus () + { + if (radioSelect.Active) { + tableNewClass.Sensitive = false; + comboClasses.Sensitive = true; + okButton.Sensitive = true; + } else { + tableNewClass.Sensitive = true; + comboClasses.Sensitive = false; + okButton.Sensitive = ClassName != "" && Folder != ""; + } + } + + public void Dispose () + { + dialog.Destroy (); + } + } + +} diff --git a/main/src/addins/MonoDevelop.GtkCore2/MonoDevelop.GtkCore.Dialogs/ChangeLog b/main/src/addins/MonoDevelop.GtkCore2/MonoDevelop.GtkCore.Dialogs/ChangeLog new file mode 100644 index 0000000000..c48d43c59e --- /dev/null +++ b/main/src/addins/MonoDevelop.GtkCore2/MonoDevelop.GtkCore.Dialogs/ChangeLog @@ -0,0 +1,18 @@ +2010-08-15 Krzysztof Marecki <freefirma@gmail.com> + + * ProjectConversionDialog.cs: + +2010-08-13 Krzysztof Marecki <freefirma@gmail.com> + + * ProjectConversionDialog.cs: + * WidgetBuilderOptionPanel.cs: + +2010-07-06 Krzysztof Marecki <marecki.krzysztof@gmail.com> + + * ProjectConversionDialog.cs: + +2010-06-23 Krzysztof Marecki <marecki.krzysztof@gmail.com> + + * ProjectConversionDialog.cs: Initial commit + * WidgetBuilderOptionPanel.cs: + diff --git a/main/src/addins/MonoDevelop.GtkCore2/MonoDevelop.GtkCore.Dialogs/ConfirmWindowDeleteDialog.cs b/main/src/addins/MonoDevelop.GtkCore2/MonoDevelop.GtkCore.Dialogs/ConfirmWindowDeleteDialog.cs new file mode 100644 index 0000000000..b0c8031ba5 --- /dev/null +++ b/main/src/addins/MonoDevelop.GtkCore2/MonoDevelop.GtkCore.Dialogs/ConfirmWindowDeleteDialog.cs @@ -0,0 +1,79 @@ +// +// ConfirmWindowDeleteDialog.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 Glade; +using Gtk; +using MonoDevelop.Core; +using MonoDevelop.Ide; + +namespace MonoDevelop.GtkCore.Dialogs +{ + class ConfirmWindowDeleteDialog: IDisposable + { + [Glade.Widget ("ConfirmWindowDeleteDialog")] protected Gtk.Dialog dialog; + [Glade.Widget] protected Gtk.Label label; + [Glade.Widget] protected Gtk.CheckButton checkbox; + + public ConfirmWindowDeleteDialog (string windowName, string fileName, Stetic.ProjectItemInfo obj) + { + XML glade = new XML (null, "gui.glade", "ConfirmWindowDeleteDialog", null); + glade.Autoconnect (this); + + if (obj is Stetic.WidgetInfo && ((Stetic.WidgetInfo)obj).IsWindow) { + label.Text = GettextCatalog.GetString ("Are you sure you want to delete the window '{0}'?", windowName); + } else if (obj is Stetic.WidgetInfo) { + label.Text = GettextCatalog.GetString ("Are you sure you want to delete the widget '{0}'?", windowName); + } else if (obj is Stetic.ActionGroupInfo) { + label.Text = GettextCatalog.GetString ("Are you sure you want to delete the action group '{0}'?", windowName); + } else + label.Text = GettextCatalog.GetString ("Are you sure you want to delete '{0}'?", windowName); + + if (fileName != null) { + checkbox.Label = string.Format (checkbox.Label, fileName); + checkbox.Active = true; + } else + checkbox.Hide (); + } + + public void Dispose () + { + dialog.Destroy (); + } + + public int Run () + { + dialog.TransientFor = IdeApp.Workbench.RootWindow; + return dialog.Run (); + } + + public bool DeleteFile { + get { return checkbox.Active; } + } + } +} diff --git a/main/src/addins/MonoDevelop.GtkCore2/MonoDevelop.GtkCore.Dialogs/GtkDesignerOptionsPanelWidget.cs b/main/src/addins/MonoDevelop.GtkCore2/MonoDevelop.GtkCore.Dialogs/GtkDesignerOptionsPanelWidget.cs new file mode 100644 index 0000000000..cce24542b0 --- /dev/null +++ b/main/src/addins/MonoDevelop.GtkCore2/MonoDevelop.GtkCore.Dialogs/GtkDesignerOptionsPanelWidget.cs @@ -0,0 +1,64 @@ +// +// GtkDesignerOptionPanelWidget.cs +// +// Author: +// Lluis Sanchez Gual <lluis@novell.com> +// +// Copyright (c) 2009 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 MonoDevelop.GtkCore.GuiBuilder; +using Gtk; +using MonoDevelop.Ide.Gui.Dialogs; + +namespace MonoDevelop.GtkCore.Dialogs +{ + public class GtkDesignerOptionPanel: OptionsPanel + { + GtkDesignerOptionsPanelWidget widget; + + public override Widget CreatePanelWidget () + { + widget = new GtkDesignerOptionsPanelWidget (); + widget.AutoSwitchLayout = GuiBuilderService.AutoSwitchGuiLayout; + return widget; + } + + public override void ApplyChanges () + { + GuiBuilderService.AutoSwitchGuiLayout = widget.AutoSwitchLayout; + } + } + + [System.ComponentModel.ToolboxItem(true)] + public partial class GtkDesignerOptionsPanelWidget : Gtk.Bin + { + public GtkDesignerOptionsPanelWidget() + { + this.Build(); + } + + public bool AutoSwitchLayout { + get { return checkSwitchLayout.Active; } + set { checkSwitchLayout.Active = value; } + } + } +} diff --git a/main/src/addins/MonoDevelop.GtkCore2/MonoDevelop.GtkCore.Dialogs/GtkFeatureWidget.cs b/main/src/addins/MonoDevelop.GtkCore2/MonoDevelop.GtkCore.Dialogs/GtkFeatureWidget.cs new file mode 100644 index 0000000000..133a6a4a22 --- /dev/null +++ b/main/src/addins/MonoDevelop.GtkCore2/MonoDevelop.GtkCore.Dialogs/GtkFeatureWidget.cs @@ -0,0 +1,81 @@ + +using System; +using MonoDevelop.Ide.Templates; +using MonoDevelop.Core; +using MonoDevelop.Projects; +using Gtk; + +namespace MonoDevelop.GtkCore.Dialogs +{ + class GtkFeatureWidget : Gtk.VBox + { + ComboBox versionCombo; + + public GtkFeatureWidget (DotNetProject project) + { + Spacing = 6; + + versionCombo = Gtk.ComboBox.NewText (); + ReferenceManager refmgr = new ReferenceManager (project); + foreach (string v in refmgr.SupportedGtkVersions) + versionCombo.AppendText (v); + versionCombo.Active = 0; + refmgr.Dispose (); + + // GTK# version selector + HBox box = new HBox (false, 6); + Gtk.Label vlab = new Label (GettextCatalog.GetString ("Target GTK# version:")); + box.PackStart (vlab, false, false, 0); + box.PackStart (versionCombo, false, false, 0); + box.PackStart (new Label (GettextCatalog.GetString ("(or upper)")), false, false, 0); + PackStart (box, false, false, 0); + + ShowAll (); + } + + public string SelectedVersion { + get { return versionCombo.ActiveText; } + } + } + + class GtkProjectFeature: ISolutionItemFeature + { + public string Title { + get { return GettextCatalog.GetString ("GTK# Support"); } + } + + public string Description { + get { return GettextCatalog.GetString ("Enables support for GTK# in the project. Allows the visual design of GTK# windows, and the creation of a GTK# widget library."); } + } + + public FeatureSupportLevel GetSupportLevel (SolutionFolder parentCombine, SolutionItem entry) + { + if (!(entry is DotNetProject) || !GtkDesignInfo.SupportsRefactoring (entry as DotNetProject)) + return FeatureSupportLevel.NotSupported; + else if (GtkDesignInfo.SupportsDesigner ((Project)entry)) + return FeatureSupportLevel.Enabled; + else if (entry is DotNetAssemblyProject) + return FeatureSupportLevel.SupportedByDefault; + else + return FeatureSupportLevel.Supported; + } + + public Widget CreateFeatureEditor (SolutionFolder parentCombine, SolutionItem entry) + { + return new GtkFeatureWidget ((DotNetProject) entry); + } + + public void ApplyFeature (SolutionFolder parentCombine, SolutionItem entry, Widget editor) + { + GtkFeatureWidget fw = (GtkFeatureWidget) editor; + ReferenceManager refmgr = new ReferenceManager ((DotNetProject) entry); + refmgr.GtkPackageVersion = fw.SelectedVersion; + refmgr.Dispose (); + } + + public string Validate (SolutionFolder parentCombine, SolutionItem entry, Gtk.Widget editor) + { + return null; + } + } +} diff --git a/main/src/addins/MonoDevelop.GtkCore2/MonoDevelop.GtkCore.Dialogs/ProjectConversionDialog.cs b/main/src/addins/MonoDevelop.GtkCore2/MonoDevelop.GtkCore.Dialogs/ProjectConversionDialog.cs new file mode 100644 index 0000000000..c7b091c6aa --- /dev/null +++ b/main/src/addins/MonoDevelop.GtkCore2/MonoDevelop.GtkCore.Dialogs/ProjectConversionDialog.cs @@ -0,0 +1,40 @@ +using System; +using Gtk; + +using MonoDevelop.Projects; + +namespace MonoDevelop.GtkCore.Dialogs +{ + public partial class ProjectConversionDialog : Gtk.Dialog + { + public ProjectConversionDialog (IntPtr raw) + : base (raw) + { + } + + public string GuiFolderName { get; private set; } + + public bool MakeBackup { get; private set; } + + + public ProjectConversionDialog (Project project, string guiFolderName) + { + this.Build (); + + entryFolder.Text = guiFolderName; + Title = project.Name; + entryFolder.Position = -1; + + buttonConvert.Clicked += HandleButtonConvertClicked; + } + + void HandleButtonConvertClicked (object sender, EventArgs e) + { + GuiFolderName = entryFolder.Text; + MakeBackup = checkBackup.Active; + + Respond (ResponseType.Yes); + } + } +} + diff --git a/main/src/addins/MonoDevelop.GtkCore2/MonoDevelop.GtkCore.Dialogs/SelectRenamedClassDialog.cs b/main/src/addins/MonoDevelop.GtkCore2/MonoDevelop.GtkCore.Dialogs/SelectRenamedClassDialog.cs new file mode 100644 index 0000000000..323a98ba19 --- /dev/null +++ b/main/src/addins/MonoDevelop.GtkCore2/MonoDevelop.GtkCore.Dialogs/SelectRenamedClassDialog.cs @@ -0,0 +1,93 @@ +// +// SelectRenamedClassDialog.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 System.Collections.Generic; +using Gtk; +using Gdk; +using Glade; +using MonoDevelop.Projects.Dom; +using MonoDevelop.Ide; + +namespace MonoDevelop.GtkCore.Dialogs +{ + public class SelectRenamedClassDialog: IDisposable + { + [Glade.Widget ("SelectRenamedClassDialog")] protected Gtk.Dialog dialog; + [Glade.Widget] protected Gtk.TreeView treeClasses; + ListStore store; + + public SelectRenamedClassDialog (IEnumerable<IType> classes) + { + XML glade = new XML (null, "gui.glade", "SelectRenamedClassDialog", null); + glade.Autoconnect (this); + + store = new ListStore (typeof(Pixbuf), typeof(string)); + treeClasses.Model = store; + + TreeViewColumn column = new TreeViewColumn (); + + var pr = new CellRendererPixbuf (); + column.PackStart (pr, false); + column.AddAttribute (pr, "pixbuf", 0); + + CellRendererText crt = new CellRendererText (); + column.PackStart (crt, true); + column.AddAttribute (crt, "text", 1); + + treeClasses.AppendColumn (column); + + foreach (IType cls in classes) { + Pixbuf pic = ImageService.GetPixbuf (cls.StockIcon); + store.AppendValues (pic, cls.FullName); + } + } + + public bool Run () + { + dialog.TransientFor = IdeApp.Workbench.RootWindow; + return dialog.Run () == (int) ResponseType.Ok; + } + + public string SelectedClass { + get { + Gtk.TreeModel foo; + Gtk.TreeIter iter; + if (!treeClasses.Selection.GetSelected (out foo, out iter)) + return null; + return (string) store.GetValue (iter, 1); + } + } + + public void Dispose () + { + dialog.Destroy (); + } + } + +} diff --git a/main/src/addins/MonoDevelop.GtkCore2/MonoDevelop.GtkCore.Dialogs/WidgetBuilderOptionPanel.cs b/main/src/addins/MonoDevelop.GtkCore2/MonoDevelop.GtkCore.Dialogs/WidgetBuilderOptionPanel.cs new file mode 100644 index 0000000000..fae7e91e7b --- /dev/null +++ b/main/src/addins/MonoDevelop.GtkCore2/MonoDevelop.GtkCore.Dialogs/WidgetBuilderOptionPanel.cs @@ -0,0 +1,143 @@ +// +// WidgetBuilderOptionPanel.cs +// +// Author: +// Lluis Sanchez Gual +// Mike Kestner +// +// Copyright (C) 2006, 2008 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 Gtk; + +using MonoDevelop.Core; +using MonoDevelop.Projects; +using MonoDevelop.Ide.Gui.Dialogs; + +namespace MonoDevelop.GtkCore.Dialogs +{ + class WidgetBuilderOptionPanel: ItemOptionsPanel + { + class WidgetBuilderOptionPanelWidget : Gtk.VBox + { + Gtk.CheckButton checkGettext; + Gtk.Entry entryGettext; + Gtk.ComboBox comboVersions; + Gtk.Entry entryFolderName; + Gtk.CheckButton checkHideFiles; + + DotNetProject project; + + public WidgetBuilderOptionPanelWidget (Project project) : base (false, 6) + { + this.project = project as DotNetProject; + + Gtk.HBox box = new Gtk.HBox (false, 3); + Gtk.Label lbl = new Gtk.Label (GettextCatalog.GetString ("Target Gtk# version:")); + box.PackStart (lbl, false, false, 0); + comboVersions = ComboBox.NewText (); + ReferenceManager refmgr = new ReferenceManager (project as DotNetProject); + foreach (string v in refmgr.SupportedGtkVersions) + comboVersions.AppendText (v); + comboVersions.Active = refmgr.SupportedGtkVersions.IndexOf (refmgr.GtkPackageVersion); + refmgr.Dispose (); + box.PackStart (comboVersions, false, false, 0); + box.ShowAll (); + PackStart (box, false, false, 0); + + HSeparator sep = new HSeparator (); + sep.Show (); + PackStart (sep, false, false, 0); + + if (!GtkDesignInfo.HasDesignedObjects (project)) + return; + + GtkDesignInfo designInfo = GtkDesignInfo.FromProject (project); + checkGettext = new CheckButton (GettextCatalog.GetString ("Enable gettext support")); + checkGettext.Active = designInfo.GenerateGettext; + checkGettext.Show (); + PackStart (checkGettext, false, false, 0); + box = new Gtk.HBox (false, 3); + box.PackStart (new Label (GettextCatalog.GetString ("Gettext class:")), false, false, 0); + entryGettext = new Gtk.Entry (); + entryGettext.Text = designInfo.GettextClass; + entryGettext.Sensitive = checkGettext.Active; + box.PackStart (entryGettext, false, false, 0); + box.ShowAll (); + PackStart (box, false, false, 0); + + sep= new HSeparator (); + sep.Show (); + PackStart (sep, false, false, 0); + + box = new Gtk.HBox (false, 3); + box.PackStart (new Label (GettextCatalog.GetString ("Stetic folder name :")), false, false, 0); + entryFolderName = new Gtk.Entry (); + entryFolderName.Text = designInfo.SteticFolderName; + entryFolderName.Sensitive = false; + box.PackStart (entryFolderName, false, false, 0); + box.ShowAll (); + PackStart (box, false, false, 0); + + checkHideFiles = new CheckButton (GettextCatalog.GetString ("Hide designer files")); + checkHideFiles.Active = designInfo.HideGtkxFiles; + checkHideFiles.Show (); + PackStart (checkHideFiles, false, false, 0); + } + + public void Store () + { + ReferenceManager refmgr = new ReferenceManager (project); + if (!string.IsNullOrEmpty (comboVersions.ActiveText)) + refmgr.GtkPackageVersion = comboVersions.ActiveText; + if (GtkDesignInfo.HasDesignedObjects (project)) { + GtkDesignInfo info = GtkDesignInfo.FromProject (project); + info.GenerateGettext = checkGettext.Active; + info.GettextClass = entryGettext.Text; + info.GuiBuilderProject.SteticProject.TargetGtkVersion = comboVersions.ActiveText; + info.SteticFolderName = entryFolderName.Text; + info.HideGtkxFiles = checkHideFiles.Active; + info.GuiBuilderProject.Save (false); + } + refmgr.Dispose (); + } + } + + WidgetBuilderOptionPanelWidget widget; + + public override Widget CreatePanelWidget() + { + return (widget = new WidgetBuilderOptionPanelWidget (ConfiguredProject)); + } + + public override bool IsVisible () + { + return GtkDesignInfo.SupportsDesigner (DataObject as Project); + } + + public override void ApplyChanges () + { + widget.Store (); + } + } +} diff --git a/main/src/addins/MonoDevelop.GtkCore2/MonoDevelop.GtkCore.GuiBuilder/ActionGroupDisplayBinding.cs b/main/src/addins/MonoDevelop.GtkCore2/MonoDevelop.GtkCore.GuiBuilder/ActionGroupDisplayBinding.cs new file mode 100644 index 0000000000..dd8bb93383 --- /dev/null +++ b/main/src/addins/MonoDevelop.GtkCore2/MonoDevelop.GtkCore.GuiBuilder/ActionGroupDisplayBinding.cs @@ -0,0 +1,206 @@ +// +// ActionGroupDisplayBinding.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.Collections; +using System.CodeDom; + +using MonoDevelop.Core; +using MonoDevelop.Ide.Gui; +using MonoDevelop.Projects; +using MonoDevelop.Projects.Dom; +using MonoDevelop.Projects.Dom.Parser; +using MonoDevelop.Projects.CodeGeneration; +using MonoDevelop.GtkCore.Dialogs; +using MonoDevelop.Ide; + +namespace MonoDevelop.GtkCore.GuiBuilder +{ + public class ActionGroupDisplayBinding : DisplayBinding + { + bool excludeThis = false; + + public override string Name { + get { return "Action Group Editor"; } + } + + public override bool CanCreateContentForUri (string fileName) + { + Project project = IdeApp.Workspace.GetProjectContainingFile (fileName); + GtkDesignInfo info = GtkDesignInfo.FromProject ((DotNetProject) project); + + if (excludeThis) + return false; + + if (fileName.Contains (info.BuildFileExtension)) + return false; + + if (!IdeApp.Workspace.IsOpen) + return false; + + if (GetActionGroup (fileName) == null) + return false; + + + excludeThis = true; + var db = DisplayBindingService.GetDefaultBindingForUri (fileName); + excludeThis = false; + return db != null; + } + + public override IViewContent CreateContentForUri (string fileName) + { + excludeThis = true; + var db = DisplayBindingService.GetDefaultBindingForUri (fileName); + + Project project = IdeApp.Workspace.GetProjectContainingFile (fileName); + GtkDesignInfo info = GtkDesignInfo.FromProject ((DotNetProject) project); + + ActionGroupView view = new ActionGroupView (db.CreateContentForUri (fileName), GetActionGroup (fileName), info.GuiBuilderProject); + excludeThis = false; + return view; + } + Stetic.ActionGroupInfo GetActionGroup (string file) + { + Project project = IdeApp.Workspace.GetProjectContainingFile (file); + if (!GtkDesignInfo.HasDesignedObjects (project)) + return null; + + return GtkDesignInfo.FromProject (project).GuiBuilderProject.GetActionGroupForFile (file); + } + + internal static string BindToClass (Project project, Stetic.ActionGroupInfo group) + { + GuiBuilderProject gproject = GtkDesignInfo.FromProject (project).GuiBuilderProject; + string file = gproject.GetSourceCodeFile (group); + if (file != null) + return file; + + // Find the classes that could be bound to this design + + ArrayList list = new ArrayList (); + ProjectDom ctx = gproject.GetParserContext (); + foreach (IType cls in ctx.Types) + if (IsValidClass (ctx, cls)) + list.Add (cls.FullName); + + // Ask what to do + + using (BindDesignDialog dialog = new BindDesignDialog (group.Name, list, project.BaseDirectory)) { + if (!dialog.Run ()) + return null; + + if (dialog.CreateNew) + CreateClass (project, (Stetic.ActionGroupComponent) group.Component, dialog.ClassName, dialog.Namespace, dialog.Folder); + + string fullName = dialog.Namespace.Length > 0 ? dialog.Namespace + "." + dialog.ClassName : dialog.ClassName; + group.Name = fullName; + } + return gproject.GetSourceCodeFile (group); + } + + static IType CreateClass (Project project, Stetic.ActionGroupComponent group, string name, string namspace, string folder) + { + string fullName = namspace.Length > 0 ? namspace + "." + name : name; + + CodeRefactorer gen = new CodeRefactorer (project.ParentSolution); + + CodeTypeDeclaration type = new CodeTypeDeclaration (); + type.Name = name; + type.IsClass = true; + type.BaseTypes.Add (new CodeTypeReference ("Gtk.ActionGroup")); + + // Generate the constructor. It contains the call that builds the widget. + + CodeConstructor ctor = new CodeConstructor (); + ctor.Attributes = MemberAttributes.Public | MemberAttributes.Final; + ctor.BaseConstructorArgs.Add (new CodePrimitiveExpression (fullName)); + + CodeMethodInvokeExpression call = new CodeMethodInvokeExpression ( + new CodeMethodReferenceExpression ( + new CodeTypeReferenceExpression ("Stetic.Gui"), + "Build" + ), + new CodeThisReferenceExpression (), + new CodeTypeOfExpression (fullName) + ); + ctor.Statements.Add (call); + type.Members.Add (ctor); + + // Add signal handlers + + foreach (Stetic.ActionComponent action in group.GetActions ()) { + foreach (Stetic.Signal signal in action.GetSignals ()) { + CodeMemberMethod met = new CodeMemberMethod (); + met.Name = signal.Handler; + met.Attributes = MemberAttributes.Family; + met.ReturnType = new CodeTypeReference (signal.SignalDescriptor.HandlerReturnTypeName); + + foreach (Stetic.ParameterDescriptor pinfo in signal.SignalDescriptor.HandlerParameters) + met.Parameters.Add (new CodeParameterDeclarationExpression (pinfo.TypeName, pinfo.Name)); + + type.Members.Add (met); + } + } + + // Create the class + + IType cls = null; + cls = gen.CreateClass (project, ((DotNetProject)project).LanguageName, folder, namspace, type); + if (cls == null) + throw new UserException ("Could not create class " + fullName); + + project.AddFile (cls.CompilationUnit.FileName, BuildAction.Compile); + IdeApp.ProjectOperations.Save (project); + +#if TRUNK + // Make sure the database is up-to-date + ProjectDomService.Parse (project, cls.CompilationUnit.FileName); +#else + ProjectDomService.Parse (project, cls.CompilationUnit.FileName, null); + +#endif + return cls; + } + + internal static bool IsValidClass (ProjectDom ctx, IType cls) + { + if (cls.BaseTypes != null) { + foreach (IReturnType bt in cls.BaseTypes) { + if (bt.FullName == "Gtk.ActionGroup") + return true; + + IType baseCls = ctx.GetType (bt); + if (baseCls != null && IsValidClass (ctx, baseCls)) + return true; + } + } + return false; + } + } +} diff --git a/main/src/addins/MonoDevelop.GtkCore2/MonoDevelop.GtkCore.GuiBuilder/ActionGroupView.cs b/main/src/addins/MonoDevelop.GtkCore2/MonoDevelop.GtkCore.GuiBuilder/ActionGroupView.cs new file mode 100644 index 0000000000..0be5db765f --- /dev/null +++ b/main/src/addins/MonoDevelop.GtkCore2/MonoDevelop.GtkCore.GuiBuilder/ActionGroupView.cs @@ -0,0 +1,316 @@ +// +// ActionGroupView.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 System.Collections; + +using MonoDevelop.Projects; +using MonoDevelop.Projects.Dom; +using MonoDevelop.Core; +using MonoDevelop.Ide.Gui; +using MonoDevelop.Ide.Commands; +using MonoDevelop.Components.Commands; +using MonoDevelop.DesignerSupport; + +namespace MonoDevelop.GtkCore.GuiBuilder +{ + public class ActionGroupView: CombinedDesignView + { + Stetic.ActionGroupDesigner designer; + CodeBinder codeBinder; + GuiBuilderProject project; + Stetic.ActionGroupComponent group; + Stetic.ActionGroupInfo groupInfo; + string groupName; + + public ActionGroupView (IViewContent content, Stetic.ActionGroupInfo group, GuiBuilderProject project): base (content) + { + groupName = group.Name; + this.project = project; + LoadDesigner (); + } + + void LoadDesigner () + { + groupInfo = project.GetActionGroup (groupName); + if (groupInfo == null) + // Group not found + return; + + group = (Stetic.ActionGroupComponent) groupInfo.Component; + project.Unloaded += OnDisposeProject; + + designer = project.SteticProject.CreateActionGroupDesigner (groupInfo, false); + designer.AllowActionBinding = project.Project.UsePartialTypes; + designer.BindField += new EventHandler (OnBindField); + + ActionGroupPage actionsPage = new ActionGroupPage (); + actionsPage.PackStart (designer, true, true, 0); + actionsPage.ShowAll (); + + AddButton (GettextCatalog.GetString ("Actions"), actionsPage); + + designer.ModifiedChanged += OnGroupModified; + designer.SignalAdded += OnSignalAdded; + designer.SignalChanged += OnSignalChanged; + designer.RootComponentChanged += OnRootComponentChanged; + + codeBinder = new CodeBinder (project.Project, new OpenDocumentFileProvider (), designer.RootComponent); + } + + public void CloseDesigner () + { + if (designer == null) + return; + project.Unloaded -= OnDisposeProject; + designer.BindField -= OnBindField; + designer.RootComponentChanged -= OnRootComponentChanged; + designer.ModifiedChanged -= OnGroupModified; + designer.SignalAdded -= OnSignalAdded; + designer.SignalChanged -= OnSignalChanged; + designer.Destroy (); + designer = null; + + project.Reloaded += OnReloadProject; + } + + public override Stetic.Designer Designer { + get { return designer; } + } + + void OnDisposeProject (object s, EventArgs args) + { + RemoveButton (1); + CloseDesigner (); + } + + void OnReloadProject (object s, EventArgs args) + { + if (designer == null) + LoadDesigner (); + } + + public Stetic.ActionGroupComponent ActionGroup { + get { return group; } + set { Load (value.Name); } + } + + public override void ShowPage (int npage) + { + if (designer != null && group != null) { + // At every page switch update the generated code, to make sure code completion works + // for the generated fields. The call to GenerateSteticCodeStructure will generate + // the code for the window (only the fields in fact) and update the parser database, it + // will not save the code to disk. + if (project.Project.UsePartialTypes) + GuiBuilderService.GenerateSteticCodeStructure ((DotNetProject)project.Project, designer.RootComponent, null, false, false); + } + base.ShowPage (npage); + } + + void OnRootComponentChanged (object s, EventArgs args) + { + codeBinder.TargetObject = designer.RootComponent; + } + + public override void Save (string fileName) + { + string oldBuildFile = GuiBuilderService.GetBuildCodeFileName (project.Project, groupInfo.Name); + + base.Save (fileName); + if (designer == null) + return; + + codeBinder.UpdateBindings (fileName); + + designer.Save (); + + string newBuildFile = GuiBuilderService.GetBuildCodeFileName (project.Project, groupInfo.Name); + if (oldBuildFile != newBuildFile && oldBuildFile != null && newBuildFile != null) + FileService.MoveFile (oldBuildFile, newBuildFile); + + project.Save (true); + OnDirtyChanged (EventArgs.Empty); + } + + public override void Dispose () + { + CloseDesigner (); + project.Reloaded -= OnReloadProject; + base.Dispose (); + } + + public void ShowDesignerView () + { + ShowPage (1); + } + + public void SelectAction (Stetic.ActionComponent action) + { + if (designer != null) + designer.SelectedAction = action; + } + + public override void JumpToSignalHandler (Stetic.Signal signal) + { + IType cls = codeBinder.GetClass (); + foreach (IMethod met in cls.Methods) { + if (met.Name == signal.Handler) { + ShowPage (1); + JumpTo (met.Location.Line, met.Location.Column); + break; + } + } + } + + void OnGroupModified (object s, EventArgs a) + { + if (designer.Modified) + OnContentChanged (a); + IsDirty = designer.Modified; + } + + void OnSignalAdded (object s, Stetic.ComponentSignalEventArgs a) + { + codeBinder.BindSignal (a.Signal); + } + + void OnSignalChanged (object s, Stetic.ComponentSignalEventArgs a) + { + codeBinder.UpdateSignal (a.OldSignal, a.Signal); + } + + void OnBindField (object s, EventArgs args) + { + if (designer.SelectedAction != null) { + codeBinder.BindToField (designer.SelectedAction); + } + } + } + + class ActionGroupPage: Gtk.VBox, ICustomPropertyPadProvider + { + public ActionGroupPage () + { + } + + Gtk.Widget ICustomPropertyPadProvider.GetCustomPropertyWidget () + { + return PropertiesWidget.Instance; + } + + void ICustomPropertyPadProvider.DisposeCustomPropertyWidget () + { + } + + public void ClearChild () + { + if (Children.Length > 0) { + Gtk.Widget w = Children [0]; + Remove (w); + w.Destroy (); + } + } + + Stetic.ActionGroupDesigner actionsBox { + get { return Children[0] as Stetic.ActionGroupDesigner; } + } + + [CommandHandler (EditCommands.Delete)] + protected void OnDelete () + { + actionsBox.DeleteSelection (); + } + + [CommandUpdateHandler (EditCommands.Delete)] + protected void OnUpdateDelete (CommandInfo cinfo) + { + cinfo.Enabled = actionsBox != null && actionsBox.SelectedAction != null; + } + + [CommandHandler (EditCommands.Copy)] + protected void OnCopy () + { + actionsBox.CopySelection (); + } + + [CommandUpdateHandler (EditCommands.Copy)] + protected void OnUpdateCopy (CommandInfo cinfo) + { + cinfo.Enabled = actionsBox != null && actionsBox.SelectedAction != null; + } + + [CommandHandler (EditCommands.Cut)] + protected void OnCut () + { + actionsBox.CutSelection (); + } + + [CommandUpdateHandler (EditCommands.Cut)] + protected void OnUpdateCut (CommandInfo cinfo) + { + cinfo.Enabled = actionsBox != null && actionsBox.SelectedAction != null; + } + + [CommandHandler (EditCommands.Paste)] + protected void OnPaste () + { + actionsBox.PasteToSelection (); + } + + [CommandUpdateHandler (EditCommands.Paste)] + protected void OnUpdatePaste (CommandInfo cinfo) + { + cinfo.Enabled = false; + } + + [CommandHandler (EditCommands.Undo)] + protected void OnUndo () + { + actionsBox.UndoQueue.Undo (); + } + + [CommandHandler (EditCommands.Redo)] + protected void OnRedo () + { + actionsBox.UndoQueue.Redo (); + } + + [CommandUpdateHandler (EditCommands.Undo)] + protected void OnUpdateUndo (CommandInfo cinfo) + { + cinfo.Enabled = actionsBox != null && actionsBox.UndoQueue.CanUndo; + } + + [CommandUpdateHandler (EditCommands.Redo)] + protected void OnUpdateRedo (CommandInfo cinfo) + { + cinfo.Enabled = actionsBox != null && actionsBox.UndoQueue.CanRedo; + } + } +} diff --git a/main/src/addins/MonoDevelop.GtkCore2/MonoDevelop.GtkCore.GuiBuilder/ChangeLog b/main/src/addins/MonoDevelop.GtkCore2/MonoDevelop.GtkCore.GuiBuilder/ChangeLog new file mode 100644 index 0000000000..a57bb556bb --- /dev/null +++ b/main/src/addins/MonoDevelop.GtkCore2/MonoDevelop.GtkCore.GuiBuilder/ChangeLog @@ -0,0 +1,101 @@ +2010-10-28 Krzysztof Marecki <marecki.krzysztof@gmail.com> + + * GuiBuilderView.cs: + * GuiBuilderWindow.cs: + * GuiBuilderProject.cs: + +2010-09-08 Krzysztof Marecki <freefirma@gmail.com> + + * GuiBuilderWindow.cs: + * GuiBuilderService.cs: + * CombinedDesignView.cs: + +2010-08-30 Krzysztof Marecki <freefirma@gmail.com> + + * GuiBuilderProject.cs: + +2010-08-16 Krzysztof Marecki <freefirma@gmail.com> + + * GuiBuilderView.cs: + * ActionGroupView.cs: + * GuiBuilderProject.cs: + * GuiBuilderService.cs: + * GuiBuilderDisplayBinding.cs: + * ActionGroupDisplayBinding.cs: + * GtkProjectServiceExtension.cs: + +2010-08-15 Krzysztof Marecki <freefirma@gmail.com> + + * GuiBuilderProject.cs: + +2010-08-15 Krzysztof Marecki <freefirma@gmail.com> + + * GuiBuilderProject.cs: + * GuiBuilderService.cs: + +2010-08-13 Krzysztof Marecki <freefirma@gmail.com> + + * GuiBuilderView.cs: + * GuiBuilderProject.cs: + * GuiBuilderService.cs: + * GuiBuilderDisplayBinding.cs: + * ActionGroupDisplayBinding.cs: + +2010-08-09 Krzysztof Marecki <freefirma@gmail.com> + + * GuiBuilderProject.cs: Generate stetic code after a project converting + * GuiBuilderService.cs: + * GuiBuilderDisplayBinding.cs: Don't use component display binding for + generated partial files + +2010-08-07 Krzysztof Marecki <marecki.krzysztof@gmail.com> + + * GuiBuilderView.cs: Raise OnDirtyChanged after saving. + * CombinedDesignView.cs: Track Api Changes. + +2010-08-05 Krzysztof Marecki <freefirma@gmail.com> + + * GuiBuilderView.cs: Remove ModifiedChanged handler + +2010-08-04 Krzysztof Marecki <freefirma@gmail.com> + + * CodeBinder.cs: Bump Api + * GuiBuilderWindow.cs: + * GuiBuilderService.cs: + * CombinedDesignView.cs: + * ActionGroupDisplayBinding.cs: + +2010-08-03 Krzysztof Marecki <marecki.krzysztof@gmail.com> + + * GuiBuilderProject.cs: When Updatinglibraries don't save + if Stetic.Project was uninitialized + +2010-07-27 Krzysztof Marecki <marecki.krzysztof@gmail.com> + + * GuiBuilderView.cs: + * CombinedDesignView.cs: + +2010-07-06 Krzysztof Marecki <marecki.krzysztof@gmail.com> + + * GuiBuilderProject.cs: + * GuiBuilderService.cs: + +2010-07-05 Krzysztof Marecki <marecki.krzysztof@gmail.com> + + * GuiBuilderProject.cs: + * CombinedDesignView.cs: + +2010-06-23 Krzysztof Marecki <marecki.krzysztof@gmail.com> + + * GuiBuilderProject.cs: + +2010-06-21 Krzysztof Marecki <marecki.krzysztof@gmail.com> + + * GuiBuilderProject.cs: Add Convert method + +2010-06-07 Krzysztof Marecki <marecki.krzysztof@gmail.com> + + * GuiBuilderProject.cs: + * GuiBuilderService.cs: + * GtkProjectServiceExtension.cs: + diff --git a/main/src/addins/MonoDevelop.GtkCore2/MonoDevelop.GtkCore.GuiBuilder/ClassUtils.cs b/main/src/addins/MonoDevelop.GtkCore2/MonoDevelop.GtkCore.GuiBuilder/ClassUtils.cs new file mode 100644 index 0000000000..ec5c5ea988 --- /dev/null +++ b/main/src/addins/MonoDevelop.GtkCore2/MonoDevelop.GtkCore.GuiBuilder/ClassUtils.cs @@ -0,0 +1,64 @@ +// +// ClassUtils.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 Gtk; +using System; +using System.Collections; +using System.CodeDom; +using MonoDevelop.Projects.Dom; + +namespace MonoDevelop.GtkCore.GuiBuilder +{ + internal class ClassUtils + { + public static IField FindWidgetField (IType cls, string name) + { + foreach (IField field in cls.Fields) { + if (name == GetWidgetFieldName (field)) + return field; + } + return null; + } + + public static string GetWidgetFieldName (IField field) + { + foreach (IAttribute att in field.Attributes) { + if (att.Name == "Glade.Widget" || att.Name == "Widget" || att.Name == "Glade.WidgetAttribute" || att.Name == "WidgetAttribute") { + if (att.PositionalArguments != null && att.PositionalArguments.Count > 0) { + CodePrimitiveExpression exp = att.PositionalArguments [0] as CodePrimitiveExpression; + if (exp != null) + return exp.Value.ToString (); + } else { + return field.Name; + } + } + } + return field.Name; + } + } +} diff --git a/main/src/addins/MonoDevelop.GtkCore2/MonoDevelop.GtkCore.GuiBuilder/CodeBinder.cs b/main/src/addins/MonoDevelop.GtkCore2/MonoDevelop.GtkCore.GuiBuilder/CodeBinder.cs new file mode 100644 index 0000000000..fc19797521 --- /dev/null +++ b/main/src/addins/MonoDevelop.GtkCore2/MonoDevelop.GtkCore.GuiBuilder/CodeBinder.cs @@ -0,0 +1,360 @@ +// +// CodeBinder.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.CodeDom; +using System.Collections; + +using MonoDevelop.Core; +using MonoDevelop.Core.ProgressMonitoring; +using MonoDevelop.Projects; +using MonoDevelop.Projects.Text; +using MonoDevelop.Projects.Dom; +using MonoDevelop.Projects.Dom.Parser; +using MonoDevelop.Projects.CodeGeneration; +using MonoDevelop.Ide.Gui; +using MonoDevelop.GtkCore.Dialogs; +using MonoDevelop.Ide; + +namespace MonoDevelop.GtkCore.GuiBuilder +{ + /// This class provides several methods for managing the relation + /// between an object (e.g. a window) and the source code that will implement the + /// code for that object. + /// + /// Once created, a CodeBinder object will keep track of the class bound to the + /// object. If the class is renamed, it will properly update the object name. + + public class CodeBinder + { + ITextFileProvider textFileProvider; + Stetic.Component targetObject; + Project project; + GuiBuilderProject gproject; + string className; + string classFile; + + public CodeBinder (Project project, ITextFileProvider textFileProvider, Stetic.Component targetObject) + { + this.project = project; + this.textFileProvider = textFileProvider; + + gproject = GtkDesignInfo.FromProject (project).GuiBuilderProject; + + TargetObject = targetObject; + } + + public Stetic.Component TargetObject { + get { return targetObject; } + set { + this.targetObject = value; + if (targetObject != null) { + IType cls = gproject.FindClass (GetClassName (targetObject)); + if (cls != null) { + className = cls.FullName; + classFile = cls.CompilationUnit.FileName; + } + } + } + } + + /// Synchronizes the bindings between the object and the source code + public void UpdateBindings (string fileName) + { + if (targetObject == null) + return; +#if TRUNK + ParsedDocument doc = ProjectDomService.Parse (project, fileName); +#else + ParsedDocument doc = ProjectDomService.Parse (project, fileName, null); +#endif + classFile = fileName; + + if (doc != null && doc.CompilationUnit != null) { + IType cls = GetClass (); + UpdateBindings (targetObject, cls); + + if (cls != null) + targetObject.GeneratePublic = cls.IsPublic; + } + } + + void UpdateBindings (Stetic.Component obj, IType cls) + { + if (targetObject == null) + return; + + // Remove signals for which there isn't a handler in the class + + Stetic.SignalCollection objectSignals = obj.GetSignals (); + if (objectSignals != null) { + Stetic.Signal[] signals = new Stetic.Signal [objectSignals.Count]; + objectSignals.CopyTo (signals, 0); + + foreach (Stetic.Signal signal in signals) { + if (FindSignalHandler (cls, signal) == null) { + obj.RemoveSignal (signal); + } + } + } + + // Update children + + foreach (Stetic.Component ob in obj.GetChildren ()) + UpdateBindings (ob, cls); + } + + IMethod FindSignalHandler (IType cls, Stetic.Signal signal) + { + foreach (IMethod met in cls.Methods) { + if (met.Name == signal.Handler) { + return met; + } + } + return null; + } + + public void UpdateField (Stetic.Component obj, string oldName) + { + if (targetObject == null) + return; + + CodeRefactorer cr = GetCodeGenerator (); + + IType cls; + + if (obj == targetObject) + return; // The root widget name can only be changed internally. + else + cls = GetClass (false); + + string newName = GetObjectName (obj); + if (newName.Length == 0) + return; + + if (cls != null) { + IField f = ClassUtils.FindWidgetField (cls, oldName); + if (f != null) { + cr.RenameMember (new NullProgressMonitor (), cls, f, newName, RefactoryScope.File); + } + } + } + + /// Adds a signal handler to the class + public void BindSignal (Stetic.Signal signal) + { + if (targetObject == null) + return; + + IType cls = GetClass (); + if (cls == null) + return; + + if (FindSignalHandler (cls, signal) != null) + return; + + CodeMemberMethod met = new CodeMemberMethod (); + met.Name = signal.Handler; + met.Attributes = MemberAttributes.Family; + met.ReturnType = new CodeTypeReference (signal.SignalDescriptor.HandlerReturnTypeName); + + foreach (Stetic.ParameterDescriptor pinfo in signal.SignalDescriptor.HandlerParameters) + met.Parameters.Add (new CodeParameterDeclarationExpression (pinfo.TypeName, pinfo.Name)); + CodeRefactorer gen = GetCodeGenerator (); + gen.AddMember (cls, met); + } + + public void UpdateSignal (Stetic.Signal oldSignal, Stetic.Signal newSignal) + { + if (targetObject == null) + return; + + if (oldSignal.Handler == newSignal.Handler) + return; + + IType cls = GetClass (); + if (cls == null) return; + + IMethod met = FindSignalHandler (cls, oldSignal); + if (met == null) return; + CodeRefactorer gen = GetCodeGenerator (); + gen.RenameMember (new NullProgressMonitor (), cls, met, newSignal.Handler, RefactoryScope.File); + } + + /// Adds a field to the class + public void BindToField (Stetic.Component obj) + { + if (targetObject == null) + return; + + string name = GetMemberName (obj); + IType cls = GetClass (); + + if (FindField (cls, name) != null) + return; + + Document doc = IdeApp.Workbench.OpenDocument (cls.CompilationUnit.FileName, true); + + IEditableTextFile editor = doc.GetContent<IEditableTextFile> (); + if (editor != null) { + CodeRefactorer gen = GetCodeGenerator (); + gen.AddMember (cls, GetFieldCode (obj, name)); + } + } + + CodeMemberField GetFieldCode (Stetic.Component obj, string name) + { + string type = obj.Type.ClassName; + CodeMemberField field = new CodeMemberField (type, name); + field.Attributes = MemberAttributes.Family; + return field; + } + + IField FindField (IType cls, string name) + { + foreach (IField field in cls.Fields) + if (field.Name == name) + return field; + return null; + } + + CodeRefactorer GetCodeGenerator () + { + CodeRefactorer cr = new CodeRefactorer (project.ParentSolution); + cr.TextFileProvider = textFileProvider; + return cr; + } + + public IType GetClass () + { + return GetClass (true); + } + + public IType GetClass (bool getUserClass) + { + if (targetObject == null) + return null; + + IType cls = gproject.FindClass (className, getUserClass); + if (cls != null) + return cls; + + // The class name may have changed. Try to guess the new name. + + ArrayList matches = new ArrayList (); + ICompilationUnit unit = null; + ProjectDom ctx = gproject.GetParserContext (); +#if TRUNK + ParsedDocument doc = ProjectDomService.Parse (project, classFile); +#else + ParsedDocument doc = ProjectDomService.Parse (project, classFile, null); +#endif + + if (doc != null && doc.CompilationUnit != null) { + unit = doc.CompilationUnit; + foreach (IType fcls in unit.Types) { + if (IsValidClass (ctx, fcls, targetObject)) + matches.Add (fcls); + } + } + + // If found the class, just return it + if (matches.Count == 1) { + cls = (IType) matches [0]; + className = cls.FullName; + targetObject.Name = className; + gproject.Save (true); + return cls; + } + + // If not found, warn the user. + + if (unit != null && unit.Types.Count > 0) { + using (SelectRenamedClassDialog dialog = new SelectRenamedClassDialog (unit.Types)) { + if (dialog.Run ()) { + className = dialog.SelectedClass; + if (className == null) + return null; + else { + targetObject.Name = className; + gproject.Save (true); + return gproject.FindClass (className); + } + } + } + } else { + MessageService.ShowError (GettextCatalog.GetString ("The class bound to the component '{0}' could not be found. This may be due to syntax errors in the source code file.", GetObjectName(targetObject))); + } + + return null; + } + + static bool IsValidClass (ProjectDom ctx, IType cls, Stetic.Component obj) + { + if (cls.BaseTypes != null) { + string typeName = obj.Type.ClassName; + + foreach (IReturnType bt in cls.BaseTypes) { + System.Console.WriteLine("tn:" + typeName + " bt:" + bt.FullName); + if (bt.FullName == typeName) + return true; + + IType baseCls = ctx.GetType (bt); + if (baseCls != null && IsValidClass (ctx, baseCls, obj)) + return true; + } + } + return false; + } + + internal static string GetClassName (Stetic.Component obj) + { + return GetObjectName (obj); + } + + internal static string GetMemberName (Stetic.Component obj) + { + return obj.Name; + } + + internal static string GetObjectName (Stetic.Component obj) + { + return obj.Name; + } + + internal static string GetClassName (Stetic.ProjectItemInfo obj) + { + return GetObjectName (obj); + } + + internal static string GetObjectName (Stetic.ProjectItemInfo obj) + { + return obj.Name; + } + } +} diff --git a/main/src/addins/MonoDevelop.GtkCore2/MonoDevelop.GtkCore.GuiBuilder/CombinedDesignView.cs b/main/src/addins/MonoDevelop.GtkCore2/MonoDevelop.GtkCore.GuiBuilder/CombinedDesignView.cs new file mode 100644 index 0000000000..b7e3313317 --- /dev/null +++ b/main/src/addins/MonoDevelop.GtkCore2/MonoDevelop.GtkCore.GuiBuilder/CombinedDesignView.cs @@ -0,0 +1,307 @@ +// +// CombinedDesignView.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 MonoDevelop.Core; +using MonoDevelop.Ide.Gui.Content; +using MonoDevelop.Ide.Gui; +using MonoDevelop.Components.Commands; +using MonoDevelop.Ide; + +namespace MonoDevelop.GtkCore.GuiBuilder +{ + public class CombinedDesignView : AbstractViewContent + { + IViewContent content; + Gtk.Notebook notebook; + VBox box; + Toolbar toolbar; + + bool updating; + + public CombinedDesignView (IViewContent content) + { + this.content = content; + if (content is IEditableTextBuffer) { + ((IEditableTextBuffer)content).CaretPositionSet += delegate { + ShowPage (0); + }; + } + content.ContentChanged += new EventHandler (OnTextContentChanged); + content.DirtyChanged += new EventHandler (OnTextDirtyChanged); + + notebook = new Gtk.Notebook (); + + // Main notebook + + notebook.TabPos = Gtk.PositionType.Bottom; + notebook.ShowTabs = false; + notebook.ShowBorder = false; + notebook.Show (); + box = new VBox (); + + // Bottom toolbar + + toolbar = new Toolbar (); + toolbar.IconSize = IconSize.SmallToolbar; + toolbar.ToolbarStyle = ToolbarStyle.BothHoriz; + toolbar.ShowArrow = false; + + CommandRouterContainer crc = new CommandRouterContainer (content.Control, content, true); + crc.Show (); + AddButton (GettextCatalog.GetString ("Source Code"), crc).Active = true; + + toolbar.ShowAll (); + + box.PackStart (notebook, true, true, 0); + box.PackStart (toolbar, false, false, 0); + + box.Show (); + + IdeApp.Workbench.ActiveDocumentChanged += new EventHandler (OnActiveDocumentChanged); + content.Control.Realized += delegate { + if (content != null && content.WorkbenchWindow != null) + content.WorkbenchWindow.ActiveViewContent = notebook.CurrentPageWidget == content.Control ? content : this; + }; + notebook.SwitchPage += delegate { + if (content != null && content.WorkbenchWindow != null) + content.WorkbenchWindow.ActiveViewContent = notebook.CurrentPageWidget == content.Control ? content : this; + }; + } + + public virtual Stetic.Designer Designer { + get { return null; } + } + + protected ToggleToolButton AddButton (string label, Gtk.Widget page) + { + updating = true; + ToggleToolButton button = new ToggleToolButton (); + button.Label = label; + button.IsImportant = true; + button.Clicked += new EventHandler (OnButtonToggled); + button.ShowAll (); + toolbar.Insert (button, -1); + notebook.AppendPage (page, new Gtk.Label ()); + updating = false; + return button; + } + + public bool HasPage (Gtk.Widget page) + { + return notebook.PageNum (page) != -1; + } + + public void RemoveButton (Gtk.Widget page) + { + int i = notebook.PageNum (page); + if (i != -1) + RemoveButton (i); + } + + public void RemoveButton (int npage) + { + if (npage >= toolbar.Children.Length) + return; + notebook.RemovePage (npage); + Gtk.Widget cw = toolbar.Children [npage]; + toolbar.Remove (cw); + cw.Destroy (); + ShowPage (0); + } + + public override MonoDevelop.Projects.Project Project { + get { return base.Project; } + set { + base.Project = value; + content.Project = value; + } + } + + protected override void OnWorkbenchWindowChanged (EventArgs e) + { + base.OnWorkbenchWindowChanged (e); + content.WorkbenchWindow = WorkbenchWindow; + } + + void OnButtonToggled (object s, EventArgs args) + { + int i = Array.IndexOf (toolbar.Children, s); + if (i != -1) + ShowPage (i); + } + + public virtual void ShowPage (int npage) + { + if (notebook.CurrentPage == npage) + return; + + if (updating) return; + updating = true; + + notebook.CurrentPage = npage; + Gtk.Widget[] buttons = toolbar.Children; + for (int n=0; n<buttons.Length; n++) { + ToggleToolButton b = (ToggleToolButton) buttons [n]; + b.Active = (n == npage); + } + updating = false; + } + + public override void Dispose () + { + content.ContentChanged -= new EventHandler (OnTextContentChanged); + content.DirtyChanged -= new EventHandler (OnTextDirtyChanged); + IdeApp.Workbench.ActiveDocumentChanged -= new EventHandler (OnActiveDocumentChanged); + content.Dispose (); + + // Remove and destroy the contents of the Notebook, since the destroy event is + // not propagated to pages in some gtk versions. + + foreach (Gtk.Widget cw in notebook.Children) { + Gtk.Widget lw = notebook.GetTabLabel (cw); + notebook.Remove (cw); + cw.Destroy (); + if (lw != null) + lw.Destroy (); + } + content = null; + box = null; + + base.Dispose (); + } + + public override void Load (string fileName) + { + ShowPage (1); + ContentName = fileName; + content.Load (fileName); + } + + public override Gtk.Widget Control { + get { return box; } + } + + public override void Save (string fileName) + { + content.Save (fileName); + } + + public override bool IsDirty { + get { + return content.IsDirty; + } + set { + content.IsDirty = value; + } + } + + public override bool IsReadOnly + { + get { + return content.IsReadOnly; + } + } + + public virtual void AddCurrentWidgetToClass () + { + } + + public virtual void JumpToSignalHandler (Stetic.Signal signal) + { + } + + void OnTextContentChanged (object s, EventArgs args) + { + OnContentChanged (args); + } + + void OnTextDirtyChanged (object s, EventArgs args) + { + OnDirtyChanged (args); + } + + void OnActiveDocumentChanged (object s, EventArgs args) + { + if (IdeApp.Workbench.ActiveDocument != null && IdeApp.Workbench.ActiveDocument.GetContent<CombinedDesignView>() == this) + OnDocumentActivated (); + } + + protected virtual void OnDocumentActivated () + { + } + +#if TRUNK + public override T GetContent<T> () + { +// if (type == typeof(IEditableTextBuffer)) { +// // Intercept the IPositionable interface, since we need to +// // switch to the text editor when jumping to a line +// if (content.GetContent (type) != null) +// return this; +// else +// return null; +// } +// + return base.GetContent<T> () ?? content.GetContent<T> (); + } + + public void JumpTo (int line, int column) + { + IEditableTextBuffer ip = content.GetContent<IEditableTextBuffer> (); + if (ip != null) { + ShowPage (0); + ip.SetCaretTo (line, column); + } + } +#else + public override object GetContent (Type contentType) + { + object ob = base.GetContent (contentType); + if (ob != null) + return ob; + else if (content != null) + return content.GetContent (contentType); + else + return null; + } + + public void JumpTo (int line, int column) + { + IEditableTextBuffer ip = (IEditableTextBuffer) content.GetContent (typeof (IEditableTextBuffer)); + if (ip != null) { + ShowPage (0); + ip.SetCaretTo (line, column); + } + } +#endif + } +} + diff --git a/main/src/addins/MonoDevelop.GtkCore2/MonoDevelop.GtkCore.GuiBuilder/GtkProjectServiceExtension.cs b/main/src/addins/MonoDevelop.GtkCore2/MonoDevelop.GtkCore.GuiBuilder/GtkProjectServiceExtension.cs new file mode 100644 index 0000000000..2570dc6d09 --- /dev/null +++ b/main/src/addins/MonoDevelop.GtkCore2/MonoDevelop.GtkCore.GuiBuilder/GtkProjectServiceExtension.cs @@ -0,0 +1,71 @@ + +using System; +using System.Threading; +using MonoDevelop.Core; +using MonoDevelop.Projects; +using MonoDevelop.Ide; + +namespace MonoDevelop.GtkCore.GuiBuilder +{ + public class GtkProjectServiceExtension: ProjectServiceExtension + { + public override bool SupportsItem (IBuildTarget item) + { + if (!IdeApp.IsInitialized) + return false; + + DotNetProject project = item as DotNetProject; + return project != null && GtkDesignInfo.HasDesignedObjects (project); + } + + protected override BuildResult Build (IProgressMonitor monitor, SolutionEntityItem entry, ConfigurationSelector configuration) + { + DotNetProject project = (DotNetProject) entry; + GtkDesignInfo info = GtkDesignInfo.FromProject (project); + + // The code generator must run in the GUI thread since it needs to + // access to Gtk classes + Generator gen = new Generator (); + lock (gen) { + Gtk.Application.Invoke (delegate { gen.Run (monitor, project, configuration); }); + Monitor.Wait (gen); + } + + BuildResult res = base.Build (monitor, entry, configuration); + + if (gen.Messages != null) { + foreach (string s in gen.Messages) +// res.AddWarning (info.GuiBuilderProject.File, 0, 0, null, s); +// TODO: Add gtkx file name in the Generator + res.AddWarning ("", 0, 0, null, s); + + if (gen.Messages.Length > 0) + info.ForceCodeGenerationOnBuild (); + } + return res; + } + + + } + + class Generator + { + public void Run (IProgressMonitor monitor, DotNetProject project, ConfigurationSelector configuration) + { + lock (this) { + try { + Stetic.CodeGenerationResult res = GuiBuilderService.GenerateSteticCode (monitor, project, configuration); + if (res != null) + Messages = res.Warnings; + } catch (Exception ex) { + Error = ex; + LoggingService.LogError (ex.ToString ()); + Messages = new string [] { Error.Message }; + } + Monitor.PulseAll (this); + } + } + public string[] Messages; + public Exception Error; + } +} diff --git a/main/src/addins/MonoDevelop.GtkCore2/MonoDevelop.GtkCore.GuiBuilder/GuiBuilderDisplayBinding.cs b/main/src/addins/MonoDevelop.GtkCore2/MonoDevelop.GtkCore.GuiBuilder/GuiBuilderDisplayBinding.cs new file mode 100644 index 0000000000..b496919221 --- /dev/null +++ b/main/src/addins/MonoDevelop.GtkCore2/MonoDevelop.GtkCore.GuiBuilder/GuiBuilderDisplayBinding.cs @@ -0,0 +1,105 @@ +// +// GuiBuilderDisplayBinding.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 MonoDevelop.Ide.Gui; +using MonoDevelop.Projects; +using MonoDevelop.Projects.Dom; +using MonoDevelop.Projects.Dom.Parser; +using MonoDevelop.Ide; + +namespace MonoDevelop.GtkCore.GuiBuilder +{ + public class GuiBuilderDisplayBinding : DisplayBinding + { + bool excludeThis = false; + + public override string Name { + get { return "Window Designer"; } + } + + public override bool CanCreateContentForUri (string fileName) + { + Project project = IdeApp.Workspace.GetProjectContainingFile (fileName); + GtkDesignInfo info = GtkDesignInfo.FromProject ((DotNetProject) project); + + if (excludeThis) return false; + + if (fileName.Contains (info.BuildFileExtension)) + return false; + + if (GetWindow (fileName) == null) + return false; + + excludeThis = true; + var db = DisplayBindingService.GetDefaultBindingForUri (fileName); + excludeThis = false; + return db != null; + } + + public override IViewContent CreateContentForUri (string fileName) + { + excludeThis = true; + var db = DisplayBindingService.GetDefaultBindingForUri (fileName); + GuiBuilderView view = new GuiBuilderView (db.CreateContentForUri (fileName), GetWindow (fileName)); + excludeThis = false; + return view; + } + + internal static GuiBuilderWindow GetWindow (string file) + { + if (!IdeApp.Workspace.IsOpen) + return null; + + Project project = null; + foreach (Project p in IdeApp.Workspace.GetAllProjects ()) { + if (p.IsFileInProject (file)) { + project = p; + break; + } + } + + if (!GtkDesignInfo.HasDesignedObjects (project)) + return null; + + GtkDesignInfo info = GtkDesignInfo.FromProject (project); + if (file.StartsWith (info.SteticFolder)) + return null; + + ParsedDocument doc = ProjectDomService.GetParsedDocument (null, file); + if (doc == null || doc.CompilationUnit == null) + return null; + + foreach (IType t in doc.CompilationUnit.Types) { + GuiBuilderWindow win = info.GuiBuilderProject.GetWindowForClass (t.FullName); + if (win != null) + return win; + } + return null; + } + } +} diff --git a/main/src/addins/MonoDevelop.GtkCore2/MonoDevelop.GtkCore.GuiBuilder/GuiBuilderDocumentOutline.cs b/main/src/addins/MonoDevelop.GtkCore2/MonoDevelop.GtkCore.GuiBuilder/GuiBuilderDocumentOutline.cs new file mode 100644 index 0000000000..8cbf2677bb --- /dev/null +++ b/main/src/addins/MonoDevelop.GtkCore2/MonoDevelop.GtkCore.GuiBuilder/GuiBuilderDocumentOutline.cs @@ -0,0 +1,104 @@ +// +// GuiBuilderProjectPad.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 MonoDevelop.Ide.Gui; +using MonoDevelop.Ide.Commands; +using MonoDevelop.Components.Commands; +using MonoDevelop.DesignerSupport; + +namespace MonoDevelop.GtkCore.GuiBuilder +{ + internal class GuiBuilderDocumentOutline: Alignment, ICustomPropertyPadProvider + { + static GuiBuilderDocumentOutline instance; + + GuiBuilderDocumentOutline () : base (0, 0, 1, 1) + { + BorderWidth = 0; + GuiBuilderService.SteticApp.WidgetTreeWidget.BorderWidth = 0; + Add (GuiBuilderService.SteticApp.WidgetTreeWidget); + ShowAll (); + } + + internal static GuiBuilderDocumentOutline Instance { + get { + if (instance == null) + instance = new GuiBuilderDocumentOutline (); + return instance; + } + } + + Gtk.Widget ICustomPropertyPadProvider.GetCustomPropertyWidget () + { + return PropertiesWidget.Instance; + } + + void ICustomPropertyPadProvider.DisposeCustomPropertyWidget () + { + } + + [CommandHandler (EditCommands.Undo)] + protected void OnUndo () + { +// GuiBuilderService.App.CommandUndo (); + } + + [CommandHandler (EditCommands.Redo)] + protected void OnRedo () + { +// GuiBuilderService.App.CommandRedo (); + } + + [CommandHandler (EditCommands.Copy)] + protected void OnCopy () + { +// GuiBuilderService.App.CommandCopy (); + } + + [CommandHandler (EditCommands.Cut)] + protected void OnCut () + { +// GuiBuilderService.App.CommandCut (); + } + + [CommandHandler (EditCommands.Paste)] + protected void OnPaste () + { +// GuiBuilderService.App.CommandPaste (); + } + + [CommandHandler (EditCommands.Delete)] + protected void OnDelete () + { +// GuiBuilderService.App.CommandDelete (); + } + } +} diff --git a/main/src/addins/MonoDevelop.GtkCore2/MonoDevelop.GtkCore.GuiBuilder/GuiBuilderProject.cs b/main/src/addins/MonoDevelop.GtkCore2/MonoDevelop.GtkCore.GuiBuilder/GuiBuilderProject.cs new file mode 100644 index 0000000000..5dd66c5b6d --- /dev/null +++ b/main/src/addins/MonoDevelop.GtkCore2/MonoDevelop.GtkCore.GuiBuilder/GuiBuilderProject.cs @@ -0,0 +1,743 @@ +// +// GuiBuilderProject.cs +// +// Author: +// Lluis Sanchez Gual +// Krzysztof Marecki +// +// 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 System.Xml; +using System.IO; +using System.Collections; +using System.Collections.Generic; +using System.Collections.Specialized; +using System.CodeDom.Compiler; + +using MonoDevelop.Core; +using MonoDevelop.Projects; +using MonoDevelop.Projects.Dom; +using MonoDevelop.Projects.Dom.Parser; +using MonoDevelop.Ide; + +namespace MonoDevelop.GtkCore.GuiBuilder +{ + public class GuiBuilderProject + { + //to save temporarily GuiBuilderWindow while files are being moved between projects + static List<GuiBuilderWindow> formInfosRemoved; + + internal object MemoryProbe = Counters.GuiProjectsInMemory.CreateMemoryProbe (); + + List<GuiBuilderWindow> formInfos; + Stetic.Project gproject; + DotNetProject project; + string folderName; + bool hasError; + bool needsUpdate = true; + + FileSystemWatcher watcher; + DateTime lastSaveTime; + object fileSaveLock = new object (); + bool disposed; + bool librariesUpdated; + + public event WindowEventHandler WindowAdded; + public event WindowEventHandler WindowRemoved; + public event EventHandler Reloaded; + public event EventHandler Unloaded; + public event EventHandler Changed; + + static GuiBuilderProject () + { + formInfosRemoved = new List<GuiBuilderWindow> (); + } + + public GuiBuilderProject (DotNetProject project, string folderName) + { + this.folderName = folderName; + this.project = project; + Counters.GuiProjectsLoaded++; + } + + public void Convert (string guiFolderName, bool makeBackup) + { + GtkDesignInfo info = GtkDesignInfo.FromProject (project); + Stetic.Project gproject = GuiBuilderService.SteticApp.CreateProject (info); + //Stetic.Project does not implement IDisposable + try { + string newGuiFolderName = project.BaseDirectory.Combine (guiFolderName); + gproject.ConvertProject (info.SteticFile, newGuiFolderName); + info.ConvertGtkFolder (guiFolderName, makeBackup); + info.UpdateGtkFolder (); + folderName = newGuiFolderName; + IProgressMonitor monitor = IdeApp.Workbench.ProgressMonitors.GetBuildProgressMonitor (); + try { + ConfigurationSelector configuration = IdeApp.Workspace.ActiveConfiguration; + Generator generator = new Generator (); + generator.Run (monitor, project, configuration); + monitor.ReportSuccess ("Converting was succesfull"); + } finally { + monitor.Dispose (); + } + } finally { + gproject.Dispose (); + } + } + + public void GenerateCode (string componentFile) + { + GtkDesignInfo info = GtkDesignInfo.FromProject (project); + string gtkxFile = info.GetDesignerFileFromComponent (componentFile); + if (gtkxFile != null && File.Exists (gtkxFile)) { + + Save (false); + FileInfo fi = new FileInfo (gtkxFile); + fi.LastWriteTime = DateTime.Now; + + IProgressMonitor monitor = IdeApp.Workbench.ProgressMonitors.GetBuildProgressMonitor (); + try { + ConfigurationSelector configuration = IdeApp.Workspace.ActiveConfiguration; + Generator generator = new Generator (); + generator.Run (monitor, project, configuration); + } finally { + monitor.Dispose (); + } + } + } + + void Load () + { + if (gproject != null || disposed || folderName == null) + return; + + GtkDesignInfo info = GtkDesignInfo.FromProject (project); + gproject = GuiBuilderService.SteticApp.CreateProject (info); + formInfos = new List<GuiBuilderWindow> (); + +// TODO : when expanding project, UpdateGtkFolder causes in throwing exception by gtk +// info.UpdateGtkFolder (); + + try { + gproject.Load (folderName); + } catch (Exception ex) { + MessageService.ShowException (ex, GettextCatalog.GetString ("The GUI designer project folder '{0}' could not be loaded.", folderName)); + hasError = true; + } + + Counters.SteticProjectsLoaded++; + gproject.ResourceProvider = GtkDesignInfo.FromProject (project).ResourceProvider; +// gproject.DesignInfo = info; + gproject.WidgetAdded += OnAddWidget; + gproject.WidgetRemoved += OnRemoveWidget; + gproject.ActionGroupsChanged += OnGroupsChanged; + project.FileAddedToProject += OnFileAdded; + project.FileRemovedFromProject += OnFileRemoved; + project.ReferenceAddedToProject += OnReferenceAdded; + project.ReferenceRemovedFromProject += OnReferenceRemoved; + + foreach (Stetic.WidgetInfo ob in gproject.Widgets) + RegisterWindow (ob, false); + } + + void Unload () + { + if (gproject == null) + return; + + Counters.SteticProjectsLoaded--; + + if (Unloaded != null) + Unloaded (this, EventArgs.Empty); + if (formInfos != null) { + foreach (GuiBuilderWindow win in formInfos) + win.Dispose (); + formInfos = null; + } + if (gproject != null) { + gproject.WidgetAdded -= OnAddWidget; + gproject.WidgetRemoved -= OnRemoveWidget; + gproject.ActionGroupsChanged -= OnGroupsChanged; + gproject.Dispose (); + gproject = null; + } + if (project != null) { + project.FileAddedToProject -= OnFileAdded; + project.FileRemovedFromProject -= OnFileRemoved; + project.ReferenceAddedToProject -= OnReferenceAdded; + project.ReferenceRemovedFromProject -= OnReferenceRemoved; + } + needsUpdate = true; + hasError = false; + librariesUpdated = false; + if (watcher != null) { + watcher.Dispose (); + watcher = null; + } + NotifyChanged (); + } + + void OnSteticFileChanged (object s, FileSystemEventArgs args) + { + lock (fileSaveLock) { + if (lastSaveTime == System.IO.File.GetLastWriteTime (folderName)) + return; + } + + if (GuiBuilderService.HasOpenDesigners (project, true)) { + if (MessageService.AskQuestion (GettextCatalog.GetString ("The project '{0}' has been modified by an external application. Do you want to reload it?", project.Name), GettextCatalog.GetString ("Unsaved changes in the open GTK designers will be lost."), AlertButton.Cancel, AlertButton.Reload) != AlertButton.Reload) + return; + } + if (!disposed) + Reload (); + } + + public void Reload () + { + if (disposed) + return; + Unload (); + if (Reloaded != null) + Reloaded (this, EventArgs.Empty); + NotifyChanged (); + } + + public void ReloadFile (string fileName) + { + GuiBuilderWindow window = GetWindowForFile (fileName); + if (window != null) { + var root = window.RootWidget; + UnregisterWindow (window); + gproject.ReloadComponent (window.Name); + RegisterWindow (root, false); + } + } + + public bool HasError { + get { return hasError; } + } + + public bool IsEmpty { + get { + // If the project is not loaded, assume not empty + return gproject != null && Windows != null && Windows.Count == 0; + } + } + + public void Save (bool saveMdProject) + { + if (disposed) + return; + + if (gproject != null && !hasError) { + lock (fileSaveLock) { + gproject.Save (folderName); + lastSaveTime = System.IO.File.GetLastWriteTime (folderName); + } + } + + if (GtkDesignInfo.FromProject (project).UpdateGtkFolder () && saveMdProject) + IdeApp.ProjectOperations.Save (project); + } + + public Stetic.Project SteticProject { + get { + Load (); + return gproject; + + } + } + + public ICollection<GuiBuilderWindow> Windows { + get { + Load (); + return formInfos; + } + } + + public DotNetProject Project { + get { return project; } + } + + public void Dispose () + { + if (disposed) + return; + Counters.GuiProjectsLoaded--; + disposed = true; + if (watcher != null) + watcher.Dispose (); + Unload (); + } + + public Stetic.WidgetInfo AddNewComponent (Stetic.ComponentType type, string name) + { + Stetic.WidgetInfo c = SteticProject.AddNewComponent (type, name); + RegisterWindow (c, true); + return c; + } + + public Stetic.WidgetInfo AddNewComponent (XmlElement element) + { + Stetic.WidgetInfo c = SteticProject.AddNewComponent (element); + // Register the window now, don't wait for the WidgetAdded event since + // it may take some time, and the GuiBuilderWindow object is needed + // just after this call + RegisterWindow (c, true); + return c; + } + + public void AddNewComponent (string fileName) + { + object ob = SteticProject.AddNewComponent (fileName); + + if (ob is Stetic.WidgetInfo) { + var c = (Stetic.WidgetInfo) ob; + RegisterWindow (c, true); + } + } + + public void RegisterWindow (Stetic.WidgetInfo widget, bool notify) + { + if (formInfos != null) { + foreach (GuiBuilderWindow w in formInfos) + if (w.RootWidget == widget) + return; + + GuiBuilderWindow win = new GuiBuilderWindow (this, gproject, widget); + formInfos.Add (win); + + GuiBuilderWindow winToRemove = null; + foreach (GuiBuilderWindow form in formInfosRemoved) + if (form.RootWidget == widget) { + winToRemove = form; + break; + } + + if (winToRemove != null) + formInfosRemoved.Remove (winToRemove); + + if (notify) { + if (WindowAdded != null) + WindowAdded (this, new WindowEventArgs (win)); + NotifyChanged (); + } + } + } + + public void UnregisterWindow (GuiBuilderWindow win) + { + if (!formInfos.Contains (win)) + return; + + formInfos.Remove (win); + formInfosRemoved.Add (win); + + if (WindowRemoved != null) + WindowRemoved (this, new WindowEventArgs (win)); + + win.Dispose (); + NotifyChanged (); + } + + public void Remove (GuiBuilderWindow win) + { + gproject.RemoveComponent (win.RootWidget); + UnregisterWindow (win); + } + + public void RemoveActionGroup (Stetic.ActionGroupInfo group) + { + gproject.RemoveActionGroup (group); + } + + void OnAddWidget (object s, Stetic.WidgetInfoEventArgs args) + { + if (!disposed) + RegisterWindow (args.WidgetInfo, true); + } + + void OnRemoveWidget (object s, Stetic.WidgetInfoEventArgs args) + { + if (disposed || Windows == null) + return; + foreach (GuiBuilderWindow form in Windows) { + if (form.RootWidget.Name == args.WidgetInfo.Name) { + UnregisterWindow (form); + break; + } + } + } + + void OnFileAdded (object sender, ProjectFileEventArgs args) + { + FilePath path = args.ProjectFile.FilePath; + + if (path.Extension == ".gtkx") { + AddNewComponent (path); + } + } + + void OnFileRemoved (object sender, ProjectFileEventArgs args) + { + ArrayList toDelete = new ArrayList (); + ArrayList toDeleteGroups = new ArrayList (); + + ParsedDocument doc = ProjectDomService.GetParsedDocument (ProjectDomService.GetProjectDom (args.Project), args.ProjectFile.Name); + if (doc == null || doc.CompilationUnit == null) + return; + + foreach (IType t in doc.CompilationUnit.Types) { + GuiBuilderWindow win = GetWindowForClass (t.FullName); + if (win != null) { + toDelete.Add (win); + continue; + } + + Stetic.ActionGroupInfo group = GetActionGroup (t.FullName); + if (group != null) { + toDeleteGroups.Add (group); + } + } + + foreach (GuiBuilderWindow win in toDelete) + Remove (win); + + foreach (Stetic.ActionGroupInfo group in toDeleteGroups) + RemoveActionGroup (group); + } + + void OnGroupsChanged (object s, EventArgs a) + { + if (!disposed) + NotifyChanged (); + } + + void OnReferenceAdded (object ob, ProjectReferenceEventArgs args) + { + if (disposed || !librariesUpdated) + return; + string pref = GetReferenceLibraryPath (args.ProjectReference); + if (pref != null) { + gproject.AddWidgetLibrary (pref); + Save (false); + } + } + + void OnReferenceRemoved (object ob, ProjectReferenceEventArgs args) + { + if (disposed || !librariesUpdated) + return; + string pref = GetReferenceLibraryPath (args.ProjectReference); + if (pref != null) { + gproject.RemoveWidgetLibrary (pref); + Save (false); + } + } + + string GetReferenceLibraryPath (ProjectReference pref) + { + string path = null; + + if (pref.ReferenceType == ReferenceType.Project) { + DotNetProject p = project.ParentSolution.FindProjectByName (pref.Reference) as DotNetProject; + if (p != null) + path = p.GetOutputFileName (IdeApp.Workspace.ActiveConfiguration); + } else if (pref.ReferenceType == ReferenceType.Assembly) { + path = pref.Reference; + } else if (pref.ReferenceType == ReferenceType.Gac) { + path = pref.Reference; + } + if (path != null && GuiBuilderService.SteticApp.IsWidgetLibrary (path)) + return path; + else + return null; + } + + public void ImportGladeFile () + { + var dlg = new MonoDevelop.Components.SelectFileDialog (GettextCatalog.GetString ("Open Glade File")); + dlg.AddFilter (GettextCatalog.GetString ("Glade files"), "*.glade"); + dlg.AddAllFilesFilter (); + if (dlg.Run ()) { + SteticProject.ImportGlade (dlg.SelectedFile); + Save (true); + } + } + + public GuiBuilderWindow GetWindowForClass (string className) + { + if (Windows != null) { + foreach (GuiBuilderWindow form in Windows) { + if (CodeBinder.GetObjectName (form.RootWidget) == className) + return form; + } + } + + if (formInfosRemoved != null) { + foreach (GuiBuilderWindow form in formInfosRemoved) { + if (CodeBinder.GetObjectName (form.RootWidget) == className) + return form; + } + } + return null; + }
+
+ public GuiBuilderWindow GetWindowForFile (FilePath fileName) + { + if (Windows != null) { + foreach (GuiBuilderWindow win in Windows) { + if (fileName == win.SourceCodeFile) + return win; + } + } + return null; + } + + public GuiBuilderWindow GetWindow (string name) + { + if (Windows != null) { + foreach (GuiBuilderWindow win in Windows) { + if (name == win.Name) + return win; + } + } + return null; + }
+
+ public Stetic.ActionGroupInfo GetActionGroupForFile (FilePath fileName) + { + foreach (Stetic.ActionGroupInfo group in SteticProject.ActionGroups) { + if (fileName == GetSourceCodeFile (group, true)) + return group; + } + return null; + } + + public Stetic.ActionGroupInfo GetActionGroup (string name) + { + return (SteticProject != null) ? SteticProject.GetActionGroup (name) : null; + }
+
+ public FilePath GetSourceCodeFile (Stetic.ProjectItemInfo obj) + { + return GetSourceCodeFile (obj, true); + }
+
+ public FilePath GetSourceCodeFile (Stetic.ProjectItemInfo obj, bool getUserClass) + { + IType cls = GetClass (obj, getUserClass); + if (cls != null && cls.CompilationUnit != null) + return cls.CompilationUnit.FileName; + return null; + } + + IType GetClass (Stetic.ProjectItemInfo obj, bool getUserClass) + { + string name = CodeBinder.GetClassName (obj); + return FindClass (name, getUserClass); + } + + public IType FindClass (string className) + { + return FindClass (className, true); + } + + public IType FindClass (string className, bool getUserClass) + { + GtkDesignInfo info = GtkDesignInfo.FromProject (project);
+ FilePath gui_folder = info.SteticFolder; + ProjectDom ctx = GetParserContext (); + + if (ctx == null) + return null; + IEnumerable<IType> classes = ctx.Types; + if (classes == null) + return null; + foreach (IType cls in classes) { + if (cls.FullName == className) { + if (getUserClass) { + // Return this class only if it is declared outside the gtk-gui + // folder. Generated partial classes will be ignored. + foreach (IType part in cls.Parts) { + if (part.CompilationUnit.FileName.FullPath.IsChildPathOf (gui_folder)) + continue; + if (part.CompilationUnit != null && !part.CompilationUnit.FileName.IsNullOrEmpty && !part.CompilationUnit.FileName.FileName.Contains (info.BuildFileExtension)) { + return part; + } + } + continue; + } + if (getUserClass && cls.CompilationUnit != null && !string.IsNullOrEmpty (cls.CompilationUnit.FileName) && cls.CompilationUnit.FileName.IsChildPathOf (gui_folder)) + continue; + return cls; + } + } + return null; + } + + public ProjectDom GetParserContext () + { + ProjectDom dom = ProjectDomService.GetProjectDom (Project); + if (dom != null && needsUpdate) { + needsUpdate = false; + dom.ForceUpdate (); + } + return dom; + } + + public WidgetParser WidgetParser { + get { + return new WidgetParser (GetParserContext ()); + } + } + + public void UpdateLibraries () + { + if (hasError || disposed || gproject == null) + return; + + bool needsSave = false; + librariesUpdated = true; + + string[] oldLibs = gproject.WidgetLibraries; + + ArrayList libs = new ArrayList (); + string[] internalLibs; + + foreach (ProjectReference pref in project.References) { + string wref = GetReferenceLibraryPath (pref); + if (wref != null) + libs.Add (wref); + } + + ReferenceManager refmgr = new ReferenceManager (project); + string target_version = refmgr.TargetGtkVersion; + refmgr.Dispose (); + + // Make sure the target gtk version is properly set + if (gproject.TargetGtkVersion != target_version) { + if (gproject.TargetGtkVersion != string.Empty) { + needsSave = true; + } + gproject.TargetGtkVersion = target_version; + } + + string outLib = project.GetOutputFileName (IdeApp.Workspace.ActiveConfiguration); + if (!string.IsNullOrEmpty (outLib)) + internalLibs = new string [] { outLib }; + else + internalLibs = new string [0]; + + string[] newLibs = (string[]) libs.ToArray (typeof(string)); + + // See if something has changed + if (LibrariesChanged (oldLibs, internalLibs, newLibs)) { + // If oldLibs is empty, gproject was uninitialized, so there are no changes to save + if (oldLibs.Length > 0) { + needsSave = true; + } + gproject.SetWidgetLibraries (newLibs, internalLibs); + } else { + GuiBuilderService.SteticApp.UpdateWidgetLibraries (false); + } + + if (needsSave) + Save (true); + } + + bool LibrariesChanged (string[] oldLibs, string[] internalLibs, string[] newLibs) + { + if (oldLibs.Length == newLibs.Length + internalLibs.Length) { + foreach (string s in newLibs) { + if (!((IList)oldLibs).Contains (s)) + return true; + } + foreach (string s in internalLibs) { + if (!((IList)oldLibs).Contains (s)) + return true; + } + return false; + } else + return true; + } + + void NotifyChanged () + { + if (Changed != null && !disposed) + Changed (this, EventArgs.Empty); + } + + public StringCollection GenerateFiles (string guiFolder) + { + StringCollection files = new StringCollection (); + + if (hasError) + return files; + + IDotNetLanguageBinding binding = LanguageBindingService.GetBindingPerLanguageName (project.LanguageName) as IDotNetLanguageBinding; + CodeDomProvider provider = binding.GetCodeDomProvider (); + + if (provider == null) + throw new UserException ("Code generation not supported for language: " + project.LanguageName); +// string path = Path.Combine (guiFolder, binding.GetFileName ("generated")); +// if (!System.IO.File.Exists (path)) { +// GuiBuilderService.SteticApp.GenerateProjectCode (path, "Stetic", provider, null); +// } +// files.Add (path); +// +// if (Windows != null) { +// foreach (GuiBuilderWindow win in Windows) +// files.Add (GuiBuilderService.GenerateSteticCodeStructure (project, win.RootWidget, true, false)); +// } +// +// foreach (Stetic.ActionGroupInfo ag in SteticProject.ActionGroups) +// files.Add (GuiBuilderService.GenerateSteticCodeStructure (project, ag, true, false)); + GtkDesignInfo info = GtkDesignInfo.FromProject (project); + string extension = string.Format("{0}.{1}",info.BuildFileExtension, provider.FileExtension); + foreach (string file in Directory.GetFiles (guiFolder)) { + if (file.Contains (extension)) + files.Add (file); + } + + return files; + } + } + + public delegate void WindowEventHandler (object s, WindowEventArgs args); + + public class WindowEventArgs: EventArgs + { + GuiBuilderWindow win; + + public WindowEventArgs (GuiBuilderWindow win) + { + this.win = win; + } + + public GuiBuilderWindow Window { + get { return win; } + } + } +} diff --git a/main/src/addins/MonoDevelop.GtkCore2/MonoDevelop.GtkCore.GuiBuilder/GuiBuilderService.cs b/main/src/addins/MonoDevelop.GtkCore2/MonoDevelop.GtkCore.GuiBuilder/GuiBuilderService.cs new file mode 100644 index 0000000000..de0d2692ae --- /dev/null +++ b/main/src/addins/MonoDevelop.GtkCore2/MonoDevelop.GtkCore.GuiBuilder/GuiBuilderService.cs @@ -0,0 +1,635 @@ +// +// GuiBuilderService.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 System.IO; +using System.Collections; +using System.CodeDom; +using System.CodeDom.Compiler; + +using MonoDevelop.Ide.Gui; +using MonoDevelop.Projects; +using MonoDevelop.Projects.Dom; +using MonoDevelop.Projects.Dom.Parser; +using MonoDevelop.Projects.Text; +using MonoDevelop.Core; +using MonoDevelop.Core.Execution; +using MonoDevelop.Deployment; +using MonoDevelop.Projects.Policies; +using MonoDevelop.Ide; + +namespace MonoDevelop.GtkCore.GuiBuilder +{ + class GuiBuilderService + { + static string GuiBuilderLayout = "Visual Design"; + +#if DUMMY_STRINGS_FOR_TRANSLATION_DO_NOT_COMPILE + private void DoNotCompile () + { + //The default GUI Builder layout, translated indirectly because it's used as an ID + GettextCatalog.GetString ("GUI Builder"); + } +#endif + + static string defaultLayout; + + static Stetic.Application steticApp; + + static bool generating; + + static Stetic.IsolationMode IsolationMode = Stetic.IsolationMode.None; +// static Stetic.IsolationMode IsolationMode = Stetic.IsolationMode.ProcessUnix; + + static GuiBuilderService () + { + if (IdeApp.Workbench == null) + return; + IdeApp.Workbench.ActiveDocumentChanged += new EventHandler (OnActiveDocumentChanged); + IdeApp.ProjectOperations.EndBuild += OnProjectCompiled; +// IdeApp.Workspace.ParserDatabase.AssemblyInformationChanged += (AssemblyInformationEventHandler) DispatchService.GuiDispatch (new AssemblyInformationEventHandler (OnAssemblyInfoChanged)); + + IdeApp.Exited += delegate { + if (steticApp != null) { + StoreConfiguration (); + steticApp.Dispose (); + } + }; + } + + public static Stetic.Application SteticApp { + get { + // Stetic is not thread safe, so all has to be done in the gui thread + DispatchService.AssertGuiThread (); + if (steticApp == null) { + steticApp = Stetic.ApplicationFactory.CreateApplication (Stetic.IsolationMode.None); + steticApp.AllowInProcLibraries = false; + steticApp.ShowNonContainerWarning = PropertyService.Get ("MonoDevelop.GtkCore.ShowNonContainerWarning", true); + steticApp.MimeResolver = OnMimeResolve; + steticApp.ShowUrl = OnShowUrl; + steticApp.WidgetLibraryResolver = OnAssemblyResolve; + } + return steticApp; + } + } + + static string OnAssemblyResolve (string assemblyName) + { + return Runtime.SystemAssemblyService.DefaultAssemblyContext.GetAssemblyLocation (assemblyName, null); + } + + static string OnMimeResolve (string url) + { + return DesktopService.GetMimeTypeForUri (url); + } + + static void OnShowUrl (string url) + { + DesktopService.ShowUrl (url); + } + + internal static void StoreConfiguration () + { + PropertyService.Set ("MonoDevelop.GtkCore.ShowNonContainerWarning", steticApp.ShowNonContainerWarning); + PropertyService.SaveProperties (); + } + + public static bool AutoSwitchGuiLayout { + get { + return PropertyService.Get ("MonoDevelop.GtkCore.AutoSwitchGuiLayout", false); + } + set { + PropertyService.Set ("MonoDevelop.GtkCore.AutoSwitchGuiLayout", value); + } + } + + public static ActionGroupView OpenActionGroup (Project project, Stetic.ActionGroupInfo group) + { + GuiBuilderProject p = GtkDesignInfo.FromProject (project).GuiBuilderProject ; + string file = p != null ? p.GetSourceCodeFile (group) : null; + if (file == null) { + file = ActionGroupDisplayBinding.BindToClass (project, group); + } + + Document doc = IdeApp.Workbench.OpenDocument (file, true); + if (doc != null) { + ActionGroupView view = doc.GetContent<ActionGroupView> (); + if (view != null) { + view.ShowDesignerView (); + return view; + } + } + return null; + } + + static void OnActiveDocumentChanged (object s, EventArgs args) + { + if (IdeApp.Workbench.ActiveDocument == null) { + if (SteticApp.ActiveDesigner != null) { + SteticApp.ActiveDesigner = null; + RestoreLayout (); + } + return; + } + + CombinedDesignView view = IdeApp.Workbench.ActiveDocument.GetContent<CombinedDesignView> (); + if (view != null) { + SteticApp.ActiveDesigner = view.Designer; + SetDesignerLayout (); + return; + } + else if (SteticApp.ActiveDesigner != null) { + SteticApp.ActiveDesigner = null; + RestoreLayout (); + } + } + + static void SetDesignerLayout () + { + if (AutoSwitchGuiLayout && IdeApp.Workbench.CurrentLayout != GuiBuilderLayout) { + bool exists = IdeApp.Workbench.Layouts.Contains (GuiBuilderLayout); + defaultLayout = IdeApp.Workbench.CurrentLayout; + IdeApp.Workbench.CurrentLayout = GuiBuilderLayout; + if (!exists) { + Pad p = IdeApp.Workbench.GetPad<MonoDevelop.DesignerSupport.ToolboxPad> (); + if (p != null) p.Visible = true; + p = IdeApp.Workbench.GetPad<MonoDevelop.DesignerSupport.PropertyPad> (); + if (p != null) p.Visible = true; + } + } + } + + static void RestoreLayout () + { + if (AutoSwitchGuiLayout && defaultLayout != null) { + IdeApp.Workbench.CurrentLayout = defaultLayout; + defaultLayout = null; + } + } + + static void OnProjectCompiled (object s, BuildEventArgs args) + { + if (args.Success) { + // Unload stetic projects which are not currently + // being used by the IDE. This will avoid unnecessary updates. + if (IdeApp.Workspace.IsOpen) { + foreach (Project prj in IdeApp.Workspace.GetAllProjects ()) { + GtkDesignInfo info = GtkDesignInfo.FromProject (prj); + if (!HasOpenDesigners (prj, false)) { + info.ReloadGuiBuilderProject (); + } + } + } + + SteticApp.UpdateWidgetLibraries (false); + } + else { + // Some gtk# packages don't include the .pc file unless you install gtk-sharp-devel + if (Runtime.SystemAssemblyService.DefaultAssemblyContext.GetPackage ("gtk-sharp-2.0") == null) { + string msg = GettextCatalog.GetString ("ERROR: MonoDevelop could not find the Gtk# 2.0 development package. Compilation of projects depending on Gtk# libraries will fail. You may need to install development packages for gtk-sharp-2.0."); + args.ProgressMonitor.Log.WriteLine (); + args.ProgressMonitor.Log.WriteLine (msg); + } + } + } + + internal static bool HasOpenDesigners (Project project, bool modifiedOnly) + { + foreach (Document doc in IdeApp.Workbench.Documents) { + if ((doc.GetContent<GuiBuilderView>() != null || doc.GetContent<ActionGroupView>() != null) && doc.Project == project && (!modifiedOnly || doc.IsDirty)) + return true; + } + return false; + } + + //static void OnAssemblyInfoChanged (object s, AssemblyInformationEventArgs args) +// { + //SteticApp.UpdateWidgetLibraries (false); +// } + + internal static void AddCurrentWidgetToClass () + { + if (IdeApp.Workbench.ActiveDocument != null) { + GuiBuilderView view = IdeApp.Workbench.ActiveDocument.GetContent<GuiBuilderView> (); + if (view != null) + view.AddCurrentWidgetToClass (); + } + } + + internal static void JumpToSignalHandler (Stetic.Signal signal) + { + if (IdeApp.Workbench.ActiveDocument != null) { + CombinedDesignView view = IdeApp.Workbench.ActiveDocument.GetContent<CombinedDesignView> (); + if (view != null) + view.JumpToSignalHandler (signal); + } + } + + public static void ImportGladeFile (Project project) + { + GtkDesignInfo info = GtkDesignInfo.FromProject (project); + info.GuiBuilderProject.ImportGladeFile (); + } + + public static string GetBuildCodeFileName (Project project, string componentName) + { + return GetBuildCodeFileName (project, componentName, string.Empty); + } + + public static string GetBuildCodeFileName (Project project, string componentName, string nameSpace) + { + GtkDesignInfo info = GtkDesignInfo.FromProject (project); + string componentFile = info.GetComponentFile (componentName); + + if (componentFile == null) { + if (nameSpace == "Stetic") { + return info.GetBuildFileInSteticFolder (componentName); + } +// else +// throw new UserException ("Cannot find component file for " + componentName); + } else + return info.GetBuildFileFromComponent (componentFile); + + return null; + } + + public static void GenerateSteticCodeStructure (DotNetProject project, Stetic.ProjectItemInfo item, bool saveToFile, bool overwrite) + { + GenerateSteticCodeStructure (project, item, null, null, saveToFile, overwrite); + } + + public static void GenerateSteticCodeStructure (DotNetProject project, Stetic.Component component, Stetic.ComponentNameEventArgs args, bool saveToFile, bool overwrite) + { + GenerateSteticCodeStructure (project, null, component, args, saveToFile, overwrite); + } + + static void GenerateSteticCodeStructure (DotNetProject project, Stetic.ProjectItemInfo item, Stetic.Component component, Stetic.ComponentNameEventArgs args, bool saveToFile, bool overwrite) + { + // Generate a class which contains fields for all bound widgets of the component + + string name = item != null ? item.Name : component.Name; + string fileName = GetBuildCodeFileName (project, name); + if (fileName == null) + return; + + string ns = ""; + int i = name.LastIndexOf ('.'); + if (i != -1) { + ns = name.Substring (0, i); + name = name.Substring (i+1); + } + + if (saveToFile && !overwrite && File.Exists (fileName)) + return; + + if (item != null) + component = item.Component; + + CodeCompileUnit cu = new CodeCompileUnit (); + + if (project.UsePartialTypes) { + CodeNamespace cns = new CodeNamespace (ns); + cu.Namespaces.Add (cns); + + CodeTypeDeclaration type = new CodeTypeDeclaration (name); + type.IsPartial = true; + type.Attributes = MemberAttributes.Public; + type.TypeAttributes = System.Reflection.TypeAttributes.Public; + cns.Types.Add (type); + + foreach (Stetic.ObjectBindInfo binfo in component.GetObjectBindInfo ()) { + // When a component is being renamed, we have to generate the + // corresponding field using the old name, since it will be renamed + // later using refactory + string nname = args != null && args.NewName == binfo.Name ? args.OldName : binfo.Name; + type.Members.Add ( + new CodeMemberField ( + binfo.TypeName, + nname + ) + ); + } + } + else { + if (!saveToFile) + return; + CodeNamespace cns = new CodeNamespace (); + cns.Comments.Add (new CodeCommentStatement ("Generated code for component " + component.Name)); + cu.Namespaces.Add (cns); + } + + CodeDomProvider provider = project.LanguageBinding.GetCodeDomProvider (); + if (provider == null) + throw new UserException ("Code generation not supported for language: " + project.LanguageName); + + TextWriter fileStream; + if (saveToFile) + fileStream = new StreamWriter (fileName); + else + fileStream = new StringWriter (); + + try { + provider.GenerateCodeFromCompileUnit (cu, fileStream, new CodeGeneratorOptions ()); + } finally { + fileStream.Close (); + } + + if (ProjectDomService.HasDom (project)) { + // Only update the parser database if the project is actually loaded in the IDE. + if (saveToFile) { + ProjectDomService.Parse (project, fileName, ""); + FileService.NotifyFileChanged (fileName); + } + else + ProjectDomService.Parse (project, fileName, ((StringWriter)fileStream).ToString ()); + } + } + + public static Stetic.CodeGenerationResult GenerateSteticCode (IProgressMonitor monitor, DotNetProject project, ConfigurationSelector configuration) + { + if (generating || !GtkDesignInfo.HasDesignedObjects (project)) + return null; + + GtkDesignInfo info = GtkDesignInfo.FromProject (project); + info.CheckGtkFolder (); + + DateTime last_gen_time = File.Exists (info.SteticGeneratedFile) ? File.GetLastWriteTime (info.SteticGeneratedFile) : DateTime.MinValue; + + bool ref_changed = false; + foreach (ProjectReference pref in project.References) { + if (!pref.IsValid) + continue; + foreach (string filename in pref.GetReferencedFileNames (configuration)) { + if (File.GetLastWriteTime (filename) > last_gen_time) { + ref_changed = true; + break; + } + } + if (ref_changed) + break; + } + + // Check if generated code is already up to date. +// if (!ref_changed && last_gen_time >= File.GetLastWriteTime (info.SteticFile)) +// return null; + + if (info.GuiBuilderProject.HasError) { + monitor.ReportError (GettextCatalog.GetString ("GUI code generation failed for project '{0}'. The file '{1}' could not be loaded.", project.Name, info.SteticFile), null); + monitor.AsyncOperation.Cancel (); + return null; + } + + if (info.GuiBuilderProject.IsEmpty) + return null; + + monitor.Log.WriteLine (GettextCatalog.GetString ("Generating GUI code for project '{0}'...", project.Name)); + + // Make sure the referenced assemblies are up to date. It is necessary to do + // it now since they may contain widget libraries. + project.CopySupportFiles (monitor, configuration); + + info.GuiBuilderProject.UpdateLibraries (); + + ArrayList projectFolders = new ArrayList (); + projectFolders.Add (info.SteticFolder.FullPath); + + generating = true; + Stetic.CodeGenerationResult generationResult = null; + Exception generatedException = null; + + bool canGenerateInProcess = IsolationMode != Stetic.IsolationMode.None || info.GuiBuilderProject.SteticProject.CanGenerateCode; + + if (!canGenerateInProcess) { + // Run the generation in another thread to avoid freezing the GUI + System.Threading.ThreadPool.QueueUserWorkItem ( delegate { + try { + // Generate the code in another process if stetic is not isolated + CodeGeneratorProcess cob = (CodeGeneratorProcess) Runtime.ProcessService.CreateExternalProcessObject (typeof (CodeGeneratorProcess), false); + using (cob) { + generationResult = cob.GenerateCode (projectFolders, info.GenerateGettext, info.GettextClass, project.UsePartialTypes, info); + } + } catch (Exception ex) { + generatedException = ex; + } finally { + generating = false; + } + }); + + while (generating) { + DispatchService.RunPendingEvents (); + System.Threading.Thread.Sleep (100); + } + } else { + // No need to create another process, since stetic has its own backend process + // or the widget libraries have no custom wrappers + try { + Stetic.GenerationOptions options = new Stetic.GenerationOptions (); + options.UseGettext = info.GenerateGettext; + options.GettextClass = info.GettextClass; + generationResult = SteticApp.GenerateProjectCode (options, info.GuiBuilderProject.SteticProject); + } catch (Exception ex) { + generatedException = ex; + } + generating = false; + } + + if (generatedException != null) { + string msg = string.Empty; + + if (generatedException.InnerException != null) { + msg = string.Format("{0}\n{1}\nInner Exception {2}\n{3}", + generatedException.Message, + generatedException.StackTrace, + generatedException.InnerException.Message, + generatedException.InnerException.StackTrace); + } else { + msg = string.Format("{0}\n{1}", + generatedException.Message, + generatedException.StackTrace); + } + +// LoggingService.LogError ("GUI code generation failed", generatedException); + LoggingService.LogError ("GUI code generation failed: " + msg); + throw new UserException ("GUI code generation failed: " + msg); + } + + if (generationResult == null) + return null; + + CodeDomProvider provider = project.LanguageBinding.GetCodeDomProvider (); + if (provider == null) + throw new UserException ("Code generation not supported for language: " + project.LanguageName); + + foreach (Stetic.SteticCompilationUnit unit in generationResult.Units) { + string fname; + if (unit.Name.Length == 0) + fname = info.SteticGeneratedFile; + else + fname = GetBuildCodeFileName (project, + unit.Name, + (unit.Namespace != null) ? unit.Namespace.Name : string.Empty); + + StringWriter sw = new StringWriter (); + try { + foreach (CodeNamespace ns in unit.Namespaces) + ns.Comments.Add (new CodeCommentStatement ("This file has been generated by the GUI designer. Do not modify.")); + provider.GenerateCodeFromCompileUnit (unit, sw, new CodeGeneratorOptions ()); + string content = sw.ToString (); + content = FormatGeneratedFile (fname, content, provider); + File.WriteAllText (fname, content); + } finally { + FileService.NotifyFileChanged (fname); + } + } + + // Make sure the generated files are added to the project + if (info.UpdateGtkFolder ()) { + Gtk.Application.Invoke (delegate { + IdeApp.ProjectOperations.Save (project); + }); + } + + return generationResult; + } + + internal static string ImportFile (Project prj, string file) + { + ProjectFile pfile = prj.Files.GetFile (file); + if (pfile == null) { + var files = IdeApp.ProjectOperations.AddFilesToProject (prj, new string[] { file }, prj.BaseDirectory); + if (files.Count == 0 || files[0] == null) + return null; + pfile = files [0]; + } + if (pfile.BuildAction == BuildAction.EmbeddedResource) { + AlertButton embedButton = new AlertButton (GettextCatalog.GetString ("_Use as Source")); + if (MessageService.AskQuestion (GettextCatalog.GetString ("You are requesting the file '{0}' to be used as source for an image. However, this file is already added to the project as a resource. Are you sure you want to continue (the file will have to be removed from the resource list)?"), AlertButton.Cancel, embedButton) == embedButton) + return null; + } + pfile.BuildAction = BuildAction.Content; + DeployProperties props = DeployService.GetDeployProperties (pfile); + props.UseProjectRelativePath = true; + return pfile.FilePath; + } + + static string FormatGeneratedFile (string file, string content, CodeDomProvider provider) + { + //TODO : Wait for a fix for Mono.TextEditor.Document in the trunk + //content = StripHeaderAndBlankLines (content, provider); + string mt = DesktopService.GetMimeTypeForUri (file); + Formatter formatter = TextFileService.GetFormatter (mt); + if (formatter != null) + content = formatter.FormatText (PolicyService.InvariantPolicies, content); + return content; + } + + static string StripHeaderAndBlankLines (string text, CodeDomProvider provider) + { + Mono.TextEditor.Document doc = new Mono.TextEditor.Document (); + doc.Text = text; + int realStartLine = 0; + for (int i = 0; i < doc.LineCount; i++) { + var lineSegment = doc.GetLine (i); + if (lineSegment == null) + continue; + string lineText = doc.GetTextAt (lineSegment); + // Microsoft.NET generates "auto-generated" tags where Mono generates "autogenerated" tags. + if (lineText.Contains ("</autofgenerated>") || lineText.Contains ("</auto-generated>")) { + realStartLine = i + 2; + break; + } + } + + // The Mono provider inserts additional blank lines, so strip them out + // But blank lines might actually be significant in other languages. + // We reformat the C# generated output to the user's coding style anyway, but the reformatter preserves blank lines + if (provider is Microsoft.CSharp.CSharpCodeProvider) { + bool previousWasBlank = false; + for (int i = 0; i < doc.LineCount; i++) { + Mono.TextEditor.LineSegment line = doc.GetLine (i); + bool isBlank, isBracket; + CheckLine (doc, line, out isBlank, out isBracket); + if (isBlank && previousWasBlank && line.Length > 0) { + ((Mono.TextEditor.IBuffer)doc).Remove (line.Offset, line.Length); + i--; + } + previousWasBlank = isBlank || isBracket; + } + } + + int offset = doc.GetLine (realStartLine).Offset; + return doc.GetTextAt (offset, doc.Length - offset); + } + + static void CheckLine (Mono.TextEditor.Document doc, Mono.TextEditor.LineSegment line, out bool isBlank, out bool isBracket) + { + isBlank = true; + isBracket = false; + if (line == null) + return; + + for (int i = 0; i < line.Length; i++) { + char c = doc.GetCharAt (line.Offset + i); + if (c == '{') { + isBracket = true; + isBlank = false; + } + else if (!Char.IsWhiteSpace (c)) { + isBlank = false; + if (isBracket) { + isBracket = false; + break; + } + } + } + } + } + + + public class CodeGeneratorProcess: RemoteProcessObject + { + public Stetic.CodeGenerationResult GenerateCode (ArrayList projectFolders, bool useGettext, string gettextClass, bool usePartialClasses, GtkDesignInfo info) + { + Gtk.Application.Init (); + + Stetic.Application app = Stetic.ApplicationFactory.CreateApplication (Stetic.IsolationMode.None); + + Stetic.Project[] projects = new Stetic.Project [projectFolders.Count]; + for (int n=0; n < projectFolders.Count; n++) { + projects [n] = app.CreateProject (info); + projects [n].Load ((string) projectFolders [n]); + } + + Stetic.GenerationOptions options = new Stetic.GenerationOptions (); + options.UseGettext = useGettext; + options.GettextClass = gettextClass; + + return app.GenerateProjectCode (options, projects); + } + } +} diff --git a/main/src/addins/MonoDevelop.GtkCore2/MonoDevelop.GtkCore.GuiBuilder/GuiBuilderView.cs b/main/src/addins/MonoDevelop.GtkCore2/MonoDevelop.GtkCore.GuiBuilder/GuiBuilderView.cs new file mode 100644 index 0000000000..6bff298a7c --- /dev/null +++ b/main/src/addins/MonoDevelop.GtkCore2/MonoDevelop.GtkCore.GuiBuilder/GuiBuilderView.cs @@ -0,0 +1,613 @@ +// +// GuiBuilderView.cs +// +// Author: +// Lluis Sanchez Gual +// Krzysztof Marecki +// +// 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 System.ComponentModel; + +using MonoDevelop.Core; +using MonoDevelop.Ide.Gui.Content; +using MonoDevelop.Ide.Gui; +using MonoDevelop.Ide.Commands; +using MonoDevelop.Components.Commands; +using MonoDevelop.Projects; +using MonoDevelop.Projects.Dom; +using MonoDevelop.DesignerSupport.Toolbox; +using MonoDevelop.DesignerSupport; + +using Gtk; +using Gdk; +using MonoDevelop.Ide; + +namespace MonoDevelop.GtkCore.GuiBuilder +{ + public class GuiBuilderView : CombinedDesignView, IToolboxConsumer, MonoDevelop.DesignerSupport.IOutlinedDocument, ISupportsProjectReload + { + Stetic.WidgetDesigner designer; + Stetic.ActionGroupDesigner actionsBox; + GuiBuilderWindow window; + + DesignerPage designerPage; + ActionGroupPage actionsPage; + + + CodeBinder codeBinder; + GuiBuilderProject gproject; + string rootName; + object designerStatus; + + public GuiBuilderView (IViewContent content, GuiBuilderWindow window): base (content) + { + rootName = window.Name; + + designerPage = new DesignerPage (); + designerPage.Show (); + AddButton (GettextCatalog.GetString ("Designer"), designerPage); + + actionsPage = new ActionGroupPage (); + actionsPage.Show (); + + AttachWindow (window); + } + + void AttachWindow (GuiBuilderWindow window) + { + gproject = window.Project; + GtkDesignInfo info = GtkDesignInfo.FromProject (gproject.Project); + gproject.SteticProject.ImagesRootPath = FileService.AbsoluteToRelativePath (info.SteticFolder, gproject.Project.BaseDirectory); + gproject.UpdateLibraries (); + LoadDesigner (); + } + + ProjectReloadCapability ISupportsProjectReload.ProjectReloadCapability { + get { + return ProjectReloadCapability.Full; + } + } + + void ISupportsProjectReload.Update (Project project) + { + if (gproject != null && gproject.Project == project) + return; + + ReloadDesigner (project); + } + + void LoadDesigner () + { + this.window = gproject.GetWindow (rootName); + if (window == null) { + // The window doesn't exist anymore + return; + } + + gproject.Unloaded += OnDisposeProject; + + designer = gproject.SteticProject.CreateWidgetDesigner (window.RootWidget); + + // Designer page + designerPage.ClearChild (); + designerPage.Add (designer); + + if (designer.RootComponent == null) { + // Something went wrong while creating the designer. Show it, but don't do aything else. + designer.ShowAll (); + return; + } + + designer.AllowWidgetBinding = !gproject.Project.UsePartialTypes; + + codeBinder = new CodeBinder (gproject.Project, new OpenDocumentFileProvider (), designer.RootComponent); + + designer.BindField += OnBindWidgetField; + designer.Changed += OnChanged; + designer.SignalAdded += OnSignalAdded; + designer.SignalRemoved += OnSignalRemoved; + designer.SignalChanged += OnSignalChanged; + designer.ComponentNameChanged += OnComponentNameChanged; + designer.RootComponentChanged += OnRootComponentChanged; + designer.ComponentTypesChanged += OnComponentTypesChanged; + designer.ImportFileCallback = ImportFile; + + // Actions designer + actionsBox = designer.CreateActionGroupDesigner (); + actionsBox.AllowActionBinding = !gproject.Project.UsePartialTypes; + actionsBox.BindField += new EventHandler (OnBindActionField); + actionsBox.ModifiedChanged += new EventHandler (OnActionshanged); + + actionsPage.ClearChild (); + actionsPage.PackStart (actionsBox, true, true, 0); + actionsPage.ShowAll (); + + if (actionsBox.HasData) { + if (!HasPage (actionsPage)) + AddButton (GettextCatalog.GetString ("Actions"), actionsPage); + } else { + RemoveButton (actionsPage); + } + + designer.ShowAll (); + GuiBuilderService.SteticApp.ActiveDesigner = designer; + } + + public void ReloadDesigner (Project project) + { + if (designer != null) + designerStatus = designer.SaveStatus (); + + CloseDesigner (); + CloseProject (); + if (project != null) { + GuiBuilderWindow w = GuiBuilderDisplayBinding.GetWindow (this.ContentName); + if (w != null) { + AttachWindow (w); + if (designerStatus != null) + designer.LoadStatus (designerStatus); + designerStatus = null; + } + } + } + + public override Stetic.Designer Designer { + get { return designer; } + } + + void OnDisposeProject (object s, EventArgs args) + { + CloseDesigner (); + } + + void OnReloadProject (object s, EventArgs args) + { + if (designer == null) + LoadDesigner (); + } + + public GuiBuilderWindow Window { + get { return window; } + } + + void CloseDesigner () + { + if (designer == null) + return; + + gproject.Unloaded -= OnDisposeProject; + designer.BindField -= OnBindWidgetField; + designer.Changed -= OnChanged; + designer.SignalAdded -= OnSignalAdded; + designer.SignalRemoved -= OnSignalRemoved; + designer.SignalChanged -= OnSignalChanged; + designer.ComponentNameChanged -= OnComponentNameChanged; + designer.RootComponentChanged -= OnRootComponentChanged; + designer.ComponentTypesChanged -= OnComponentTypesChanged; + + if (actionsBox != null) { + actionsBox.BindField -= OnBindActionField; + actionsBox.ModifiedChanged -= OnActionshanged; + actionsBox = null; + } + + actionsPage.ClearChild (); + designerPage.ClearChild (); + + designerPage.Add (CreateDesignerNotAvailableWidget ()); + actionsPage.Add (CreateDesignerNotAvailableWidget ()); + + designer = null; + + gproject.Reloaded += OnReloadProject; + } + + void CloseProject () + { + gproject.Reloaded -= OnReloadProject; + } + + public override void Dispose () + { + CloseDesigner (); + CloseProject (); + codeBinder = null; + base.Dispose (); + } + + Gtk.Widget CreateDesignerNotAvailableWidget () + { + Gtk.Label label = new Gtk.Label (GettextCatalog.GetString ("Designer not available")); + label.Show (); + return label; + } + + public override void ShowPage (int npage) + { + if (npage == 0 && designer != null && window != null && !ErrorMode) { + // At every page switch update the generated code, to make sure code completion works + // for the generated fields. The call to GenerateSteticCodeStructure will generate + // the code for the window (only the fields in fact) and update the parser database, it + // will not save the code to disk. + if (gproject.Project.UsePartialTypes) + GuiBuilderService.GenerateSteticCodeStructure ((DotNetProject)gproject.Project, designer.RootComponent, null, false, false); + } + base.ShowPage (npage); + } + + string ImportFile (string file) + { + return GuiBuilderService.ImportFile (gproject.Project, file); + } + + void OnRootComponentChanged (object s, EventArgs args) + { + codeBinder.TargetObject = designer.RootComponent; + } + + void OnComponentNameChanged (object s, Stetic.ComponentNameEventArgs args) + { + try { + // Make sure the fields in the partial class are up to date. + // Provide the args parameter to GenerateSteticCodeStructure, in this + // way the component that has been renamed will be generated with the + // old name, and UpdateField will be able to find it (to rename the + // references to the field, it needs to have the old name). + if (gproject.Project.UsePartialTypes) + GuiBuilderService.GenerateSteticCodeStructure ((DotNetProject)gproject.Project, designer.RootComponent, args, false, false); + + codeBinder.UpdateField (args.Component, args.OldName); + } + catch (Exception ex) { + MessageService.ShowException (ex); + } + } + + void OnComponentTypesChanged (object s, EventArgs a) + { + if (ToolboxProvider.Instance != null) + ToolboxProvider.Instance.NotifyItemsChanged (); + } + + void OnActionshanged (object s, EventArgs args) + { + if (designer != null && !HasPage (actionsPage) && !ErrorMode) + AddButton (GettextCatalog.GetString ("Actions"), actionsPage); + } + + void OnChanged (object s, EventArgs args) + { + if (IsDirty) + OnContentChanged (args); + OnDirtyChanged (args); + } + + void OnBindWidgetField (object o, EventArgs a) + { + if (designer.Selection != null) + codeBinder.BindToField (designer.Selection); + } + + void OnBindActionField (object o, EventArgs a) + { + if (actionsBox.SelectedAction != null) + codeBinder.BindToField (actionsBox.SelectedAction); + } + + void OnSignalAdded (object sender, Stetic.ComponentSignalEventArgs args) + { + codeBinder.BindSignal (args.Signal); + } + + void OnSignalRemoved (object sender, Stetic.ComponentSignalEventArgs args) + { + } + + void OnSignalChanged (object sender, Stetic.ComponentSignalEventArgs args) + { + codeBinder.UpdateSignal (args.OldSignal, args.Signal); + } + + public override void Save (string fileName) + { + base.Save (fileName); + + if (designer == null) + return; + + string oldBuildFile = GuiBuilderService.GetBuildCodeFileName (gproject.Project, window.RootWidget.Name); + codeBinder.UpdateBindings (fileName); + + if (!ErrorMode) { + if (designer != null) + designer.Save (); + if (actionsBox != null) + actionsBox.Save (); + } + + string newBuildFile = GuiBuilderService.GetBuildCodeFileName (gproject.Project, window.RootWidget.Name); + + if (oldBuildFile != newBuildFile && oldBuildFile != null && newBuildFile != null) { + if (System.IO.File.Exists (newBuildFile)) + FileService.DeleteFile (newBuildFile); + if (System.IO.File.Exists (oldBuildFile)) + FileService.MoveFile (oldBuildFile, newBuildFile); + } + + gproject.Save (true); + OnDirtyChanged (EventArgs.Empty); + } + + public override bool IsDirty { + get { + // There is no need to check if the action group designer is modified + // since changes in the action group are as well changes in the designed widget + return base.IsDirty || (designer != null && designer.Modified); + } + set { + base.IsDirty = value; + } + } + + public override void JumpToSignalHandler (Stetic.Signal signal) + { + IType cls = codeBinder.GetClass (); + if (cls == null) + return; + foreach (IMethod met in cls.Methods) { + if (met.Name == signal.Handler) { + ShowPage (0); + JumpTo (met.Location.Line, met.Location.Column); + break; + } + } + } + + public void ShowDesignerView () + { + if (designer != null) + ShowPage (1); + } + + public void ShowActionDesignerView (string name) + { + if (designer != null) { + ShowPage (2); + if (!ErrorMode) + actionsBox.ActiveGroup = name; + } + } + + bool ErrorMode { + get { return designer.RootComponent == null; } + } + + public Stetic.ComponentType[] GetComponentTypes () + { + if (designer != null) + return designer.GetComponentTypes (); + else + return null; + } + + void IToolboxConsumer.ConsumeItem (ItemToolboxNode item) + { + } + + //Toolbox service uses this to filter toolbox items. + ToolboxItemFilterAttribute[] IToolboxConsumer.ToolboxFilterAttributes { + get { + return new ToolboxItemFilterAttribute [] { + new ToolboxItemFilterAttribute ("gtk-sharp", ToolboxItemFilterType.Custom) + }; + } + } + + //Used if ToolboxItemFilterAttribute demands ToolboxItemFilterType.Custom + //If not expecting it, should just return false + bool IToolboxConsumer.CustomFilterSupports (ItemToolboxNode item) + { + ComponentToolboxNode cnode = item as ComponentToolboxNode; + if (cnode != null && gproject.SteticProject != null) { + if (cnode.GtkVersion == null || Mono.Addins.Addin.CompareVersions (gproject.SteticProject.TargetGtkVersion, cnode.GtkVersion) <= 0) + return true; + } + return false; + } + + string IToolboxConsumer.DefaultItemDomain { + get { return ComponentToolboxNode.GtkWidgetDomain; } + } + + void IToolboxConsumer.DragItem (ItemToolboxNode item, Gtk.Widget source, Gdk.DragContext ctx) + { + if (designer != null) { + ComponentToolboxNode node = item as ComponentToolboxNode; + if (node != null) { + if (node.Reference == null) + designer.BeginComponentDrag (node.ComponentType, source, ctx); + else + designer.BeginComponentDrag (node.Name, node.ClassName, source, ctx, delegate { CheckReference (node); }); + } + } + } + + void CheckReference (ComponentToolboxNode node) + { + if (node.Reference == null) + return; + + ProjectReference pref; + + // If the class name includes an assembly name it means that the + // widget is implemented in another assembly, not in the one that + // has the objects.xml file. + int i = node.ClassName.IndexOf (','); + if (i != -1) { + string asm = node.ClassName.Substring (i+1).Trim (); + if (asm == "gtk-sharp") + // If we are adding a widget to a window, the project must already have a gtk# reference + return; + + asm = gproject.Project.AssemblyContext.GetAssemblyFullName (asm, gproject.Project.TargetFramework); + if (asm == null) + return; + if (gproject.Project.AssemblyContext.GetPackagesFromFullName (asm).Length > 0) { + pref = new ProjectReference (ReferenceType.Gac, asm); + } else { + asm = gproject.Project.AssemblyContext.GetAssemblyLocation (asm, gproject.Project.TargetFramework); + pref = new ProjectReference (ReferenceType.Assembly, asm); + } + } + else + pref = new ProjectReference (node.ReferenceType, node.Reference); + + foreach (ProjectReference pr in gproject.Project.References) { + if (pr.Reference == pref.Reference) + return; + } + gproject.Project.References.Add (pref); + } + + Widget MonoDevelop.DesignerSupport.IOutlinedDocument.GetOutlineWidget () + { + return GuiBuilderDocumentOutline.Instance; + } + + void MonoDevelop.DesignerSupport.IOutlinedDocument.ReleaseOutlineWidget () + { + //Do nothing. We keep the instance to avoid creation cost when switching documents. + } + + TargetEntry[] IToolboxConsumer.DragTargets { + get { return Stetic.DND.Targets; } + } + } + + class DesignerPage: Gtk.EventBox, ICustomPropertyPadProvider + { + public DesignerPage () + { + } + + Gtk.Widget ICustomPropertyPadProvider.GetCustomPropertyWidget () + { + return PropertiesWidget.Instance; + } + + void ICustomPropertyPadProvider.DisposeCustomPropertyWidget () + { + } + + Stetic.WidgetDesigner Designer { + get { + return Child as Stetic.WidgetDesigner; + } + } + + public void ClearChild () + { + if (Child != null) { + Gtk.Widget w = Child; + Remove (w); + w.Destroy (); + } + } + + [CommandHandler (EditCommands.Delete)] + protected void OnDelete () + { + Designer.DeleteSelection (); + } + + [CommandUpdateHandler (EditCommands.Delete)] + protected void OnUpdateDelete (CommandInfo cinfo) + { + cinfo.Bypass = Designer != null && !Designer.CanDeleteSelection; + } + + [CommandHandler (EditCommands.Copy)] + protected void OnCopy () + { + Designer.CopySelection (); + } + + [CommandUpdateHandler (EditCommands.Copy)] + protected void OnUpdateCopy (CommandInfo cinfo) + { + cinfo.Enabled = Designer != null && Designer.CanCopySelection; + } + + [CommandHandler (EditCommands.Cut)] + protected void OnCut () + { + Designer.CutSelection (); + } + + [CommandUpdateHandler (EditCommands.Cut)] + protected void OnUpdateCut (CommandInfo cinfo) + { + cinfo.Enabled = Designer != null && Designer.CanCutSelection; + } + + [CommandHandler (EditCommands.Paste)] + protected void OnPaste () + { + Designer.PasteToSelection (); + } + + [CommandHandler (EditCommands.Undo)] + protected void OnUndo () + { + Designer.UndoQueue.Undo (); + } + + [CommandHandler (EditCommands.Redo)] + protected void OnRedo () + { + Designer.UndoQueue.Redo (); + } + + [CommandUpdateHandler (EditCommands.Paste)] + protected void OnUpdatePaste (CommandInfo cinfo) + { + cinfo.Enabled = Designer != null && Designer.CanPasteToSelection; + } + + [CommandUpdateHandler (EditCommands.Undo)] + protected void OnUpdateUndo (CommandInfo cinfo) + { + cinfo.Enabled = Designer != null && Designer.UndoQueue.CanUndo; + } + + [CommandUpdateHandler (EditCommands.Redo)] + protected void OnUpdateRedo (CommandInfo cinfo) + { + cinfo.Enabled = Designer != null && Designer.UndoQueue.CanRedo; + } + } +} + diff --git a/main/src/addins/MonoDevelop.GtkCore2/MonoDevelop.GtkCore.GuiBuilder/GuiBuilderWindow.cs b/main/src/addins/MonoDevelop.GtkCore2/MonoDevelop.GtkCore.GuiBuilder/GuiBuilderWindow.cs new file mode 100644 index 0000000000..9b4fc06ed8 --- /dev/null +++ b/main/src/addins/MonoDevelop.GtkCore2/MonoDevelop.GtkCore.GuiBuilder/GuiBuilderWindow.cs @@ -0,0 +1,260 @@ +// +// GuiBuilderWindow.cs +// +// Author: +// Lluis Sanchez Gual +// Krzysztof Marecki +// +// 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 System.Collections; +using System.CodeDom; + +using MonoDevelop.Core; +using MonoDevelop.Ide.Gui; +using MonoDevelop.Projects; +using MonoDevelop.Projects.Dom; +using MonoDevelop.Projects.Dom.Parser; +using MonoDevelop.Projects.CodeGeneration; +using MonoDevelop.Projects.Text; +using MonoDevelop.GtkCore.Dialogs; +using MonoDevelop.Ide; + +namespace MonoDevelop.GtkCore.GuiBuilder +{ + public class GuiBuilderWindow: IDisposable + { + Stetic.WidgetInfo rootWidget; + GuiBuilderProject fproject; + Stetic.Project gproject; + string name; + + public event WindowEventHandler Changed; + + internal GuiBuilderWindow (GuiBuilderProject fproject, Stetic.Project gproject, Stetic.WidgetInfo rootWidget) + { + this.fproject = fproject; + this.rootWidget = rootWidget; + this.gproject = gproject; + name = rootWidget.Name; + gproject.ProjectReloaded += OnProjectReloaded; + rootWidget.Changed += OnChanged; + } + + public Stetic.WidgetInfo RootWidget { + get { return rootWidget; } + } + + public GuiBuilderProject Project { + get { return fproject; } + } + + public string Name { + get { return rootWidget.Name; } + } + + public FilePath SourceCodeFile { + get { return fproject.GetSourceCodeFile (rootWidget); } + } + + public void Dispose () + { + gproject.ProjectReloaded -= OnProjectReloaded; + rootWidget.Changed -= OnChanged; + } + + void OnProjectReloaded (object s, EventArgs args) + { + rootWidget.Changed -= OnChanged; + rootWidget = gproject.GetWidget (name); + if (rootWidget != null) + rootWidget.Changed += OnChanged; + } + + void OnChanged (object o, EventArgs args) + { + // Update the name, it may have changed + name = rootWidget.Name; + + if (Changed != null) + Changed (this, new WindowEventArgs (this)); + } + + public bool BindToClass () + { + if (SourceCodeFile != FilePath.Null) + return true; + + // Find the classes that could be bound to this design + ProjectDom ctx = fproject.GetParserContext (); + ArrayList list = new ArrayList (); + foreach (IType cls in ctx.Types) { + if (IsValidClass (ctx, cls)) + list.Add (cls.FullName); + } + + // Ask what to do + + try { + using (BindDesignDialog dialog = new BindDesignDialog (Name, list, Project.Project.BaseDirectory)) { + if (!dialog.Run ()) + return false; + + if (dialog.CreateNew) + CreateClass (dialog.ClassName, dialog.Namespace, dialog.Folder); + + string fullName = dialog.Namespace.Length > 0 ? dialog.Namespace + "." + dialog.ClassName : dialog.ClassName; + rootWidget.Name = fullName; + fproject.Save (true); + } + return true; + } catch (Exception ex) { + MessageService.ShowException (ex); + return false; + } + } + + void CreateClass (string name, string namspace, string folder) + { + string fullName = namspace.Length > 0 ? namspace + "." + name : name; + + CodeRefactorer gen = new CodeRefactorer (fproject.Project.ParentSolution); + bool partialSupport = fproject.Project.UsePartialTypes; + Stetic.WidgetComponent component = (Stetic.WidgetComponent) rootWidget.Component; + + CodeTypeDeclaration type = new CodeTypeDeclaration (); + type.Name = name; + type.IsClass = true; + type.IsPartial = partialSupport; + type.BaseTypes.Add (new CodeTypeReference (component.Type.ClassName)); + + // Generate the constructor. It contains the call that builds the widget. + + CodeConstructor ctor = new CodeConstructor (); + ctor.Attributes = MemberAttributes.Public | MemberAttributes.Final; + + foreach (object val in component.Type.InitializationValues) { + if (val is Enum) { + ctor.BaseConstructorArgs.Add ( + new CodeFieldReferenceExpression ( + new CodeTypeReferenceExpression (val.GetType ()), + val.ToString () + ) + ); + } + else + ctor.BaseConstructorArgs.Add (new CodePrimitiveExpression (val)); + } + + if (partialSupport) { + CodeMethodInvokeExpression call = new CodeMethodInvokeExpression ( + new CodeMethodReferenceExpression ( + new CodeThisReferenceExpression (), + "Build" + ) + ); + ctor.Statements.Add (call); + } else { + CodeMethodInvokeExpression call = new CodeMethodInvokeExpression ( + new CodeMethodReferenceExpression ( + new CodeTypeReferenceExpression ("Stetic.Gui"), + "Build" + ), + new CodeThisReferenceExpression (), + new CodeTypeOfExpression (fullName) + ); + ctor.Statements.Add (call); + } + type.Members.Add (ctor); + + // Add signal handlers + + AddSignalsRec (type, component); + foreach (Stetic.Component ag in component.GetActionGroups ()) + AddSignalsRec (type, ag); + + // Create the class + IType cls = gen.CreateClass (Project.Project, ((DotNetProject)Project.Project).LanguageName, folder, namspace, type); + if (cls == null) + throw new UserException ("Could not create class " + fullName); + + Project.Project.AddFile (cls.CompilationUnit.FileName, BuildAction.Compile); + IdeApp.ProjectOperations.Save (Project.Project); + +#if TRUNK + // Make sure the database is up-to-date + ProjectDomService.Parse (Project.Project, cls.CompilationUnit.FileName); +#else + ProjectDomService.Parse (Project.Project, cls.CompilationUnit.FileName, null); +#endif + } + + void AddSignalsRec (CodeTypeDeclaration type, Stetic.Component comp) + { + foreach (Stetic.Signal signal in comp.GetSignals ()) { + CodeMemberMethod met = new CodeMemberMethod (); + met.Name = signal.Handler; + met.Attributes = MemberAttributes.Family; + met.ReturnType = new CodeTypeReference (signal.SignalDescriptor.HandlerReturnTypeName); + + foreach (Stetic.ParameterDescriptor pinfo in signal.SignalDescriptor.HandlerParameters) + met.Parameters.Add (new CodeParameterDeclarationExpression (pinfo.TypeName, pinfo.Name)); + + type.Members.Add (met); + } + foreach (Stetic.Component cc in comp.GetChildren ()) { + AddSignalsRec (type, cc); + } + } + + internal bool IsValidClass (ProjectDom ctx, IType cls) + { + if (cls.BaseTypes != null) { + foreach (IReturnType bt in cls.BaseTypes) { + if (bt.FullName == rootWidget.Component.Type.ClassName) + return true; + + IType baseCls = ctx.GetType (bt); + if (baseCls != null && IsValidClass (ctx, baseCls)) + return true; + } + } + return false; + } + } + + class OpenDocumentFileProvider: ITextFileProvider + {
+ public IEditableTextFile GetEditableTextFile (FilePath filePath) + { + foreach (Document doc in IdeApp.Workbench.Documents) { + if (doc.FileName == filePath) { + IEditableTextFile ef = doc.GetContent<IEditableTextFile> (); + if (ef != null) return ef; + } + } + return null; + } + } +} diff --git a/main/src/addins/MonoDevelop.GtkCore2/MonoDevelop.GtkCore.GuiBuilder/PropertiesWidget.cs b/main/src/addins/MonoDevelop.GtkCore2/MonoDevelop.GtkCore.GuiBuilder/PropertiesWidget.cs new file mode 100644 index 0000000000..6cedb0f4b2 --- /dev/null +++ b/main/src/addins/MonoDevelop.GtkCore2/MonoDevelop.GtkCore.GuiBuilder/PropertiesWidget.cs @@ -0,0 +1,211 @@ +// +// GuiBuilderPropertiesPad.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 MonoDevelop.Core; +using MonoDevelop.Projects; +using MonoDevelop.Ide.Gui; +using MonoDevelop.Components.Commands; +using MonoDevelop.Ide.Commands; + +namespace MonoDevelop.GtkCore.GuiBuilder +{ + class PropertiesWidget: Gtk.VBox + { + public static PropertiesWidget Instance; + + Stetic.SignalsEditor signalsEditor; + + static PropertiesWidget () + { + Instance = new PropertiesWidget (); + } + + public PropertiesWidget () + { + Stetic.WidgetPropertyTree grid = GuiBuilderService.SteticApp.PropertiesWidget; + + Notebook tabs = new Notebook (); + + tabs.AppendPage (grid, new Label (GettextCatalog.GetString ("Properties"))); + + signalsEditor = GuiBuilderService.SteticApp.SignalsWidget; + signalsEditor.SignalActivated += new EventHandler (OnSignalActivated); + tabs.AppendPage (signalsEditor, new Label (GettextCatalog.GetString ("Signals"))); + + Gtk.EventBox infoBox = new Gtk.EventBox (); + tabs.AppendPage (infoBox, new Gtk.Label ("")); + + PackStart (tabs, true, true, 0); + + ShowAll (); + infoBox.Hide (); + + tabs.Page = 0; + } + + void OnSignalActivated (object s, EventArgs a) + { + GuiBuilderService.JumpToSignalHandler (signalsEditor.SelectedSignal); + } + } + +/* public class GuiBuilderPropertiesPad: AbstractPadContent + { + Stetic.WidGetTree grid; + Stetic.SignalsEditor signalsEditor; + Gtk.EventBox infoBox; + Gtk.Widget widget; + Stetic.Wrapper.Action currentAction; + Notebook tabs; + + public GuiBuilderPropertiesPad (): base ("") + { + grid = GuiBuilderService.SteticApp.PropertiesWidget; + + DefaultPlacement = "MonoDevelop.GtkCore.GuiBuilder.GuiBuilderPalettePad/bottom; right"; + + tabs = new Notebook (); + + tabs.AppendPage (grid, new Label (GettextCatalog.GetString ("Properties"))); + + signalsEditor = GuiBuilderService.SteticApp.SignalsWidget; + signalsEditor.SignalActivated += new EventHandler (OnSignalActivated); + tabs.AppendPage (signalsEditor, new Label (GettextCatalog.GetString ("Signals"))); + + infoBox = new Gtk.EventBox (); + tabs.AppendPage (infoBox, new Gtk.Label ("")); + + widget = tabs; + + widget.ShowAll (); + infoBox.Hide (); + + tabs.Page = 0; + } + + public override Gtk.Widget Control { + get { return widget; } + } + + void OnSignalActivated (object s, EventArgs a) + { + GuiBuilderService.JumpToSignalHandler (signalsEditor.SelectedSignal); + } + + public object TargetObject { + get { + return grid.TargetObject; + } + set { + Stetic.Wrapper.Action action = Stetic.ObjectWrapper.Lookup (value) as Stetic.Wrapper.Action; + if (action != null) { + // Don't allow editing of global actions + if (grid.Project != null && grid.Project.ActionGroups.IndexOf (action.ActionGroup) != -1) { + if (infoBox.Child != null) + infoBox.Remove (infoBox.Child); + infoBox.Add (CreateGlobalActionInfo (action)); + infoBox.ShowAll (); + tabs.Page = 2; + tabs.ShowTabs = false; + grid.Hide (); + signalsEditor.Hide (); + return; + } + } + + if (!grid.Visible) { + tabs.ShowTabs = true; + grid.Show (); + signalsEditor.Show (); + tabs.Page = 0; + infoBox.Hide (); + } + + grid.TargetObject = value; + signalsEditor.TargetObject = value; + } + } + + Gtk.Widget CreateGlobalActionInfo (Stetic.Wrapper.Action action) + { + currentAction = action; + + Gtk.HBox hbox = new Gtk.HBox (); + hbox.BorderWidth = 12; + Gtk.Image img = new Gtk.Image (Gtk.Stock.DialogInfo, Gtk.IconSize.Menu); + img.Yalign = 0; + hbox.PackStart (img, false, false, 0); + + Gtk.VBox box = new Gtk.VBox (); + Gtk.Label info = new Gtk.Label (GettextCatalog.GetString ("The action '{0}' belongs to the global action group '{1}'. To modify it, open the action group file.", action.MenuLabel, action.ActionGroup.Name)); + info.Xalign = 0; + info.WidthRequest = 200; + info.LineWrap = true; + box.PackStart (info, false, false, 0); + + HBox bb = new HBox (); + Gtk.Button but = new Gtk.Button (GettextCatalog.GetString ("Open Action Group")); + but.Clicked += new EventHandler (OnOpenGroup); + bb.PackStart (but, false, false, 0); + box.PackStart (bb, false, false, 12); + + hbox.PackStart (box, true, true, 12); + hbox.ShowAll (); + return hbox; + } + + void OnOpenGroup (object s, EventArgs args) + { + Project prj = GetProjectFromDesign (currentAction.ActionGroup); + if (prj != null) { + ActionGroupView view = GuiBuilderService.OpenActionGroup (prj, currentAction.ActionGroup); + if (view != null) + view.SelectAction (currentAction); + } + } + + + public static Project GetProjectFromDesign (Stetic.Wrapper.ActionGroup group) + { + if (IdeApp.ProjectOperations.CurrentOpenCombine == null) + return null; + + foreach (Project prj in IdeApp.ProjectOperations.CurrentOpenCombine.GetAllProjects ()) { + GtkDesignInfo info = GtkCoreService.GetGtkInfo (prj); + if (info != null && info.GuiBuilderProject != null && info.GuiBuilderProject.SteticProject.ActionGroups.IndexOf (group) != -1) + return prj; + } + return null; + } + + } +*/ +} diff --git a/main/src/addins/MonoDevelop.GtkCore2/MonoDevelop.GtkCore.GuiBuilder/ToolboxLoader.cs b/main/src/addins/MonoDevelop.GtkCore2/MonoDevelop.GtkCore.GuiBuilder/ToolboxLoader.cs new file mode 100644 index 0000000000..9e62498e33 --- /dev/null +++ b/main/src/addins/MonoDevelop.GtkCore2/MonoDevelop.GtkCore.GuiBuilder/ToolboxLoader.cs @@ -0,0 +1,77 @@ +// +// ToolboxLoader.cs +// +// Author: +// Lluis Sanchez Gual +// +// Copyright (C) 2007 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 System.Collections.Generic; +using MonoDevelop.DesignerSupport.Toolbox; +using MonoDevelop.Projects; +using MonoDevelop.Core; +using MonoDevelop.Core.Assemblies; +using Stetic; +using MonoDevelop.Ide; + +namespace MonoDevelop.GtkCore.GuiBuilder +{ + public class ToolboxLoader: IToolboxLoader + { + public virtual string[] FileTypes { + get { return new string [] { "dll", "exe" }; } + } + + public virtual IList<ItemToolboxNode> Load (LoaderContext ctx, string filename) + { + SystemPackage sp = Runtime.SystemAssemblyService.DefaultAssemblyContext.GetPackageFromPath (filename); + ReferenceType rt; + string rname; + + if (sp != null) { + rt = ReferenceType.Gac; + rname = Runtime.SystemAssemblyService.DefaultAssemblyContext.GetAssemblyFullName (filename, null); + } else { + rt = ReferenceType.Assembly; + rname = filename; + } + + List<ItemToolboxNode> list = new List<ItemToolboxNode> (); + ComponentType[] types = null; + DispatchService.GuiSyncDispatch (delegate { + // Stetic is not thread safe, it has to be used from the gui thread + types = GuiBuilderService.SteticApp.GetComponentTypes (filename); + }); + foreach (ComponentType ct in types) { + if (ct.Category == "window") + continue; + ComponentToolboxNode cn = new ComponentToolboxNode (ct); + cn.ReferenceType = rt; + cn.Reference = rname; + list.Add (cn); + } + return list; + } + } +} diff --git a/main/src/addins/MonoDevelop.GtkCore2/MonoDevelop.GtkCore.GuiBuilder/ToolboxProvider.cs b/main/src/addins/MonoDevelop.GtkCore2/MonoDevelop.GtkCore.GuiBuilder/ToolboxProvider.cs new file mode 100644 index 0000000000..9d46b89d04 --- /dev/null +++ b/main/src/addins/MonoDevelop.GtkCore2/MonoDevelop.GtkCore.GuiBuilder/ToolboxProvider.cs @@ -0,0 +1,201 @@ + +using System; +using System.ComponentModel; +using System.Collections; +using System.Collections.Generic; + +using MonoDevelop.DesignerSupport.Toolbox; +using MonoDevelop.Projects; +using MonoDevelop.Core.Serialization; +using Stetic; +using MonoDevelop.Core; +using MonoDevelop.Ide; + +namespace MonoDevelop.GtkCore.GuiBuilder +{ + public class ToolboxProvider: IToolboxDynamicProvider, IToolboxDefaultProvider + { + internal static ToolboxProvider Instance; + + public ToolboxProvider () + { + Instance = this; + } + + public IEnumerable<ItemToolboxNode> GetDynamicItems (IToolboxConsumer consumer) + { + GuiBuilderView view = consumer as GuiBuilderView; + if (view == null) + return null; + + ComponentType[] types = view.GetComponentTypes (); + if (types == null) + return null; + + Hashtable refs = new Hashtable (); + Hashtable projects = new Hashtable (); + string of = FileService.GetFullPath (view.Project.GetOutputFileName (IdeApp.Workspace.ActiveConfiguration)); + projects [of] = view.Project.Name; + foreach (ProjectReference pr in ((DotNetProject)view.Project).References) + foreach (string f in pr.GetReferencedFileNames (IdeApp.Workspace.ActiveConfiguration)) { + if (pr.ReferenceType == ReferenceType.Project) + projects[FileService.GetFullPath (f)] = pr.Reference; + else + refs[FileService.GetFullPath (f)] = f; + } + + List<ItemToolboxNode> list = new List<ItemToolboxNode> (); + foreach (ComponentType type in types) { + if (type.Category == "window") + continue; + + string fullName = null; + if (!String.IsNullOrEmpty (type.Library)) + fullName = FileService.GetFullPath (type.Library); + + if (type.ClassName == "Gtk.Action" || (fullName != null && refs.Contains (fullName))) { + ComponentToolboxNode node = new ComponentToolboxNode (type); + list.Add (node); + } else if (fullName != null && projects.Contains (fullName)) { + ComponentToolboxNode node = new ComponentToolboxNode (type); + node.Category = (string) projects [fullName]; + list.Add (node); + } + } + list.Sort (); + return list; + } + + public void NotifyItemsChanged () + { + if (ItemsChanged != null) + ItemsChanged (this, EventArgs.Empty); + } + + public virtual IEnumerable<ItemToolboxNode> GetDefaultItems () + { + return null; + } + + public virtual IEnumerable<string> GetDefaultFiles () + { + yield return typeof(Stetic.Wrapper.Widget).Assembly.Location; + } + + public event EventHandler ItemsChanged; + } + + class ComponentToolboxNode: ItemToolboxNode + { + public ComponentType componentType; + + [ItemProperty] + ReferenceType refType; + [ItemProperty] + string reference; + [ItemProperty] + string className; + [ItemProperty] + string gtkVersion; + + static ToolboxItemFilterAttribute[] attributes = new ToolboxItemFilterAttribute[] { + new ToolboxItemFilterAttribute ("gtk-sharp", ToolboxItemFilterType.Require) + }; + + internal static readonly string GtkWidgetDomain = GettextCatalog.GetString ("GTK# Widgets"); + + public ComponentToolboxNode () + { + } + + public ComponentToolboxNode (ComponentType type) + { + if (type.Description.Length > 0) + Name = type.Description; + else { + int i = type.Name.LastIndexOf ('.'); + if (i == -1) + Name = type.Name; + else + Name = type.Name.Substring (i+1); + } + + componentType = type; + className = type.ClassName; + Category = GetCategoryName (type.Category); + Icon = type.Icon; + gtkVersion = type.TargetGtkVersion; + } + + [Browsable (false)] + public override IList<ToolboxItemFilterAttribute> ItemFilters { + get { return attributes; } + } + + [Browsable (false)] + public Stetic.ComponentType ComponentType { + get { + return componentType; + } + } + + [ReadOnly (true)] + [LocalizedCategory ("Misc")] + [LocalizedDisplayName ("Reference Type")] + [LocalizedDescription ("The type of the project or assembly from which this component originates.")] + public ReferenceType ReferenceType { + get { + return refType; + } + set { + refType = value; + } + } + + [ReadOnly (true)] + [LocalizedCategory ("Misc")] + [LocalizedDisplayName ("Reference Path")] + [LocalizedDescription ("The project or assembly from which this component originates.")] + public string Reference { + get { + return reference; + } + set { + reference = value; + } + } + + [LocalizedCategory ("Misc")] + [LocalizedDisplayName ("Class Name")] + [LocalizedDescription ("The name of the component class.")] + public string ClassName { + get { + return className; + } + } + + [LocalizedCategory ("Misc")] + [LocalizedDisplayName ("GTK# Version")] + [LocalizedDescription ("The minimum GTK# version required to use this component.")] + public string GtkVersion { + get { + return gtkVersion; + } + } + + string GetCategoryName (string cat) + { + if (cat == "container") + return GettextCatalog.GetString ("Containers"); + else if (cat == "widget") + return GettextCatalog.GetString ("Widgets"); + else + return cat; + } + + [Browsable (false)] + public override string ItemDomain { + get { return GtkWidgetDomain; } + } + } +} diff --git a/main/src/addins/MonoDevelop.GtkCore2/MonoDevelop.GtkCore.NodeBuilders/ActionGroupNodeBuilder.cs b/main/src/addins/MonoDevelop.GtkCore2/MonoDevelop.GtkCore.NodeBuilders/ActionGroupNodeBuilder.cs new file mode 100644 index 0000000000..0a3436e189 --- /dev/null +++ b/main/src/addins/MonoDevelop.GtkCore2/MonoDevelop.GtkCore.NodeBuilders/ActionGroupNodeBuilder.cs @@ -0,0 +1,145 @@ +// +// ActionGroupNodeBuilder.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 MonoDevelop.Core; +using MonoDevelop.Ide.Gui; +using MonoDevelop.GtkCore.GuiBuilder; +using MonoDevelop.GtkCore.Dialogs; +using MonoDevelop.Projects; +using MonoDevelop.Ide.Gui.Components; +using MonoDevelop.Ide; + +namespace MonoDevelop.GtkCore.NodeBuilders +{ + public class ActionGroupNodeBuilder: TypeNodeBuilder + { + public override Type CommandHandlerType { + get { return typeof(ActionGroupCommandHandler); } + } + + public override string ContextMenuAddinPath { + get { return "/MonoDevelop/GtkCore/ContextMenu/ProjectPad.ActionGroup"; } + } + + public override Type NodeDataType { + get { return typeof(Stetic.ActionGroupInfo); } + } + + public override string GetNodeName (ITreeNavigator thisNode, object dataObject) + { + Stetic.ActionGroupInfo group = (Stetic.ActionGroupInfo) dataObject; + return group.Name; + } + + public override void BuildNode (ITreeBuilder treeBuilder, object dataObject, ref string label, ref Gdk.Pixbuf icon, ref Gdk.Pixbuf closedIcon) + { + Stetic.ActionGroupInfo group = (Stetic.ActionGroupInfo) dataObject; + label = group.Name; + icon = ImageService.GetPixbuf ("md-gtkcore-actiongroup", Gtk.IconSize.Menu); + } + + public override void OnNodeAdded (object dataObject) + { + Stetic.ActionGroupInfo group = (Stetic.ActionGroupInfo) dataObject; + group.Changed += new EventHandler (OnChanged); + } + + public override void OnNodeRemoved (object dataObject) + { + Stetic.ActionGroupInfo group = (Stetic.ActionGroupInfo) dataObject; + group.Changed -= new EventHandler (OnChanged); + } + + void OnChanged (object s, EventArgs a) + { + ITreeBuilder tb = Context.GetTreeBuilder (s); + if (tb != null) + tb.Update (); + } + } + + class ActionGroupCommandHandler: NodeCommandHandler + { + public override void ActivateItem () + { + GuiBuilderWindow w = (GuiBuilderWindow) CurrentNode.GetParentDataItem (typeof(GuiBuilderWindow), false); + if (w != null) { + if (w.SourceCodeFile == FilePath.Null && !w.BindToClass ()) + return; + + Document doc = IdeApp.Workbench.OpenDocument (w.SourceCodeFile, true); + if (doc != null) { + GuiBuilderView view = doc.GetContent<GuiBuilderView> (); + if (view != null) + view.ShowActionDesignerView (((Stetic.ActionGroupInfo) CurrentNode.DataItem).Name); + } + } + else { + Project project = (Project) CurrentNode.GetParentDataItem (typeof(Project), false); + Stetic.ActionGroupInfo group = (Stetic.ActionGroupInfo) CurrentNode.DataItem; + GuiBuilderService.OpenActionGroup (project, group); + } + } + + public override bool CanDeleteItem () + { + // Don't allow deleting action groups local to a window + GuiBuilderWindow w = (GuiBuilderWindow) CurrentNode.GetParentDataItem (typeof(GuiBuilderWindow), false); + return (w == null); + } + + public override void DeleteItem () + { + // Don't allow deleting action groups local to a window + GuiBuilderWindow w = (GuiBuilderWindow) CurrentNode.GetParentDataItem (typeof(GuiBuilderWindow), false); + if (w != null) + return; + + Project project = (Project) CurrentNode.GetParentDataItem (typeof(Project), false); + Stetic.ActionGroupInfo group = (Stetic.ActionGroupInfo) CurrentNode.DataItem; + GuiBuilderProject gproject = GtkDesignInfo.FromProject (project).GuiBuilderProject; + string sfile = gproject.GetSourceCodeFile (group); + + if (sfile != null) { + using (ConfirmWindowDeleteDialog dialog = new ConfirmWindowDeleteDialog (group.Name, sfile, group)) { + if (dialog.Run () == (int) Gtk.ResponseType.Yes) { + if (dialog.DeleteFile) { + ProjectFile file = project.GetProjectFile (sfile); + if (file != null) + project.Files.Remove (file); + } + gproject.RemoveActionGroup (group); + gproject.Save (false); + IdeApp.ProjectOperations.Save (project); + } + } + } + } + } +} diff --git a/main/src/addins/MonoDevelop.GtkCore2/MonoDevelop.GtkCore.NodeBuilders/ChangeLog b/main/src/addins/MonoDevelop.GtkCore2/MonoDevelop.GtkCore.NodeBuilders/ChangeLog new file mode 100644 index 0000000000..f73c1a92e9 --- /dev/null +++ b/main/src/addins/MonoDevelop.GtkCore2/MonoDevelop.GtkCore.NodeBuilders/ChangeLog @@ -0,0 +1,83 @@ +2010-09-17 Krzysztof Marecki <marecki.krzysztof@gmail.com> + + * GuiProjectFolderNodeBuilder.cs: + +2010-09-09 Krzysztof Marecki <freefirma@gmail.com> + + * ProjectNodeBuilder.cs: + +2010-08-30 Krzysztof Marecki <freefirma@gmail.com> + + * ProjectFileNodeBuilderExtension.cs: + +2010-08-17 Krzysztof Marecki <freefirma@gmail.com> + + * WindowsFolder.cs: + * WidgetNodeBuilder.cs: + * WindowsFolderNodeBuilder.cs: + * ProjectFileNodeBuilderExtension.cs: + +2010-08-16 Krzysztof Marecki <freefirma@gmail.com> + + * ProjectNodeBuilder.cs: + * GuiProjectFolderNodeBuilder.cs: + * ProjectFolderNodeBuilderExtension.cs: + +2010-08-15 Krzysztof Marecki <freefirma@gmail.com> + + * ProjectNodeBuilder.cs: + * GuiProjectFolderNodeBuilder.cs: + +2010-08-15 Krzysztof Marecki <freefirma@gmail.com> + + * ProjectFileExtension.cs: + * GuiProjectFolderNodeBuilder.cs: + * ProjectFileNodeBuilderExtension.cs: + * ProjectFolderNodeBuilderExtension.cs: + +2010-08-13 Krzysztof Marecki <freefirma@gmail.com> + + * ProjectNodeBuilder.cs: + * StockIconsNodeBuilder.cs: + * ProjectFileNodeBuilderExtension.cs: + * ProjectFolderNodeBuilderExtension.cs: + +2010-08-09 Krzysztof Marecki <freefirma@gmail.com> + + * GuiProjectFolder.cs: Put gui project folder directly below References + in the project pad + * ProjectNodeBuilder.cs: + * GuiProjectFolderNodeBuilder.cs: + * ProjectFolderNodeBuilderExtension.cs: + +2010-07-06 Krzysztof Marecki <marecki.krzysztof@gmail.com> + + * ProjectFileExtension.cs: Move cursor in entryFolder to the end. + +2010-07-05 Krzysztof Marecki <marecki.krzysztof@gmail.com> + + * ProjectFileExtension.cs: Better approach for obtaining GtkComponentType + * ProjectFileNodeBuilderExtension.cs: + * ProjectFolderNodeBuilderExtension.cs: + +2010-06-28 Krzysztof Marecki <marecki.krzysztof@gmail.com> + + * ProjectNodeBuilder.cs: + * ProjectFileNodeBuilderExtension.cs: + * ProjectFolderNodeBuilderExtension.cs: + +2010-06-23 Krzysztof Marecki <marecki.krzysztof@gmail.com> + + * ProjectNodeBuilder.cs: + * ProjectFileNodeBuilderExtension.cs: Show ProjectConversionDialog before + conversion + +2010-06-21 Krzysztof Marecki <marecki.krzysztof@gmail.com> + + * ProjectNodeBuilder.cs: Convert a project file layout on open + * ProjectFileNodeBuilderExtension.cs: Group components files + +2010-06-16 Krzysztof Marecki <marecki.krzysztof@gmail.com> + + * ProjectFileNodeBuilderExtension.cs: + diff --git a/main/src/addins/MonoDevelop.GtkCore2/MonoDevelop.GtkCore.NodeBuilders/GuiProjectFolder.cs b/main/src/addins/MonoDevelop.GtkCore2/MonoDevelop.GtkCore.NodeBuilders/GuiProjectFolder.cs new file mode 100644 index 0000000000..3324cee3d2 --- /dev/null +++ b/main/src/addins/MonoDevelop.GtkCore2/MonoDevelop.GtkCore.NodeBuilders/GuiProjectFolder.cs @@ -0,0 +1,42 @@ +// +// GuiProjectFolder.cs +// +// Author: +// Krzysztof Marecki <marecki.krzysztof@gmail.com> +// +// Copyright (c) 2010 KrzysztofMarecki +// +// 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 MonoDevelop.Core; +using MonoDevelop.Ide.Gui.Pads.ProjectPad; +using MonoDevelop.Projects; +using MonoDevelop.Projects.Dom; + +namespace MonoDevelop.GtkCore.NodeBuilders +{ + public class GuiProjectFolder : ProjectFolder + { + public GuiProjectFolder (FilePath absolutePath, IWorkspaceObject parentWorkspaceObject, object parent) + : base (absolutePath, parentWorkspaceObject, parent) + { + } + } +} + diff --git a/main/src/addins/MonoDevelop.GtkCore2/MonoDevelop.GtkCore.NodeBuilders/GuiProjectFolderNodeBuilder.cs b/main/src/addins/MonoDevelop.GtkCore2/MonoDevelop.GtkCore.NodeBuilders/GuiProjectFolderNodeBuilder.cs new file mode 100644 index 0000000000..a5e9b46dec --- /dev/null +++ b/main/src/addins/MonoDevelop.GtkCore2/MonoDevelop.GtkCore.NodeBuilders/GuiProjectFolderNodeBuilder.cs @@ -0,0 +1,177 @@ +// +// GuiProjectFolderNodeBuilder.cs +// +// Author: +// Krzysztof Marecki <marecki.krzysztof@gmail.com> +// +// Copyright (c) 2010 KrzysztofMarecki +// +// 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 MonoDevelop.Components.Commands; +using MonoDevelop.Core; +using MonoDevelop.Ide.Commands; +using MonoDevelop.Ide; +using MonoDevelop.Ide.Gui; +using MonoDevelop.Ide.Gui.Components; +using MonoDevelop.Ide.Gui.Pads.ProjectPad; +using MonoDevelop.Projects; + +using MonoDevelop.GtkCore.GuiBuilder; + +namespace MonoDevelop.GtkCore.NodeBuilders +{ + public class GuiProjectFolderNodeBuilder : ProjectFolderNodeBuilder + { + public override Type NodeDataType { + get { return typeof(GuiProjectFolder); } + } + + public override Type CommandHandlerType { + get { return typeof(GuiProjectFolderCommandHandler); } + } + + public override string GetNodeName (ITreeNavigator thisNode, object dataObject) + { + //nodes are sorted alphabetically and we want to have gui folder on the top + return string.Empty; + } + + + public override void BuildNode (ITreeBuilder treeBuilder, object dataObject, ref string label, ref Gdk.Pixbuf icon, ref Gdk.Pixbuf closedIcon) + { + GuiProjectFolder folder = (GuiProjectFolder) dataObject; + + icon = Context.GetIcon (Stock.OpenResourceFolder); + closedIcon = Context.GetIcon (Stock.ClosedResourceFolder); + label = folder.Name; + } + } + + public class GuiProjectFolderCommandHandler : ProjectFolderCommandHandler + { + [CommandHandler (GtkCommands.ImportGladeFile)] + protected void OnImportGladeFile () + { + Project project = CurrentNode.GetParentDataItem (typeof(Project), true) as Project; + GuiBuilderService.ImportGladeFile (project); + } + + [CommandUpdateHandler (GtkCommands.ImportGladeFile)] + protected void UpdateImportGladeFile (CommandInfo cinfo) + { + cinfo.Visible = CanAddWindow (); + } + + [CommandHandler (GtkCommands.EditIcons)] + protected void OnEditIcons () + { + Project project = CurrentNode.GetParentDataItem (typeof(Project), true) as Project; + GuiBuilderProject gp = GtkDesignInfo.FromProject (project).GuiBuilderProject; + Stetic.Project sp = gp.SteticProject; + sp.EditIcons (); + gp.Save (true); + } + + [CommandUpdateHandler (GtkCommands.EditIcons)] + protected void UpdateEditIcons (CommandInfo cinfo) + { + cinfo.Visible = CanAddWindow (); + } + + [CommandHandler (GtkCommands.GtkSettings)] + protected void OnGtkSettings () + { + Project project = CurrentNode.GetParentDataItem (typeof(Project), true) as Project; + IdeApp.ProjectOperations.ShowOptions (project, "SteticOptionsPanel"); + } + + [CommandUpdateHandler (GtkCommands.EditIcons)] + protected void UpdateGtkSettings (CommandInfo cinfo) + { + cinfo.Visible = CanAddWindow (); + } + + [CommandUpdateHandler (EditCommands.Delete)] + [CommandUpdateHandler (EditCommands.Rename)] + [CommandUpdateHandler (ProjectCommands.AddNewFiles)] + [CommandUpdateHandler (ProjectCommands.AddFiles)] + [CommandUpdateHandler (ProjectCommands.AddSolutionFolder)] + [CommandUpdateHandler (ProjectCommands.AddItem)] + [CommandUpdateHandler (ProjectCommands.NewFolder)] + [CommandUpdateHandler ("MonoDevelop.Refactoring.RefactoryCommands.Rename")] + protected void UpdateDisabledCommands (CommandInfo cinfo) + { + cinfo.Visible = false; + cinfo.Enabled = false; + } + + bool CanAddWindow () + { + DotNetProject project = CurrentNode.GetParentDataItem (typeof(Project), true) as DotNetProject; + return GtkDesignInfo.SupportsDesigner (project); + } + + public override DragOperation CanDragNode () + { + return DragOperation.None; + } + + public override bool CanDeleteItem () + { + return false; + } + + public override bool CanDropMultipleNodes (object[] dataObjects, DragOperation operation) + { + return false; + } + + public override bool CanDropMultipleNodes (object[] dataObjects, DragOperation operation, DropPosition position) + { + return false; + } + + public override bool CanDeleteMultipleItems () + { + return false; + } + + public override bool CanDropNode (object dataObject, DragOperation operation) + { + return false; + } + + public override bool CanDropNode (object dataObject, DragOperation operation, DropPosition position) + { + return false; + } + + public override void RenameItem (string newName) + { + Project project = CurrentNode.GetParentDataItem (typeof(Project), true) as Project; + GtkDesignInfo info = GtkDesignInfo.FromProject (project); + info.SteticFolderName = newName; + + base.RenameItem (newName); + } + } +} + diff --git a/main/src/addins/MonoDevelop.GtkCore2/MonoDevelop.GtkCore.NodeBuilders/ProjectFileExtension.cs b/main/src/addins/MonoDevelop.GtkCore2/MonoDevelop.GtkCore.NodeBuilders/ProjectFileExtension.cs new file mode 100644 index 0000000000..9919981679 --- /dev/null +++ b/main/src/addins/MonoDevelop.GtkCore2/MonoDevelop.GtkCore.NodeBuilders/ProjectFileExtension.cs @@ -0,0 +1,52 @@ +using System; +using MonoDevelop.GtkCore.GuiBuilder; +using MonoDevelop.Projects; +using MonoDevelop.Projects.Dom; +using MonoDevelop.Projects.Dom.Parser; + +namespace MonoDevelop.GtkCore.NodeBuilders +{ + public enum GtkComponentType + { + Dialog, + Widget, + ActionGroup, + IconFactory, + None + } + + public static class ProjectFileExtension + { + public static bool IsComponentFile (this ProjectFile pf) + { + return pf.GetComponentType () != GtkComponentType.None; + } + + public static GtkComponentType GetComponentType (this ProjectFile pf) + { + GtkDesignInfo info = GtkDesignInfo.FromProject (pf.Project); + ParsedDocument doc = ProjectDomService.GetParsedDocument (ProjectDomService.GetProjectDom (pf.Project), pf.Name); + //ParsedDocument doc = ProjectDomService.ParseFile (ProjectDomService.GetProjectDom (pf.Project), pf.FilePath.ToString ()); + if (doc != null && doc.CompilationUnit != null) { + foreach (IType t in doc.CompilationUnit.Types) { + string className = t.FullName; + if (className != null) { + GuiBuilderWindow win = info.GuiBuilderProject.GetWindowForClass (className); + if (win != null) + return win.RootWidget.IsWindow ? GtkComponentType.Dialog : GtkComponentType.Widget; + + Stetic.ActionGroupInfo action = info.GuiBuilderProject.GetActionGroup (className); + if (action != null) + return GtkComponentType.ActionGroup; + + } + } + } + if (pf.Name.Contains ("IconFactory.gtkx")) + return GtkComponentType.IconFactory; + + return GtkComponentType.None; + } + } +} + diff --git a/main/src/addins/MonoDevelop.GtkCore2/MonoDevelop.GtkCore.NodeBuilders/ProjectFileNodeBuilderExtension.cs b/main/src/addins/MonoDevelop.GtkCore2/MonoDevelop.GtkCore.NodeBuilders/ProjectFileNodeBuilderExtension.cs new file mode 100644 index 0000000000..8e449efcd1 --- /dev/null +++ b/main/src/addins/MonoDevelop.GtkCore2/MonoDevelop.GtkCore.NodeBuilders/ProjectFileNodeBuilderExtension.cs @@ -0,0 +1,179 @@ +using System; + +using MonoDevelop.Components.Commands; +using MonoDevelop.GtkCore.GuiBuilder; +using MonoDevelop.Ide; +using MonoDevelop.Ide.Commands; +using MonoDevelop.Ide.Gui; +using MonoDevelop.Ide.Gui.Components; +using MonoDevelop.Ide.Gui.Content; +using MonoDevelop.Ide.Gui.Pads.ProjectPad; +using MonoDevelop.Projects; +using MonoDevelop.Projects.Dom; + +namespace MonoDevelop.GtkCore.NodeBuilders +{ + public class ProjectFileBuilder : ProjectFileNodeBuilder + { + + } + + public class ProjectFileNodeBuilderExtension : NodeBuilderExtension + { + public override bool CanBuildNode (Type dataType) + { + return typeof(ProjectFile).IsAssignableFrom (dataType); + } + + public override Type CommandHandlerType { + get { return typeof (ComponentCommandHandler); } + } + + public override void GetNodeAttributes (ITreeNavigator treeNavigator, object dataObject, ref NodeAttributes attributes) + { + if (treeNavigator.Options ["ShowAllFiles"]) + return; + + ProjectFile pf = (ProjectFile) dataObject; + GtkDesignInfo info = GtkDesignInfo.FromProject (pf.Project); + //Designer files in the designer folder like IconFactory.gtkx should be always visible + if (info.HideGtkxFiles && + pf.FilePath.Extension == ".gtkx" && + !pf.FilePath.IsChildPathOf (info.SteticFolder)) + attributes |= NodeAttributes.Hidden; + } + + + public override void BuildNode (ITreeBuilder treeBuilder, object dataObject, ref string label, ref Gdk.Pixbuf icon, ref Gdk.Pixbuf closedIcon) + { + ProjectFile pf = (ProjectFile) dataObject; + + //do not show custom icon for generated source files + if (pf.DependsOn == null) { + GtkComponentType type = pf.GetComponentType (); + + switch (type) { + case GtkComponentType.Dialog : + icon = ImageService.GetPixbuf ("md-gtkcore-dialog", Gtk.IconSize.Menu); + break; + case GtkComponentType.Widget : + icon = ImageService.GetPixbuf ("md-gtkcore-widget", Gtk.IconSize.Menu); + break; + case GtkComponentType.ActionGroup : + icon = ImageService.GetPixbuf ("md-gtkcore-actiongroup", Gtk.IconSize.Menu); + break; + case GtkComponentType.IconFactory : + icon = ImageService.GetPixbuf ("md-gtkcore-iconfactory", Gtk.IconSize.Menu); + label = "Stock icons"; + break; + } + } + } + + //override + public override bool HasChildNodes (ITreeBuilder builder, object dataObject) + { + return base.HasChildNodes (builder, dataObject); + } + } + + public class ComponentCommandHandler : NodeCommandHandler + { + /*public override void ActivateItem () + { + ProjectFile pf = (ProjectFile) CurrentNode.DataItem; + + if (pf.IsComponentFile ()) { + Document doc = IdeApp.Workbench.OpenDocument (pf.FilePath, true); + + if (doc != null) { + GuiBuilderView view = doc.GetContent<GuiBuilderView> (); + if (view != null) { + GtkComponentType type = pf.GetComponentType (); + + switch (type) { + case GtkComponentType.Dialog : + case GtkComponentType.Widget : + view.ShowDesignerView (); + break; + case GtkComponentType.ActionGroup : + view.ShowActionDesignerView (((Stetic.ActionGroupInfo) CurrentNode.DataItem).Name); + break; + } + } + } + return; + } + base.ActivateItem (); + } + */ + + [CommandHandler (GtkCommands.GenerateCode)] + protected void OnGenerateCode () + { + ProjectFile pf = CurrentNode.DataItem as ProjectFile; + Project project = CurrentNode.GetParentDataItem (typeof(Project), true) as Project; + GtkDesignInfo info = GtkDesignInfo.FromProject (project); + GuiBuilderProject gproject = info.GuiBuilderProject; + + gproject.GenerateCode (pf.FilePath); + } + + [CommandHandler (GtkCommands.ReloadDesigner)] + protected void OnReloadDesigner () + { + ProjectFile pf = CurrentNode.DataItem as ProjectFile; + Project project = CurrentNode.GetParentDataItem (typeof(Project), true) as Project; + GtkDesignInfo info = GtkDesignInfo.FromProject (project); + GuiBuilderProject gproject = info.GuiBuilderProject; + + Document doc = IdeApp.Workbench.GetDocument (pf.FilePath); + if (doc != null) { + gproject.ReloadFile(pf.FilePath); + GuiBuilderView view = doc.ActiveView as GuiBuilderView; + if (view != null) + view.ReloadDesigner (project); + } + } + + [CommandUpdateHandler (GtkCommands.GenerateCode)] + [CommandUpdateHandler (GtkCommands.ReloadDesigner)] + protected void UpdateGenerateCode (CommandInfo cinfo) + { + ProjectFile pf = CurrentNode.DataItem as ProjectFile; + + if (pf.DependsOn == null && pf.HasChildren) + cinfo.Visible = pf.IsComponentFile (); + else + cinfo.Visible = false; + } + + [CommandUpdateHandler (EditCommands.Copy)] + [CommandUpdateHandler (EditCommands.Delete)] + [CommandUpdateHandler (EditCommands.Rename)] + protected void UpdateDisabledCommands (CommandInfo cinfo) + { + //disable operations for generated files in designer folder + cinfo.Visible = false;//(CurrentNode.GetParentDataItem (typeof (GuiProjectFolder), true) == null); + } + + public override DragOperation CanDragNode () + { + return DragOperation.None; + } + + public override void RenameItem (string newName) + { + base.RenameItem (newName); + + Project project = CurrentNode.GetParentDataItem (typeof(Project), true) as Project; + if (project != null) { + ProjectFile pf = CurrentNode.DataItem as ProjectFile; + if (pf.IsComponentFile ()) { + GtkDesignInfo info = GtkDesignInfo.FromProject (project); + info.RenameComponentFile (pf); + } + } + } + } +}
\ No newline at end of file diff --git a/main/src/addins/MonoDevelop.GtkCore2/MonoDevelop.GtkCore.NodeBuilders/ProjectFolderNodeBuilderExtension.cs b/main/src/addins/MonoDevelop.GtkCore2/MonoDevelop.GtkCore.NodeBuilders/ProjectFolderNodeBuilderExtension.cs new file mode 100644 index 0000000000..6a20ae85de --- /dev/null +++ b/main/src/addins/MonoDevelop.GtkCore2/MonoDevelop.GtkCore.NodeBuilders/ProjectFolderNodeBuilderExtension.cs @@ -0,0 +1,156 @@ +// +// ProjectFolderNodeBuilderExtension.cs +// +// Author: +// Lluis Sanchez Gual, Krzysztof Marecki +// +// Copyright (C) 2006 Novell, Inc (http://www.novell.com) +// Copyright (C) 2010 Krzysztof Marecki +// +// 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 MonoDevelop.Projects; +using MonoDevelop.Ide.Gui.Pads.ProjectPad; +using MonoDevelop.Components.Commands; +using MonoDevelop.GtkCore.GuiBuilder; +using MonoDevelop.Ide.Gui; +using MonoDevelop.Ide.Gui.Components; +using MonoDevelop.Ide; +using MonoDevelop.Ide.Commands; + +namespace MonoDevelop.GtkCore.NodeBuilders +{ + class ProjectFolderNodeBuilderExtension: NodeBuilderExtension + { + public override bool CanBuildNode (Type dataType) + { + return typeof(ProjectFolder).IsAssignableFrom (dataType) && !(dataType is GuiProjectFolder); + } + + public override Type CommandHandlerType { + get { return typeof(UserInterfaceCommandHandler); } + } + + public override void GetNodeAttributes (ITreeNavigator treeNavigator, object dataObject, ref NodeAttributes attributes) + { + if (dataObject is GuiProjectFolder) + return; + + ProjectFolder folder = dataObject as ProjectFolder; + if (folder != null && folder.Project is DotNetProject) { + GtkDesignInfo info = GtkDesignInfo.FromProject (folder.Project); + if (info.SteticFolder == folder.Path) + attributes |= NodeAttributes.Hidden; + } + } + } + + class UserInterfaceCommandHandler: NodeCommandHandler + { + [CommandHandler (MonoDevelop.GtkCore.GtkCommands.AddNewDialog)] + public void AddNewDialogToProject() + { + AddNewWindow ("DialogFileTemplate"); + } + + [CommandUpdateHandler (MonoDevelop.GtkCore.GtkCommands.AddNewDialog)] + public void UpdateAddNewDialogToProject (CommandInfo cinfo) + { + cinfo.Visible = CanAddWindow () && !(CurrentNode.DataItem is GuiProjectFolder); + } + + [CommandHandler (MonoDevelop.GtkCore.GtkCommands.AddNewWindow)] + public void AddNewWindowToProject() + { + AddNewWindow ("WindowFileTemplate"); + } + + [CommandUpdateHandler (MonoDevelop.GtkCore.GtkCommands.AddNewWindow)] + public void UpdateAddNewWindowToProject (CommandInfo cinfo) + { + cinfo.Visible = CanAddWindow () && !(CurrentNode.DataItem is GuiProjectFolder); + } + + [CommandHandler (MonoDevelop.GtkCore.GtkCommands.AddNewWidget)] + public void AddNewWidgetToProject() + { + AddNewWindow ("WidgetFileTemplate"); + } + + [CommandUpdateHandler (MonoDevelop.GtkCore.GtkCommands.AddNewWidget)] + public void UpdateAddNewWidgetToProject (CommandInfo cinfo) + { + cinfo.Visible = CanAddWindow () && !(CurrentNode.DataItem is GuiProjectFolder); + } + + [CommandHandler (MonoDevelop.GtkCore.GtkCommands.AddNewActionGroup)] + public void AddNewActionGroupToProject() + { + AddNewWindow ("ActionGroupFileTemplate"); + } + + [CommandUpdateHandler (MonoDevelop.GtkCore.GtkCommands.AddNewActionGroup)] + public void UpdateAddNewActionGroupToProject(CommandInfo cinfo) + { + cinfo.Visible = CanAddWindow () && !(CurrentNode.DataItem is GuiProjectFolder); + } + + public override bool CanDropMultipleNodes (object[] dataObjects, DragOperation operation, DropPosition position) + { + foreach (object dataObject in dataObjects) + if (dataObjects is GuiProjectFolder) + return false; + + return base.CanDropMultipleNodes (dataObjects, operation, position); + } + + bool CanAddWindow () + { + DotNetProject project = CurrentNode.GetParentDataItem (typeof(Project), true) as DotNetProject; + return GtkDesignInfo.SupportsDesigner (project); + } + + public void AddNewWindow (string id) + { + DotNetProject project = CurrentNode.GetParentDataItem (typeof(Project), true) as DotNetProject; + if (project == null) + return; + + object dataItem = CurrentNode.DataItem; + + ProjectFolder folder = CurrentNode.GetParentDataItem (typeof(ProjectFolder), true) as ProjectFolder; + id = "Partial" + id; + + string path; + if (folder != null) + path = folder.Path; + else + path = project.BaseDirectory; + + IdeApp.ProjectOperations.CreateProjectFile (project, path, id); + IdeApp.ProjectOperations.Save (project); + + ITreeNavigator nav = Tree.GetNodeAtObject (dataItem); + if (nav != null) + nav.Expanded = true; + } + } +} diff --git a/main/src/addins/MonoDevelop.GtkCore2/MonoDevelop.GtkCore.NodeBuilders/ProjectNodeBuilder.cs b/main/src/addins/MonoDevelop.GtkCore2/MonoDevelop.GtkCore.NodeBuilders/ProjectNodeBuilder.cs new file mode 100644 index 0000000000..20de8ff9f4 --- /dev/null +++ b/main/src/addins/MonoDevelop.GtkCore2/MonoDevelop.GtkCore.NodeBuilders/ProjectNodeBuilder.cs @@ -0,0 +1,140 @@ +// +// ProjectNodeBuilder.cs +// +// Author: +// Lluis Sanchez Gual, Krzysztof Marecki +// +// Copyright (C) 2006 Novell, Inc (http://www.novell.com) +// Copyright (C) 2010 Krzysztof Marecki +// +// Permission is hereby granted, free of charge, to any person obtaining +// a copy of this software and associated documentation files (the +// "Software"), to deal in the Software without restriction, including +// without limitation the rights to use, copy, modify, merge, publish, +// distribute, sublicense, and/or sell copies of the Software, and to +// permit persons to whom the Software is furnished to do so, subject to +// the following conditions: +// +// The above copyright notice and this permission notice shall be +// included in all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, +// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND +// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE +// LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION +// OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION +// WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. +// +using System; +using System.Collections; +using System.IO; + +using Gtk; + +using MonoDevelop.Projects; +using MonoDevelop.Core; +using MonoDevelop.Ide.Gui.Pads; +using MonoDevelop.Ide.Gui; +using MonoDevelop.Ide.Gui.Components; +using MonoDevelop.Ide.Gui.Pads.ProjectPad; +using MonoDevelop.GtkCore.Dialogs; +using MonoDevelop.GtkCore.GuiBuilder; +using MonoDevelop.Ide; + +namespace MonoDevelop.GtkCore.NodeBuilders +{ + public class ProjectNodeBuilder: NodeBuilderExtension + { + static ProjectNodeBuilder instance; + + public override bool CanBuildNode (Type dataType) + { + return typeof(DotNetProject).IsAssignableFrom (dataType); + } + + public override Type CommandHandlerType { + get { + return typeof (UserInterfaceCommandHandler); + } + } + + protected override void Initialize () + { + lock (typeof (ProjectNodeBuilder)) + instance = this; + } + + public override void Dispose () + { + lock (typeof (ProjectNodeBuilder)) + instance = null; + } + + public override void BuildNode (ITreeBuilder treeBuilder, object dataObject, ref string label, ref Gdk.Pixbuf icon, ref Gdk.Pixbuf closedIcon) + { + Project project = dataObject as Project; + + if (project is DotNetProject) { + GtkDesignInfo info = GtkDesignInfo.FromProject (project); + + if (info.NeedsConversion) { + ProjectConversionDialog dialog = new ProjectConversionDialog (project, info.SteticFolderName); + + try + { + if (dialog.Run () == (int)ResponseType.Yes) { + info.GuiBuilderProject.Convert (dialog.GuiFolderName, dialog.MakeBackup); + IdeApp.ProjectOperations.Save (project); + } + } finally { + dialog.Destroy (); + } + } + + project.FileAddedToProject += HandleProjectFileAddedToProject; + } + } + + void HandleProjectFileAddedToProject (object sender, ProjectFileEventArgs e) + { + Project project = e.Project; + ProjectFile pf = e.ProjectFile; + string fileName = pf.FilePath.FullPath.ToString (); + GtkDesignInfo info = GtkDesignInfo.FromProject (project); + + string buildFile = info.GetBuildFileFromComponent (fileName); + if (!project.IsFileInProject(buildFile) && File.Exists (buildFile)) { + ProjectFile pf2 = project.AddFile (buildFile, BuildAction.Compile); + pf2.DependsOn = pf.FilePath.FileName; + } + + string gtkxFile = info.GetDesignerFileFromComponent (fileName); + if (!project.IsFileInProject(gtkxFile) && File.Exists (gtkxFile)) { + ProjectFile pf3 = project.AddFile (gtkxFile, BuildAction.EmbeddedResource); + pf3.DependsOn = pf.FilePath.FileName; + } + } + + public override void BuildChildNodes (ITreeBuilder builder, object dataObject) + { + Project project = (Project)dataObject; + GtkDesignInfo info = GtkDesignInfo.FromProject (project); + + if (GtkDesignInfo.HasDesignedObjects (project)) { + GuiProjectFolder folder = new GuiProjectFolder(info.SteticFolder.FullPath, project, null); + builder.AddChild (folder); + } + } + + public static void OnSupportChanged (Project p) + { + if (instance == null) + return; + + ITreeBuilder tb = instance.Context.GetTreeBuilder (p); + if (tb != null) + tb.UpdateAll (); + } + } +} diff --git a/main/src/addins/MonoDevelop.GtkCore2/MonoDevelop.GtkCore.NodeBuilders/StockIconsNodeBuilder.cs b/main/src/addins/MonoDevelop.GtkCore2/MonoDevelop.GtkCore.NodeBuilders/StockIconsNodeBuilder.cs new file mode 100644 index 0000000000..862112d5ff --- /dev/null +++ b/main/src/addins/MonoDevelop.GtkCore2/MonoDevelop.GtkCore.NodeBuilders/StockIconsNodeBuilder.cs @@ -0,0 +1,88 @@ + +using System; +using Gdk; + +using MonoDevelop.Ide.Gui.Pads; +using MonoDevelop.Core; +using MonoDevelop.Projects; +using MonoDevelop.Components.Commands; +using MonoDevelop.GtkCore.GuiBuilder; +using MonoDevelop.Ide.Gui.Components; + +namespace MonoDevelop.GtkCore.NodeBuilders +{ + class StockIconsNode + { + public StockIconsNode (Project project) + { + this.Project = project; + } + + public Project Project; + } + + public class StockIconsNodeBuilder: TypeNodeBuilder + { + Pixbuf iconsIcon; + + public override Type NodeDataType { + get { return typeof(StockIconsNode); } + } + + public override Type CommandHandlerType { + get { return typeof(StockIconsNodeCommandHandler); } + } + + public override string ContextMenuAddinPath { + get { return "/MonoDevelop/GtkCore/ContextMenu/ProjectPad.StockIcons"; } + } + public StockIconsNodeBuilder () + { + try { + iconsIcon = Pixbuf.LoadFromResource ("image-x-generic.png"); + } catch (Exception e) { + Console.WriteLine ("Error while loading pixbuf 'image-x-generic.png': " + e); + } + } + public override int CompareObjects (ITreeNavigator thisNode, ITreeNavigator otherNode) + { + return -1; + } + + + public override string GetNodeName (ITreeNavigator thisNode, object dataObject) + { + return "StockIcons"; + } + + public override void BuildNode (ITreeBuilder treeBuilder, object dataObject, ref string label, ref Pixbuf icon, ref Pixbuf closedIcon) + { + label = GettextCatalog.GetString ("Stock Icons"); + icon = iconsIcon; + } + } + + public class StockIconsNodeCommandHandler: NodeCommandHandler + { + public override void ActivateItem () + { + StockIconsNode node = (StockIconsNode) CurrentNode.DataItem; + GtkDesignInfo info = GtkDesignInfo.FromProject (node.Project); + GuiBuilderProject gp = info.GuiBuilderProject; + Stetic.Project sp = gp.SteticProject; + sp.ImagesRootPath = FileService.AbsoluteToRelativePath (info.SteticFolder, gp.Project.BaseDirectory); + sp.ImportFileCallback = delegate (string file) { + return GuiBuilderService.ImportFile (gp.Project, file); + }; + sp.EditIcons (); + gp.Save (true); + } + + [CommandHandler (GtkCommands.EditIcons)] + protected void OnEditIcons () + { + ActivateItem (); + } + } +} + diff --git a/main/src/addins/MonoDevelop.GtkCore2/MonoDevelop.GtkCore/ChangeLog b/main/src/addins/MonoDevelop.GtkCore2/MonoDevelop.GtkCore/ChangeLog new file mode 100644 index 0000000000..a613ab6eb0 --- /dev/null +++ b/main/src/addins/MonoDevelop.GtkCore2/MonoDevelop.GtkCore/ChangeLog @@ -0,0 +1,68 @@ +2010-09-20 Krzysztof Marecki <marecki.krzysztof@gmail.com> + + * WidgetFileDescriptionTemplate.cs: + +2010-09-17 Krzysztof Marecki <marecki.krzysztof@gmail.com> + + * GtkDesignInfo.cs: + +2010-09-09 Krzysztof Marecki <freefirma@gmail.com> + + * GtkDesignInfo.cs: + +2010-09-08 Krzysztof Marecki <freefirma@gmail.com> + + * WidgetFileDescriptionTemplate.cs: + +2010-08-30 Krzysztof Marecki <freefirma@gmail.com> + + * GtkDesignInfo.cs: + +2010-08-27 Krzysztof Marecki <freefirma@gmail.com> + + * GtkDesignInfo.cs: + +2010-08-17 Krzysztof Marecki <freefirma@gmail.com> + + * GtkDesignInfo.cs: + +2010-08-16 Krzysztof Marecki <freefirma@gmail.com> + + * GtkDesignInfo.cs: + +2010-08-15 Krzysztof Marecki <freefirma@gmail.com> + + * WidgetFileDescriptionTemplate.cs: + +2010-08-15 Krzysztof Marecki <freefirma@gmail.com> + + * GtkDesignInfo.cs: + +2010-08-13 Krzysztof Marecki <freefirma@gmail.com> + + * GtkDesignInfo.cs: + +2010-08-09 Krzysztof Marecki <freefirma@gmail.com> + + * GtkDesignInfo.cs: Add ComponentNeedsCodeGeneration method, + +2010-08-04 Krzysztof Marecki <freefirma@gmail.com> + + * WidgetFileDescriptionTemplate.cs: Bump Api + +2010-07-06 Krzysztof Marecki <marecki.krzysztof@gmail.com> + + * GtkDesignInfo.cs: Remove gtk-gui folder after project conversion + +2010-06-23 Krzysztof Marecki <marecki.krzysztof@gmail.com> + + * GtkDesignInfo.cs: + +2010-06-16 Krzysztof Marecki <marecki.krzysztof@gmail.com> + + * GtkDesignInfo.cs: + +2010-06-07 Krzysztof Marecki <marecki.krzysztof@gmail.com> + + * GtkDesignInfo.cs: Transition from project file name to project folder. + diff --git a/main/src/addins/MonoDevelop.GtkCore2/MonoDevelop.GtkCore/Counters.cs b/main/src/addins/MonoDevelop.GtkCore2/MonoDevelop.GtkCore/Counters.cs new file mode 100644 index 0000000000..970caa63d0 --- /dev/null +++ b/main/src/addins/MonoDevelop.GtkCore2/MonoDevelop.GtkCore/Counters.cs @@ -0,0 +1,38 @@ +// +// Counters.cs +// +// Author: +// Lluis Sanchez Gual <lluis@novell.com> +// +// Copyright (c) 2009 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 MonoDevelop.Core.Instrumentation; + +namespace MonoDevelop.GtkCore +{ + internal static class Counters + { + public static Counter GuiProjectsInMemory = InstrumentationService.CreateCounter ("GUI Projects in Memory", "GTK# Designer"); + public static Counter GuiProjectsLoaded = InstrumentationService.CreateCounter ("GUI Projects Loaded", "GTK# Designer"); + public static Counter SteticProjectsLoaded = InstrumentationService.CreateCounter ("Stetic Projects Loaded", "GTK# Designer"); + } +} diff --git a/main/src/addins/MonoDevelop.GtkCore2/MonoDevelop.GtkCore/GtkCoreService.cs b/main/src/addins/MonoDevelop.GtkCore2/MonoDevelop.GtkCore/GtkCoreService.cs new file mode 100644 index 0000000000..ce3bf3268a --- /dev/null +++ b/main/src/addins/MonoDevelop.GtkCore2/MonoDevelop.GtkCore/GtkCoreService.cs @@ -0,0 +1,43 @@ +// +// GtkCoreService.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 System.Collections.Generic; +using MonoDevelop.Core; +using MonoDevelop.Components.Commands; + +namespace MonoDevelop.GtkCore +{ + class GtkCoreStartupCommand: CommandHandler + { + protected override void Run() + { + ReferenceManager.Initialize (); + } + } +} diff --git a/main/src/addins/MonoDevelop.GtkCore2/MonoDevelop.GtkCore/GtkDesignInfo.cs b/main/src/addins/MonoDevelop.GtkCore2/MonoDevelop.GtkCore/GtkDesignInfo.cs new file mode 100644 index 0000000000..1a5d790644 --- /dev/null +++ b/main/src/addins/MonoDevelop.GtkCore2/MonoDevelop.GtkCore/GtkDesignInfo.cs @@ -0,0 +1,676 @@ +// +// GtkDesignInfo.cs +// +// Authors: +// Lluis Sanchez Gual +// Mike Kestner +// Krzysztof Marecki +// +// Copyright (C) 2006-2008 Novell, Inc (http://www.novell.com) +// Copyright (C) 2010 Krzysztof Marecki +// +// Permission is hereby granted, free of charge, to any person obtaining +// a copy of this software and associated documentation files (the +// "Software"), to deal in the Software without restriction, including +// without limitation the rights to use, copy, modify, merge, publish, +// distribute, sublicense, and/or sell copies of the Software, and to +// permit persons to whom the Software is furnished to do so, subject to +// the following conditions: +// +// The above copyright notice and this permission notice shall be +// included in all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, +// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND +// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE +// LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION +// OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION +// WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. +// + +using System; +using System.IO; +using System.CodeDom; +using System.CodeDom.Compiler; +using System.Collections.Generic; +using System.Collections.Specialized; + +using MonoDevelop.Core; +using MonoDevelop.Projects; +using MonoDevelop.Projects.CodeGeneration; +using MonoDevelop.Projects.Dom; +using MonoDevelop.Projects.Dom.Parser; +using MonoDevelop.Core.Serialization; +using MonoDevelop.GtkCore.GuiBuilder; +using MonoDevelop.GtkCore.NodeBuilders; +using MonoDevelop.Ide; + +namespace MonoDevelop.GtkCore +{ + public class GtkDesignInfo: IDisposable, Stetic.IProjectDesignInfo + { + DotNetProject project; + GuiBuilderProject builderProject; + IDotNetLanguageBinding binding; + ProjectResourceProvider resourceProvider; + ReferenceManager referenceManager; + string langExtension; + + [ItemProperty (DefaultValue = true)] + bool generateGettext = true; + + [ItemProperty (DefaultValue = "Mono.Unix.Catalog")] + string gettextClass = "Mono.Unix.Catalog"; + + [ItemProperty (DefaultValue = "Designer")] + string steticFolderName = "Designer"; + + [ItemProperty (DefaultValue = true)] + bool hideGtkxFiles = true; + + GtkDesignInfo () + { + } + + GtkDesignInfo (DotNetProject project) + { + IExtendedDataItem item = (IExtendedDataItem) project; + item.ExtendedProperties ["GtkDesignInfo"] = this; + Project = project; + } + + DotNetProject Project { + get { return project; } + set { + if (project == value) + return; + + if (project != null) { + project.FileAddedToProject -= OnFileEvent; + project.FileChangedInProject -= OnFileEvent; + project.FileRemovedFromProject -= OnFileEvent; + binding = null; + if (referenceManager != null) + referenceManager.Dispose (); + referenceManager = null; + } + project = value; + + if (project != null) { + binding = LanguageBindingService.GetBindingPerLanguageName (project.LanguageName) as IDotNetLanguageBinding; + + CodeDomProvider provider = binding.GetCodeDomProvider (); + if (provider == null) + throw new UserException ("Code generation not supported for language: " + project.LanguageName); + langExtension = "." + provider.FileExtension; + + project.FileAddedToProject += OnFileEvent; + project.FileChangedInProject += OnFileEvent; + project.FileRemovedFromProject += OnFileEvent; + } + } + } + + void OnFileEvent (object o, ProjectFileEventArgs args) + { + if (!IdeApp.Workspace.IsOpen || !File.Exists (ObjectsFile)) + return; + + UpdateObjectsFile (); + } + + public void Dispose () + { + if (resourceProvider != null) + System.Runtime.Remoting.RemotingServices.Disconnect (resourceProvider); + resourceProvider = null; + if (builderProject != null) + builderProject.Dispose (); + builderProject = null; + if (referenceManager != null) + referenceManager.Dispose (); + referenceManager = null; + Project = null; + } + + public GuiBuilderProject GuiBuilderProject { + get { + if (builderProject == null) { + if (SupportsDesigner (project)) { + builderProject = new GuiBuilderProject (project, SteticFolder.FullPath.FullPath); + } else + builderProject = new GuiBuilderProject (project, null); + } + return builderProject; + } + } + + public ReferenceManager ReferenceManager { + get { + if (referenceManager == null) + referenceManager = new ReferenceManager (project); + return referenceManager; + } + } + + public void ReloadGuiBuilderProject () + { + if (builderProject != null) + builderProject.Reload (); + } + + public ProjectResourceProvider ResourceProvider { + get { + if (resourceProvider == null) { + resourceProvider = new ProjectResourceProvider (project); + System.Runtime.Remoting.RemotingServices.Marshal (resourceProvider, null, typeof(Stetic.IResourceProvider)); + } + return resourceProvider; + } + } + + public bool NeedsConversion { + get { return project.IsFileInProject (SteticFile); } + } + + FilePath ObjectsFile { + get { return SteticFolder.Combine ("objects.xml"); } + } + + [Obsolete] + public FilePath SteticGeneratedFile { + get { return SteticFolder.Combine (binding.GetFileName ("generated")); } + } + + [Obsolete] + public FilePath SteticFile { + get { return SteticFolder.Combine ("gui.stetic"); } + } + + public string BuildFileExtension { + get { return ".designer"; } + } + + public string DesignerFileExtension { + get { return ".gtkx"; } + } + + public FilePath SteticFolder { + get { + FilePath oldfolder = project.BaseDirectory.Combine ("gtk-gui"); + if (Directory.Exists (oldfolder)) + return oldfolder; + + return project.BaseDirectory.Combine (steticFolderName); + } + } + + public bool GenerateGettext { + get { return generateGettext; } + set { + generateGettext = value; + // Set to default value if gettext is not enabled + if (!generateGettext) + gettextClass = "Mono.Unix.Catalog"; + } + } + + public string GettextClass { + get { return gettextClass; } + set { gettextClass = value; } + } + + public string SteticFolderName { + get { return steticFolderName; } + set { steticFolderName = value; } + } + + public bool HideGtkxFiles { + get { return hideGtkxFiles; } + set { hideGtkxFiles = value; } + } + + public static bool HasDesignedObjects (Project project) + { + if (project == null) + return false; + + return SupportsDesigner (project); + } + + public static bool SupportsDesigner (Project project) + { + DotNetProject dnp = project as DotNetProject; + return dnp != null && HasGtkReference (dnp) && SupportsRefactoring (dnp); + } + + public static bool SupportsRefactoring (DotNetProject project) + { + if (project == null || project.LanguageBinding == null || project.LanguageBinding.GetCodeDomProvider () == null) + return false; + RefactorOperations ops = RefactorOperations.AddField | RefactorOperations.AddMethod | RefactorOperations.RenameField | RefactorOperations.AddAttribute; + CodeRefactorer cref = IdeApp.Workspace.GetCodeRefactorer (project.ParentSolution); + return cref.LanguageSupportsOperation (project.LanguageBinding.Language, ops); + } + + static bool IsGtkReference (ProjectReference pref) + { + if (pref.ReferenceType != ReferenceType.Gac) + return false; + + int idx = pref.StoredReference.IndexOf (","); + if (idx == -1) + return false; + + string name = pref.StoredReference.Substring (0, idx).Trim (); + return name == "gtk-sharp"; + } + + static bool HasGtkReference (DotNetProject project) + { + foreach (ProjectReference pref in project.References) + if (IsGtkReference (pref)) + return true; + return false; + } + + public void ForceCodeGenerationOnBuild () + { + if (!SupportsDesigner (project)) + return; + try { + FileInfo fi = new FileInfo (SteticFile); + fi.LastWriteTime = DateTime.Now; + project.SetNeedsBuilding (true); + } catch { + // Ignore errors here + } + } + + public void CheckGtkFolder () + { + foreach (string designerFile in GetDesignerFiles ()) { + string componentFile = GetComponentFileFromDesigner (designerFile); + if (componentFile != null) { + string buildFile = GetBuildFileFromComponent (componentFile); + if (buildFile != null) { + // if build file is missing, force to generate it again + if ((project.GetProjectFile (buildFile) == null) || !File.Exists (buildFile)) { + FileInfo fi = new FileInfo (designerFile); + fi.LastWriteTime = DateTime.Now; + } + } + } + } + } + + bool CleanGtkFolder (StringCollection remaining_files) + { + bool projectModified = false; + // Remove all project files which are not in the generated list + foreach (ProjectFile pf in project.Files.GetFilesInPath (SteticFolder)) { + if (remaining_files.Contains (pf.FilePath)) + continue; + + project.Files.Remove (pf); + FileService.DeleteFile (pf.FilePath); + projectModified = true; + } + + if (remaining_files.Count == 0) + FileService.DeleteDirectory (SteticFolder); + + return projectModified; + } + + public void ConvertGtkFolder (string guiFolderName, bool makeBackup) + { + foreach (ProjectFile pf in project.Files.GetFilesInPath (SteticFolder)) { + FilePath path = pf.FilePath; + + if (path != SteticGeneratedFile) { + project.Files.Remove (path); + + if (path != SteticFile) + FileService.DeleteFile (path.FullPath); + } + } + + string oldGuiFolder = SteticFolder.FullPath; + string oldSteticFile = SteticFile; + string oldGeneratedFile = SteticGeneratedFile; + SteticFolderName = guiFolderName; + + if (!Directory.Exists (SteticFolder)) + FileService.CreateDirectory (SteticFolder); + + if (makeBackup && File.Exists (oldSteticFile)) { + string backupFile = SteticFolder.Combine ("old.stetic"); + FileService.MoveFile (oldSteticFile, backupFile); + } + + if (File.Exists (oldGeneratedFile)) + FileService.DeleteFile (oldGeneratedFile); + + if (Directory.Exists (oldGuiFolder)) + FileService.DeleteDirectory (oldGuiFolder); + } + + public bool UpdateGtkFolder () + { + if (!SupportsDesigner (project)) + return false; + + // This method synchronizes the current gtk project configuration info + // with the needed support files in the gtk-gui folder. + + FileService.CreateDirectory (SteticFolder); + bool projectModified = false; + + foreach (string filename in GetDesignerFiles ()) { + ProjectFile pf = project.AddFile (filename, BuildAction.EmbeddedResource); + pf.ResourceId = Path.GetFileName (filename); + + string componentFile = GetComponentFileFromDesigner (filename); + + if (componentFile != null && File.Exists (componentFile)) { + pf.DependsOn = componentFile; + + string buildFile = GetBuildFileFromComponent (componentFile); + if (buildFile != null && File.Exists (buildFile)) { + ProjectFile pf2 = project.AddFile (buildFile, BuildAction.Compile); + pf2.ResourceId = Path.GetFileName (buildFile); + pf2.DependsOn = componentFile; + } + } + + projectModified = true; + } + + StringCollection files = GuiBuilderProject.GenerateFiles (SteticFolder); + foreach (string filename in files) { + if (!project.IsFileInProject (filename)) { + project.AddFile (filename, BuildAction.Compile); + projectModified = true; + } + + } + + UpdateObjectsFile (); + + return ReferenceManager.Update () || projectModified; + } + +// public bool UpdateGtkFolder () +// { +// if (!SupportsDesigner (project)) +// return false; +// +// // This method synchronizes the current gtk project configuration info +// // with the needed support files in the gtk-gui folder. +// +// FileService.CreateDirectory (GtkGuiFolder); +// bool projectModified = false; +// bool initialGeneration = false; +// +// if (!File.Exists (SteticFile)) { +// initialGeneration = true; +// StreamWriter sw = new StreamWriter (SteticFile); +// sw.WriteLine ("<stetic-interface />"); +// sw.Close (); +// FileService.NotifyFileChanged (SteticFile); +// } +// +// if (!project.IsFileInProject (SteticFile)) { +// ProjectFile pf = project.AddFile (SteticFile, BuildAction.EmbeddedResource); +// pf.ResourceId = "gui.stetic"; +// projectModified = true; +// } +// +// StringCollection files = GuiBuilderProject.GenerateFiles (GtkGuiFolder); +// DateTime generatedTime = File.GetLastWriteTime (SteticFile).Subtract (TimeSpan.FromSeconds (2)); +// +// foreach (string filename in files) { +// if (initialGeneration) { +// // Ensure that the generation date of this file is < the date of the .stetic file +// // In this way the code will be properly regenerated when building the project. +// File.SetLastWriteTime (filename, generatedTime); +// } +// if (!project.IsFileInProject (filename)) { +// project.AddFile (filename, BuildAction.Compile); +// projectModified = true; +// } +// } +// +// UpdateObjectsFile (); +// files.Add (ObjectsFile); +// files.Add (SteticFile); +// +// if (CleanGtkFolder (files)) +// projectModified = true; +// +// return ReferenceManager.Update () || projectModified; +// return true; +// } + + public void RenameComponentFile (ProjectFile pfComponent) + { + foreach (ProjectFile pf in pfComponent.DependentChildren) { + if (pf.FilePath.FileName.Contains (BuildFileExtension)) { + FileService.RenameFile (pf.FilePath, + GetBuildFileNameFromComponent (pfComponent.FilePath)); + } + if (pf.FilePath.FileName.Contains (DesignerFileExtension)) { + FileService.RenameFile (pf.FilePath, + GetDesignerFileNameFromComponent (pfComponent.FilePath)); + } + } + } + + public string GetComponentFile (string componentName) + { + IType type = GuiBuilderProject.FindClass (componentName); + if (type != null) { + foreach (IType part in type.Parts) { + string componentFile = part.CompilationUnit.FileName.FullPath; + if (componentFile.Contains (BuildFileExtension)) + componentFile = componentFile.Replace (BuildFileExtension, string.Empty); + + return componentFile; + } + } + + //If ProjectDom does not exist, assume that project is being created + //and return component file path that is located in the project root folder + ProjectDom ctx = ProjectDomService.GetProjectDom (project); + if (ctx == null) { + string componentFile = Path.Combine (project.BaseDirectory, componentName + langExtension); + if (File.Exists (componentFile)) + return componentFile; + } + + return null; + } + + public string GetBuildFileInSteticFolder (string componentName) + { + string name = string.Format ("{0}{1}{2}", componentName, BuildFileExtension, langExtension); + string buildFile = Path.Combine (SteticFolder, name); + + return buildFile; + } + + public string GetBuildFileFromComponent (string componentFile) + { + if (componentFile != null) { + ProjectFile pf = project.Files.GetFile (componentFile); + if (pf != null) { + foreach (var child in pf.DependentChildren) { + if (child.Name.Contains (BuildFileExtension)) + return child.FilePath; + } + } + return GetBuildFileNameFromComponent (componentFile); + } + return null; + } + + public string GetBuildFileNameFromComponent (string componentFile) + { + string buildFile = componentFile.Replace + (langExtension, BuildFileExtension + langExtension); + return buildFile; + } + + public string GetDesignerFileFromComponent (string componentFile) + { + if (componentFile != null) { + ProjectFile pf = project.Files.GetFile (componentFile); + if (pf != null) { + foreach (var child in pf.DependentChildren) { + if (child.Name.Contains (DesignerFileExtension)) + return child.FilePath; + } + } + return GetDesignerFileNameFromComponent (componentFile); + } + return null; + } + + public string GetDesignerFileNameFromComponent (string componentFile) + { + string gtkxFile = componentFile.Replace (langExtension, DesignerFileExtension); + return gtkxFile; + } + + public string GetComponentFileFromDesigner (string gtkxFile) + { + if (gtkxFile != null) { + ProjectFile pf = project.Files.GetFile (gtkxFile); + if (pf != null) { + if (pf.DependsOn != null) + return pf.DependsOn; + } + string componentFile = gtkxFile.Replace (DesignerFileExtension, langExtension); + return componentFile; + } + + return null; + } + +// public string GetBuildFileFromDesigner (string gtkxFile) +// { +// string buildFile = gtkxFile.Replace (DesignerFileExtension, BuildFileExtension + langExtension); +// return buildFile; +// } + + + public string GetComponentFolder (string componentName) + { + IType type = GuiBuilderProject.FindClass (componentName); + + if (type != null) { + FilePath folder = type.CompilationUnit.FileName.ParentDirectory; + return folder.FullPath.ToString (); + } + + return null; + } + + public string[] GetComponentFolders () + { + List<string> folders = new List<string> (); + ProjectDom ctx = GuiBuilderProject.GetParserContext (); + + if (ctx != null) { + foreach (IType type in ctx.Types) + foreach (IType part in type.Parts) { + FilePath folder = part.CompilationUnit.FileName.ParentDirectory; + string folderName = folder.FullPath.ToString (); + + if (!folders.Contains (folderName)) + folders.Add (folder); + } + } + + return folders.ToArray (); + } + + public string[] GetDesignerFiles () + { + List<string> files = new List<string> (); + + foreach (string folder in GetComponentFolders ()) { + DirectoryInfo dir = new DirectoryInfo (folder); + + foreach (FileInfo file in dir.GetFiles ()) + if (file.Extension == DesignerFileExtension) + files.Add (file.ToString ()); + } + + return files.ToArray (); + } + + public bool HasComponentFile (string componentName) + { + return (GetComponentFile (componentName) != null); + } + + public bool ComponentNeedsCodeGeneration (string componentName) + { + string componentFile = GetComponentFile (componentName); + string gtkxFile = GetDesignerFileFromComponent (componentFile); + string buildFile = GetBuildFileFromComponent (componentFile); + FileInfo gtkxFileInfo = File.Exists (gtkxFile) ? new FileInfo (gtkxFile) : null; + FileInfo buildFileInfo = File.Exists (buildFile) ? new FileInfo (buildFile) : null; + if (gtkxFileInfo == null) + return false; + //file does not exist + if (buildFileInfo == null) + return true; + + return gtkxFileInfo.LastWriteTime > buildFileInfo.LastWriteTime; + } + + void UpdateObjectsFile () + { + if (!File.Exists (ObjectsFile)) + return; + + ObjectsDocument doc = new ObjectsDocument (ObjectsFile); + doc.Update (GuiBuilderProject.WidgetParser, GuiBuilderProject.SteticProject, IdeApp.Workspace.GetCodeRefactorer (project.ParentSolution)); + } + + public static void DisableProject (Project project) + { + if (HasDesignedObjects (project)) + return; + + GtkDesignInfo info = FromProject (project); + StringCollection saveFiles = new StringCollection (); + saveFiles.AddRange (new string[] {info.ObjectsFile, info.SteticFile}); + info.CleanGtkFolder (saveFiles); + project.Files.Remove (info.ObjectsFile); + project.Files.Remove (info.SteticFile); + IExtendedDataItem item = (IExtendedDataItem) project; + item.ExtendedProperties.Remove ("GtkDesignInfo"); + info.Dispose (); + ProjectNodeBuilder.OnSupportChanged (project); + } + + public static GtkDesignInfo FromProject (Project project) + { + if (!(project is DotNetProject)) + return new GtkDesignInfo (); + + IExtendedDataItem item = (IExtendedDataItem) project; + GtkDesignInfo info = item.ExtendedProperties ["GtkDesignInfo"] as GtkDesignInfo; + if (info == null) + info = new GtkDesignInfo ((DotNetProject) project); + else + info.Project = (DotNetProject) project; + return info; + } + } +} diff --git a/main/src/addins/MonoDevelop.GtkCore2/MonoDevelop.GtkCore/ObjectsDocument.cs b/main/src/addins/MonoDevelop.GtkCore2/MonoDevelop.GtkCore/ObjectsDocument.cs new file mode 100644 index 0000000000..90e7deb7be --- /dev/null +++ b/main/src/addins/MonoDevelop.GtkCore2/MonoDevelop.GtkCore/ObjectsDocument.cs @@ -0,0 +1,301 @@ +// +// ObjectsDocument.cs +// +// Authors: +// Lluis Sanchez Gual +// Mike Kestner +// +// Copyright (C) 2006-2008 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 System.Xml; +using System.CodeDom; +using System.Collections; +using System.Collections.Generic; +using System.Collections.Specialized; + +using MonoDevelop.Projects.Dom; +using MonoDevelop.Projects.CodeGeneration; + +namespace MonoDevelop.GtkCore +{ + + + public class ObjectsDocument : XmlDocument + { + string path; + + public ObjectsDocument (string path) : base () + { + this.path = path; + Load (path); + } + + public StringCollection ObjectNames { + get { + StringCollection names = new StringCollection (); + foreach (XmlNode node in DocumentElement) { + if (node.Name != "object") + continue; + XmlElement elem = node as XmlElement; + names.Add (elem.GetAttribute ("type")); + } + return names; + } + } + + enum SyncState + { + Unspecified, + Off, + On, + } + + SyncState AttrSyncState { + get { + if (DocumentElement.HasAttribute ("attr-sync")) { + if (DocumentElement.GetAttribute ("attr-sync").ToLower () == "off") + return SyncState.Off; + else + return SyncState.On; + } else + return SyncState.Unspecified; + } + set { + switch (value) { + case SyncState.Unspecified: + DocumentElement.RemoveAttribute ("attr-sync"); + break; + case SyncState.Off: + DocumentElement.SetAttribute ("attr-sync", "off"); + break; + case SyncState.On: + DocumentElement.SetAttribute ("attr-sync", "on"); + break; + default: + throw new ArgumentOutOfRangeException ("value"); + } + Save (); + } + } + + public void Save () + { + Save (path); + } + + void InsertToolboxItemAttributes (WidgetParser parser, CodeRefactorer cref) + { + Dictionary<string, IType> tb_items = parser.GetToolboxItems (); + foreach (string clsname in ObjectNames) { + if (tb_items.ContainsKey (clsname)) + continue; + + IType cls = parser.GetClass (clsname); + if (cls == null) + continue; + + cref.AddAttribute (cls, "System.ComponentModel.ToolboxItem", true); + XmlElement elem = DocumentElement.SelectSingleNode ("object[@type='" + clsname + "']") as XmlElement; + if (elem != null && elem.HasAttribute ("palette-category")) + cref.AddAttribute (cls, "System.ComponentModel.Category", elem.GetAttribute ("palette-category")); + } + } + + public void Update (WidgetParser parser, Stetic.Project stetic, CodeRefactorer refactorer) + { + if (AttrSyncState == SyncState.Unspecified) { + if (refactorer != null) { + InsertToolboxItemAttributes (parser, refactorer); + AttrSyncState = SyncState.On; + } + return; + } else if (AttrSyncState == SyncState.Off) + return; + + StringCollection tb_names = new StringCollection (); + foreach (IType cls in parser.GetToolboxItems().Values) { + UpdateClass (parser, stetic, cls, null); + tb_names.Add (cls.FullName); + } + + List<XmlElement> toDelete = new List<XmlElement> (); + + foreach (XmlElement elem in SelectNodes ("objects/object")) { + string name = elem.GetAttribute ("type"); + if (!tb_names.Contains (name)) + toDelete.Add (elem); + } + + foreach (XmlElement elem in toDelete) + elem.ParentNode.RemoveChild (elem); + + Save (); + } + + void UpdateClass (WidgetParser parser, Stetic.Project stetic, IType widgetClass, IType wrapperClass) + { + string typeName = widgetClass.FullName; + string basetypeName = GetBaseType (parser, widgetClass, stetic); + XmlElement objectElem = (XmlElement) SelectSingleNode ("objects/object[@type='" + typeName + "']"); + + if (objectElem == null) { + + // The widget class is not yet in the XML file. Create an element for it. + objectElem = CreateElement ("object"); + objectElem.SetAttribute ("type", typeName); + string category = parser.GetCategory (widgetClass); + if (category == String.Empty) + objectElem.SetAttribute ("palette-category", "General"); + else + objectElem.SetAttribute ("palette-category", category); + objectElem.SetAttribute ("allow-children", "false"); + if (wrapperClass != null) + objectElem.SetAttribute ("wrapper", wrapperClass.FullName); + + // By default add a reference to Gtk.Widget properties and events + XmlElement itemGroups = objectElem.OwnerDocument.CreateElement ("itemgroups"); + objectElem.AppendChild (itemGroups); + + itemGroups = objectElem.OwnerDocument.CreateElement ("signals"); + objectElem.AppendChild (itemGroups); + + objectElem.SetAttribute ("base-type", basetypeName); + DocumentElement.AppendChild (objectElem); + } + + UpdateObject (parser, basetypeName, objectElem, widgetClass, wrapperClass); + } + + string GetBaseType (WidgetParser parser, IType widgetClass, Stetic.Project stetic) + { + string[] types = stetic.GetWidgetTypes (); + Hashtable typesHash = new Hashtable (); + foreach (string t in types) + typesHash [t] = t; + + string ret = parser.GetBaseType (widgetClass, typesHash); + return ret ?? "Gtk.Widget"; + } + + void UpdateObject (WidgetParser parser, string topType, XmlElement objectElem, IType widgetClass, IType wrapperClass) + { + if (widgetClass.IsPublic) + objectElem.RemoveAttribute ("internal"); + else + objectElem.SetAttribute ("internal", "true"); + + ListDictionary properties = new ListDictionary (); + ListDictionary events = new ListDictionary (); + + parser.CollectMembers (widgetClass, true, topType, properties, events); + if (wrapperClass != null) + parser.CollectMembers (wrapperClass, false, null, properties, events); + + foreach (IProperty prop in properties.Values) + MergeProperty (parser, objectElem, prop); + + foreach (IEvent ev in events.Values) + MergeEvent (parser, objectElem, ev); + + // Remove old properties + ArrayList toDelete = new ArrayList (); + foreach (XmlElement xprop in objectElem.SelectNodes ("itemgroups/itemgroup/property")) { + if (!properties.Contains (xprop.GetAttribute ("name"))) + toDelete.Add (xprop); + } + + // Remove old signals + foreach (XmlElement xevent in objectElem.SelectNodes ("signals/itemgroup/signal")) { + if (!events.Contains (xevent.GetAttribute ("name"))) + toDelete.Add (xevent); + } + + foreach (XmlElement el in toDelete) { + XmlElement pe = (XmlElement) el.ParentNode; + pe.RemoveChild (el); + if (pe.ChildNodes.Count == 0) + pe.ParentNode.RemoveChild (pe); + } + } + + void MergeProperty (WidgetParser parser, XmlElement objectElem, IProperty prop) + { + XmlElement itemGroups = objectElem ["itemgroups"]; + if (itemGroups == null) { + itemGroups = objectElem.OwnerDocument.CreateElement ("itemgroups"); + objectElem.AppendChild (itemGroups); + } + + string cat = parser.GetCategory (prop); + XmlElement itemGroup = GetItemGroup (prop.DeclaringType, itemGroups, cat, "Properties"); + + XmlElement propElem = (XmlElement) itemGroup.SelectSingleNode ("property[@name='" + prop.Name + "']"); + if (propElem == null) { + propElem = itemGroup.OwnerDocument.CreateElement ("property"); + propElem.SetAttribute ("name", prop.Name); + itemGroup.AppendChild (propElem); + } + } + + void MergeEvent (WidgetParser parser, XmlElement objectElem, IEvent evnt) + { + XmlElement itemGroups = objectElem ["signals"]; + if (itemGroups == null) { + itemGroups = objectElem.OwnerDocument.CreateElement ("signals"); + objectElem.AppendChild (itemGroups); + } + + string cat = parser.GetCategory (evnt); + XmlElement itemGroup = GetItemGroup (evnt.DeclaringType, itemGroups, cat, "Signals"); + + XmlElement signalElem = (XmlElement) itemGroup.SelectSingleNode ("signal[@name='" + evnt.Name + "']"); + if (signalElem == null) { + signalElem = itemGroup.OwnerDocument.CreateElement ("signal"); + signalElem.SetAttribute ("name", evnt.Name); + itemGroup.AppendChild (signalElem); + } + } + + XmlElement GetItemGroup (IType cls, XmlElement itemGroups, string cat, string groupName) + { + XmlElement itemGroup; + + if (cat != "") + itemGroup = (XmlElement) itemGroups.SelectSingleNode ("itemgroup[@name='" + cat + "']"); + else + itemGroup = (XmlElement) itemGroups.SelectSingleNode ("itemgroup[(not(@name) or @name='') and not(@ref)]"); + + if (itemGroup == null) { + itemGroup = itemGroups.OwnerDocument.CreateElement ("itemgroup"); + if (cat != null && cat != "") { + itemGroup.SetAttribute ("name", cat); + itemGroup.SetAttribute ("label", cat); + } else + itemGroup.SetAttribute ("label", cls.Name + " " + groupName); + itemGroups.AppendChild (itemGroup); + } + return itemGroup; + } + } +} diff --git a/main/src/addins/MonoDevelop.GtkCore2/MonoDevelop.GtkCore/ProjectResourceProvider.cs b/main/src/addins/MonoDevelop.GtkCore2/MonoDevelop.GtkCore/ProjectResourceProvider.cs new file mode 100644 index 0000000000..e1c46517d8 --- /dev/null +++ b/main/src/addins/MonoDevelop.GtkCore2/MonoDevelop.GtkCore/ProjectResourceProvider.cs @@ -0,0 +1,89 @@ +// +// ProjectResourceProvider.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 System.Collections; +using System.IO; +using MonoDevelop.Projects; +using MonoDevelop.Ide; + +namespace MonoDevelop.GtkCore +{ + public class ProjectResourceProvider: MarshalByRefObject, Stetic.IResourceProvider + { + Project project; + + public ProjectResourceProvider (Project project) + { + this.project = project; + } + + public Stetic.ResourceInfo[] GetResources () + { + ArrayList list = new ArrayList (); + foreach (ProjectFile file in project.Files) { + if (file.BuildAction == BuildAction.EmbeddedResource) + list.Add (new Stetic.ResourceInfo (file.ResourceId, file.Name, DesktopService.GetMimeTypeForUri (file.Name))); + } + return (Stetic.ResourceInfo[]) list.ToArray (typeof(Stetic.ResourceInfo)); + } + + public Stream GetResourceStream (string resourceName) + { + foreach (ProjectFile file in project.Files) { + if (resourceName == file.ResourceId) + return File.OpenRead (file.Name); + } + return null; + } + + public Stetic.ResourceInfo AddResource (string fileName) + { + ProjectFile file = project.AddFile (fileName, BuildAction.EmbeddedResource); + IdeApp.ProjectOperations.Save (project); + return new Stetic.ResourceInfo (file.ResourceId, fileName); + } + + public void RemoveResource (string resourceName) + { + foreach (ProjectFile file in project.Files) { + if (resourceName == file.ResourceId) { + project.Files.Remove (file); + IdeApp.ProjectOperations.Save (project); + return; + } + } + } + + public override object InitializeLifetimeService () + { + return null; + } + } + +} diff --git a/main/src/addins/MonoDevelop.GtkCore2/MonoDevelop.GtkCore/ReferenceManager.cs b/main/src/addins/MonoDevelop.GtkCore2/MonoDevelop.GtkCore/ReferenceManager.cs new file mode 100644 index 0000000000..920df75a88 --- /dev/null +++ b/main/src/addins/MonoDevelop.GtkCore2/MonoDevelop.GtkCore/ReferenceManager.cs @@ -0,0 +1,291 @@ +// ReferenceManager.cs +// +// Author: Mike Kestner <mkestner@novell.com> +// +// Copyright (C) 2008 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 System.Collections.Generic; + +using MonoDevelop.Core; +using MonoDevelop.Core.Assemblies; +using MonoDevelop.Projects; +using MonoDevelop.Ide; + +namespace MonoDevelop.GtkCore { + + public class ReferenceManager : IDisposable { + + DotNetProject project; + + public ReferenceManager (DotNetProject project) + { + this.project = project; + project.AssemblyContext.Changed += ResetSupportedVersions; + } + + public void Dispose () + { + project.AssemblyContext.Changed -= ResetSupportedVersions; + project = null; + } + + void ResetSupportedVersions (object o, EventArgs a) + { + supported_versions = null; + } + + string CurrentAssemblyVersion { + get { + foreach (ProjectReference pref in project.References) { + if (!IsGtkReference (pref)) + continue; + string val = pref.StoredReference; + int idx = val.IndexOf (",") + 1; + return val.Substring (idx).Trim (); + } + return String.Empty; + } + } + + public string GtkPackageVersion { + get { return GetGtkPackageVersion (CurrentAssemblyVersion); } + set { + if (String.IsNullOrEmpty (value)) + throw new ArgumentException ("value"); + + Update (GetGtkAssemblyVersion (value)); + } + } + + public string TargetGtkVersion { + get { + string assm_version = CurrentAssemblyVersion; + if (String.IsNullOrEmpty (assm_version)) + return String.Empty; + int idx = assm_version.IndexOf (","); + if (idx > 0) + assm_version = assm_version.Substring (0, idx); + idx = assm_version.IndexOf ("="); + if (idx > 0) + assm_version = assm_version.Substring (idx + 1); + string[] toks = assm_version.Split ('.'); + if (toks.Length > 1) + return toks[0] + "." + toks[1]; + return String.Empty; + } + } + + string GetGtkAssemblyVersion (string pkg_version) + { + if (String.IsNullOrEmpty (pkg_version)) + return String.Empty; + + pkg_version = pkg_version + "."; + foreach (SystemAssembly asm in project.AssemblyContext.GetAssemblies ()) { + if (asm.Name == "gtk-sharp" && asm.Version.StartsWith (pkg_version)) { + int i = asm.FullName.IndexOf (','); + return asm.FullName.Substring (i+1).Trim (); + } + } + return string.Empty; + } + + string GetGtkPackageVersion (string assembly_version) + { + if (String.IsNullOrEmpty (assembly_version)) + return String.Empty; + + return GetVersionPrefix (assembly_version); + } + + public bool Update () + { + return Update (CurrentAssemblyVersion); + } + + bool Update (string assm_version) + { + if (assm_version == null) + throw new ArgumentException (assm_version); + + bool changed = false; + updating = true; + + bool gdk = false, gtk = false, posix = false; + + foreach (ProjectReference r in new List<ProjectReference> (project.References)) { + if (r.ReferenceType != ReferenceType.Gac) + continue; + string name = GetReferenceName (r); + if (name == "gdk-sharp") + gdk = true; + if (name == "gtk-sharp") + gtk = true; + else if (name == "Mono.Posix") + posix = true; + + // Is a gtk-sharp-2.0 assembly? + if (Array.IndexOf (gnome_assemblies, name) == -1) + continue; + + string sr = r.StoredReference; + string version = sr.Substring (sr.IndexOf (",") + 1).Trim (); + if (version != assm_version) { + project.References.Remove (r); + if (name == "gnome-sharp" && assm_version == "Version=2.12.0.0, Culture=neutral, PublicKeyToken=35e10195dab3c99f") { + project.References.Add (new ProjectReference (ReferenceType.Gac, name + ", Version=2.24.0.0, Culture=neutral, PublicKeyToken=35e10195dab3c99f")); + } else { + project.References.Add (new ProjectReference (ReferenceType.Gac, name + ", " + assm_version)); + } + changed = true; + } + } + + if (!gtk) { + project.References.Add (new ProjectReference (ReferenceType.Gac, "gtk-sharp" + ", " + assm_version)); + changed = true; + } + + if (!GtkDesignInfo.HasDesignedObjects (project)) + return changed; + + GtkDesignInfo info = GtkDesignInfo.FromProject (project); + if (!gdk) { + project.References.Add (new ProjectReference (ReferenceType.Gac, "gdk-sharp" + ", " + assm_version)); + changed = true; + } + + if (!posix && info.GenerateGettext && info.GettextClass == "Mono.Unix.Catalog") { + // Add a reference to Mono.Posix. Use the version for the selected project's runtime version. + string aname = project.AssemblyContext.FindInstalledAssembly ("Mono.Posix, Version=1.0.5000.0, Culture=neutral, PublicKeyToken=0738eb9f132ed756", null, project.TargetFramework); + aname = project.AssemblyContext.GetAssemblyNameForVersion (aname, project.TargetFramework); + project.References.Add (new ProjectReference (ReferenceType.Gac, aname)); + changed = true; + } + updating = false; + return changed; + } + + static bool updating; + static string[] gnome_assemblies = new string [] { + "art-sharp", "atk-sharp", "gconf-sharp", "gdk-sharp", + "glade-sharp","glib-sharp", "gnome-sharp", + "gnome-vfs-sharp", "gtk-dotnet", "gtkhtml-sharp", + "gtk-sharp", "pango-sharp", "rsvg-sharp" + }; + + public static void Initialize () + { + IdeApp.Workspace.ReferenceAddedToProject += OnReferenceAdded; + IdeApp.Workspace.ReferenceRemovedFromProject += OnReferenceRemoved; + } + + static void OnReferenceAdded (object o, ProjectReferenceEventArgs args) + { + if (updating || !IsGtkReference (args.ProjectReference)) + return; + + string sr = args.ProjectReference.StoredReference; + string version = sr.Substring (sr.IndexOf (",") + 1).Trim (); + ReferenceManager rm = new ReferenceManager (args.Project as DotNetProject); + rm.Update (version); + } + + static void OnReferenceRemoved (object o, ProjectReferenceEventArgs args) + { + if (updating || !IsGtkReference (args.ProjectReference)) + return; + + DotNetProject dnp = args.Project as DotNetProject; + + if (MessageService.Confirm (GettextCatalog.GetString ("The Gtk# User Interface designer will be disabled by removing the gtk-sharp reference."), new AlertButton (GettextCatalog.GetString ("Disable Designer")))) + GtkDesignInfo.DisableProject (dnp); + else + dnp.References.Add (new ProjectReference (ReferenceType.Gac, args.ProjectReference.StoredReference)); + } + + static string GetReferenceName (ProjectReference pref) + { + string stored = pref.StoredReference; + int idx =stored.IndexOf (","); + if (idx == -1) + return stored.Trim (); + + return stored.Substring (0, idx).Trim (); + } + + static bool IsGtkReference (ProjectReference pref) + { + if (pref.ReferenceType != ReferenceType.Gac) + return false; + + return GetReferenceName (pref) == "gtk-sharp"; + } + + public static bool HasGtkReference (DotNetProject project) + { + foreach (ProjectReference pref in project.References) + if (IsGtkReference (pref)) + return true; + return false; + } + + List<string> supported_versions; + string default_version; + + public string DefaultGtkVersion { + get { + if (SupportedGtkVersions.Count > 0 && default_version == null) + default_version = SupportedGtkVersions [0]; + return default_version; + } + } + + public List<string> SupportedGtkVersions { + get { + if (supported_versions == null) { + supported_versions = new List<string> (); + foreach (SystemAssembly asm in project.AssemblyContext.GetAssemblies ()) { + if (asm.Name == "gtk-sharp") { + string v = GetVersionPrefix (asm.Version); + if (!supported_versions.Contains (v)) + supported_versions.Add (v); + if (v == "2.8") + default_version = v; + } + } + supported_versions.Sort (); + } + return supported_versions; + } + } + + string GetVersionPrefix (string version) + { + int i = version.IndexOf ('.'); + i = version.IndexOf ('.', i + 1); + return version.Substring (0, i); + } + } +} diff --git a/main/src/addins/MonoDevelop.GtkCore2/MonoDevelop.GtkCore/WidgetFileDescriptionTemplate.cs b/main/src/addins/MonoDevelop.GtkCore2/MonoDevelop.GtkCore/WidgetFileDescriptionTemplate.cs new file mode 100644 index 0000000000..abb9198654 --- /dev/null +++ b/main/src/addins/MonoDevelop.GtkCore2/MonoDevelop.GtkCore/WidgetFileDescriptionTemplate.cs @@ -0,0 +1,172 @@ +// +// WidgetFileDescriptionTemplate.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 System.Xml; +using System.IO; + +using MonoDevelop.Core; +using MonoDevelop.Projects; +using MonoDevelop.Projects.Dom.Parser; +using MonoDevelop.Ide.Templates; +using MonoDevelop.GtkCore.GuiBuilder; +using MonoDevelop.Ide; + +namespace MonoDevelop.GtkCore +{ + public class WidgetFileDescriptionTemplate: FileDescriptionTemplate + { + SingleFileDescriptionTemplate fileTemplate; + XmlElement steticTemplate; + + public override string Name { + get { return "Widget"; } + } +#if TRUNK + public override void Load (XmlElement filenode, FilePath baseDirectory) + { + foreach (XmlNode node in filenode.ChildNodes) { + XmlElement elem = node as XmlElement; + if (elem == null) continue; + + if (elem.Name == "SteticTemplate") { + if (steticTemplate != null) + throw new InvalidOperationException ("Widget templates can't contain more than one SteticTemplate element"); + steticTemplate = elem; + } else if (fileTemplate == null) { + fileTemplate = FileDescriptionTemplate.CreateTemplate (elem, baseDirectory) as SingleFileDescriptionTemplate; + if (fileTemplate == null) + throw new InvalidOperationException ("Widget templates can only contain single-file and stetic templates."); + } + } + if (fileTemplate == null) + throw new InvalidOperationException ("File template not found in widget template."); + if (steticTemplate == null) + throw new InvalidOperationException ("Stetic template not found in widget template."); + } +#else + public override void Load (XmlElement filenode) + { + foreach (XmlNode node in filenode.ChildNodes) { + XmlElement elem = node as XmlElement; + if (elem == null) continue; + + if (elem.Name == "SteticTemplate") { + if (steticTemplate != null) + throw new InvalidOperationException ("Widget templates can't contain more than one SteticTemplate element"); + steticTemplate = elem; + } else if (fileTemplate == null) { + fileTemplate = FileDescriptionTemplate.CreateTemplate (elem) as SingleFileDescriptionTemplate; + if (fileTemplate == null) + throw new InvalidOperationException ("Widget templates can only contain single-file and stetic templates."); + } + } + if (fileTemplate == null) + throw new InvalidOperationException ("File template not found in widget template."); + if (steticTemplate == null) + throw new InvalidOperationException ("Stetic template not found in widget template."); + } +#endif + + public override bool SupportsProject (Project project, string projectPath) + { + return (project is DotNetProject) && GtkDesignInfo.SupportsRefactoring (project as DotNetProject); + } + + public override bool AddToProject (SolutionItem policyParent, Project project, string language, string directory, string name) + { + if (!GtkDesignInfo.SupportsDesigner (project)) { + ReferenceManager mgr = new ReferenceManager (project as DotNetProject); + mgr.GtkPackageVersion = mgr.DefaultGtkVersion; + mgr.Dispose (); + } + + GtkDesignInfo info = GtkDesignInfo.FromProject ((DotNetProject) project); + + GuiBuilderProject gproject = info.GuiBuilderProject; + + string fileName = fileTemplate.GetFileName (policyParent, project, language, directory, name); + fileTemplate.AddToProject (policyParent, project, language, directory, name); + +#if TRUNK + ProjectDomService.Parse (project, fileName); +#else + ProjectDomService.Parse (project, fileName, null); +#endif + + DotNetProject netProject = project as DotNetProject; + string ns = netProject != null ? netProject.GetDefaultNamespace (fileName) : ""; + string cname = Path.GetFileNameWithoutExtension (fileName); + string fullName = ns.Length > 0 ? ns + "." + cname : cname; + string[,] tags = { + {"Name", cname}, + {"Namespace", ns}, + {"FullName", fullName} + }; + + XmlElement widgetElem = steticTemplate ["widget"]; + if (widgetElem != null) { + string content = widgetElem.OuterXml; + content = StringParserService.Parse (content, tags); + + XmlDocument doc = new XmlDocument (); + doc.LoadXml (content); + + gproject.AddNewComponent (doc.DocumentElement); + gproject.Save (false); + gproject.GenerateCode (fileName); + IdeApp.ProjectOperations.Save (project); + return true; + } + + widgetElem = steticTemplate ["action-group"]; + if (widgetElem != null) { + string content = widgetElem.OuterXml; + content = StringParserService.Parse (content, tags); + + XmlDocument doc = new XmlDocument (); + doc.LoadXml (content); + + Stetic.Project sproject = gproject.SteticProject; + sproject.AddNewActionGroup (doc.DocumentElement); + gproject.Save (false); + gproject.GenerateCode (fileName); + IdeApp.ProjectOperations.Save (project); + return true; + } + + throw new InvalidOperationException ("<widget> or <action-group> element not found in widget template."); + } + + public override void Show () + { + fileTemplate.Show (); + } + } +}
\ No newline at end of file diff --git a/main/src/addins/MonoDevelop.GtkCore2/MonoDevelop.GtkCore/WidgetParser.cs b/main/src/addins/MonoDevelop.GtkCore2/MonoDevelop.GtkCore/WidgetParser.cs new file mode 100644 index 0000000000..c846970e5e --- /dev/null +++ b/main/src/addins/MonoDevelop.GtkCore2/MonoDevelop.GtkCore/WidgetParser.cs @@ -0,0 +1,226 @@ +// +// ObjectsDocument.cs +// +// Authors: +// Lluis Sanchez Gual +// Mike Kestner +// +// Copyright (C) 2006-2008 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 System.Xml; +using System.CodeDom; +using System.Collections; +using System.Collections.Generic; +using System.Collections.Specialized; + +using MonoDevelop.Projects.Dom; +using MonoDevelop.Projects.Dom.Parser; + +namespace MonoDevelop.GtkCore +{ + + public class WidgetParser + { + + ProjectDom ctx; + + public WidgetParser (ProjectDom ctx) + { + this.ctx = ctx; + } + + public Dictionary<string, IType> GetToolboxItems () + { + Dictionary<string, IType> tb_items = new Dictionary<string, IType> (); + + IType wt = ctx.GetType ("Gtk.Widget", true); + if (wt != null) { + foreach (IType t in ctx.GetSubclasses (wt, true)) { + if (t.SourceProjectDom == ctx && IsToolboxWidget (t)) + tb_items [t.FullName] = t; + } + } + + return tb_items; + } + + public void CollectMembers (IType cls, bool inherited, string topType, ListDictionary properties, ListDictionary events) + { + if (cls.FullName == topType) + return; + + foreach (IProperty prop in cls.Properties) + if (IsBrowsable (prop)) + properties [prop.Name] = prop; + + foreach (IEvent ev in cls.Events) + if (IsBrowsable (ev)) + events [ev.Name] = ev; + + if (inherited) { + foreach (IReturnType bt in cls.BaseTypes) { + IType bcls = ctx.GetType (bt); + if (bcls != null && bcls.ClassType != ClassType.Interface) + CollectMembers (bcls, true, topType, properties, events); + } + } + } + + public string GetBaseType (IType cls, Hashtable knownTypes) + { + foreach (IReturnType bt in cls.BaseTypes) { + if (knownTypes.Contains (bt.FullName)) + return bt.FullName; + } + + foreach (IReturnType bt in cls.BaseTypes) { + IType bcls = ctx.GetType (bt); + if (bcls != null) { + string ret = GetBaseType (bcls, knownTypes); + if (ret != null) + return ret; + } + } + return null; + } + + public string GetCategory (IMember decoration) + { +// foreach (IAttributeSection section in decoration.Attributes) { + foreach (IAttribute at in decoration.Attributes) { + switch (at.Name) { + case "Category": + case "CategoryAttribute": + case "System.ComponentModel.Category": + case "System.ComponentModel.CategoryAttribute": + break; + default: + continue; + } + if (at.PositionalArguments != null && at.PositionalArguments.Count > 0) { + CodePrimitiveExpression exp = at.PositionalArguments [0] as CodePrimitiveExpression; + if (exp != null && exp.Value != null) + return exp.Value.ToString (); + } + } + // } + return ""; + } + + public IType GetClass (string classname) + { + return ctx.GetType (classname); + } + + public bool IsBrowsable (IMember member) + { + if (!member.IsPublic) + return false; + + IProperty prop = member as IProperty; + if (prop != null) { + if (!prop.HasGet || !prop.HasSet) + return false; + if (Array.IndexOf (supported_types, prop.ReturnType.FullName) == -1) + return false; + } + + // foreach (IAttributeSection section in member.Attributes) { + foreach (IAttribute at in member.Attributes) { + switch (at.Name) { + case "Browsable": + case "BrowsableAttribute": + case "System.ComponentModel.Browsable": + case "System.ComponentModel.BrowsableAttribute": + break; + default: + continue; + } + if (at.PositionalArguments != null && at.PositionalArguments.Count > 0) { + CodePrimitiveExpression exp = at.PositionalArguments [0] as CodePrimitiveExpression; + if (exp != null && exp.Value != null && exp.Value is bool) { + return (bool) exp.Value; + } + } + } + // } + return true; + } + + public bool IsToolboxWidget (IType cls) + { + if (!cls.IsPublic) + return false; + + foreach (IAttribute at in cls.Attributes) { + switch (at.Name) { + case "ToolboxItem": + case "ToolboxItemAttribute": + case "System.ComponentModel.ToolboxItem": + case "System.ComponentModel.ToolboxItemAttribute": + break; + default: + continue; + } + if (at.PositionalArguments != null && at.PositionalArguments.Count > 0) { + CodePrimitiveExpression exp = at.PositionalArguments [0] as CodePrimitiveExpression; + if (exp == null || exp.Value == null) + return false; + else if (exp.Value is bool) + return (bool) exp.Value; + else + return exp.Value != null; + } + } + + foreach (IReturnType bt in cls.BaseTypes) { + IType bcls = ctx.GetType (bt); + if (bcls != null && bcls.ClassType != ClassType.Interface) + return IsToolboxWidget (bcls); + } + + return false; + } + + static string[] supported_types = new string[] { + "System.Boolean", + "System.Char", + "System.SByte", + "System.Byte", + "System.Int16", + "System.UInt16", + "System.Int32", + "System.UInt32", + "System.Int64", + "System.UInt64", + "System.Decimal", + "System.Single", + "System.Double", + "System.DateTime", + "System.String", + "System.TimeSpan", + "Gtk.Adjustment", + }; + } +} diff --git a/main/src/addins/MonoDevelop.GtkCore2/MonoDevelop.GtkCore2.addin.xml b/main/src/addins/MonoDevelop.GtkCore2/MonoDevelop.GtkCore2.addin.xml new file mode 100644 index 0000000000..ffd642436f --- /dev/null +++ b/main/src/addins/MonoDevelop.GtkCore2/MonoDevelop.GtkCore2.addin.xml @@ -0,0 +1,210 @@ +<Addin id = "GtkCore2" + namespace = "MonoDevelop" + name = "GTK# Visual Designer (GSOC)" + author = "Lluis Sanchez Gual, Krzysztof Marecki" + copyright = "X11" + url = "" + description = "Experimental GTK# visual designer developed during GSOC 2010 as a fork of stetic" + category = "IDE extensions" + version = "2.4.0.5"> + + <Runtime> + <Import assembly="libstetic2.dll"/> + <Import file="libstetic2.dll.config"/> + <Import assembly="libsteticui2.dll"/> + <Import file="libsteticui2.dll.config"/> + <Import assembly="MonoDevelop.GtkCore2.dll"/> + </Runtime> + + <Dependencies> + <Addin id="Core" version="2.4"/> + <Addin id="Ide" version="2.4"/> + <Addin id="DesignerSupport" version="2.4"/> + <Addin id="XmlEditor" version="2.4"/> + <Addin id="Refactoring" version="2.4"/> + </Dependencies> + + <ExtensionPoint path = "/MonoDevelop/GtkCore/ContextMenu/ProjectPad.ActionGroup"> + <ExtensionNodeSet id="MonoDevelop.Components.Commands.ItemSet"/> + </ExtensionPoint> + + <ExtensionPoint path = "/MonoDevelop/GtkCore/ContextMenu/ProjectPad.UserInterfaceFolder"> + <ExtensionNodeSet id="MonoDevelop.Components.Commands.ItemSet"/> + </ExtensionPoint> + + <ExtensionPoint path = "/MonoDevelop/GtkCore/ContextMenu/ProjectPad.Component"> + <ExtensionNodeSet id="MonoDevelop.Components.Commands.ItemSet"/> + </ExtensionPoint> + + <ExtensionPoint path = "/MonoDevelop/GtkCore/ContextMenu/ProjectPad.StockIcons"> + <ExtensionNodeSet id="MonoDevelop.Components.Commands.ItemSet"/> + </ExtensionPoint> + + <Extension path = "/MonoDevelop/Ide/WorkbenchContexts/Edit"> + <ContextPad id = "MonoDevelop.GtkCore.GuiBuilder.GuiBuilderProjectPad" /> + </Extension> + + <Extension path = "/MonoDevelop/Ide/Pads/ProjectPad"> + <NodeBuilder class = "MonoDevelop.GtkCore.NodeBuilders.GuiProjectFolderNodeBuilder"/> + <NodeBuilder class = "MonoDevelop.GtkCore.NodeBuilders.ProjectFolderNodeBuilderExtension"/> + <NodeBuilder class = "MonoDevelop.GtkCore.NodeBuilders.ProjectFileNodeBuilderExtension"/> + <NodeBuilder class = "MonoDevelop.GtkCore.NodeBuilders.ProjectNodeBuilder"/> + <NodeBuilder class = "MonoDevelop.GtkCore.NodeBuilders.StockIconsNodeBuilder"/> + <NodeBuilder class = "MonoDevelop.GtkCore.NodeBuilders.ProjectFileNodeBuilderExtension" /> + </Extension> + + <Extension path = "/MonoDevelop/Ide/FileTemplates"> + <FileTemplate id = "DialogFileTemplate" resource = "Dialog.xft.xml"/> + <FileTemplate id = "DrawingAreaFileTemplate" resource = "DrawingArea.xft.xml"/> + <FileTemplate id = "WindowFileTemplate" resource = "Window.xft.xml"/> + <FileTemplate id = "WidgetFileTemplate" resource = "Widget.xft.xml"/> + <FileTemplate id = "ActionGroupFileTemplate" resource = "ActionGroup.xft.xml"/> + <FileTemplate id = "PartialDialogFileTemplate" resource = "DialogPartial.xft.xml"/> + <FileTemplate id = "PartialWindowFileTemplate" resource = "WindowPartial.xft.xml"/> + <FileTemplate id = "PartialWidgetFileTemplate" resource = "WidgetPartial.xft.xml"/> + <FileTemplate id = "PartialActionGroupFileTemplate" resource = "ActionGroupPartial.xft.xml"/> + </Extension> + + <Extension path = "/MonoDevelop/Ide/DisplayBindings"> + <DisplayBinding insertbefore = "DefaultDisplayBinding" + class = "MonoDevelop.GtkCore.GuiBuilder.GuiBuilderDisplayBinding" /> + <DisplayBinding + class = "MonoDevelop.GtkCore.GuiBuilder.ActionGroupDisplayBinding" /> + </Extension> + + <Extension path = "/MonoDevelop/Ide/Commands"> + <Category _name = "Gtk# Designer" id = "GtkCore"> + <Command id = "MonoDevelop.GtkCore.GtkCommands.AddNewDialog" + icon = "md-gtkcore-dialog" + _label = "New Dialog..." /> + <Command id = "MonoDevelop.GtkCore.GtkCommands.AddNewWindow" + icon = "md-gtkcore-window" + _label = "New Window..." /> + <Command id = "MonoDevelop.GtkCore.GtkCommands.AddNewWidget" + icon = "md-gtkcore-widget" + _label = "New Widget..." /> + <Command id = "MonoDevelop.GtkCore.GtkCommands.AddNewActionGroup" + icon = "md-gtkcore-actiongroup" + _label = "New Action Group..." /> + <Command id = "MonoDevelop.GtkCore.GtkCommands.ImportGladeFile" + _label = "Import Glade file..." /> + <Command id = "MonoDevelop.GtkCore.GtkCommands.EditIcons" + icon = "md-gtkcore-iconfactory" + _label = "Edit Project Icons..." /> + <Command id = "MonoDevelop.GtkCore.GtkCommands.GtkSettings" + _label = "GTK# support settings..." + icon = "md-gtkcore-gtk-logo"/> + <Command id = "MonoDevelop.GtkCore.GtkCommands.GenerateCode" + _label = "Generate designer code..." + icon="md-gtkcore-gtkx"/> + <Command id = "MonoDevelop.GtkCore.GtkCommands.ReloadDesigner" + _label = "Reload designer..."/> + </Category> + </Extension> + + <Extension path = "/MonoDevelop/Ide/ContextMenu/ProjectPad/Add"> + <Condition id="ItemType" value="Project|ProjectFolder"> + <SeparatorItem insertafter = "MonoDevelop.Ide.Commands.ProjectCommands.AddFiles" /> + <CommandItem id = "MonoDevelop.GtkCore.GtkCommands.AddNewDialog" /> + <CommandItem id = "MonoDevelop.GtkCore.GtkCommands.AddNewWindow" /> + <CommandItem id = "MonoDevelop.GtkCore.GtkCommands.AddNewWidget" /> + <CommandItem id = "MonoDevelop.GtkCore.GtkCommands.AddNewActionGroup" /> + </Condition> + </Extension> + + <Extension path = "/MonoDevelop/Ide/ContextMenu/ProjectPad"> + <Condition id="ItemType" value="MonoDevelop.GtkCore.NodeBuilders.GuiProjectFolder"> + <CommandItem id = "MonoDevelop.GtkCore.GtkCommands.EditIcons" insertafter="BuildSectionEnd"/> + <CommandItem id = "MonoDevelop.GtkCore.GtkCommands.ImportGladeFile" /> + <SeparatorItem/> + <CommandItem id = "MonoDevelop.GtkCore.GtkCommands.GtkSettings" /> + </Condition> + <Condition id="ItemType" value="ProjectFile"> + <CommandItem id = "MonoDevelop.GtkCore.GtkCommands.GenerateCode" insertafter="BuildSectionEnd"/> + <CommandItem id = "MonoDevelop.GtkCore.GtkCommands.ReloadDesigner"/> + </Condition> + </Extension> + + <Extension path = "/MonoDevelop/GtkCore/ContextMenu/ProjectPad.Component"> + <CommandItem id = "MonoDevelop.Ide.Commands.ViewCommands.Open" /> + <CommandItem id = "MonoDevelop.Ide.Commands.EditCommands.Delete" /> + </Extension> + + <Extension path = "/MonoDevelop/GtkCore/ContextMenu/ProjectPad.ActionGroup"> + <CommandItem id = "MonoDevelop.Ide.Commands.ViewCommands.Open" /> + <CommandItem id = "MonoDevelop.Ide.Commands.EditCommands.Delete" /> + </Extension> + + <Extension path = "/MonoDevelop/GtkCore/ContextMenu/ProjectPad.StockIcons"> + <CommandItem id = "MonoDevelop.GtkCore.GtkCommands.EditIcons" /> + </Extension> + + <Extension path = "/MonoDevelop/ProjectModel/ExtendedProperties"> + <ItemProperty class = "MonoDevelop.Projects.Project" + name = "GtkDesignInfo" + skipEmpty = "True" + type = "MonoDevelop.GtkCore.GtkDesignInfo" /> + </Extension> + + <Extension path = "/MonoDevelop/Ide/StartupHandlers"> + <Class class="MonoDevelop.GtkCore.GtkCoreStartupCommand" /> + </Extension> + + <Extension path = "/MonoDevelop/ProjectModel/Gui/ItemOptionPanels/Common"> + <Condition id="ItemType" value ="DotNetProject"> + <Section id = "SteticOptionsPanel" + _label = "GTK# Settings" + fill="true" + class = "MonoDevelop.GtkCore.Dialogs.WidgetBuilderOptionPanel" + icon = "md-gtkcore-gtk-logo"/> + </Condition> + </Extension> + + <Extension path = "/MonoDevelop/Ide/FileTemplateTypes"> + <FileTemplateType name = "Widget" class = "MonoDevelop.GtkCore.WidgetFileDescriptionTemplate"/> + </Extension> + + <Extension path = "/MonoDevelop/Core/StockIcons"> + <StockIcon stockid = "md-gtkcore-window" resource = "window.png" /> + <StockIcon stockid = "md-gtkcore-dialog" resource = "dialog.png" /> + <StockIcon stockid = "md-gtkcore-widget" resource = "widget.png" /> + <StockIcon stockid = "md-gtkcore-actiongroup" resource = "actiongroup.png" /> + <StockIcon stockid = "md-gtkcore-iconfactory" resource = "image-x-generic.png" /> + <StockIcon stockid = "md-gtkcore-gtkx" resource = "gtkx.png" /> + <StockIcon stockid = "md-gtkcore-gtk-logo" resource = "gtk-logo.png"/> + </Extension> + + <Extension path = "/MonoDevelop/Core/MimeTypes"> + <MimeType id="text/x-gtkx" _description="Gtk# designer file" icon="gtk-page-setup" isText="true"> + <File pattern="*.gtkx" /> + </MimeType> + </Extension> + + <Extension path = "/MonoDevelop/ProjectModel/ProjectServiceExtensions"> + <Class class = "MonoDevelop.GtkCore.GuiBuilder.GtkProjectServiceExtension" insertafter="MidStep"/> + </Extension> + + <Extension path = "/MonoDevelop/DesignerSupport/ToolboxProviders"> + <Class class = "MonoDevelop.GtkCore.GuiBuilder.ToolboxProvider" /> + </Extension> + + <Extension path = "/MonoDevelop/DesignerSupport/ToolboxLoaders"> + <Class id="ToolboxItemLoader" class="MonoDevelop.GtkCore.GuiBuilder.ToolboxLoader"/> + </Extension> + + <Extension path = "/MonoDevelop/ProjectModel/SerializableClasses"> + <DataType class = "MonoDevelop.GtkCore.GuiBuilder.ComponentToolboxNode" /> + </Extension> + + <Extension path = "/MonoDevelop/Ide/ProjectFeatures"> + <Class class = "MonoDevelop.GtkCore.Dialogs.GtkProjectFeature" /> + </Extension> + + <Extension path = "/MonoDevelop/Ide/GlobalOptionsDialog/Preferences/Style"> + <Panel _label = "GTK# Designer" class = "MonoDevelop.GtkCore.Dialogs.GtkDesignerOptionPanel" /> + </Extension> + + <Extension path = "/MonoDevelop/XmlEditor/XmlFileExtensions"> + <XmlFileExtension extension = ".gtkx"/> + </Extension> +</Addin> diff --git a/main/src/addins/MonoDevelop.GtkCore2/MonoDevelop.GtkCore2.csproj b/main/src/addins/MonoDevelop.GtkCore2/MonoDevelop.GtkCore2.csproj new file mode 100644 index 0000000000..94bba9eb12 --- /dev/null +++ b/main/src/addins/MonoDevelop.GtkCore2/MonoDevelop.GtkCore2.csproj @@ -0,0 +1,223 @@ +<?xml version="1.0" encoding="utf-8"?> +<Project DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003" ToolsVersion="3.5"> + <PropertyGroup> + <Configuration Condition=" '$(Configuration)' == '' ">Debug</Configuration> + <Platform Condition=" '$(Platform)' == '' ">AnyCPU</Platform> + <ProductVersion>9.0.21022</ProductVersion> + <SchemaVersion>2.0</SchemaVersion> + <ProjectGuid>{4F2E994F-E4F5-407A-8D80-80E3377DEF6E}</ProjectGuid> + <OutputType>Library</OutputType> + <AssemblyName>MonoDevelop.GtkCore2</AssemblyName> + <TargetFrameworkVersion>v3.5</TargetFrameworkVersion> + <RootNamespace>MonoDevelop.GtkCore</RootNamespace> + </PropertyGroup> + <PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|AnyCPU' "> + <DebugSymbols>true</DebugSymbols> + <DebugType>full</DebugType> + <Optimize>true</Optimize> + <OutputPath>..\..\..\build\AddIns\MonoDevelop.GtkCore2</OutputPath> + <ErrorReport>prompt</ErrorReport> + <WarningLevel>4</WarningLevel> + <CheckForOverflowUnderflow>true</CheckForOverflowUnderflow> + <Execution> + <Execution clr-version="Net_2_0" /> + </Execution> + <DefineConstants>TRUNK</DefineConstants> + </PropertyGroup> + <PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|AnyCPU' "> + <DebugType>none</DebugType> + <Optimize>true</Optimize> + <OutputPath>..\..\..\build\AddIns\MonoDevelop.GtkCore2 </OutputPath> + <ErrorReport>prompt</ErrorReport> + <WarningLevel>4</WarningLevel> + <CheckForOverflowUnderflow>true</CheckForOverflowUnderflow> + <Execution> + <Execution clr-version="Net_2_0" /> + </Execution> + <DefineConstants>TRUNK</DefineConstants> + </PropertyGroup> + <ItemGroup> + <Reference Include="System" /> + <Reference Include="System.Xml" /> + <Reference Include="Mono.Posix" /> + <Reference Include="glade-sharp, Version=2.12.0.0, Culture=neutral, PublicKeyToken=35e10195dab3c99f"> + <SpecificVersion>False</SpecificVersion> + </Reference> + <Reference Include="glib-sharp, Version=2.12.0.0, Culture=neutral, PublicKeyToken=35e10195dab3c99f"> + <SpecificVersion>False</SpecificVersion> + </Reference> + <Reference Include="pango-sharp, Version=2.12.0.0, Culture=neutral, PublicKeyToken=35e10195dab3c99f"> + <SpecificVersion>False</SpecificVersion> + </Reference> + <Reference Include="atk-sharp, Version=2.12.0.0, Culture=neutral, PublicKeyToken=35e10195dab3c99f"> + <SpecificVersion>False</SpecificVersion> + </Reference> + <Reference Include="gdk-sharp, Version=2.12.0.0, Culture=neutral, PublicKeyToken=35e10195dab3c99f"> + <SpecificVersion>False</SpecificVersion> + </Reference> + <Reference Include="gtk-sharp, Version=2.12.0.0, Culture=neutral, PublicKeyToken=35e10195dab3c99f"> + <SpecificVersion>False</SpecificVersion> + </Reference> + <Reference Include="System.Core" /> + <Reference Include="NRefactory, Version=2.1.1.0, Culture=neutral, PublicKeyToken=efe927acf176eea2"> + <Package>monodevelop</Package> + </Reference> + <Reference Include="Mono.Addins, Version=0.5.0.0, Culture=neutral, PublicKeyToken=0738eb9f132ed756" /> + <Reference Include="Mono.Cecil, Version=0.6.9.0, Culture=neutral, PublicKeyToken=0738eb9f132ed756"> + <Package>monodevelop</Package> + </Reference> + <Reference Include="Mono.Debugging, Version=0.0.0.0, Culture=neutral, PublicKeyToken=9307d64546e0580d"> + <Package>monodevelop</Package> + </Reference> + </ItemGroup> + <ItemGroup> + <ProjectReference Include="libsteticui\libsteticui2.csproj"> + <Project>{8951D80F-B2D6-4B4E-B119-28FFE3B7B1C0}</Project> + <Name>libsteticui2</Name> + </ProjectReference> + <ProjectReference Include="libstetic\libstetic2.csproj"> + <Project>{90CBA7FD-CB46-4711-97BB-2420DC01F016}</Project> + <Name>libstetic2</Name> + </ProjectReference> + <ProjectReference Include="..\..\core\MonoDevelop.Core\MonoDevelop.Core.csproj"> + <Project>{7525BB88-6142-4A26-93B9-A30C6983390A}</Project> + <Name>MonoDevelop.Core</Name> + </ProjectReference> + <ProjectReference Include="..\Deployment\MonoDevelop.Deployment\MonoDevelop.Deployment.csproj"> + <Project>{9BC670A8-1851-40EC-9685-279F4C98433D}</Project> + <Name>MonoDevelop.Deployment</Name> + </ProjectReference> + <ProjectReference Include="..\MonoDevelop.DesignerSupport\MonoDevelop.DesignerSupport.csproj"> + <Project>{2C24D515-4A2C-445C-8419-C09231913CFA}</Project> + <Name>MonoDevelop.DesignerSupport</Name> + </ProjectReference> + <ProjectReference Include="..\..\core\MonoDevelop.Ide\MonoDevelop.Ide.csproj"> + <Project>{27096E7F-C91C-4AC6-B289-6897A701DF21}</Project> + <Name>MonoDevelop.Ide</Name> + </ProjectReference> + <ProjectReference Include="..\..\core\Mono.Texteditor\Mono.TextEditor.csproj"> + <Project>{A2329308-3751-4DBD-9A75-5F7B8B024625}</Project> + <Name>Mono.TextEditor</Name> + </ProjectReference> + </ItemGroup> + <ItemGroup> + <None Include="ChangeLog" /> + <None Include="Makefile.am" /> + <None Include="icons\window.png" /> + <None Include="icons\dialog.png" /> + </ItemGroup> + <ItemGroup> + <EmbeddedResource Include="templates\Dialog.xft.xml"> + <LogicalName>Dialog.xft.xml</LogicalName> + </EmbeddedResource> + <EmbeddedResource Include="templates\Window.xft.xml"> + <LogicalName>Window.xft.xml</LogicalName> + </EmbeddedResource> + <EmbeddedResource Include="templates\Widget.xft.xml"> + <LogicalName>Widget.xft.xml</LogicalName> + </EmbeddedResource> + <EmbeddedResource Include="templates\ActionGroup.xft.xml"> + <LogicalName>ActionGroup.xft.xml</LogicalName> + </EmbeddedResource> + <EmbeddedResource Include="gui.glade"> + <LogicalName>gui.glade</LogicalName> + </EmbeddedResource> + <EmbeddedResource Include="templates\ActionGroupPartial.xft.xml"> + <LogicalName>ActionGroupPartial.xft.xml</LogicalName> + </EmbeddedResource> + <EmbeddedResource Include="templates\DialogPartial.xft.xml"> + <LogicalName>DialogPartial.xft.xml</LogicalName> + </EmbeddedResource> + <EmbeddedResource Include="templates\WidgetPartial.xft.xml"> + <LogicalName>WidgetPartial.xft.xml</LogicalName> + </EmbeddedResource> + <EmbeddedResource Include="templates\DrawingArea.xft.xml"> + <LogicalName>DrawingArea.xft.xml</LogicalName> + </EmbeddedResource> + <EmbeddedResource Include="templates\WindowPartial.xft.xml"> + <LogicalName>WindowPartial.xft.xml</LogicalName> + </EmbeddedResource> + <EmbeddedResource Include="icons\widget.png"> + <LogicalName>widget.png</LogicalName> + </EmbeddedResource> + <EmbeddedResource Include="icons\actiongroup.png"> + <LogicalName>actiongroup.png</LogicalName> + </EmbeddedResource> + <EmbeddedResource Include="icons\image-x-generic.png"> + <LogicalName>image-x-generic.png</LogicalName> + </EmbeddedResource> + <EmbeddedResource Include="gtk-gui\gui.stetic"> + <LogicalName>gui.stetic</LogicalName> + </EmbeddedResource> + <EmbeddedResource Include="icons\gtkx.png"> + <LogicalName>gtkx.png</LogicalName> + </EmbeddedResource> + <EmbeddedResource Include="icons\gtk-logo.png"> + <LogicalName>gtk-logo.png</LogicalName> + </EmbeddedResource> + <EmbeddedResource Include="MonoDevelop.GtkCore2.addin.xml"> + <LogicalName>MonoDevelop.GtkCore.addin.xml</LogicalName> + </EmbeddedResource> + </ItemGroup> + <ItemGroup> + <Compile Include="MonoDevelop.GtkCore.GuiBuilder\ClassUtils.cs" /> + <Compile Include="MonoDevelop.GtkCore.GuiBuilder\GuiBuilderDisplayBinding.cs" /> + <Compile Include="MonoDevelop.GtkCore.GuiBuilder\GuiBuilderProject.cs" /> + <Compile Include="MonoDevelop.GtkCore.GuiBuilder\GuiBuilderDocumentOutline.cs" /> + <Compile Include="MonoDevelop.GtkCore.GuiBuilder\PropertiesWidget.cs" /> + <Compile Include="MonoDevelop.GtkCore.GuiBuilder\GuiBuilderService.cs" /> + <Compile Include="MonoDevelop.GtkCore.GuiBuilder\GuiBuilderView.cs" /> + <Compile Include="MonoDevelop.GtkCore.GuiBuilder\GuiBuilderWindow.cs" /> + <Compile Include="MonoDevelop.GtkCore\GtkDesignInfo.cs" /> + <Compile Include="MonoDevelop.GtkCore\GtkCoreService.cs" /> + <Compile Include="MonoDevelop.GtkCore.Dialogs\WidgetBuilderOptionPanel.cs" /> + <Compile Include="MonoDevelop.GtkCore.NodeBuilders\ProjectNodeBuilder.cs" /> + <Compile Include="MonoDevelop.GtkCore.NodeBuilders\ProjectFolderNodeBuilderExtension.cs" /> + <Compile Include="MonoDevelop.GtkCore\WidgetFileDescriptionTemplate.cs" /> + <Compile Include="MonoDevelop.GtkCore.Dialogs\SelectRenamedClassDialog.cs" /> + <Compile Include="MonoDevelop.GtkCore.Dialogs\BindDesignDialog.cs" /> + <Compile Include="MonoDevelop.GtkCore.Dialogs\ConfirmWindowDeleteDialog.cs" /> + <Compile Include="MonoDevelop.GtkCore\ProjectResourceProvider.cs" /> + <Compile Include="MonoDevelop.GtkCore.GuiBuilder\ActionGroupView.cs" /> + <Compile Include="MonoDevelop.GtkCore.GuiBuilder\ActionGroupDisplayBinding.cs" /> + <Compile Include="MonoDevelop.GtkCore.GuiBuilder\CombinedDesignView.cs" /> + <Compile Include="MonoDevelop.GtkCore.GuiBuilder\CodeBinder.cs" /> + <Compile Include="MonoDevelop.GtkCore.GuiBuilder\GtkProjectServiceExtension.cs" /> + <Compile Include="MonoDevelop.GtkCore.GuiBuilder\ToolboxProvider.cs" /> + <Compile Include="MonoDevelop.GtkCore.NodeBuilders\StockIconsNodeBuilder.cs" /> + <Compile Include="MonoDevelop.GtkCore.Dialogs\GtkFeatureWidget.cs" /> + <Compile Include="MonoDevelop.GtkCore.GuiBuilder\ToolboxLoader.cs" /> + <Compile Include="gtk-gui\generated.cs" /> + <Compile Include="MonoDevelop.GtkCore\ObjectsDocument.cs" /> + <Compile Include="MonoDevelop.GtkCore\WidgetParser.cs" /> + <Compile Include="MonoDevelop.GtkCore\ReferenceManager.cs" /> + <Compile Include="AssemblyInfo.cs" /> + <Compile Include="MonoDevelop.GtkCore.Dialogs\GtkDesignerOptionsPanelWidget.cs" /> + <Compile Include="gtk-gui\MonoDevelop.GtkCore.Dialogs.GtkDesignerOptionsPanelWidget.cs" /> + <Compile Include="MonoDevelop.GtkCore\Counters.cs" /> + <Compile Include="MonoDevelop.GtkCore.NodeBuilders\ProjectFileNodeBuilderExtension.cs" /> + <Compile Include="MonoDevelop.GtkCore.NodeBuilders\ProjectFileExtension.cs" /> + <Compile Include="MonoDevelop.GtkCore.Dialogs\ProjectConversionDialog.cs" /> + <Compile Include="MonoDevelop.GtkCore.NodeBuilders\GuiProjectFolder.cs" /> + <Compile Include="MonoDevelop.GtkCore.NodeBuilders\GuiProjectFolderNodeBuilder.cs" /> + <Compile Include="gtk-gui\MonoDevelop.GtkCore.Dialogs.ProjectConversionDialog.cs" /> + <Compile Include="MonoDevelop.GtkCore.Commands\GtkCommands.cs" /> + </ItemGroup> + <Import Project="$(MSBuildBinPath)\Microsoft.CSharp.targets" /> + <Import Project="$(MSBuildExtensionsPath)\Mono.Addins.targets" /> + <ProjectExtensions> + <MonoDevelop> + <Properties> + <MonoDevelop.Autotools.MakefileInfo IntegrationEnabled="true" RelativeMakefileName="Makefile.am" BuildTargetName="" CleanTargetName="" SyncReferences="true" IsAutotoolsProject="true" RelativeConfigureInPath="../../../"> + <BuildFilesVar Sync="true" Name="FILES" /> + <DeployFilesVar /> + <ResourcesVar Sync="true" Name="RES" /> + <OthersVar /> + <GacRefVar Sync="true" Name="REFS" Prefix="-r:" /> + <AsmRefVar Sync="true" Name="REFS" Prefix="-r:" /> + <ProjectRefVar Sync="true" Name="DEPS" /> + </MonoDevelop.Autotools.MakefileInfo> + </Properties> + </MonoDevelop> + </ProjectExtensions> +</Project> diff --git a/main/src/addins/MonoDevelop.GtkCore2/MonoDevelop.GtkCore2.sln b/main/src/addins/MonoDevelop.GtkCore2/MonoDevelop.GtkCore2.sln new file mode 100644 index 0000000000..3f7850226d --- /dev/null +++ b/main/src/addins/MonoDevelop.GtkCore2/MonoDevelop.GtkCore2.sln @@ -0,0 +1,32 @@ +
+Microsoft Visual Studio Solution File, Format Version 10.00
+# Visual Studio 2008
+Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "libstetic2", "libstetic\libstetic2.csproj", "{90CBA7FD-CB46-4711-97BB-2420DC01F016}"
+EndProject
+Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "libsteticui2", "libsteticui\libsteticui2.csproj", "{8951D80F-B2D6-4B4E-B119-28FFE3B7B1C0}"
+EndProject
+Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "MonoDevelop.GtkCore2.xbuild", "MonoDevelop.GtkCore2.xbuild.csproj", "{4F2E994F-E4F5-407A-8D80-80E3377DEF6E}"
+EndProject
+Global
+ GlobalSection(SolutionConfigurationPlatforms) = preSolution
+ Debug|Any CPU = Debug|Any CPU
+ Release|Any CPU = Release|Any CPU
+ EndGlobalSection
+ GlobalSection(ProjectConfigurationPlatforms) = postSolution
+ {4F2E994F-E4F5-407A-8D80-80E3377DEF6E}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
+ {4F2E994F-E4F5-407A-8D80-80E3377DEF6E}.Debug|Any CPU.Build.0 = Debug|Any CPU
+ {4F2E994F-E4F5-407A-8D80-80E3377DEF6E}.Release|Any CPU.ActiveCfg = Release|Any CPU
+ {4F2E994F-E4F5-407A-8D80-80E3377DEF6E}.Release|Any CPU.Build.0 = Release|Any CPU
+ {8951D80F-B2D6-4B4E-B119-28FFE3B7B1C0}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
+ {8951D80F-B2D6-4B4E-B119-28FFE3B7B1C0}.Debug|Any CPU.Build.0 = Debug|Any CPU
+ {8951D80F-B2D6-4B4E-B119-28FFE3B7B1C0}.Release|Any CPU.ActiveCfg = Release|Any CPU
+ {8951D80F-B2D6-4B4E-B119-28FFE3B7B1C0}.Release|Any CPU.Build.0 = Release|Any CPU
+ {90CBA7FD-CB46-4711-97BB-2420DC01F016}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
+ {90CBA7FD-CB46-4711-97BB-2420DC01F016}.Debug|Any CPU.Build.0 = Debug|Any CPU
+ {90CBA7FD-CB46-4711-97BB-2420DC01F016}.Release|Any CPU.ActiveCfg = Release|Any CPU
+ {90CBA7FD-CB46-4711-97BB-2420DC01F016}.Release|Any CPU.Build.0 = Release|Any CPU
+ EndGlobalSection
+ GlobalSection(MonoDevelopProperties) = preSolution
+ StartupItem = MonoDevelop.GtkCore2.xbuild.csproj
+ EndGlobalSection
+EndGlobal
diff --git a/main/src/addins/MonoDevelop.GtkCore2/MonoDevelop.GtkCore2.xbuild.csproj b/main/src/addins/MonoDevelop.GtkCore2/MonoDevelop.GtkCore2.xbuild.csproj new file mode 100644 index 0000000000..761692829f --- /dev/null +++ b/main/src/addins/MonoDevelop.GtkCore2/MonoDevelop.GtkCore2.xbuild.csproj @@ -0,0 +1,232 @@ +<?xml version="1.0" encoding="utf-8"?> +<Project DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003" ToolsVersion="3.5"> + <PropertyGroup> + <Configuration Condition=" '$(Configuration)' == '' ">Debug</Configuration> + <Platform Condition=" '$(Platform)' == '' ">AnyCPU</Platform> + <ProductVersion>9.0.21022</ProductVersion> + <SchemaVersion>2.0</SchemaVersion> + <ProjectGuid>{4F2E994F-E4F5-407A-8D80-80E3377DEF6E}</ProjectGuid> + <OutputType>Library</OutputType> + <AssemblyName>MonoDevelop.GtkCore2</AssemblyName> + <TargetFrameworkVersion>v3.5</TargetFrameworkVersion> + <RootNamespace>MonoDevelop.GtkCore</RootNamespace> + </PropertyGroup> + <PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|AnyCPU' "> + <DebugSymbols>true</DebugSymbols> + <DebugType>full</DebugType> + <Optimize>true</Optimize> + <OutputPath>build\debug\</OutputPath> + <ErrorReport>prompt</ErrorReport> + <WarningLevel>4</WarningLevel> + <CheckForOverflowUnderflow>true</CheckForOverflowUnderflow> + <Execution> + <Execution clr-version="Net_2_0" /> + </Execution> + </PropertyGroup> + <PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|AnyCPU' "> + <DebugType>none</DebugType> + <Optimize>true</Optimize> + <OutputPath>build\release\ </OutputPath> + <ErrorReport>prompt</ErrorReport> + <WarningLevel>4</WarningLevel> + <CheckForOverflowUnderflow>true</CheckForOverflowUnderflow> + <Execution> + <Execution clr-version="Net_2_0" /> + </Execution> + <DefineConstants>TRUNK</DefineConstants> + </PropertyGroup> + <ItemGroup> + <Reference Include="System" /> + <Reference Include="System.Xml" /> + <Reference Include="Mono.Posix" /> + <Reference Include="Mono.Addins, Version=0.4.0.0, Culture=neutral, PublicKeyToken=0738eb9f132ed756"> + <SpecificVersion>False</SpecificVersion> + </Reference> + <Reference Include="glade-sharp, Version=2.12.0.0, Culture=neutral, PublicKeyToken=35e10195dab3c99f"> + <SpecificVersion>False</SpecificVersion> + </Reference> + <Reference Include="glib-sharp, Version=2.12.0.0, Culture=neutral, PublicKeyToken=35e10195dab3c99f"> + <SpecificVersion>False</SpecificVersion> + </Reference> + <Reference Include="pango-sharp, Version=2.12.0.0, Culture=neutral, PublicKeyToken=35e10195dab3c99f"> + <SpecificVersion>False</SpecificVersion> + </Reference> + <Reference Include="atk-sharp, Version=2.12.0.0, Culture=neutral, PublicKeyToken=35e10195dab3c99f"> + <SpecificVersion>False</SpecificVersion> + </Reference> + <Reference Include="gdk-sharp, Version=2.12.0.0, Culture=neutral, PublicKeyToken=35e10195dab3c99f"> + <SpecificVersion>False</SpecificVersion> + </Reference> + <Reference Include="gtk-sharp, Version=2.12.0.0, Culture=neutral, PublicKeyToken=35e10195dab3c99f"> + <SpecificVersion>False</SpecificVersion> + </Reference> + <Reference Include="System.Core" /> + <Reference Include="MonoDevelop.Core, Version=2.4.0.0, Culture=neutral"> + <Package>monodevelop</Package> + </Reference> + <Reference Include="MonoDevelop.Ide, Version=2.4.0.0, Culture=neutral"> + <Package>monodevelop</Package> + </Reference> + <Reference Include="Mono.TextEditor, Version=1.0.0.0, Culture=neutral"> + <Package>monodevelop</Package> + </Reference> + <Reference Include="Mono.Cecil, Version=0.6.9.0, Culture=neutral, PublicKeyToken=0738eb9f132ed756"> + <Package>monodevelop</Package> + </Reference> + <Reference Include="NRefactory, Version=2.1.1.0, Culture=neutral, PublicKeyToken=efe927acf176eea2"> + <Package>monodevelop</Package> + </Reference> + <Reference Include="Mono.Debugging, Version=0.0.0.0, Culture=neutral, PublicKeyToken=9307d64546e0580d"> + <Package>monodevelop</Package> + </Reference> + <Reference Include="MonoDevelop.Deployment, Version=2.4.0.0, Culture=neutral, PublicKeyToken=null"> + <SpecificVersion>False</SpecificVersion> + <HintPath>..\..\..\build\AddIns\MonoDevelop.Deployment\MonoDevelop.Deployment.dll</HintPath> + </Reference> + <Reference Include="MonoDevelop.DesignerSupport, Version=2.4.0.0, Culture=neutral, PublicKeyToken=null"> + <SpecificVersion>False</SpecificVersion> + <HintPath>..\..\..\build\AddIns\MonoDevelop.DesignerSupport\MonoDevelop.DesignerSupport.dll</HintPath> + </Reference> + <Reference Include="Mono.TextEditor, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null"> + <SpecificVersion>False</SpecificVersion> + <HintPath>..\..\..\build\bin\Mono.TextEditor.dll</HintPath> + </Reference> + <Reference Include="MonoDevelop.Core, Version=2.4.0.0, Culture=neutral, PublicKeyToken=null"> + <SpecificVersion>False</SpecificVersion> + <HintPath>..\..\..\build\bin\MonoDevelop.Core.dll</HintPath> + </Reference> + <Reference Include="MonoDevelop.Ide, Version=2.4.0.0, Culture=neutral, PublicKeyToken=null"> + <SpecificVersion>False</SpecificVersion> + <HintPath>..\..\..\build\bin\MonoDevelop.Ide.dll</HintPath> + </Reference> + </ItemGroup> + <ItemGroup> + <ProjectReference Include="libsteticui\libsteticui2.csproj"> + <Project>{8951D80F-B2D6-4B4E-B119-28FFE3B7B1C0}</Project> + <Name>libsteticui2</Name> + </ProjectReference> + <ProjectReference Include="libstetic\libstetic2.csproj"> + <Project>{90CBA7FD-CB46-4711-97BB-2420DC01F016}</Project> + <Name>libstetic2</Name> + </ProjectReference> + </ItemGroup> + <ItemGroup> + <None Include="ChangeLog" /> + <None Include="Makefile.am" /> + <None Include="icons\window.png" /> + <None Include="icons\dialog.png" /> + </ItemGroup> + <ItemGroup> + <EmbeddedResource Include="templates\Dialog.xft.xml"> + <LogicalName>Dialog.xft.xml</LogicalName> + </EmbeddedResource> + <EmbeddedResource Include="templates\Window.xft.xml"> + <LogicalName>Window.xft.xml</LogicalName> + </EmbeddedResource> + <EmbeddedResource Include="templates\Widget.xft.xml"> + <LogicalName>Widget.xft.xml</LogicalName> + </EmbeddedResource> + <EmbeddedResource Include="templates\ActionGroup.xft.xml"> + <LogicalName>ActionGroup.xft.xml</LogicalName> + </EmbeddedResource> + <EmbeddedResource Include="gui.glade"> + <LogicalName>gui.glade</LogicalName> + </EmbeddedResource> + <EmbeddedResource Include="templates\ActionGroupPartial.xft.xml"> + <LogicalName>ActionGroupPartial.xft.xml</LogicalName> + </EmbeddedResource> + <EmbeddedResource Include="templates\DialogPartial.xft.xml"> + <LogicalName>DialogPartial.xft.xml</LogicalName> + </EmbeddedResource> + <EmbeddedResource Include="templates\WidgetPartial.xft.xml"> + <LogicalName>WidgetPartial.xft.xml</LogicalName> + </EmbeddedResource> + <EmbeddedResource Include="templates\DrawingArea.xft.xml"> + <LogicalName>DrawingArea.xft.xml</LogicalName> + </EmbeddedResource> + <EmbeddedResource Include="templates\WindowPartial.xft.xml"> + <LogicalName>WindowPartial.xft.xml</LogicalName> + </EmbeddedResource> + <EmbeddedResource Include="icons\widget.png"> + <LogicalName>widget.png</LogicalName> + </EmbeddedResource> + <EmbeddedResource Include="icons\actiongroup.png"> + <LogicalName>actiongroup.png</LogicalName> + </EmbeddedResource> + <EmbeddedResource Include="icons\image-x-generic.png"> + <LogicalName>image-x-generic.png</LogicalName> + </EmbeddedResource> + <EmbeddedResource Include="gtk-gui\gui.stetic"> + <LogicalName>gui.stetic</LogicalName> + </EmbeddedResource> + <EmbeddedResource Include="icons\gtkx.png"> + <LogicalName>gtkx.png</LogicalName> + </EmbeddedResource> + <EmbeddedResource Include="icons\gtk-logo.png"> + <LogicalName>gtk-logo.png</LogicalName> + </EmbeddedResource> + <EmbeddedResource Include="MonoDevelop.GtkCore2.addin.xml"> + <LogicalName>MonoDevelop.GtkCore.addin.xml</LogicalName> + </EmbeddedResource> + </ItemGroup> + <ItemGroup> + <Compile Include="MonoDevelop.GtkCore.Commands\GladeCommands.cs" /> + <Compile Include="MonoDevelop.GtkCore.GuiBuilder\ClassUtils.cs" /> + <Compile Include="MonoDevelop.GtkCore.GuiBuilder\GuiBuilderDisplayBinding.cs" /> + <Compile Include="MonoDevelop.GtkCore.GuiBuilder\GuiBuilderProject.cs" /> + <Compile Include="MonoDevelop.GtkCore.GuiBuilder\GuiBuilderDocumentOutline.cs" /> + <Compile Include="MonoDevelop.GtkCore.GuiBuilder\PropertiesWidget.cs" /> + <Compile Include="MonoDevelop.GtkCore.GuiBuilder\GuiBuilderService.cs" /> + <Compile Include="MonoDevelop.GtkCore.GuiBuilder\GuiBuilderView.cs" /> + <Compile Include="MonoDevelop.GtkCore.GuiBuilder\GuiBuilderWindow.cs" /> + <Compile Include="MonoDevelop.GtkCore\GtkDesignInfo.cs" /> + <Compile Include="MonoDevelop.GtkCore\GtkCoreService.cs" /> + <Compile Include="MonoDevelop.GtkCore.Dialogs\WidgetBuilderOptionPanel.cs" /> + <Compile Include="MonoDevelop.GtkCore.NodeBuilders\ProjectNodeBuilder.cs" /> + <Compile Include="MonoDevelop.GtkCore.NodeBuilders\ProjectFolderNodeBuilderExtension.cs" /> + <Compile Include="MonoDevelop.GtkCore\WidgetFileDescriptionTemplate.cs" /> + <Compile Include="MonoDevelop.GtkCore.Dialogs\SelectRenamedClassDialog.cs" /> + <Compile Include="MonoDevelop.GtkCore.Dialogs\BindDesignDialog.cs" /> + <Compile Include="MonoDevelop.GtkCore.Dialogs\ConfirmWindowDeleteDialog.cs" /> + <Compile Include="MonoDevelop.GtkCore\ProjectResourceProvider.cs" /> + <Compile Include="MonoDevelop.GtkCore.GuiBuilder\ActionGroupView.cs" /> + <Compile Include="MonoDevelop.GtkCore.GuiBuilder\ActionGroupDisplayBinding.cs" /> + <Compile Include="MonoDevelop.GtkCore.GuiBuilder\CombinedDesignView.cs" /> + <Compile Include="MonoDevelop.GtkCore.GuiBuilder\CodeBinder.cs" /> + <Compile Include="MonoDevelop.GtkCore.GuiBuilder\GtkProjectServiceExtension.cs" /> + <Compile Include="MonoDevelop.GtkCore.GuiBuilder\ToolboxProvider.cs" /> + <Compile Include="MonoDevelop.GtkCore.NodeBuilders\StockIconsNodeBuilder.cs" /> + <Compile Include="MonoDevelop.GtkCore.Dialogs\GtkFeatureWidget.cs" /> + <Compile Include="MonoDevelop.GtkCore.GuiBuilder\ToolboxLoader.cs" /> + <Compile Include="gtk-gui\generated.cs" /> + <Compile Include="MonoDevelop.GtkCore\ObjectsDocument.cs" /> + <Compile Include="MonoDevelop.GtkCore\WidgetParser.cs" /> + <Compile Include="MonoDevelop.GtkCore\ReferenceManager.cs" /> + <Compile Include="AssemblyInfo.cs" /> + <Compile Include="MonoDevelop.GtkCore.Dialogs\GtkDesignerOptionsPanelWidget.cs" /> + <Compile Include="gtk-gui\MonoDevelop.GtkCore.Dialogs.GtkDesignerOptionsPanelWidget.cs" /> + <Compile Include="MonoDevelop.GtkCore\Counters.cs" /> + <Compile Include="MonoDevelop.GtkCore.NodeBuilders\ProjectFileNodeBuilderExtension.cs" /> + <Compile Include="MonoDevelop.GtkCore.NodeBuilders\ProjectFileExtension.cs" /> + <Compile Include="MonoDevelop.GtkCore.Dialogs\ProjectConversionDialog.cs" /> + <Compile Include="MonoDevelop.GtkCore.NodeBuilders\GuiProjectFolder.cs" /> + <Compile Include="MonoDevelop.GtkCore.NodeBuilders\GuiProjectFolderNodeBuilder.cs" /> + <Compile Include="gtk-gui\MonoDevelop.GtkCore.Dialogs.ProjectConversionDialog.cs" /> + </ItemGroup> + <Import Project="$(MSBuildBinPath)\Microsoft.CSharp.targets" /> + <ProjectExtensions> + <MonoDevelop> + <Properties> + <MonoDevelop.Autotools.MakefileInfo IntegrationEnabled="true" RelativeMakefileName="Makefile.am" BuildTargetName="" CleanTargetName="" SyncReferences="true" IsAutotoolsProject="true" RelativeConfigureInPath="../../../"> + <BuildFilesVar Sync="true" Name="FILES" /> + <DeployFilesVar /> + <ResourcesVar Sync="true" Name="RES" /> + <OthersVar /> + <GacRefVar Sync="true" Name="REFS" Prefix="-r:" /> + <AsmRefVar Sync="true" Name="REFS" Prefix="-r:" /> + <ProjectRefVar Sync="true" Name="DEPS" /> + </MonoDevelop.Autotools.MakefileInfo> + </Properties> + </MonoDevelop> + </ProjectExtensions> +</Project> diff --git a/main/src/addins/MonoDevelop.GtkCore2/README b/main/src/addins/MonoDevelop.GtkCore2/README new file mode 100644 index 0000000000..3c12c0b5ec --- /dev/null +++ b/main/src/addins/MonoDevelop.GtkCore2/README @@ -0,0 +1,14 @@ +To build and test experimental GTK# visual designer : +- checkout and build MonoDevelop trunk +- copy entire MonoDevelop.GtkCore2 folder into monodevelop-trunk/main/src/ +- create monodevelop-slim folder in the monodevelop-trunk, +- copy monodevelop-slim.sln into monodevelop-trunk/monodevelop-slim +- open solution in MonoDevelop +- build and run + +Remarks : + - monodevelop-trunk is the name of folder where MonoDevelop was checkouted + - old stetic designer should be disabled + + +Krzysztof Marecki <marecki.krzysztof@gmail.com> diff --git a/main/src/addins/MonoDevelop.GtkCore2/addin-project.xml b/main/src/addins/MonoDevelop.GtkCore2/addin-project.xml new file mode 100644 index 0000000000..8b3e1e4863 --- /dev/null +++ b/main/src/addins/MonoDevelop.GtkCore2/addin-project.xml @@ -0,0 +1,7 @@ +<AddinProject appVersion="2.4"> + <Project platforms="Linux Win32 Mac"> + <AddinFile>build/debug/MonoDevelop.GtkCore2.dll</AddinFile> + <BuildFile>MonoDevelop.GtkCore2.sln</BuildFile> + <BuildConfiguration>Debug</BuildConfiguration> + </Project> +</AddinProject> diff --git a/main/src/addins/MonoDevelop.GtkCore2/build/debug/Mono.TextEditor.dll.config b/main/src/addins/MonoDevelop.GtkCore2/build/debug/Mono.TextEditor.dll.config new file mode 100644 index 0000000000..3fd1526914 --- /dev/null +++ b/main/src/addins/MonoDevelop.GtkCore2/build/debug/Mono.TextEditor.dll.config @@ -0,0 +1,18 @@ +<?xml version="1.0" encoding="utf-8"?> +<configuration> + <dllmap os="!windows,osx" dll="libglib-2.0-0.dll" target="libglib-2.0.so.0"/> + <dllmap os="!windows,osx" dll="libgobject-2.0-0.dll" target="libgobject-2.0.so.0"/> + <dllmap os="!windows,osx" dll="libatk-1.0-0.dll" target="libatk-1.0.so.0"/> + <dllmap os="!windows,osx" dll="libgtk-win32-2.0-0.dll" target="libgtk-x11-2.0.so.0"/> + <dllmap os="!windows,osx" dll="libgdk-win32-2.0-0.dll" target="libgdk-x11-2.0.so.0"/> + <dllmap os="!windows,osx" dll="libpango-1.0-0.dll" target="libpango-1.0.so.0"/> + <dllmap os="!windows,osx" dll="libpangocairo-1.0-0.dll" target="libpangocairo-1.0.so.0"/> + + <dllmap os="osx" dll="libglib-2.0-0.dll" target="libglib-2.0.0.dylib"/> + <dllmap os="osx" dll="libgobject-2.0-0.dll" target="libgobject-2.0.0.dylib"/> + <dllmap os="osx" dll="libatk-1.0-0.dll" target="libatk-1.0.0.dylib"/> + <dllmap os="osx" dll="libgtk-win32-2.0-0.dll" target="libgtk-quartz-2.0.0.dylib"/> + <dllmap os="osx" dll="libgdk-win32-2.0-0.dll" target="libgdk-quartz-2.0.0.dylib"/> + <dllmap os="osx" dll="libpango-1.0-0.dll" target="libpango-1.0.0.dylib"/> + <dllmap os="osx" dll="libpangocairo-1.0-0.dll" target="libpangocairo-1.0.0.dylib"/> +</configuration>
\ No newline at end of file diff --git a/main/src/addins/MonoDevelop.GtkCore2/build/debug/MonoDevelop.Core.dll.config b/main/src/addins/MonoDevelop.GtkCore2/build/debug/MonoDevelop.Core.dll.config new file mode 100644 index 0000000000..9551af1543 --- /dev/null +++ b/main/src/addins/MonoDevelop.GtkCore2/build/debug/MonoDevelop.Core.dll.config @@ -0,0 +1,4 @@ +<configuration> + <dllmap dll="libglib-2.0-0.dll" target="libglib-2.0.so.0" os="!osx,windows" /> + <dllmap dll="libglib-2.0-0.dll" target="libglib-2.0.dylib" os="osx" /> +</configuration> diff --git a/main/src/addins/MonoDevelop.GtkCore2/build/debug/MonoDevelop.Projects.Formats.MSBuild.exe b/main/src/addins/MonoDevelop.GtkCore2/build/debug/MonoDevelop.Projects.Formats.MSBuild.exe Binary files differnew file mode 100755 index 0000000000..1b37b819d1 --- /dev/null +++ b/main/src/addins/MonoDevelop.GtkCore2/build/debug/MonoDevelop.Projects.Formats.MSBuild.exe diff --git a/main/src/addins/MonoDevelop.GtkCore2/build/debug/MonoDevelop.Projects.Formats.MSBuild.exe.config b/main/src/addins/MonoDevelop.GtkCore2/build/debug/MonoDevelop.Projects.Formats.MSBuild.exe.config new file mode 100644 index 0000000000..4e4303ebdf --- /dev/null +++ b/main/src/addins/MonoDevelop.GtkCore2/build/debug/MonoDevelop.Projects.Formats.MSBuild.exe.config @@ -0,0 +1,16 @@ +<?xml version="1.0" encoding="utf-8"?> +<configuration> + <runtime> + <generatePublisherEvidence enabled="false" /> + <assemblyBinding xmlns="urn:schemas-microsoft-com:asm.v1"> + <dependentAssembly> + <assemblyIdentity name="Microsoft.Build.Framework" publicKeyToken="b03f5f7f11d50a3a" culture="neutral" /> + <bindingRedirect oldVersion="0.0.0.0-100.0.0.0" newVersion="2.0.0.0" /> + </dependentAssembly> + <dependentAssembly> + <assemblyIdentity name="Microsoft.Build.Engine" publicKeyToken="b03f5f7f11d50a3a" culture="neutral" /> + <bindingRedirect oldVersion="0.0.0.0-100.0.0.0" newVersion="2.0.0.0" /> + </dependentAssembly> + </assemblyBinding> + </runtime> +</configuration> diff --git a/main/src/addins/MonoDevelop.GtkCore2/build/debug/libstetic2.dll.config b/main/src/addins/MonoDevelop.GtkCore2/build/debug/libstetic2.dll.config new file mode 100644 index 0000000000..8c4c6ab9a9 --- /dev/null +++ b/main/src/addins/MonoDevelop.GtkCore2/build/debug/libstetic2.dll.config @@ -0,0 +1,8 @@ +<configuration> + <dllmap dll="libgobject-2.0-0.dll" target="libgobject-2.0.so.0" os="!osx,windows" /> + <dllmap dll="libgobject-2.0-0.dll" target="libgobject-2.0.dylib" os="osx" /> + <dllmap dll="libgtk-win32-2.0-0.dll" target="libgtk-x11-2.0.so.0" os="!osx,windows"/> + <dllmap dll="libgtk-win32-2.0-0.dll" target="libgtk-quartz-2.0.dylib" os="osx"/> + <dllmap dll="libgdk-win32-2.0-0.dll" target="libgdk-x11-2.0.so.0" os="!osx,windows"/> + <dllmap dll="libgdk-win32-2.0-0.dll" target="libgdk-quartz-2.0.dylib" os="osx"/> +</configuration> diff --git a/main/src/addins/MonoDevelop.GtkCore2/build/debug/libsteticui2.dll.config b/main/src/addins/MonoDevelop.GtkCore2/build/debug/libsteticui2.dll.config new file mode 100644 index 0000000000..8c4c6ab9a9 --- /dev/null +++ b/main/src/addins/MonoDevelop.GtkCore2/build/debug/libsteticui2.dll.config @@ -0,0 +1,8 @@ +<configuration> + <dllmap dll="libgobject-2.0-0.dll" target="libgobject-2.0.so.0" os="!osx,windows" /> + <dllmap dll="libgobject-2.0-0.dll" target="libgobject-2.0.dylib" os="osx" /> + <dllmap dll="libgtk-win32-2.0-0.dll" target="libgtk-x11-2.0.so.0" os="!osx,windows"/> + <dllmap dll="libgtk-win32-2.0-0.dll" target="libgtk-quartz-2.0.dylib" os="osx"/> + <dllmap dll="libgdk-win32-2.0-0.dll" target="libgdk-x11-2.0.so.0" os="!osx,windows"/> + <dllmap dll="libgdk-win32-2.0-0.dll" target="libgdk-quartz-2.0.dylib" os="osx"/> +</configuration> diff --git a/main/src/addins/MonoDevelop.GtkCore2/changes.patch b/main/src/addins/MonoDevelop.GtkCore2/changes.patch new file mode 100644 index 0000000000..9fbc84e921 --- /dev/null +++ b/main/src/addins/MonoDevelop.GtkCore2/changes.patch @@ -0,0 +1,6455 @@ +Index: libsteticui/ProjectBackend.cs +=================================================================== +--- libsteticui/ProjectBackend.cs (revision 17) ++++ libsteticui/ProjectBackend.cs (working copy) +@@ -16,7 +16,7 @@ + bool modified; + Gtk.Widget selection; + string id; +- string fileName; ++ string folderName; + XmlDocument tempDoc; + bool loading; + IResourceProvider resourceProvider; +@@ -33,7 +33,9 @@ + AssemblyResolver resolver; + string imagesRootPath; + string targetGtkVersion; +- //version of stetic xml files ++ List<string> modifiedTopLevels; ++ //During project conversion flag is set ++ bool converting; + + // The action collection of the last selected widget + Stetic.Wrapper.ActionGroupCollection oldTopActionCollection; +@@ -49,8 +51,7 @@ + public event SignalChangedEventHandler SignalChanged; + + public event Wrapper.WidgetEventHandler SelectionChanged; +- public event EventHandler ModifiedChanged; +- public event EventHandler Changed; ++ public event ProjectChangedEventHandler Changed; + + // Fired when the project has been reloaded, due for example to + // a change in the registry +@@ -70,6 +71,7 @@ + iconFactory = new ProjectIconFactory (); + widgetLibraries = new ArrayList (); + internalLibs = new ArrayList (); ++ modifiedTopLevels = new List<string> (); + } + + public void Dispose () +@@ -95,12 +97,18 @@ + return null; + } + ++ + public string FileName { +- get { return fileName; } ++ get { throw new Exception("FileName is obsolete"); } ++ set { throw new Exception("FileName is obsolete"); } ++ } ++ ++ public string FolderName { ++ get { return folderName; } + set { +- this.fileName = value; +- if (fileName != null) +- Id = System.IO.Path.GetFileName (fileName); ++ this.folderName = value; ++ if (folderName != null ) ++ Id = System.IO.Path.GetFullPath (folderName); + else + Id = null; + } +@@ -134,7 +142,7 @@ + } + + public string TargetGtkVersion { +- get { return targetGtkVersion != null ? targetGtkVersion : "2.4"; } ++ get { return targetGtkVersion ?? string.Empty; } + set { + if (TargetGtkVersion == value) + return; +@@ -149,16 +157,16 @@ + public string ImagesRootPath { + get { + if (string.IsNullOrEmpty (imagesRootPath)) { +- if (string.IsNullOrEmpty (fileName)) ++ if (string.IsNullOrEmpty (folderName)) + return "."; + else +- return Path.GetDirectoryName (fileName); ++ return Path.GetFullPath (folderName); + } + else { + if (Path.IsPathRooted (imagesRootPath)) + return imagesRootPath; +- else if (!string.IsNullOrEmpty (fileName)) +- return Path.GetFullPath (Path.Combine (Path.GetDirectoryName (fileName), imagesRootPath)); ++ else if (!string.IsNullOrEmpty (folderName)) ++ return Path.GetFullPath (Path.Combine (folderName, imagesRootPath)); + else + return imagesRootPath; + } +@@ -190,7 +198,7 @@ + widgetLibraries.Remove (lib); + internalLibs.Remove (lib); + } +- ++ + public ArrayList GetComponentTypes () + { + ArrayList list = new ArrayList (); +@@ -257,20 +265,13 @@ + set { iconFactory = value; } + } + +- internal void SetFileName (string fileName) +- { +- this.fileName = fileName; +- } +- + internal void SetFrontend (Project project) + { + frontend = project; + } + + public void Close () +- { +- fileName = null; +- ++ { + if (actionGroups != null && ownedGlobalActionGroups) { + foreach (Stetic.Wrapper.ActionGroup ag in actionGroups) + ag.Dispose (); +@@ -284,24 +285,35 @@ + + selection = null; + topLevels.Clear (); +- widgetLibraries.Clear (); ++ //widgetLibraries.Clear (); ++ + + iconFactory = new ProjectIconFactory (); + } + +- public void Load (string fileName) ++ public void Load (string folderName) + { +- Load (fileName, fileName); ++ this.folderName = folderName; ++ XmlDocument doc = new XmlDocument (); ++ doc.PreserveWhitespace = true; ++ XmlElement toplevel = doc.CreateElement ("stetic-interface"); ++ doc.AppendChild (toplevel); ++ modifiedTopLevels.Clear (); ++ ++ ReadIconFactory (doc); ++ ReadActionGroups (doc); ++ ReadTopLevels (doc); ++ Read (doc); ++ ++ Id = System.IO.Path.GetFullPath (folderName); + } + +- public void Load (string xmlFile, string fileName) ++ public void LoadOldVersion (string fileName) + { +- this.fileName = fileName; + XmlDocument doc = new XmlDocument (); + doc.PreserveWhitespace = true; +- doc.Load (xmlFile); +- ReadIconFactory (doc); +- ReadSplitFiles (doc); ++ doc.Load (fileName); ++ + Read (doc); + + Id = System.IO.Path.GetFileName (fileName); +@@ -313,7 +325,7 @@ + if (node == null) + return; + +- string basePath = fileName != null ? Path.GetDirectoryName (fileName) : null; ++ string basePath = folderName; + string xmlfile = Path.Combine(basePath, "IconFactory.gtkx"); + + if (File.Exists (xmlfile)) { +@@ -331,8 +343,18 @@ + } + } + +- void ReadSplitFiles (XmlDocument doc) ++ void ReadActionGroups (XmlDocument doc) + { ++ ReadSplitFiles (doc, "action-group", "name"); ++ } ++ ++ void ReadTopLevels (XmlDocument doc) ++ { ++ ReadSplitFiles (doc, "widget", "id"); ++ } ++ ++ void ReadSplitFiles (XmlDocument doc, string splitElement, string idAttribute) ++ { + XmlNode node = doc.SelectSingleNode ("/stetic-interface"); + if (node == null) + return; +@@ -349,88 +371,59 @@ + + XmlNode wnode = wdoc.SelectSingleNode ("/stetic-interface"); + +- foreach (XmlNode toplevel in wnode.SelectNodes ("widget | action-group")) { +- XmlNode imported = doc.ImportNode (toplevel, true); +- node.AppendChild (imported); ++ foreach (XmlElement toplevel in wnode.SelectNodes (splitElement)) { ++ string id = toplevel.GetAttribute (idAttribute); ++ ++ if (frontend.DesignInfo.HasComponentFile (id)) { ++ XmlNode imported = doc.ImportNode (toplevel, true); ++ node.AppendChild (imported); ++ } + } + } + } + } + } + ++ void AddActionGroup (XmlElement groupElem) ++ { ++ ObjectReader reader = new ObjectReader (this, FileFormat.Native); ++ ++ Wrapper.ActionGroup actionGroup = new Wrapper.ActionGroup (); ++ actionGroup.Read (reader, groupElem); ++ actionGroups.Add (actionGroup); ++ } ++ ++ void AddWidget (XmlElement toplevel) ++ { ++ topLevels.Add (new WidgetData (toplevel.GetAttribute ("id"), toplevel, null)); ++ } ++ + void Read (XmlDocument doc) + { + loading = true; +- string basePath = fileName != null ? Path.GetDirectoryName (fileName) : null; +- ++ + try { +- string fn = fileName; + Close (); +- fileName = fn; + + XmlNode node = doc.SelectSingleNode ("/stetic-interface"); + if (node == null) + throw new ApplicationException (Catalog.GetString ("Not a Stetic file according to node name.")); + +- // Load configuration options +- foreach (XmlNode configNode in node.SelectNodes ("configuration/*")) { +- XmlElement config = configNode as XmlElement; +- if (config == null) continue; +- +- if (config.LocalName == "images-root-path") +- imagesRootPath = config.InnerText; +- else if (config.LocalName == "target-gtk-version") +- targetGtkVersion = config.InnerText; +- } +- + // Load the assembly directories + resolver = new AssemblyResolver (app); +- foreach (XmlElement libElem in node.SelectNodes ("import/assembly-directory")) { +- string dir = libElem.GetAttribute ("path"); +- if (dir.Length > 0) { +- if (basePath != null && !Path.IsPathRooted (dir)) { +- dir = Path.Combine (basePath, dir); +- if (Directory.Exists (dir)) +- dir = Path.GetFullPath (dir); +- } +- resolver.Directories.Add (dir); +- } +- } +- +- // Import the referenced libraries +- foreach (XmlElement libElem in node.SelectNodes ("import/widget-library")) { +- string libname = libElem.GetAttribute ("name"); +- if (libname.EndsWith (".dll") || libname.EndsWith (".exe")) { +- if (basePath != null && !Path.IsPathRooted (libname)) { +- libname = Path.Combine (basePath, libname); +- if (File.Exists (libname)) +- libname = Path.GetFullPath (libname); +- } +- } +- widgetLibraries.Add (libname); +- if (libElem.GetAttribute ("internal") == "true") +- internalLibs.Add (libname); +- } +- + app.LoadLibraries (resolver, widgetLibraries); + +- ObjectReader reader = new ObjectReader (this, FileFormat.Native); +- + if (ownedGlobalActionGroups) { +- foreach (XmlElement groupElem in node.SelectNodes ("action-group")) { +- Wrapper.ActionGroup actionGroup = new Wrapper.ActionGroup (); +- actionGroup.Read (reader, groupElem); +- actionGroups.Add (actionGroup); +- } ++ foreach (XmlElement groupElem in node.SelectNodes ("action-group")) ++ AddActionGroup (groupElem); + } + + XmlElement iconsElem = node.SelectSingleNode ("icon-factory") as XmlElement; + if (iconsElem != null) + iconFactory.Read (this, iconsElem); + +- foreach (XmlElement toplevel in node.SelectNodes ("widget")) { +- topLevels.Add (new WidgetData (toplevel.GetAttribute ("id"), toplevel, null)); +- } ++ foreach (XmlElement toplevel in node.SelectNodes ("widget")) ++ AddWidget (toplevel); + + } finally { + loading = false; +@@ -443,8 +436,9 @@ + try { + loading = true; + ObjectReader reader = new ObjectReader (this, FileFormat.Native); +- Wrapper.Container wrapper = Stetic.ObjectWrapper.ReadObject (reader, data.XmlData) as Wrapper.Container; ++ Wrapper.Container wrapper = Stetic.ObjectWrapper.ReadObject (reader, data.XmlData, null) as Wrapper.Container; + data.Widget = wrapper.Wrapped; ++ data.Widget.Destroyed += (s,e) => data.Widget = null; + } finally { + loading = false; + } +@@ -453,9 +447,62 @@ + return data.Widget; + } + +- public void Save (string fileName) ++ public bool ReloadTopLevel (string topLevelName) + { +- this.fileName = fileName; ++ XmlElement topLevelElem = ReadDesignerFile (topLevelName, "widget"); ++ if (topLevelName != null) { ++ WidgetData data = GetWidgetData (topLevelName); ++ ++ if (data != null) { ++ //Stetic.Wrapper.Widget ww = Stetic.Wrapper.Widget.Lookup (data.Widget); ++ data.SetXmlData (topLevelName, topLevelElem); ++ GetWidget (data); ++ return true; ++ } ++ } ++ return false; ++ } ++ ++ public void ReloadActionGroup (string groupName) ++ { ++ ++ } ++ ++ XmlElement ReadDesignerFile (string componentName, string elementName) ++ { ++ string gtkxFile = GetDesignerFileName (componentName); ++ if (gtkxFile != null) { ++ XmlDocument wdoc = new XmlDocument (); ++ wdoc.PreserveWhitespace = true; ++ wdoc.Load (gtkxFile); ++ ++ XmlNode wnode = wdoc.SelectSingleNode ("/stetic-interface"); ++ foreach (XmlElement toplevel in wnode.SelectNodes (elementName)) { ++ return toplevel; ++ } ++ ++ string msg = string.Format (@"Cannot find /stetic-interface/{0} element in {1} file.", ++ elementName, gtkxFile); ++ throw new InvalidOperationException (msg); ++ } ++ ++ return null; ++ } ++ ++ public void ConvertProject (string oldSteticFileName, string newGuiFolderName) ++ { ++ converting = true; ++ try { ++ LoadOldVersion (oldSteticFileName); ++ Save (newGuiFolderName); ++ } finally { ++ converting = false; ++ } ++ } ++ ++ public void Save (string folderName) ++ { ++ this.folderName = folderName; + XmlDocument doc = Write (false); + + XmlTextWriter writer = null; +@@ -463,15 +510,7 @@ + WriteIconFactory (doc); + WriteActionGroups (doc); + WriteTopLevels (doc); +- // Write to a temporary file first, just in case something fails +- writer = new XmlTextWriter (fileName + "~", System.Text.Encoding.UTF8); +- writer.Formatting = Formatting.Indented; +- doc.Save (writer); +- writer.Close (); +- +- File.Copy (fileName + "~", fileName, true); +- File.Delete (fileName + "~"); +- ++ + } finally { + if (writer != null) + writer.Close (); +@@ -497,7 +536,7 @@ + XmlNode ifnode2 = doc2.ImportNode (ifnode, true); + node2.AppendChild (ifnode2); + +- string basePath = this.fileName != null ? Path.GetDirectoryName (this.fileName) : null; ++ string basePath = this.folderName; + string xmlFile = Path.Combine (basePath, "IconFactory.gtkx"); + WriteXmlFile (xmlFile, doc2); + +@@ -520,34 +559,35 @@ + if (node == null) + return; + +- List<XmlElement> toplevels = new List<XmlElement> (); + foreach (XmlElement toplevel in node.SelectNodes (splitElement)) { + + string id = toplevel.GetAttribute (idAttribute); +- string basePath = frontend.DesignInfo.GetComponentFolder (id); +- string xmlFile = Path.Combine (basePath, id + ".gtkx"); +- +- XmlDocument doc2 = new XmlDocument (); +- doc2.PreserveWhitespace = true; +- +- XmlElement node2 = doc2.CreateElement ("stetic-interface"); +- doc2.AppendChild (node2); +- +- XmlNode wnode2 = doc2.ImportNode (toplevel, true); +- node2.AppendChild (wnode2); +- +- //after saving component need to remove its xml element definition, +- //otherwise it would be saved in gui.stetic +- toplevels.Add (toplevel); +- +- WriteXmlFile (xmlFile, doc2); ++ if (modifiedTopLevels.Contains (id) || converting) { ++ string xmlFile = GetDesignerFileName (id); ++ if (xmlFile != null) { ++ XmlDocument doc2 = new XmlDocument (); ++ doc2.PreserveWhitespace = true; ++ ++ XmlElement node2 = doc2.CreateElement ("stetic-interface"); ++ doc2.AppendChild (node2); ++ ++ XmlNode wnode2 = doc2.ImportNode (toplevel, true); ++ node2.AppendChild (wnode2); ++ ++ WriteXmlFile (xmlFile, doc2); ++ if (modifiedTopLevels.Contains (id)) ++ modifiedTopLevels.Remove (id); ++ } ++ } + } +- +- foreach (XmlElement toplevel in toplevels) +- //now it is safe to remove +- node.RemoveChild (toplevel); + } + ++ private string GetDesignerFileName (string componentName) ++ { ++ string componentFile = frontend.DesignInfo.GetComponentFile (componentName); ++ return frontend.DesignInfo.GetGtkxFile (componentFile); ++ } ++ + void WriteXmlFile (string xmlFile, XmlDocument doc) + { + XmlTextWriter writer = null; +@@ -574,52 +614,6 @@ + XmlElement toplevel = doc.CreateElement ("stetic-interface"); + doc.AppendChild (toplevel); + +- XmlElement config = doc.CreateElement ("configuration"); +- if (!string.IsNullOrEmpty (imagesRootPath)) { +- XmlElement iroot = doc.CreateElement ("images-root-path"); +- iroot.InnerText = imagesRootPath; +- config.AppendChild (iroot); +- } +- if (!string.IsNullOrEmpty (targetGtkVersion)) { +- XmlElement iroot = doc.CreateElement ("target-gtk-version"); +- iroot.InnerText = targetGtkVersion; +- config.AppendChild (iroot); +- } +- +- if (config.ChildNodes.Count > 0) +- toplevel.AppendChild (config); +- +- if (widgetLibraries.Count > 0 || (resolver != null && resolver.Directories.Count > 0)) { +- XmlElement importElem = doc.CreateElement ("import"); +- toplevel.AppendChild (importElem); +- string basePath = Path.GetDirectoryName (fileName); +- +- if (resolver != null && resolver.Directories.Count > 0) { +- foreach (string dir in resolver.Directories) { +- XmlElement dirElem = doc.CreateElement ("assembly-directory"); +- if (basePath != null) +- dirElem.SetAttribute ("path", AbsoluteToRelativePath (basePath, dir)); +- else +- dirElem.SetAttribute ("path", dir); +- toplevel.AppendChild (dirElem); +- } +- } +- +- foreach (string wlib in widgetLibraries) { +- string libName = wlib; +- XmlElement libElem = doc.CreateElement ("widget-library"); +- if (wlib.EndsWith (".dll") || wlib.EndsWith (".exe")) { +- if (basePath != null) +- libName = AbsoluteToRelativePath (basePath, wlib); +- } +- +- libElem.SetAttribute ("name", libName); +- if (IsInternalLibrary (wlib)) +- libElem.SetAttribute ("internal", "true"); +- importElem.AppendChild (libElem); +- } +- } +- + ObjectWriter writer = new ObjectWriter (doc, FileFormat.Native); + writer.CreateUndoInfo = includeUndoInfo; + if (ownedGlobalActionGroups) { +@@ -670,9 +664,14 @@ + } + } + +- internal WidgetEditSession CreateWidgetDesignerSession (WidgetDesignerFrontend frontend, string windowName, Stetic.ProjectBackend editingBackend, bool autoCommitChanges) ++// internal WidgetEditSession CreateWidgetDesignerSession (WidgetDesignerFrontend frontend, string windowName, Stetic.ProjectBackend editingBackend, bool autoCommitChanges) ++// { ++// return new WidgetEditSession (this, frontend, windowName, editingBackend, autoCommitChanges); ++// } ++ ++ internal WidgetEditSession CreateWidgetDesignerSession (WidgetDesignerFrontend frontend, string windowName) + { +- return new WidgetEditSession (this, frontend, windowName, editingBackend, autoCommitChanges); ++ return new WidgetEditSession (this, frontend, windowName); + } + + internal ActionGroupEditSession CreateGlobalActionGroupDesignerSession (ActionGroupDesignerFrontend frontend, string groupName, bool autoCommitChanges) +@@ -687,7 +686,7 @@ + + public Wrapper.Container GetTopLevelWrapper (string name, bool throwIfNotFound) + { +- Gtk.Widget w = GetTopLevel (name); ++ Gtk.Widget w = GetWidget (name); + if (w != null) { + Wrapper.Container ww = Wrapper.Container.Lookup (w); + if (ww != null) +@@ -698,6 +697,23 @@ + return null; + } + ++ public object AddNewComponent (string fileName) ++ { ++ XmlDocument doc = new XmlDocument(); ++ doc.PreserveWhitespace = true; ++ doc.Load (fileName); ++ ++ XmlElement toplevel = (XmlElement)doc.SelectSingleNode ("/stetic-interface/widget"); ++ if (toplevel != null) ++ return AddNewWidgetFromTemplate (toplevel.OuterXml); ++ ++ XmlElement groupElem = (XmlElement)doc.SelectSingleNode ("/stetic-interface/action-group"); ++ if (groupElem != null) ++ return AddNewActionGroupFromTemplate (groupElem.OuterXml); ++ ++ return null; ++ } ++ + public object AddNewWidget (string type, string name) + { + ClassDescriptor cls = Registry.LookupClassByName (type); +@@ -724,22 +740,9 @@ + + if (frontend != null) + frontend.NotifyWidgetRemoved (data.Name); +- +- XmlElement elem; +- if (data.Widget != null) +- elem = Stetic.WidgetUtils.ExportWidget (data.Widget); +- else +- elem = (XmlElement) data.XmlData.Clone (); +- XmlDocument doc = new XmlDocument (); +- XmlNode node = doc.ImportNode (elem, true); +- doc.AppendChild (node); +- string dir = Path.Combine (Path.Combine (Environment.GetFolderPath (Environment.SpecialFolder.ApplicationData), "stetic"), "deleted-designs"); +- if (!Directory.Exists (dir)) +- Directory.CreateDirectory (dir); +- doc.Save (Path.Combine (dir, name + ".xml")); +- topLevels.Remove (data); +- if (data.Widget != null) +- data.Widget.Destroy (); ++ ++ if (modifiedTopLevels.Contains (name)) ++ modifiedTopLevels.Remove (name); + } + + public Stetic.Wrapper.ActionGroup AddNewActionGroup (string name) +@@ -747,6 +750,7 @@ + Stetic.Wrapper.ActionGroup group = new Stetic.Wrapper.ActionGroup (); + group.Name = name; + ActionGroups.Add (group); ++ this.modifiedTopLevels.Add (name); + return group; + } + +@@ -758,12 +762,16 @@ + Stetic.Wrapper.ActionGroup group = new Stetic.Wrapper.ActionGroup (); + group.Read (or, doc.DocumentElement); + ActionGroups.Add (group); ++ this.modifiedTopLevels.Add (group.Name); + return group; + } + + public void RemoveActionGroup (Stetic.Wrapper.ActionGroup group) + { + ActionGroups.Remove (group); ++ string name = group.Name; ++ if (modifiedTopLevels.Contains (name)) ++ modifiedTopLevels.Remove (name); + } + + public Wrapper.ActionGroup[] GetActionGroups () +@@ -771,40 +779,7 @@ + // Needed since ActionGroupCollection can't be made serializable + return ActionGroups.ToArray (); + } +- +- public void CopyWidgetToProject (string name, ProjectBackend other, string replacedName) +- { +- WidgetData wdata = GetWidgetData (name); +- if (name == null) +- throw new InvalidOperationException ("Component not found: " + name); + +- XmlElement data; +- if (wdata.Widget != null) +- data = Stetic.WidgetUtils.ExportWidget (wdata.Widget); +- else +- data = (XmlElement) wdata.XmlData.Clone (); +- +- // If widget already exist, replace it +- wdata = other.GetWidgetData (replacedName); +- if (wdata == null) { +- wdata = new WidgetData (name, data, null); +- other.topLevels.Add (wdata); +- } else { +- if (wdata.Widget != null) { +- // If a widget instance already exist, load the new data on it +- Wrapper.Widget sw = Wrapper.Widget.Lookup (wdata.Widget); +- sw.Read (new ObjectReader (other, FileFormat.Native), data); +- sw.NotifyChanged (); +- if (name != replacedName) +- other.OnWidgetNameChanged (new Wrapper.WidgetNameChangedArgs (sw, replacedName, name), true); +- } else { +- wdata.SetXmlData (name, data); +- if (name != replacedName) +- other.OnWidgetNameChanged (new Wrapper.WidgetNameChangedArgs (null, replacedName, name), true); +- } +- } +- } +- + void CleanUndoData (XmlElement elem) + { + elem.RemoveAttribute ("undoId"); +@@ -861,10 +836,19 @@ + NotifyComponentTypesChanged (); + } + ++ bool preserveWidgetLibraries; ++ + public void Reload () + { +- OnRegistryChanging (null, null); +- OnRegistryChanged (null, null); ++ try { ++ preserveWidgetLibraries = true; ++ OnRegistryChanging (null, null); ++ OnRegistryChanged (null, null); ++ } ++ finally ++ { ++ preserveWidgetLibraries = false; ++ } + } + + public string Id { +@@ -872,18 +856,16 @@ + set { id = value; } + } + +- public bool Modified { +- get { return modified; } +- set { +- if (modified != value) { +- modified = value; +- if (frontend != null) +- frontend.NotifyModifiedChanged (); +- OnModifiedChanged (EventArgs.Empty); +- } +- } ++ public bool WasModified (string topLevel) ++ { ++ return modifiedTopLevels.Contains (topLevel); + } + ++ public bool ComponentNeedsCodeGeneration (string topLevel) ++ { ++ return frontend.DesignInfo.ComponentNeedsCodeGeneration (topLevel); ++ } ++ + public AssemblyResolver Resolver { + get { return resolver; } + } +@@ -913,6 +895,7 @@ + + if (!loading) { + Stetic.Wrapper.Widget ww = Stetic.Wrapper.Widget.Lookup (widget); ++ + if (ww == null) + throw new InvalidOperationException ("Widget not wrapped"); + if (frontend != null) +@@ -925,7 +908,7 @@ + { + if (loading) + return; +- NotifyChanged (); ++ NotifyChanged (args.Wrapper.RootWrapperName); + if (ObjectChanged != null) + ObjectChanged (this, args); + } +@@ -934,7 +917,7 @@ + { + if (loading) + return; +- NotifyChanged (); ++ NotifyChanged (args.WidgetWrapper.RootWrapperName); + OnWidgetNameChanged (args, args.WidgetWrapper.IsTopLevel); + } + +@@ -1027,7 +1010,7 @@ + } + } + +- public Gtk.Widget GetTopLevel (string name) ++ public Gtk.Widget GetWidget (string name) + { + WidgetData w = GetWidgetData (name); + if (w != null) +@@ -1174,24 +1157,19 @@ + OnComponentTypesChanged (null, null); + } + +- void NotifyChanged () ++ void NotifyChanged (string rootWidgetName) + { +- Modified = true; ++ if (!modifiedTopLevels.Contains (rootWidgetName)) ++ modifiedTopLevels.Add (rootWidgetName); + if (frontend != null) +- frontend.NotifyChanged (); ++ frontend.NotifyChanged (rootWidgetName); + if (Changed != null) +- Changed (this, EventArgs.Empty); ++ Changed (this, new ProjectChangedEventArgs (rootWidgetName)); + } + +- protected virtual void OnModifiedChanged (EventArgs args) +- { +- if (ModifiedChanged != null) +- ModifiedChanged (this, args); +- } +- + protected virtual void OnWidgetAdded (Stetic.Wrapper.WidgetEventArgs args) + { +- NotifyChanged (); ++ NotifyChanged (args.WidgetWrapper.RootWrapperName); + if (WidgetAdded != null) + WidgetAdded (this, args); + } +@@ -1226,4 +1204,16 @@ + } + } + } ++ ++ public class ProjectChangedEventArgs : EventArgs ++ { ++ public string ChangedTopLevelName { get; private set; } ++ ++ public ProjectChangedEventArgs (string changedTopLevel) ++ { ++ ChangedTopLevelName = changedTopLevel; ++ } ++ } ++ ++ public delegate void ProjectChangedEventHandler (object sender, ProjectChangedEventArgs args); + } +Index: libsteticui/IProjectDesignInfo.cs +=================================================================== +--- libsteticui/IProjectDesignInfo.cs (revision 17) ++++ libsteticui/IProjectDesignInfo.cs (working copy) +@@ -2,14 +2,21 @@ + + namespace Stetic + { +- //Provides access to informations menaged by ide ++ //Provides access to informations managed by ide + public interface IProjectDesignInfo + { +- //Returns component source file folder +- string GetComponentFolder(string componentName); ++ //Returns component source file for given component ++ string GetComponentFile (string componentName); ++ bool HasComponentFile (string componentFile); + ++ //Returns gtkx file name for given component file ++ string GetGtkxFile (string componentFile); ++ + //Search for all components source file folders + string[] GetComponentFolders (); ++ ++ // Checks if code generation for a component is needed ++ bool ComponentNeedsCodeGeneration (string componentName); + } + } + +Index: libsteticui/WidgetEditSession.cs +=================================================================== +--- libsteticui/WidgetEditSession.cs (revision 17) ++++ libsteticui/WidgetEditSession.cs (working copy) +@@ -39,14 +39,12 @@ + internal class WidgetEditSession: MarshalByRefObject, IDisposable + { + string sourceWidget; +- Stetic.ProjectBackend sourceProject; ++ Stetic.ProjectBackend project; + +- Stetic.ProjectBackend gproject; + Stetic.Wrapper.Container rootWidget; + Stetic.WidgetDesignerBackend widget; + Gtk.VBox designer; + Gtk.Plug plug; +- bool autoCommitChanges; + WidgetActionBar toolbar; + WidgetDesignerFrontend frontend; + bool allowBinding; +@@ -55,61 +53,27 @@ + ContainerUndoRedoManager undoManager; + UndoQueue undoQueue; + +- public event EventHandler ModifiedChanged; + public event EventHandler RootWidgetChanged; + public event Stetic.Wrapper.WidgetEventHandler SelectionChanged; + +- public WidgetEditSession (ProjectBackend sourceProject, WidgetDesignerFrontend frontend, string windowName, Stetic.ProjectBackend editingBackend, bool autoCommitChanges) ++ public WidgetEditSession (ProjectBackend sourceProject, WidgetDesignerFrontend frontend, string windowName) + { + this.frontend = frontend; +- this.autoCommitChanges = autoCommitChanges; + undoManager = new ContainerUndoRedoManager (); + undoQueue = new UndoQueue (); + undoManager.UndoQueue = undoQueue; + + sourceWidget = windowName; +- this.sourceProject = sourceProject; +- +- if (!autoCommitChanges) { +- // Reuse the action groups and icon factory of the main project +- gproject = editingBackend; +- +- // Attach will prevent the destruction of the action group list by gproject +- gproject.AttachActionGroups (sourceProject.ActionGroups); +- +- gproject.IconFactory = sourceProject.IconFactory; +- gproject.FileName = sourceProject.FileName; +- gproject.ImagesRootPath = sourceProject.ImagesRootPath; +- gproject.ResourceProvider = sourceProject.ResourceProvider; +- gproject.WidgetLibraries = (ArrayList) sourceProject.WidgetLibraries.Clone (); +- gproject.InternalWidgetLibraries = (ArrayList) sourceProject.InternalWidgetLibraries.Clone (); +- gproject.TargetGtkVersion = sourceProject.TargetGtkVersion; +- sourceProject.ComponentTypesChanged += OnSourceProjectLibsChanged; +- sourceProject.ProjectReloaded += OnSourceProjectReloaded; +- +- rootWidget = editingBackend.GetTopLevelWrapper (sourceWidget, false); +- if (rootWidget == null) { +- // Copy the widget to edit from the source project +- // When saving the file, this project will be merged with the main project. +- sourceProject.CopyWidgetToProject (windowName, gproject, windowName); +- rootWidget = gproject.GetTopLevelWrapper (windowName, true); +- } +- +- gproject.Modified = false; +- } +- else { +- rootWidget = sourceProject.GetTopLevelWrapper (windowName, true); +- gproject = sourceProject; +- } +- ++ this.project = sourceProject; ++ ++ rootWidget = sourceProject.GetTopLevelWrapper (windowName, true); + rootWidget.Select (); + undoManager.RootObject = rootWidget; + +- gproject.ModifiedChanged += new EventHandler (OnModifiedChanged); +- gproject.Changed += new EventHandler (OnChanged); +- gproject.ProjectReloaded += new EventHandler (OnProjectReloaded); +- gproject.ProjectReloading += new EventHandler (OnProjectReloading); +-// gproject.WidgetMemberNameChanged += new Stetic.Wrapper.WidgetNameChangedHandler (OnWidgetNameChanged); ++ this.project.Changed += new ProjectChangedEventHandler (OnChanged); ++ this.project.ProjectReloaded += new EventHandler (OnProjectReloaded); ++ this.project.ProjectReloading += new EventHandler (OnProjectReloading); ++// this.project.WidgetMemberNameChanged += new Stetic.Wrapper.WidgetNameChangedHandler (OnWidgetNameChanged); + } + + public bool AllowWidgetBinding { +@@ -144,7 +108,8 @@ + designer.BorderWidth = 3; + designer.PackStart (toolbar, false, false, 0); + designer.PackStart (widget, true, true, 3); +- widget.DesignArea.SetSelection (gproject.Selection, gproject.Selection, false); ++ widget.DesignArea.SetSelection (project.Selection, project.Selection, false); ++ + widget.SelectionChanged += OnSelectionChanged; + + } +@@ -173,42 +138,24 @@ + } + + public void Save () +- { +- if (!autoCommitChanges) { +- gproject.CopyWidgetToProject (rootWidget.Wrapped.Name, sourceProject, sourceWidget); +- sourceWidget = rootWidget.Wrapped.Name; +- gproject.Modified = false; +- } ++ { + } + + public ProjectBackend EditingBackend { +- get { return gproject; } ++ get { return project; } + } + + public void Dispose () + { +- sourceProject.ComponentTypesChanged -= OnSourceProjectLibsChanged; +- sourceProject.ProjectReloaded -= OnSourceProjectReloaded; ++ project.ComponentTypesChanged -= OnSourceProjectLibsChanged; ++ project.ProjectReloaded -= OnSourceProjectReloaded; ++ project.Changed -= new ProjectChangedEventHandler (OnChanged); ++ project.ProjectReloaded -= OnProjectReloaded; ++ project.ProjectReloading -= OnProjectReloading; ++// project.WidgetMemberNameChanged -= new Stetic.Wrapper.WidgetNameChangedHandler (OnWidgetNameChanged); + +- gproject.ModifiedChanged -= new EventHandler (OnModifiedChanged); +- gproject.Changed -= new EventHandler (OnChanged); +- gproject.ProjectReloaded -= OnProjectReloaded; +- gproject.ProjectReloading -= OnProjectReloading; +-// gproject.WidgetMemberNameChanged -= new Stetic.Wrapper.WidgetNameChangedHandler (OnWidgetNameChanged); +- +- if (!autoCommitChanges) { +- // Don't dispose the project here! it will be disposed by the frontend +- if (widget != null) { +- widget.SelectionChanged -= OnSelectionChanged; +- // Don't dispose the widget. It will be disposed when destroyed together +- // with the container +- widget = null; +- } +- } +- + if (plug != null) + plug.Destroy (); +- gproject = null; + rootWidget = null; + frontend = null; + System.Runtime.Remoting.RemotingServices.Disconnect (this); +@@ -231,7 +178,7 @@ + } + + public bool Modified { +- get { return gproject.Modified; } ++ get { return project.WasModified (RootWidget.Name); } + } + + public UndoQueue UndoQueue { +@@ -243,32 +190,22 @@ + } + } + +- void OnModifiedChanged (object s, EventArgs a) ++ void OnChanged (object s, ProjectChangedEventArgs a) + { ++ if (a.ChangedTopLevelName != RootWidget.Name) ++ return; ++ + if (frontend != null) +- frontend.NotifyModifiedChanged (); +- } +- +- void OnChanged (object s, EventArgs a) +- { +- if (frontend != null) + frontend.NotifyChanged (); + } + + void OnSourceProjectReloaded (object s, EventArgs a) + { +- // Propagate gtk version change +- if (sourceProject.TargetGtkVersion != gproject.TargetGtkVersion) +- gproject.TargetGtkVersion = sourceProject.TargetGtkVersion; ++ + } + + void OnSourceProjectLibsChanged (object s, EventArgs a) + { +- // If component types have changed in the source project, they must also change +- // in this project. +- gproject.WidgetLibraries = (ArrayList) sourceProject.WidgetLibraries.Clone (); +- gproject.InternalWidgetLibraries = (ArrayList) sourceProject.InternalWidgetLibraries.Clone (); +- gproject.NotifyComponentTypesChanged (); + } + + void OnProjectReloading (object s, EventArgs a) +@@ -279,16 +216,10 @@ + + void OnProjectReloaded (object s, EventArgs a) + { +- // Update the actions group list +- if (!autoCommitChanges) { +- gproject.AttachActionGroups (sourceProject.ActionGroups); +- gproject.WidgetLibraries = (ArrayList) sourceProject.WidgetLibraries.Clone (); +- gproject.InternalWidgetLibraries = (ArrayList) sourceProject.InternalWidgetLibraries.Clone (); +- } ++ Gtk.Widget topWidget = project.GetWidget (sourceWidget); + +- Gtk.Widget[] tops = gproject.Toplevels; +- if (tops.Length > 0) { +- rootWidget = Stetic.Wrapper.Container.Lookup (tops[0]); ++ if (topWidget != null) { ++ rootWidget = Stetic.Wrapper.Container.Lookup (topWidget); + undoManager.RootObject = rootWidget; + if (rootWidget != null) { + Gtk.Widget oldWidget = designer; +@@ -305,8 +236,8 @@ + return false; + }); + } +- +- gproject.NotifyComponentTypesChanged (); ++ ++ project.NotifyComponentTypesChanged (); + return; + } + } +@@ -375,7 +306,7 @@ + public object SaveState () + { + return new object[] { +- gproject.SaveStatus (), ++ project.SaveStatus (), + undoQueue + }; + } +@@ -383,7 +314,7 @@ + public void RestoreState (object sessionData) + { + object[] status = (object[]) sessionData; +- gproject.LoadStatus (status [0]); ++ project.LoadStatus (status [0]); + undoQueue = (UndoQueue) status [1]; + foreach (UndoRedoChange ch in undoQueue.Changes) { + ObjectWrapperUndoRedoChange och = ch as ObjectWrapperUndoRedoChange; +Index: libsteticui/ChangeLog +=================================================================== +--- libsteticui/ChangeLog (revision 17) ++++ libsteticui/ChangeLog (working copy) +@@ -1,3 +1,155 @@ ++2010-08-15 Krzysztof Marecki <freefirma@gmail.com> ++ ++ * CodeGenerator.cs: ++ * ProjectBackend.cs: ++ * WidgetEditSession.cs: ++ * CodeGeneratorPartialClass.cs: ++ ++2010-08-13 Krzysztof Marecki <freefirma@gmail.com> ++ ++ * Project.cs: ++ * Makefile.am: ++ * CodeGenerator.cs: ++ * libsteticui2.csproj: ++ * ActionGroupEditSession.cs: ++ * CodeGeneratorPartialClass.cs: ++ * CodeGeneratorInternalClass.cs: Remove class ++ ++2010-08-09 Krzysztof Marecki <freefirma@gmail.com> ++ ++ * Project.cs: Add ComponentNeedsCodeGeneration method ++ * ProjectBackend.cs: ++ * IProjectDesignInfo.cs: ++ * CodeGeneratorPartialClass.cs: Only generate code for components that ++ have been changed ++ ++2010-08-07 Krzysztof Marecki <marecki.krzysztof@gmail.com> ++ ++ * Project.cs: Remove Modifies property ++ * ProjectBackend.cs: Add modifiedTopLevel list, handled on project loading, saving. ++ * libsteticui2.csproj: ++ * WidgetEditSession.cs: Use ProjectBackend.WasModified to determine if it was modified ++ ++2010-08-05 Krzysztof Marecki <freefirma@gmail.com> ++ ++ * WidgetDesigner.cs: ++ * ProjectBackend.cs: ++ ++2010-08-05 Krzysztof Marecki <marecki.krzysztof@gmail.com> ++ Remove ModifiedChanged event, ++ change Changed event to ProjectChangedEventHandler (pass name of changed widget) ++ * Project.cs: ++ * WidgetDesigner.cs: ++ * ProjectBackend.cs: ++ * WidgetEditSession.cs: ++ ++2010-08-04 Krzysztof Marecki <freefirma@gmail.com> ++ ++ * Project.cs: Pass root widget name in NotifyChanged ++ * Makefile.am: ++ * ProjectBackend.cs: ++ * libsteticui2.csproj: ++ ++2010-08-03 Krzysztof Marecki <marecki.krzysztof@gmail.com> ++ ++ * Glade.cs: ++ * Makefile.am: ++ * ProjectBackend.cs: ++ ++2010-08-03 Krzysztof Marecki <marecki.krzysztof@gmail.com> ++ ++ * Makefile.am: ++ * ProjectBackend.cs: Return empty string when GtktargetVersion ++ is not initialized ++ ++2010-07-27 Krzysztof Marecki <marecki.krzysztof@gmail.com> ++ ++ * Project.cs: Remove autoCommit argument ++ * Makefile.am: ++ * WidgetDesigner.cs: Remove temporary project ++ * ProjectBackend.cs: Do not clear libraries on Close ++ * WidgetEditSession.cs: Remove temporary project ++ ++2010-07-27 Krzysztof Marecki <marecki.krzysztof@gmail.com> ++ ++ * Project.cs: ++ * WidgetDesigner.cs: ++ * ProjectBackend.cs: ++ ++2010-07-06 Krzysztof Marecki <marecki.krzysztof@gmail.com> ++ ++ * Project.cs: Add parameter to Convert method for passing ++ a new gtk gui folder name. ++ * ProjectBackend.cs: ++ ++2010-07-05 Krzysztof Marecki <marecki.krzysztof@gmail.com> ++ ++ * Glade.cs: ++ * Project.cs: AddComponent method ++ * Makefile.am: ++ * ProjectBackend.cs: ++ * libsteticui2.csproj: ++ ++2010-06-28 Krzysztof Marecki <marecki.krzysztof@gmail.com> ++ ++ * Project.cs: Find class name for given .gtkx file ++ * Makefile.am: ++ * ProjectBackend.cs: ++ * IProjectDesignInfo.cs: ++ ++2010-06-28 Krzysztof Marecki <marecki.krzysztof@gmail.com> ++ ++ * Makefile.am: ++ * ProjectBackend.cs: ++ * libsteticui2.csproj: ++ ++2010-06-23 Krzysztof Marecki <marecki.krzysztof@gmail.com> ++ ++ * Makefile.am: ++ * libsteticui2.csproj: ++ ++2010-06-23 Krzysztof Marecki <marecki.krzysztof@gmail.com> ++ ++ * Makefile.am: ++ * libsteticui2.csproj: ++ ++2010-06-22 Krzysztof Marecki <marecki.krzysztof@gmail.com> ++ ++ * Makefile.am: ++ ++2010-06-16 Krzysztof Marecki <marecki.krzysztof@gmail.com> ++ ++ * Makefile.am: ++ ++2010-06-15 Krzysztof Marecki <marecki.krzysztof@gmail.com> ++ ++ * Project.cs: Create backend for Convert ++ ++2010-06-09 Krzysztof Marecki <marecki.krzysztof@gmail.com> ++ ++ * Makefile.am: ++ * libsteticui2.csproj: ++ ++2010-06-07 Krzysztof Marecki <marecki.krzysztof@gmail.com> ++ ++ * Project.cs: Transition from project file name to project folder. ++ * Makefile.am: ++ * Application.cs: ++ * ProjectBackend.cs: ++ * WidgetEditSession.cs: ++ ++2010-06-07 Krzysztof Marecki <marecki.krzysztof@gmail.com> ++ ++ * Project.cs: ++ * Makefile.am: ++ * ProjectBackend.cs: ++ * IProjectDesignInfo.cs: ++ ++2010-06-02 Krzysztof Marecki <marecki.krzysztof@gmail.com> ++ ++ * Makefile.am: ++ * libsteticui2.csproj: ++ + 2010-04-16 Lluis Sanchez Gual <lluis@novell.com> + + * CecilSignalDescriptor.cs: Cecil uses '/' as separator for +Index: libsteticui/libsteticui2.csproj +=================================================================== +--- libsteticui/libsteticui2.csproj (revision 17) ++++ libsteticui/libsteticui2.csproj (working copy) +@@ -60,17 +60,34 @@ + <SpecificVersion>False</SpecificVersion> + </Reference> + <Reference Include="System.Core" /> ++ <Reference Include="NRefactory, Version=2.1.1.0, Culture=neutral, PublicKeyToken=efe927acf176eea2"> ++ <Package>monodevelop</Package> ++ </Reference> ++ <Reference Include="Mono.TextEditor, Version=1.0.0.0, Culture=neutral"> ++ <Package>monodevelop</Package> ++ </Reference> ++ <Reference Include="MonoDevelop.Core, Version=2.4.0.0, Culture=neutral"> ++ <Package>monodevelop</Package> ++ </Reference> ++ <Reference Include="MonoDevelop.Ide, Version=2.4.0.0, Culture=neutral"> ++ <Package>monodevelop</Package> ++ </Reference> ++ <Reference Include="Mono.Debugging, Version=0.0.0.0, Culture=neutral, PublicKeyToken=9307d64546e0580d"> ++ <Package>monodevelop</Package> ++ </Reference> ++ <Reference Include="Mono.Cecil, Version=0.6.9.0, Culture=neutral, PublicKeyToken=0738eb9f132ed756"> ++ <Package>monodevelop</Package> ++ </Reference> + </ItemGroup> + <ItemGroup> ++ <ProjectReference Include="..\libstetic\libstetic2.csproj"> ++ <Project>{90CBA7FD-CB46-4711-97BB-2420DC01F016}</Project> ++ <Name>libstetic2</Name> ++ </ProjectReference> + <ProjectReference Include="..\..\..\..\contrib\Mono.Cecil\Mono.Cecil.csproj"> + <Project>{3EC06433-F168-4C5B-A885-99CE4AB617E1}</Project> + <Name>Mono.Cecil</Name> +- <Private>False</Private> + </ProjectReference> +- <ProjectReference Include="..\libstetic\libstetic2.csproj"> +- <Project>{90CBA7FD-CB46-4711-97BB-2420DC01F016}</Project> +- <Name>libstetic2</Name> +- </ProjectReference> + </ItemGroup> + <ItemGroup> + <Compile Include="ActionComponent.cs" /> +@@ -90,7 +107,6 @@ + <Compile Include="CecilWidgetLibrary.cs" /> + <Compile Include="CodeGenerationResult.cs" /> + <Compile Include="CodeGenerator.cs" /> +- <Compile Include="CodeGeneratorInternalClass.cs" /> + <Compile Include="CodeGeneratorPartialClass.cs" /> + <Compile Include="Component.cs" /> + <Compile Include="ComponentEventHandler.cs" /> +Index: libsteticui/ActionGroupEditSession.cs +=================================================================== +--- libsteticui/ActionGroupEditSession.cs (revision 17) ++++ libsteticui/ActionGroupEditSession.cs (working copy) +@@ -197,6 +197,9 @@ + get { return modified; } + set { modified = value; frontend.NotifyModified (); } + } ++// public bool Modified { ++// get { return project.WasModified (); } ++// } + + public string ActiveGroup { + get { +Index: libsteticui/CodeGenerator.cs +=================================================================== +--- libsteticui/CodeGenerator.cs (revision 17) ++++ libsteticui/CodeGenerator.cs (working copy) +@@ -36,13 +36,13 @@ + ArrayList warningList = new ArrayList (); + + List<SteticCompilationUnit> units = new List<SteticCompilationUnit> (); +- SteticCompilationUnit globalUnit = new SteticCompilationUnit (""); +- units.Add (globalUnit); ++// SteticCompilationUnit globalUnit = new SteticCompilationUnit (""); ++// units.Add (globalUnit); + + if (options == null) + options = new GenerationOptions (); + CodeNamespace globalNs = new CodeNamespace (options.GlobalNamespace); +- globalUnit.Namespaces.Add (globalNs); ++// globalUnit.Namespaces.Add (globalNs); + + // Global class + +@@ -73,11 +73,7 @@ + warningList.AddRange (initContext.Warnings); + + // Generate the code +- +- if (options.UsePartialClasses) +- CodeGeneratorPartialClass.GenerateProjectGuiCode (globalUnit, globalNs, globalType, options, units, projects, warningList); +- else +- CodeGeneratorInternalClass.GenerateProjectGuiCode (globalUnit, globalNs, globalType, options, units, projects, warningList); ++ CodeGeneratorPartialClass.GenerateProjectGuiCode (globalNs, globalType, options, units, projects, warningList); + + GenerateProjectActionsCode (globalNs, options, projects); + +@@ -108,6 +104,19 @@ + initMethod.Statements.Clear (); + initMethod.Statements.Add (initCondition); + ++ //create separate compilation unit for each type in the global namespace ++ //and insert them at the begining of the units list. ++ int index = 0; ++ foreach (CodeTypeDeclaration type in globalNs.Types) ++ { ++ SteticCompilationUnit unit = new SteticCompilationUnit (type.Name); ++ CodeNamespace ns = new CodeNamespace (globalNs.Name); ++ ++ ns.Types.Add (type); ++ unit.Namespaces.Add (ns); ++ units.Insert (index++, unit); ++ } ++ + return new CodeGenerationResult (units.ToArray (), (string[]) warningList.ToArray (typeof(string))); + } + +@@ -116,26 +125,11 @@ + foreach (Signal signal in wrapper.Signals) { + SignalDescriptor descriptor = signal.SignalDescriptor; + +- CodeExpression createDelegate; ++ CodeExpression createDelegate = new CodeDelegateCreateExpression ( ++ new CodeTypeReference (descriptor.HandlerTypeName, CodeTypeReferenceOptions.GlobalReference), ++ new CodeThisReferenceExpression (), ++ signal.Handler); + +- if (options.UsePartialClasses) { +- createDelegate = +- new CodeDelegateCreateExpression ( +- new CodeTypeReference (descriptor.HandlerTypeName, CodeTypeReferenceOptions.GlobalReference), +- new CodeThisReferenceExpression (), +- signal.Handler); +- } else { +- createDelegate = +- new CodeMethodInvokeExpression ( +- new CodeTypeReferenceExpression (new CodeTypeReference (typeof(Delegate), CodeTypeReferenceOptions.GlobalReference)), +- "CreateDelegate", +- new CodeTypeOfExpression (descriptor.HandlerTypeName), +- targetObjectVar, +- new CodePrimitiveExpression (signal.Handler)); +- +- createDelegate = new CodeCastExpression (descriptor.HandlerTypeName.ToGlobalTypeRef (), createDelegate); +- } +- + CodeAttachEventStatement cevent = new CodeAttachEventStatement ( + new CodeEventReferenceExpression ( + map.GetWidgetExp (wrapper), +@@ -374,7 +368,7 @@ + if (memberName == null) + return base.GenerateInstanceExpression (wrapper, newObject); + +- if (Options.UsePartialClasses) { ++// if (Options.UsePartialClasses) { + // Don't generate fields for top level widgets and for widgets accessible + // through other widget's properties + Wrapper.Widget ww = wrapper as Wrapper.Widget; +@@ -399,19 +393,19 @@ + return var; + } else + return base.GenerateInstanceExpression (wrapper, newObject); +- } else { +- CodeExpression var = base.GenerateInstanceExpression (wrapper, newObject); +- Statements.Add ( +- new CodeAssignStatement ( +- new CodeIndexerExpression ( +- new CodeVariableReferenceExpression ("bindings"), +- new CodePrimitiveExpression (memberName) +- ), +- var +- ) +- ); +- return var; +- } ++// } else { ++// CodeExpression var = base.GenerateInstanceExpression (wrapper, newObject); ++// Statements.Add ( ++// new CodeAssignStatement ( ++// new CodeIndexerExpression ( ++// new CodeVariableReferenceExpression ("bindings"), ++// new CodePrimitiveExpression (memberName) ++// ), ++// var ++// ) ++// ); ++// return var; ++// } + } + } + +@@ -429,5 +423,10 @@ + get { return name; } + internal set { name = value; } + } ++ ++ public CodeNamespace Namespace ++ { ++ get { return (Namespaces.Count > 0) ? Namespaces [0] : null; } ++ } + } + } +Index: libsteticui/CodeGeneratorPartialClass.cs +=================================================================== +--- libsteticui/CodeGeneratorPartialClass.cs (revision 17) ++++ libsteticui/CodeGeneratorPartialClass.cs (working copy) +@@ -11,32 +11,47 @@ + { + internal static class CodeGeneratorPartialClass + { +- public static void GenerateProjectGuiCode (SteticCompilationUnit globalUnit, CodeNamespace globalNs, CodeTypeDeclaration globalType, GenerationOptions options, List<SteticCompilationUnit> units, ProjectBackend[] projects, ArrayList warnings) ++ public static void GenerateProjectGuiCode (CodeNamespace globalNs, CodeTypeDeclaration globalType, GenerationOptions options, List<SteticCompilationUnit> units, ProjectBackend[] projects, ArrayList warnings) + { + // Generate code for each project + foreach (ProjectBackend gp in projects) { + + // Generate top levels +- foreach (Gtk.Widget w in gp.Toplevels) +- GenerateWidgetCode (globalUnit, globalNs, options, units, w, warnings); ++ foreach (Gtk.Widget w in gp.Toplevels) { ++ Stetic.Wrapper.Widget wwidget = Stetic.Wrapper.Widget.Lookup (w); ++ string topLevelName = wwidget.Name; ++ if (gp.ComponentNeedsCodeGeneration (topLevelName)) { ++ //designer file for widget could be changed beyond stetic process ++ //and we nead update wrapper before code generation ++ //during reloading wrappered widget w could be changed; ++ Gtk.Widget currentw = w; ++ if (gp.ReloadTopLevel (topLevelName)) { ++ currentw = gp.GetWidget (topLevelName); ++ } ++ GenerateWidgetCode (globalNs, options, units, currentw, warnings); ++ } ++ } + + // Generate global action groups +- foreach (Wrapper.ActionGroup agroup in gp.ActionGroups) +- GenerateGlobalActionGroupCode (globalUnit, globalNs, options, units, agroup, warnings); ++ foreach (Wrapper.ActionGroup agroup in gp.ActionGroups) { ++ string groupName = agroup.Name; ++ if (gp.ComponentNeedsCodeGeneration (groupName)) { ++ //designer file for action group could be changed beyond stetic process ++ //and we nead update wrapper ++ gp.ReloadActionGroup (groupName); ++ GenerateGlobalActionGroupCode (globalNs, options, units, agroup, warnings); ++ } ++ } + } + } + +- static CodeTypeDeclaration CreatePartialClass (SteticCompilationUnit globalUnit, List<SteticCompilationUnit> units, GenerationOptions options, string name) ++ static CodeTypeDeclaration CreatePartialClass (List<SteticCompilationUnit> units, GenerationOptions options, string name) + { + SteticCompilationUnit unit; +- +- if (options.GenerateSingleFile) +- unit = globalUnit; +- else { +- unit = new SteticCompilationUnit (name); +- units.Add (unit); +- } +- ++ ++ unit = new SteticCompilationUnit (name); ++ units.Add (unit); ++ + string ns = ""; + int i = name.LastIndexOf ('.'); + if (i != -1) { +@@ -56,11 +71,11 @@ + } + + +- static void GenerateWidgetCode (SteticCompilationUnit globalUnit, CodeNamespace globalNs, GenerationOptions options, List<SteticCompilationUnit> units, Gtk.Widget w, ArrayList warnings) ++ static void GenerateWidgetCode (CodeNamespace globalNs, GenerationOptions options, List<SteticCompilationUnit> units, Gtk.Widget w, ArrayList warnings) + { + // Generate the build method + +- CodeTypeDeclaration type = CreatePartialClass (globalUnit, units, options, w.Name); ++ CodeTypeDeclaration type = CreatePartialClass (units, options, w.Name); + CodeMemberMethod met = new CodeMemberMethod (); + met.Name = "Build"; + type.Members.Add (met); +@@ -107,9 +122,9 @@ + } + + +- static void GenerateGlobalActionGroupCode (SteticCompilationUnit globalUnit, CodeNamespace globalNs, GenerationOptions options, List<SteticCompilationUnit> units, Wrapper.ActionGroup agroup, ArrayList warnings) ++ static void GenerateGlobalActionGroupCode (CodeNamespace globalNs, GenerationOptions options, List<SteticCompilationUnit> units, Wrapper.ActionGroup agroup, ArrayList warnings) + { +- CodeTypeDeclaration type = CreatePartialClass (globalUnit, units, options, agroup.Name); ++ CodeTypeDeclaration type = CreatePartialClass (units, options, agroup.Name); + + // Generate the build method + +Index: libsteticui/WidgetDesigner.cs +=================================================================== +--- libsteticui/WidgetDesigner.cs (revision 17) ++++ libsteticui/WidgetDesigner.cs (working copy) +@@ -1,4 +1,3 @@ +- + using System; + using System.Collections; + +@@ -14,17 +13,14 @@ + Component rootWidget; + + Project project; +- Project editedProject; + int reloadCount; + + string componentName; +- bool autoCommitChanges; + bool disposed; + + bool canCut, canCopy, canPaste, canDelete; + + public event EventHandler BindField; +- public event EventHandler ModifiedChanged; + public event EventHandler Changed; + public event EventHandler SelectionChanged; + public event EventHandler RootComponentChanged; +@@ -34,26 +30,18 @@ + public event ComponentNameEventHandler ComponentNameChanged; + public event EventHandler ComponentTypesChanged; + +- internal WidgetDesigner (Project project, string componentName, bool autoCommitChanges): base (project.App) ++ internal WidgetDesigner (Project project, string componentName): base (project.App) + { + this.componentName = componentName; +- this.autoCommitChanges = autoCommitChanges; + this.project = project; + frontend = new WidgetDesignerFrontend (this); + +- if (autoCommitChanges) +- editedProject = project; +- else +- editedProject = new Project (project.App, project.DesignInfo); +- +- editedProject.SignalAdded += OnSignalAdded; +- editedProject.SignalRemoved += OnSignalRemoved; +- editedProject.SignalChanged += OnSignalChanged; +- editedProject.ComponentNameChanged += OnComponentNameChanged; +- editedProject.ComponentTypesChanged += OnComponentTypesChanged; +- ++ project.SignalAdded += OnSignalAdded; ++ project.SignalRemoved += OnSignalRemoved; ++ project.SignalChanged += OnSignalChanged; ++ project.ComponentNameChanged += OnComponentNameChanged; ++ project.ComponentTypesChanged += OnComponentTypesChanged; + project.BackendChanged += OnProjectBackendChanged; +- editedProject.BackendChanged += OnProjectBackendChanged; + + CreateSession (); + } +@@ -70,8 +58,8 @@ + { + if (!disposed) { + ArrayList types = new ArrayList (); +- types.AddRange (editedProject.GetComponentTypes ()); +- ++ types.AddRange (project.GetComponentTypes ()); ++ + // Add actions from the local action groups + + WidgetComponent c = rootWidget as WidgetComponent; +@@ -90,12 +78,14 @@ + public void BeginComponentDrag (ComponentType type, Gtk.Widget source, Gdk.DragContext ctx) + { + Stetic.ObjectWrapper wrapper = type.Action != null ? (Stetic.ObjectWrapper) type.Action.Backend : null; +- app.Backend.BeginComponentDrag (editedProject.ProjectBackend, type.Description, type.ClassName, wrapper, source, ctx, null); ++ app.Backend.BeginComponentDrag (project.ProjectBackend, type.Description, type.ClassName, wrapper, source, ctx, null); ++ + } + + public void BeginComponentDrag (string title, string className, Gtk.Widget source, Gdk.DragContext ctx, ComponentDropCallback callback) + { +- app.Backend.BeginComponentDrag (editedProject.ProjectBackend, title, className, null, source, ctx, callback); ++ app.Backend.BeginComponentDrag (project.ProjectBackend, title, className, null, source, ctx, callback); ++ + } + + // Creates an action group designer for the widget being edited by this widget designer +@@ -103,7 +93,8 @@ + { + if (disposed) + throw new ObjectDisposedException ("WidgetDesigner"); +- return new ActionGroupDesigner (editedProject, componentName, null, this, true); ++ return new ActionGroupDesigner (project, componentName, null, this, true); ++ + } + + public bool Modified { +@@ -113,7 +104,7 @@ + internal override void SetActive () + { + if (!disposed) +- project.App.SetActiveDesignSession (editedProject, session); ++ project.App.SetActiveDesignSession (project, session); + } + + public bool AllowWidgetBinding { +@@ -125,8 +116,8 @@ + } + + public ImportFileDelegate ImportFileCallback { +- get { return editedProject.ImportFileCallback; } +- set { editedProject.ImportFileCallback = value; } ++ get { return project.ImportFileCallback; } ++ set { project.ImportFileCallback = value; } + } + + public object SaveStatus () +@@ -142,7 +133,7 @@ + void CreateSession () + { + try { +- session = project.ProjectBackend.CreateWidgetDesignerSession (frontend, componentName, editedProject.ProjectBackend, autoCommitChanges); ++ session = project.ProjectBackend.CreateWidgetDesignerSession (frontend, componentName); + ResetCustomWidget (); + rootWidget = app.GetComponent (session.RootWidget, null, null); + } catch (Exception ex) { +@@ -232,27 +223,23 @@ + if (disposed) + return; + +- if (project.App.ActiveProject == editedProject) ++ if (project.App.ActiveProject == project) + project.App.ActiveProject = null; + + disposed = true; + frontend.disposed = true; +- editedProject.SignalAdded -= OnSignalAdded; +- editedProject.SignalRemoved -= OnSignalRemoved; +- editedProject.SignalChanged -= OnSignalChanged; +- editedProject.ComponentNameChanged -= OnComponentNameChanged; +- editedProject.BackendChanged -= OnProjectBackendChanged; +- editedProject.ComponentTypesChanged -= OnComponentTypesChanged; ++ project.SignalAdded -= OnSignalAdded; ++ project.SignalRemoved -= OnSignalRemoved; ++ project.SignalChanged -= OnSignalChanged; ++ project.ComponentNameChanged -= OnComponentNameChanged; ++ project.ComponentTypesChanged -= OnComponentTypesChanged; + project.BackendChanged -= OnProjectBackendChanged; + + if (session != null) { + session.Dispose (); + session = null; + } +- +- if (!autoCommitChanges) +- editedProject.Dispose (); +- ++ + System.Runtime.Remoting.RemotingServices.Disconnect (frontend); + frontend = null; + rootWidget = null; +@@ -309,10 +296,10 @@ + if (++reloadCount == 2) { + object sessionData = null; + +- if (oldBackend != null && !autoCommitChanges) { +- sessionData = session.SaveState (); +- session.DestroyWrapperWidgetPlug (); +- } ++// if (oldBackend != null && !autoCommitChanges) { ++// sessionData = session.SaveState (); ++// session.DestroyWrapperWidgetPlug (); ++// } + + // Don't dispose the session here, since it will dispose + // the underlying project, and we can't do it because +@@ -359,12 +346,6 @@ + BindField (this, EventArgs.Empty); + } + +- internal void NotifyModifiedChanged () +- { +- if (ModifiedChanged != null) +- ModifiedChanged (this, EventArgs.Empty); +- } +- + internal void NotifyChanged () + { + if (Changed != null) +@@ -405,13 +386,6 @@ + ); + } + +- public void NotifyModifiedChanged () +- { +- GuiDispatch.InvokeSync ( +- delegate { if (!disposed) designer.NotifyModifiedChanged (); } +- ); +- } +- + public void NotifyChanged () + { + GuiDispatch.InvokeSync ( +Index: libsteticui/Makefile.am +=================================================================== +--- libsteticui/Makefile.am (revision 17) ++++ libsteticui/Makefile.am (working copy) +@@ -21,7 +21,6 @@ + CecilWidgetLibrary.cs \ + CodeGenerationResult.cs \ + CodeGenerator.cs \ +- CodeGeneratorInternalClass.cs \ + CodeGeneratorPartialClass.cs \ + Component.cs \ + ComponentEventHandler.cs \ +@@ -83,6 +82,7 @@ + $(GLADE_SHARP_LIBS) \ + $(GLIB_SHARP_LIBS) \ + $(GTK_SHARP_LIBS) \ ++ -pkg:monodevelop \ + -r:Mono.Posix \ + -r:System \ + -r:System.Core \ +Index: libsteticui/Project.cs +=================================================================== +--- libsteticui/Project.cs (revision 17) ++++ libsteticui/Project.cs (working copy) +@@ -12,7 +12,8 @@ + { + Application app; + ProjectBackend backend; +- string fileName; ++ //string fileName; ++ string folderName; + IResourceProvider resourceProvider; + Component selection; + string tmpProjectFile; +@@ -72,8 +73,8 @@ + backend.SetFrontend (this); + if (resourceProvider != null) + backend.ResourceProvider = resourceProvider; +- if (fileName != null) +- backend.Load (fileName); ++ if (folderName != null) ++ backend.Load (folderName); + } + return backend; + } +@@ -114,9 +115,9 @@ + return null; + } + +- public string FileName { +- get { return fileName; } +- } ++// public string FileName { ++// get { return fileName; } ++// } + + public IResourceProvider ResourceProvider { + get { return resourceProvider; } +@@ -161,41 +162,16 @@ + backend.Close (); + } + +- public void Load (string fileName) ++ public void Load (string folderName) + { +- this.fileName = fileName; ++ this.folderName = folderName; + if (backend != null) +- backend.Load (fileName); ++ backend.Load (folderName); + +- using (StreamReader sr = new StreamReader (fileName)) { +- XmlTextReader reader = new XmlTextReader (sr); ++ foreach (string basePath in DesignInfo.GetComponentFolders ()) { ++ if (!Directory.Exists (basePath)) ++ continue; + +- reader.MoveToContent (); +- if (reader.IsEmptyElement) +- return; +- +- reader.ReadStartElement ("stetic-interface"); +- if (reader.IsEmptyElement) +- return; +- while (reader.NodeType != XmlNodeType.EndElement) { +- if (reader.NodeType == XmlNodeType.Element) { +- if (reader.LocalName == "widget") +- ReadWidget (reader); +- else if (reader.LocalName == "action-group") +- ReadActionGroup (reader); +- else +- reader.Skip (); +- } +- else { +- reader.Skip (); +- } +- reader.MoveToContent (); +- } +- } +- +-// string basePath = fileName != null ? Path.GetDirectoryName (fileName) : null; +- +- foreach (string basePath in DesignInfo.GetComponentFolders ()) { + DirectoryInfo dir = new DirectoryInfo (basePath); + + foreach (FileInfo file in dir.GetFiles ()) { +@@ -257,11 +233,21 @@ + reader.Skip (); + } + +- public void Save (string fileName) ++ public void ConvertProject (string oldSteticFileName, string newGuiFolderName) + { +- this.fileName = fileName; ++ //ProjectBackend property when created invokes Load method which is not valid ++ //for old file layout ++ ++ ProjectBackend backend = app.Backend.CreateProject (); ++ backend.SetFrontend (this); ++ backend.ConvertProject (oldSteticFileName, newGuiFolderName); ++ } ++ ++ public void Save (string folderName) ++ { ++ this.folderName = folderName; + if (backend != null) +- backend.Save (fileName); ++ backend.Save (folderName); + } + + public void ImportGlade (string fileName) +@@ -274,31 +260,6 @@ + ProjectBackend.ExportGlade (fileName); + } + +- public object SaveStatus () +- { +- return ProjectBackend.SaveStatus (); +- } +- +- public void LoadStatus (object status) +- { +- ProjectBackend.LoadStatus (status); +- } +- +- public bool Modified { +- get { +- if (backend != null) +- return backend.Modified; +- else +- return modified; +- } +- set { +- if (backend != null) +- backend.Modified = value; +- else +- modified = true; +- } +- } +- + public IEnumerable<WidgetInfo> Widgets { + get { return widgets; } + } +@@ -323,9 +284,14 @@ + return null; + } + +- public WidgetDesigner CreateWidgetDesigner (WidgetInfo widgetInfo, bool autoCommitChanges) ++// public WidgetDesigner CreateWidgetDesigner (WidgetInfo widgetInfo, bool autoCommitChanges) ++// { ++// return new WidgetDesigner (this, widgetInfo.Name, autoCommitChanges); ++// } ++ ++ public WidgetDesigner CreateWidgetDesigner (WidgetInfo widgetInfo) + { +- return new WidgetDesigner (this, widgetInfo.Name, autoCommitChanges); ++ return new WidgetDesigner (this, widgetInfo.Name); + } + + public ActionGroupDesigner CreateActionGroupDesigner (ActionGroupInfo actionGroup, bool autoCommitChanges) +@@ -341,7 +307,7 @@ + if (wi == null) { + wi = new WidgetInfo (this, wc); + widgets.Add (wi); +- } ++ } + return wi; + } + +@@ -357,6 +323,36 @@ + return wi; + } + ++ public object AddNewComponent (string fileName) ++ { ++ object ob = ProjectBackend.AddNewComponent (fileName); ++ object component = App.GetComponent (ob, null, null); ++ ++ if (component is WidgetComponent) { ++ var wc = (WidgetComponent) component; ++ WidgetInfo wi = GetWidget (wc.Name); ++ if (wi == null) { ++ wi = new WidgetInfo (this, wc); ++ widgets.Add (wi); ++ } ++ return wi; ++ } ++ ++ if (component is ActionGroupComponent) { ++ var ac = (ActionGroupComponent) component; ++ // Don't wait for the group added event to come to update the groups list since ++ // it may be too late. ++ ActionGroupInfo gi = GetActionGroup (ac.Name); ++ if (gi == null) { ++ gi = new ActionGroupInfo (this, ac.Name); ++ groups.Add (gi); ++ } ++ return gi; ++ } ++ ++ return null; ++ } ++ + public ComponentType[] GetComponentTypes () + { + ArrayList types = new ArrayList (); +@@ -574,7 +570,7 @@ + ); + } + +- internal void NotifyChanged () ++ internal void NotifyChanged (string rootWidgetName) + { + GuiDispatch.InvokeSync ( + delegate { +@@ -582,10 +578,14 @@ + Changed (this, EventArgs.Empty); + + // TODO: Optimize +- foreach (ProjectItemInfo it in widgets) +- it.NotifyChanged (); +- foreach (ProjectItemInfo it in groups) +- it.NotifyChanged (); ++ foreach (ProjectItemInfo it in widgets) { ++ if (it.Name == rootWidgetName) ++ it.NotifyChanged (); ++ } ++ foreach (ProjectItemInfo it in groups) { ++ if (it.Name == rootWidgetName) ++ it.NotifyChanged (); ++ } + } + ); + } +@@ -732,11 +732,12 @@ + backend.SetFrontend (this); + + if (tmpProjectFile != null && File.Exists (tmpProjectFile)) { +- backend.Load (tmpProjectFile, fileName); ++// backend.Load (tmpProjectFile, fileName); ++ throw new NotImplementedException ("OnBackendChanged"); + File.Delete (tmpProjectFile); + tmpProjectFile = null; +- } else if (fileName != null) { +- backend.Load (fileName); ++ } else if (folderName != null) { ++ backend.Load (folderName); + } + + if (resourceProvider != null) +Index: libsteticui/Application.cs +=================================================================== +--- libsteticui/Application.cs (revision 17) ++++ libsteticui/Application.cs (working copy) +@@ -308,14 +308,14 @@ + UpdateWidgetLibraries (false, false); + } + +- public Project LoadProject (string path, IProjectDesignInfo info) +- { +- Project p = new Project (this, info); +- p.Load (path); +- projects.Add (p); +- p.Disposed += ProjectDisposed; +- return p; +- } ++// public Project LoadProject (string path, IProjectDesignInfo info) ++// { ++// Project p = new Project (this, info); ++// p.Load (path); ++// projects.Add (p); ++// p.Disposed += ProjectDisposed; ++// return p; ++// } + + public Project CreateProject (IProjectDesignInfo info) + { +Index: libsteticui/CodeGeneratorInternalClass.cs +=================================================================== +--- libsteticui/CodeGeneratorInternalClass.cs (revision 17) ++++ libsteticui/CodeGeneratorInternalClass.cs (working copy) +@@ -1,319 +0,0 @@ +- +-using System; +-using System.Reflection; +-using System.CodeDom; +-using System.CodeDom.Compiler; +-using System.Collections.Generic; +-using System.IO; +-using System.Xml.Serialization; +-using System.Collections; +- +-namespace Stetic +-{ +- internal static class CodeGeneratorInternalClass +- { +- static CodeExpression bindingFlags; +- +- static CodeGeneratorInternalClass () +- { +- CodeTypeReferenceExpression flagsType = new CodeTypeReferenceExpression (new CodeTypeReference ("System.Reflection.BindingFlags", CodeTypeReferenceOptions.GlobalReference)); +- 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 GenerateProjectGuiCode (SteticCompilationUnit globalUnit, CodeNamespace globalNs, CodeTypeDeclaration globalType, GenerationOptions options, List<SteticCompilationUnit> units, ProjectBackend[] projects, ArrayList warnings) +- { +- bool multiProject = projects.Length > 1; +- +- // Build method overload that takes a type as parameter. +- +- CodeMemberMethod met = new CodeMemberMethod (); +- met.Name = "Build"; +- globalType.Members.Add (met); +- met.Parameters.Add (new CodeParameterDeclarationExpression (typeof(object), "cobj")); +- met.Parameters.Add (new CodeParameterDeclarationExpression (typeof(Type), "type")); +- if (multiProject) +- met.Parameters.Add (new CodeParameterDeclarationExpression (typeof(string), "file")); +- met.ReturnType = new CodeTypeReference (typeof(void)); +- met.Attributes = MemberAttributes.Public | MemberAttributes.Static; +- +- CodeMethodInvokeExpression call = new CodeMethodInvokeExpression ( +- new CodeMethodReferenceExpression ( +- new CodeTypeReferenceExpression (new CodeTypeReference (globalNs.Name + ".Gui", CodeTypeReferenceOptions.GlobalReference)), +- "Build" +- ), +- new CodeArgumentReferenceExpression ("cobj"), +- new CodePropertyReferenceExpression ( +- new CodeArgumentReferenceExpression ("type"), +- "FullName" +- ) +- ); +- if (multiProject) +- call.Parameters.Add (new CodeArgumentReferenceExpression ("file")); +- +- met.Statements.Add (call); +- +- // Generate the build method +- +- met = new CodeMemberMethod (); +- met.Name = "Build"; +- globalType.Members.Add (met); +- +- met.Parameters.Add (new CodeParameterDeclarationExpression (typeof(object), "cobj")); +- 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; +- +- if (options.GenerateEmptyBuildMethod) +- return; +- +- CodeArgumentReferenceExpression cobj = new CodeArgumentReferenceExpression ("cobj"); +- CodeArgumentReferenceExpression cfile = new CodeArgumentReferenceExpression ("file"); +- CodeArgumentReferenceExpression cid = new CodeArgumentReferenceExpression ("id"); +- +- CodeStatementCollection projectCol = met.Statements; +- +- CodeConditionStatement tcond = new CodeConditionStatement (); +- tcond.Condition = new CodeMethodInvokeExpression (new CodeTypeOfExpression (typeof(Gtk.Widget)), "IsAssignableFrom", cobj); +- +- tcond.TrueStatements.Add ( +- new CodeMethodInvokeExpression ( +- new CodeTypeReferenceExpression (new CodeTypeReference (globalNs.Name + ".Gui", CodeTypeReferenceOptions.GlobalReference)), +- "Initialize", +- cobj +- ) +- ); +- +- // Generate code for each project +- +- foreach (ProjectBackend 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; +- } +- +- // Generate top levels +- +- CodeIdentifiers ids = new CodeIdentifiers (); +- +- 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); +- +- GenerateComponentCode (w, globalUnit, globalNs, cobj, cond.TrueStatements, globalType, options, units, ids, warnings); +- +- widgetCol = cond.FalseStatements; +- } +- +- // Generate action groups +- +- foreach (Wrapper.ActionGroup agroup in gp.ActionGroups) { +- CodeConditionStatement cond = new CodeConditionStatement (); +- cond.Condition = new CodeBinaryOperatorExpression ( +- cid, +- CodeBinaryOperatorType.IdentityEquality, +- new CodePrimitiveExpression (agroup.Name) +- ); +- widgetCol.Add (cond); +- +- GenerateComponentCode (agroup, globalUnit, globalNs, cobj, cond.TrueStatements, globalType, options, units, ids, warnings); +- +- widgetCol = cond.FalseStatements; +- } +- } +- } +- +- static CodeMemberMethod GetBuildMethod (string name, string internalClassName, string typeName, SteticCompilationUnit globalUnit, GenerationOptions options, List<SteticCompilationUnit> units) +- { +- SteticCompilationUnit unit; +- +- if (options.GenerateSingleFile) +- unit = globalUnit; +- else { +- unit = new SteticCompilationUnit (name); +- units.Add (unit); +- } +- +- CodeTypeDeclaration type = new CodeTypeDeclaration (internalClassName); +- type.Attributes = MemberAttributes.Private; +- type.TypeAttributes = TypeAttributes.NestedAssembly; +- +- CodeNamespace cns = new CodeNamespace (options.GlobalNamespace + ".SteticGenerated"); +- cns.Types.Add (type); +- unit.Namespaces.Add (cns); +- +- // Create the build method for the component +- +- CodeMemberMethod met = new CodeMemberMethod (); +- met.Name = "Build"; +- type.Members.Add (met); +- +- met.Parameters.Add (new CodeParameterDeclarationExpression (new CodeTypeReference (typeName), "cobj")); +- met.ReturnType = new CodeTypeReference (typeof(void)); +- met.Attributes = MemberAttributes.Public | MemberAttributes.Static; +- +- return met; +- } +- +- static void GenerateComponentCode (object component, SteticCompilationUnit globalUnit, CodeNamespace globalNs, CodeExpression cobj, CodeStatementCollection statements, CodeTypeDeclaration globalType, GenerationOptions options, List<SteticCompilationUnit> units, CodeIdentifiers ids, ArrayList warnings) +- { +- Gtk.Widget widget = component as Gtk.Widget; +- Wrapper.Widget wwidget = Stetic.Wrapper.Widget.Lookup (widget); +- Wrapper.ActionGroup agroup = component as Wrapper.ActionGroup; +- +- string name = widget != null ? widget.Name : agroup.Name; +- string internalClassName = ids.MakeUnique (CodeIdentifier.MakeValid (name)); +- +- string typeName = widget != null ? wwidget.WrappedTypeName : "Gtk.ActionGroup"; +- // Create the build method for the top level +- +- CodeMemberMethod met; +- met = GetBuildMethod (name, internalClassName, typeName, globalUnit, options, units); +- +- // Generate the build code +- +- CodeVariableDeclarationStatement varDecHash = new CodeVariableDeclarationStatement (typeof(System.Collections.Hashtable).ToGlobalTypeRef (), "bindings"); +- met.Statements.Add (varDecHash); +- varDecHash.InitExpression = new CodeObjectCreateExpression ( +- typeof(System.Collections.Hashtable), +- new CodeExpression [0] +- ); +- +- CodeVariableReferenceExpression targetObjectVar = new CodeVariableReferenceExpression ("cobj"); +- Stetic.WidgetMap map; +- +- if (widget != null) { +- map = Stetic.CodeGenerator.GenerateCreationCode (globalNs, globalType, widget, targetObjectVar, met.Statements, options, warnings); +- CodeGenerator.BindSignalHandlers (targetObjectVar, wwidget, map, met.Statements, options); +- } else { +- map = Stetic.CodeGenerator.GenerateCreationCode (globalNs, globalType, agroup, targetObjectVar, met.Statements, options, warnings); +- foreach (Wrapper.Action ac in agroup.Actions) +- CodeGenerator.BindSignalHandlers (targetObjectVar, ac, map, met.Statements, options); +- } +- +- GenerateBindFieldCode (met.Statements, cobj); +- +- // Add a method call to the build method +- +- statements.Add ( +- new CodeMethodInvokeExpression ( +- new CodeTypeReferenceExpression (new CodeTypeReference (options.GlobalNamespace + ".SteticGenerated." + internalClassName, CodeTypeReferenceOptions.GlobalReference)), +- "Build", +- new CodeCastExpression (typeName.ToGlobalTypeRef (), cobj) +- ) +- ); +- } +- +- static void GenerateBindFieldCode (CodeStatementCollection statements, CodeExpression cobj) +- { +- // 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[]).ToGlobalTypeRef (), "fields"); +- varDecArray.InitExpression = new CodeMethodInvokeExpression ( +- new CodeMethodInvokeExpression ( +- cobj, +- "GetType", +- new CodeExpression [0] +- ), +- "GetFields", +- bindingFlags +- ); +- statements.Add (varDecArray); +- CodeVariableReferenceExpression varArray = new CodeVariableReferenceExpression ("fields"); +- +- CodeIterationStatement iteration = new CodeIterationStatement (); +- 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).ToGlobalTypeRef (), "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 ("bindings"), +- 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 +- ) +- ); +- } +- } +-} +Index: libsteticui/Glade.cs +=================================================================== +--- libsteticui/Glade.cs (revision 17) ++++ libsteticui/Glade.cs (working copy) +@@ -17,7 +17,6 @@ + doc.PreserveWhitespace = true; + doc.XmlResolver = null; + doc.Load (filename); +- project.SetFileName (filename); + project.Id = System.IO.Path.GetFileName (filename); + doc = GladeUtils.XslImportTransform (doc); + +@@ -27,7 +26,7 @@ + + ObjectReader reader = new ObjectReader (project, FileFormat.Glade); + foreach (XmlElement toplevel in node.SelectNodes ("widget")) { +- Wrapper.Container wrapper = Stetic.ObjectWrapper.ReadObject (reader, toplevel) as Wrapper.Container; ++ Wrapper.Container wrapper = Stetic.ObjectWrapper.ReadObject (reader, toplevel, null) as Wrapper.Container; + if (wrapper != null) + project.AddWidget ((Gtk.Widget)wrapper.Wrapped); + } +Index: libstetic/IProject.cs +=================================================================== +--- libstetic/IProject.cs (revision 17) ++++ libstetic/IProject.cs (working copy) +@@ -4,15 +4,16 @@ + { + public interface IProject + { +- string FileName { get; } ++ //string FileName { get; } ++ string FolderName { get; } + Gtk.Widget[] Toplevels { get; } +- Gtk.Widget GetTopLevel (string name); ++ Gtk.Widget GetWidget (string name); + Gtk.Widget Selection { get; set; } + Wrapper.ActionGroupCollection ActionGroups { get; } + ProjectIconFactory IconFactory { get; } + string ImagesRootPath { get; } + string TargetGtkVersion { get; } +- bool Modified { get; set; } ++// bool Modified { get; set; } + IResourceProvider ResourceProvider { get; set; } + + void PopupContextMenu (Stetic.Wrapper.Widget wrapper); +Index: libstetic/editor/ChangeLog +=================================================================== +--- libstetic/editor/ChangeLog (revision 0) ++++ libstetic/editor/ChangeLog (revision 111) +@@ -0,0 +1,16 @@ ++2010-08-07 Krzysztof Marecki <marecki.krzysztof@gmail.com> ++ ++ * SelectIconDialog.cs: Remove setting Project.Modified property ++ * EditIconFactoryDialog.cs: Remove setting Project.Modified property ++ ++2010-08-03 Krzysztof Marecki <marecki.krzysztof@gmail.com> ++ ++ * ActionMenu.cs: Pass root wrapper as an argument for ObjectWrapper.Create ++ * ActionToolbar.cs: ++ * ActionMenuBar.cs: ++ * ActionGroupEditor.cs: ++ ++2010-06-07 Krzysztof Marecki <marecki.krzysztof@gmail.com> ++ ++ * SelectImageDialog.cs: ++ +Index: libstetic/editor/EditIconFactoryDialog.cs +=================================================================== +--- libstetic/editor/EditIconFactoryDialog.cs (revision 17) ++++ libstetic/editor/EditIconFactoryDialog.cs (working copy) +@@ -53,7 +53,7 @@ + iconFactory.Icons.Add (icon); + customIconList.Refresh (); + customIconList.Selection = icon.Name; +- project.Modified = true; ++// project.Modified = true; + } + } + } +@@ -69,7 +69,7 @@ + if (md.Run () == (int) Gtk.ResponseType.Yes) { + iconFactory.Icons.Remove (icon); + customIconList.Refresh (); +- project.Modified = true; ++// project.Modified = true; + } + md.Destroy (); + } +@@ -86,7 +86,7 @@ + if (dlg.Run () == (int) Gtk.ResponseType.Ok) { + customIconList.Refresh (); + customIconList.Selection = icon.Name; +- project.Modified = true; ++// project.Modified = true; + } + } + } +Index: libstetic/editor/SelectIconDialog.cs +=================================================================== +--- libstetic/editor/SelectIconDialog.cs (revision 17) ++++ libstetic/editor/SelectIconDialog.cs (working copy) +@@ -137,7 +137,7 @@ + project.IconFactory.Icons.Add (icon); + customIconList.Refresh (); + customIconList.Selection = icon.Name; +- project.Modified = true; ++// project.Modified = true; + } + } + } +@@ -153,7 +153,7 @@ + if (md.Run () == (int) Gtk.ResponseType.Yes) { + project.IconFactory.Icons.Remove (icon); + customIconList.Refresh (); +- project.Modified = true; ++// project.Modified = true; + } + md.Destroy (); + } +@@ -170,7 +170,7 @@ + if (dlg.Run () == (int) Gtk.ResponseType.Ok) { + customIconList.Refresh (); + customIconList.Selection = icon.Name; +- project.Modified = true; ++// project.Modified = true; + } + } + } +Index: libstetic/editor/ActionMenuBar.cs +=================================================================== +--- libstetic/editor/ActionMenuBar.cs (revision 17) ++++ libstetic/editor/ActionMenuBar.cs (working copy) +@@ -258,7 +258,9 @@ + { + Widget wrapper = Widget.Lookup (this); + using (wrapper.UndoManager.AtomicChange) { +- Wrapper.Action ac = (Wrapper.Action) ObjectWrapper.Create (wrapper.Project, new Gtk.Action ("", "", null, null)); ++ Wrapper.Action ac = (Wrapper.Action) ObjectWrapper.Create (wrapper.Project, ++ new Gtk.Action ("", "", null, null), ++ wrapper); + ActionTreeNode node = new ActionTreeNode (Gtk.UIManagerItemType.Menu, "", ac); + actionTree.Children.Insert (pos, node); + +Index: libstetic/editor/ActionMenu.cs +=================================================================== +--- libstetic/editor/ActionMenu.cs (revision 17) ++++ libstetic/editor/ActionMenu.cs (working copy) +@@ -196,7 +196,9 @@ + ActionTreeNode InsertAction (int pos) + { + using (wrapper.UndoManager.AtomicChange) { +- Wrapper.Action ac = (Wrapper.Action) ObjectWrapper.Create (wrapper.Project, new Gtk.Action ("", "", null, null)); ++ Wrapper.Action ac = (Wrapper.Action) ObjectWrapper.Create (wrapper.Project, ++ new Gtk.Action ("", "", null, null), ++ wrapper); + ActionTreeNode newNode = new ActionTreeNode (Gtk.UIManagerItemType.Menuitem, null, ac); + nodes.Insert (pos, newNode); + ActionMenuItem item = FindMenuItem (newNode); +Index: libstetic/editor/SelectImageDialog.cs +=================================================================== +--- libstetic/editor/SelectImageDialog.cs (revision 17) ++++ libstetic/editor/SelectImageDialog.cs (working copy) +@@ -80,7 +80,7 @@ + FillResources (); + resourceList.Selection.Changed += OnResourceSelectionChanged; + +- if (project.FileName != null) ++ if (project.FolderName != null) + fileChooser.SetCurrentFolder (project.ImagesRootPath); + + fileChooser.SelectionChanged += delegate (object s, EventArgs a) { +Index: libstetic/editor/ActionToolbar.cs +=================================================================== +--- libstetic/editor/ActionToolbar.cs (revision 17) ++++ libstetic/editor/ActionToolbar.cs (working copy) +@@ -237,7 +237,9 @@ + { + Widget wrapper = Stetic.Wrapper.Widget.Lookup (this); + using (wrapper.UndoManager.AtomicChange) { +- Wrapper.Action ac = (Wrapper.Action) ObjectWrapper.Create (wrapper.Project, new Gtk.Action ("", "", null, null)); ++ Wrapper.Action ac = (Wrapper.Action) ObjectWrapper.Create (wrapper.Project, ++ new Gtk.Action ("", "", null, null), ++ wrapper); + ActionTreeNode node = new ActionTreeNode (Gtk.UIManagerItemType.Toolitem, "", ac); + actionTree.Children.Insert (pos, node); + +Index: libstetic/editor/ActionGroupEditor.cs +=================================================================== +--- libstetic/editor/ActionGroupEditor.cs (revision 17) ++++ libstetic/editor/ActionGroupEditor.cs (working copy) +@@ -275,7 +275,9 @@ + + void OnAddClicked (object s, Gtk.ButtonPressEventArgs args) + { +- Wrapper.Action ac = (Wrapper.Action) ObjectWrapper.Create (project, new Gtk.Action ("", "", null, null)); ++ Wrapper.Action ac = (Wrapper.Action) ObjectWrapper.Create (project, ++ new Gtk.Action ("", "", null, null), ++ ActionGroup); + ActionMenuItem item = InsertAction (ac, actionGroup.Actions.Count); + item.EditingDone += OnEditDone; + item.Select (); +Index: libstetic/ChangeLog +=================================================================== +--- libstetic/ChangeLog (revision 17) ++++ libstetic/ChangeLog (working copy) +@@ -1,3 +1,40 @@ ++2010-08-15 Krzysztof Marecki <freefirma@gmail.com> ++ ++ * DND.cs: ++ * IProject.cs: ++ ++2010-08-13 Krzysztof Marecki <freefirma@gmail.com> ++ ++ * GeneratorContext.cs: ++ ++2010-08-07 Krzysztof Marecki <marecki.krzysztof@gmail.com> ++ ++ * IProject.cs: Remove Modified property, add WasModified method which check state of a given top level ++ ++2010-08-03 Krzysztof Marecki <marecki.krzysztof@gmail.com> ++ ++ * GladeUtils.cs: Set ObjectWrapper.RootWrapperName when reading from xml ++ * WidgetUtils.cs: ++ * ObjectReader.cs: ++ * ObjectWrapper.cs: ++ * wrapper/Frame.cs: ++ * wrapper/Window.cs: ++ * wrapper/MenuItem.cs: ++ * wrapper/Expander.cs: ++ * undo/UndoManager.cs: ++ * wrapper/Notebook.cs: ++ * wrapper/Container.cs: ++ * wrapper/OptionMenu.cs: ++ ++2010-08-03 Krzysztof Marecki <marecki.krzysztof@gmail.com> ++ ++ * ObjectWrapper.cs: Save a root wrapper name ++ ++2010-06-07 Krzysztof Marecki <marecki.krzysztof@gmail.com> ++ ++ * IProject.cs: ++ * ErrorWidget.cs: ++ + 2010-04-30 Lluis Sanchez Gual <lluis@novell.com> + + * editor/ActionMenu.cs: Explicit destroy of children should +Index: libstetic/GeneratorContext.cs +=================================================================== +--- libstetic/GeneratorContext.cs (revision 17) ++++ libstetic/GeneratorContext.cs (working copy) +@@ -522,11 +522,6 @@ + set { gettextClass = value; } + } + +- public bool UsePartialClasses { +- get { return partialClasses; } +- set { partialClasses = value; } +- } +- + public string Path { + get { return path; } + set { path = value; } +@@ -537,11 +532,6 @@ + set { generateEmptyBuildMethod = value; } + } + +- public bool GenerateSingleFile { +- get { return generateSingleFile; } +- set { generateSingleFile = value; } +- } +- + public string GlobalNamespace { + get { return globalNamespace; } + set { globalNamespace = value; } +Index: libstetic/DND.cs +=================================================================== +--- libstetic/DND.cs (revision 17) ++++ libstetic/DND.cs (working copy) +@@ -181,7 +181,7 @@ + + if (targetWrapper.IsDisposed) { + // The project has been reloaded. Find the wrapper again. +- Gtk.Widget twidget = project.GetTopLevel (tname); ++ Gtk.Widget twidget = project.GetWidget (tname); + ObjectWrapper ow = ObjectWrapper.Lookup (twidget); + if (ow != null) + targetWrapper = ow.FindObjectByUndoId (uid); +Index: libstetic/ObjectReader.cs +=================================================================== +--- libstetic/ObjectReader.cs (revision 17) ++++ libstetic/ObjectReader.cs (working copy) +@@ -25,14 +25,14 @@ + get { return proj; } + } + +- public virtual ObjectWrapper ReadObject (XmlElement elem) ++ public virtual ObjectWrapper ReadObject (XmlElement elem, ObjectWrapper root) + { +- return Stetic.ObjectWrapper.ReadObject (this, elem); ++ return Stetic.ObjectWrapper.ReadObject (this, elem, root); + } + +- public virtual void ReadObject (ObjectWrapper wrapper, XmlElement elem) ++ public virtual void ReadExistingObject (ObjectWrapper wrapper, XmlElement elem) + {
+- Stetic.ObjectWrapper.ReadObject (this, elem, wrapper);
++ Stetic.ObjectWrapper.ReadExistingObject (this, elem, wrapper);
+ } + } + } +Index: libstetic/undo/UndoManager.cs +=================================================================== +--- libstetic/undo/UndoManager.cs (revision 17) ++++ libstetic/undo/UndoManager.cs (working copy) +@@ -227,17 +227,17 @@ + this.undoManager = undoManager; + } + +- public override ObjectWrapper ReadObject (XmlElement elem) ++ public override ObjectWrapper ReadObject (XmlElement elem, ObjectWrapper root) + { +- ObjectWrapper ww = base.ReadObject (elem); ++ ObjectWrapper ww = base.ReadObject (elem, root); + if (ww is Widget) + undoManager.RegisterObject ((Widget)ww, elem); + return ww; + } + +- public override void ReadObject (ObjectWrapper wrapper, XmlElement elem) ++ public override void ReadExistingObject (ObjectWrapper wrapper, XmlElement elem) + { +- base.ReadObject (wrapper, elem); ++ base.ReadExistingObject (wrapper, elem); + if (wrapper is Widget) + undoManager.RegisterObject ((Widget)wrapper, elem); + } +Index: libstetic/ObjectWrapper.cs +=================================================================== +--- libstetic/ObjectWrapper.cs (revision 17) ++++ libstetic/ObjectWrapper.cs (working copy) +@@ -149,10 +149,13 @@ + get { return disposed; } + } + +- public static ObjectWrapper Create (IProject proj, object wrapped) ++ public static ObjectWrapper Create (IProject proj, object wrapped, ObjectWrapper root) + { + ClassDescriptor klass = Registry.LookupClassByName (wrapped.GetType ().FullName); + ObjectWrapper wrapper = klass.CreateWrapper (); ++ if (root != null) { ++ wrapper.RootWrapperName = (root.RootWrapperName != null) ? root.RootWrapperName : root.Name; ++ } + wrapper.Loading = true; + wrapper.proj = proj; + wrapper.classDescriptor = klass; +@@ -180,7 +183,7 @@ + throw new System.NotImplementedException (); + } + +- public static ObjectWrapper ReadObject (ObjectReader reader, XmlElement elem) ++ public static ObjectWrapper ReadObject (ObjectReader reader, XmlElement elem, ObjectWrapper root) + { + string className = elem.GetAttribute ("class"); + ClassDescriptor klass; +@@ -191,24 +194,29 @@ + + if (klass == null) { + ErrorWidget we = new ErrorWidget (className, elem.GetAttribute ("id")); +- ErrorWidgetWrapper wrap = (ErrorWidgetWrapper) Create (reader.Project, we); ++ ErrorWidgetWrapper wrap = (ErrorWidgetWrapper) Create (reader.Project, we, null); + wrap.Read (reader, elem); + return wrap; + } + if (!klass.SupportsGtkVersion (reader.Project.TargetGtkVersion)) { + ErrorWidget we = new ErrorWidget (className, klass.TargetGtkVersion, reader.Project.TargetGtkVersion, elem.GetAttribute ("id")); +- ErrorWidgetWrapper wrap = (ErrorWidgetWrapper) Create (reader.Project, we); ++ ErrorWidgetWrapper wrap = (ErrorWidgetWrapper) Create (reader.Project, we, null); + wrap.Read (reader, elem); + return wrap; + } + + ObjectWrapper wrapper = klass.CreateWrapper (); ++ if (root != null) { ++ if (root.RootWrapperName != null) { ++ wrapper.RootWrapperName = root.RootWrapperName; ++ } ++ } + wrapper.classDescriptor = klass; + wrapper.proj = reader.Project;
+- return ReadObject (reader, elem, wrapper); ++ return ReadExistingObject (reader, elem, wrapper); + }
+
+- public static ObjectWrapper ReadObject (ObjectReader reader, XmlElement elem, ObjectWrapper wrapper)
++ public static ObjectWrapper ReadExistingObject (ObjectReader reader, XmlElement elem, ObjectWrapper wrapper)
+ {
+ try {
+ wrapper.OnBeginRead (reader.Format);
+@@ -218,7 +226,7 @@ + catch (Exception ex) {
+ Console.WriteLine (ex);
+ ErrorWidget we = new ErrorWidget (ex, elem.GetAttribute ("id"));
+- ErrorWidgetWrapper wrap = (ErrorWidgetWrapper) Create (reader.Project, we);
++ ErrorWidgetWrapper wrap = (ErrorWidgetWrapper) Create (reader.Project, we, null);
+ wrap.Read (reader, elem);
+ return wrap;
+ }
+@@ -329,6 +337,10 @@ + OnObjectChanged (new ObjectWrapperEventArgs (this)); + } + ++ public abstract string Name { get; set; } ++ ++ public string RootWrapperName { get; protected set; } ++ + static object GetIndentityObject (object ob) + { + if (ob is Gtk.Container.ContainerChild) { +Index: libstetic/wrapper/ChangeLog +=================================================================== +--- libstetic/wrapper/ChangeLog (revision 0) ++++ libstetic/wrapper/ChangeLog (revision 107) +@@ -0,0 +1,12 @@ ++2010-08-03 Krzysztof Marecki <marecki.krzysztof@gmail.com> ++ ++ * Frame.cs: Pass root wrapper as an argument for ObjectWrapper.Create ++ * Action.cs: ++ * Window.cs: ++ * Button.cs: ++ * Widget.cs: ++ * Expander.cs: ++ * Container.cs: ++ * ActionGroup.cs: ++ * ScrolledWindow.cs: ++ +Index: libstetic/wrapper/Button.cs +=================================================================== +--- libstetic/wrapper/Button.cs (revision 17) ++++ libstetic/wrapper/Button.cs (working copy) +@@ -208,11 +208,12 @@ + Gtk.Alignment alignment = new Gtk.Alignment (button.Xalign, button.Yalign, 0.0f, 0.0f); + alignment.Add (box); + +- Widget wrapper = (Widget)ObjectWrapper.Create (proj, labelWidget); ++ ObjectWrapper buttonWrapper = ObjectWrapper.Lookup (this); ++ Widget wrapper = (Widget)ObjectWrapper.Create (proj, labelWidget, buttonWrapper); + wrapper.Unselectable = true; +- wrapper = (Widget)ObjectWrapper.Create (proj, box); ++ wrapper = (Widget)ObjectWrapper.Create (proj, box, buttonWrapper); + wrapper.Unselectable = true; +- wrapper = (Widget)ObjectWrapper.Create (proj, alignment); ++ wrapper = (Widget)ObjectWrapper.Create (proj, alignment, buttonWrapper); + wrapper.Unselectable = true; + + alignment.ShowAll (); +Index: libstetic/wrapper/Action.cs +=================================================================== +--- libstetic/wrapper/Action.cs (revision 17) ++++ libstetic/wrapper/Action.cs (working copy) +@@ -43,7 +43,7 @@ + get { return (Gtk.Action) Wrapped; } + } + +- public string Name { ++ public override string Name { + get { + if (name == null || name.Length == 0) { + name = nameRoot = oldDefaultName = GetDefaultName (); +@@ -250,7 +250,7 @@ + + public Action Clone () + { +- Action a = (Action) ObjectWrapper.Create (Project, new Gtk.Action ("", "")); ++ Action a = (Action) ObjectWrapper.Create (Project, new Gtk.Action ("", ""), this); + a.CopyFrom (this); + return a; + } +Index: libstetic/wrapper/Container.cs +=================================================================== +--- libstetic/wrapper/Container.cs (revision 17) ++++ libstetic/wrapper/Container.cs (working copy) +@@ -41,7 +41,7 @@ + Gtk.Widget child = prop.GetValue (container) as Gtk.Widget; + if (child == null) + continue; +- Widget wrapper = ObjectWrapper.Create (proj, child) as Stetic.Wrapper.Widget; ++ Widget wrapper = ObjectWrapper.Create (proj, child, this) as Stetic.Wrapper.Widget; + wrapper.InternalChildProperty = prop; + if (child.Name == ((GLib.GType)child.GetType ()).ToString ()) + child.Name = container.Name + "_" + prop.Name; +@@ -361,7 +361,7 @@ + + protected virtual ObjectWrapper ReadChild (ObjectReader reader, XmlElement child_elem) + { +- ObjectWrapper wrapper = reader.ReadObject (child_elem["widget"]); ++ ObjectWrapper wrapper = reader.ReadObject (child_elem["widget"], this); + Container.ContainerChild childwrapper = null; + + try { +@@ -414,7 +414,7 @@ + Gtk.Widget child = prop.GetValue (container) as Gtk.Widget; + Widget wrapper = Widget.Lookup (child); + if (wrapper != null) { +- reader.ReadObject (wrapper, child_elem["widget"]); ++ reader.ReadExistingObject (wrapper, child_elem["widget"]); + if (reader.Format == FileFormat.Glade) + GladeUtils.SetPacking (ChildWrapper (wrapper), child_elem); + else +@@ -770,7 +770,7 @@ + if (cwrap != null) + return cwrap; + else +- return Stetic.ObjectWrapper.Create (parentWrapper.proj, cc) as ContainerChild; ++ return Stetic.ObjectWrapper.Create (parentWrapper.proj, cc, parentWrapper) as ContainerChild; + } + + protected Gtk.Container.ContainerChild ContextChildProps (Gtk.Widget context) +@@ -1449,6 +1449,8 @@ + EmitNotify ("AutoSize"); + } + } ++ ++ public override string Name { get; set; } + } + } + } +Index: libstetic/wrapper/Widget.cs +=================================================================== +--- libstetic/wrapper/Widget.cs (revision 17) ++++ libstetic/wrapper/Widget.cs (working copy) +@@ -241,7 +241,7 @@ + Wrapped.Name = name; + } + +- public string Name { ++ public override string Name { + get { return Wrapped.Name; } + set { Wrapped.Name = value; EmitNotify ("Name"); } + } +@@ -806,7 +806,7 @@ + Gtk.ScrolledWindow scw = new Gtk.ScrolledWindow (); + scw.HscrollbarPolicy = scw.VscrollbarPolicy = Gtk.PolicyType.Automatic; + scw.ShadowType = Gtk.ShadowType.In; +- ScrolledWindow wrapper = (ScrolledWindow) ObjectWrapper.Create (Project, scw); ++ ScrolledWindow wrapper = (ScrolledWindow) ObjectWrapper.Create (Project, scw, ParentWrapper); + ParentWrapper.ReplaceChild (Wrapped, scw, false); + if (Wrapped.SetScrollAdjustments (null, null)) + scw.Add (Wrapped); +Index: libstetic/wrapper/Frame.cs +=================================================================== +--- libstetic/wrapper/Frame.cs (revision 17) ++++ libstetic/wrapper/Frame.cs (working copy) +@@ -17,21 +17,21 @@ + if (AllowPlaceholders) { + Gtk.Alignment align = new Gtk.Alignment (0, 0, 1, 1); + align.LeftPadding = 12; +- Container align_wrapper = (Container)ObjectWrapper.Create (proj, align); ++ Container align_wrapper = (Container)ObjectWrapper.Create (proj, align, this); + align_wrapper.AddPlaceholder (); + ReplaceChild (frame.Child, (Gtk.Widget)align_wrapper.Wrapped, true); + } + } + + if (frame.LabelWidget != null) +- ObjectWrapper.Create (proj, frame.LabelWidget); ++ ObjectWrapper.Create (proj, frame.LabelWidget, this); + frame.AddNotification ("label-widget", LabelWidgetChanged); + } + + void LabelWidgetChanged (object obj, GLib.NotifyArgs args) + { + if (!IsDisposed && frame.LabelWidget != null && !(frame.LabelWidget is Stetic.Placeholder)) +- ObjectWrapper.Create (proj, frame.LabelWidget); ++ ObjectWrapper.Create (proj, frame.LabelWidget, this); + } + + Gtk.Frame frame { +@@ -43,7 +43,7 @@ + protected override ObjectWrapper ReadChild (ObjectReader reader, XmlElement child_elem) + { + if ((string)GladeUtils.GetChildProperty (child_elem, "type", "") == "label_item") { +- ObjectWrapper wrapper = reader.ReadObject (child_elem["widget"]); ++ ObjectWrapper wrapper = reader.ReadObject (child_elem["widget"], this); + frame.LabelWidget = (Gtk.Widget)wrapper.Wrapped; + return wrapper; + } else +Index: libstetic/wrapper/ActionGroup.cs +=================================================================== +--- libstetic/wrapper/ActionGroup.cs (revision 17) ++++ libstetic/wrapper/ActionGroup.cs (working copy) +@@ -39,7 +39,7 @@ + get { return actions; } + } + +- public string Name { ++ public override string Name { + get { return name; } + set { + name = value; +Index: libstetic/wrapper/OptionMenu.cs +=================================================================== +--- libstetic/wrapper/OptionMenu.cs (revision 17) ++++ libstetic/wrapper/OptionMenu.cs (working copy) +@@ -50,7 +50,7 @@ + protected override ObjectWrapper ReadChild (ObjectReader reader, XmlElement child_elem) + { + Widget wrapper = Stetic.Wrapper.Widget.Lookup (optionmenu.Menu); +- reader.ReadObject (wrapper, child_elem["widget"]); ++ reader.ReadExistingObject (wrapper, child_elem["widget"]); + return wrapper; + } + +Index: libstetic/wrapper/ScrolledWindow.cs +=================================================================== +--- libstetic/wrapper/ScrolledWindow.cs (revision 17) ++++ libstetic/wrapper/ScrolledWindow.cs (working copy) +@@ -55,7 +55,7 @@ + internal void AddWithViewport (Gtk.Widget child) + { + Gtk.Viewport viewport = new Gtk.Viewport (scrolled.Hadjustment, scrolled.Vadjustment); +- ObjectWrapper.Create (proj, viewport); ++ ObjectWrapper.Create (proj, viewport, this); + viewport.ShadowType = Gtk.ShadowType.None; + viewport.Add (child); + viewport.Show (); +Index: libstetic/wrapper/Window.cs +=================================================================== +--- libstetic/wrapper/Window.cs (revision 17) ++++ libstetic/wrapper/Window.cs (working copy) +@@ -10,7 +10,9 @@ + public override void Wrap (object obj, bool initialized) + { + TopLevelWindow window = (TopLevelWindow) obj; ++ RootWrapperName = window.Name; + ++ //during Wrap RootWrapperName will be set in the children widgets + base.Wrap (obj, initialized); + + if (!initialized) { +Index: libstetic/wrapper/Notebook.cs +=================================================================== +--- libstetic/wrapper/Notebook.cs (revision 17) ++++ libstetic/wrapper/Notebook.cs (working copy) +@@ -31,7 +31,7 @@ + protected override ObjectWrapper ReadChild (ObjectReader reader, XmlElement child_elem) + { + if ((string)GladeUtils.GetChildProperty (child_elem, "type", "") == "tab") { +- ObjectWrapper wrapper = reader.ReadObject (child_elem["widget"]); ++ ObjectWrapper wrapper = reader.ReadObject (child_elem["widget"], this); + Gtk.Widget widget = (Gtk.Widget)wrapper.Wrapped; + notebook.SetTabLabel (notebook.GetNthPage (notebook.NPages - 1), widget); + tabs.Add (widget); +Index: libstetic/wrapper/MenuItem.cs +=================================================================== +--- libstetic/wrapper/MenuItem.cs (revision 17) ++++ libstetic/wrapper/MenuItem.cs (working copy) +@@ -18,7 +18,7 @@ + + protected override ObjectWrapper ReadChild (ObjectReader reader, XmlElement child_elem) + { +- ObjectWrapper wrapper = reader.ReadObject (child_elem["widget"]); ++ ObjectWrapper wrapper = reader.ReadObject (child_elem["widget"], this); + menuitem.Submenu = (Gtk.Menu)wrapper.Wrapped; + return wrapper; + } +Index: libstetic/wrapper/objects.xml +=================================================================== +--- libstetic/wrapper/objects.xml (revision 17) ++++ libstetic/wrapper/objects.xml (working copy) +@@ -104,17 +104,17 @@ + <!-- "events" property has extra spaces around "|"s --> + <import> + <xsl:template match="widget/property[@name='events']/text()"> +- <xsl:call-template name="GtkWidget_fixevents"> ++ <xsl:call-template name="GtkWidget_fixevents2"> + <xsl:with-param name="string" select="." /> + </xsl:call-template> + </xsl:template> +- <xsl:template name="GtkWidget_fixevents"> ++ <xsl:template name="GtkWidget_fixevents2"> + <xsl:param name="string"/> + <xsl:choose> + <xsl:when test="contains($string, ' | ')"> + <xsl:value-of select="substring-before($string, ' | ')"/> + <xsl:text>|</xsl:text> +- <xsl:call-template name="GtkWidget_fixevents"> ++ <xsl:call-template name="GtkWidget_fixevents2"> + <xsl:with-param name="string" select="substring-after($string, ' | ')"/> + </xsl:call-template> + </xsl:when> +@@ -126,17 +126,17 @@ + </import> + <export> + <xsl:template match="widget/property[@name='events']/text()"> +- <xsl:call-template name="GtkWidget_breakevents"> ++ <xsl:call-template name="GtkWidget_breakevents2"> + <xsl:with-param name="string" select="." /> + </xsl:call-template> + </xsl:template> +- <xsl:template name="GtkWidget_breakevents"> ++ <xsl:template name="GtkWidget_breakevents2"> + <xsl:param name="string"/> + <xsl:choose> + <xsl:when test="contains($string, '|')"> + <xsl:value-of select="substring-before($string, '|')"/> + <xsl:text> | </xsl:text> +- <xsl:call-template name="GtkWidget_breakevents"> ++ <xsl:call-template name="GtkWidget_breakevents2"> + <xsl:with-param name="string" select="substring-after($string, '|')"/> + </xsl:call-template> + </xsl:when> +@@ -1316,19 +1316,19 @@ + <!-- Child packing options are non-standard ("expand" instead of "GTK_EXPAND") --> + <import> + <xsl:template match="widget[@class='GtkTable']/child/packing/property[@name='x_options' or @name='y_options']/text()"> +- <xsl:call-template name="GtkTable_fixoptions"> ++ <xsl:call-template name="GtkTable_fixoptions2"> + <xsl:with-param name="string" select="." /> + </xsl:call-template> + </xsl:template> +- <xsl:template name="GtkTable_fixoptions"> ++ <xsl:template name="GtkTable_fixoptions2"> + <xsl:param name="string"/> + <xsl:choose> + <xsl:when test="contains($string, '|')"> +- <xsl:call-template name="GtkTable_fixoptions"> ++ <xsl:call-template name="GtkTable_fixoptions2"> + <xsl:with-param name="string" select="substring-before($string, '|')"/> + </xsl:call-template> + <xsl:text>|</xsl:text> +- <xsl:call-template name="GtkTable_fixoptions"> ++ <xsl:call-template name="GtkTable_fixoptions2"> + <xsl:with-param name="string" select="substring-after($string, '|')"/> + </xsl:call-template> + </xsl:when> +@@ -1341,19 +1341,19 @@ + </import> + <export> + <xsl:template match="widget[@class='GtkTable']/child/packing/property[@name='x_options' or @name='y_options']/text()"> +- <xsl:call-template name="GtkTable_breakoptions"> ++ <xsl:call-template name="GtkTable_breakoptions2"> + <xsl:with-param name="options" select="." /> + </xsl:call-template> + </xsl:template> +- <xsl:template name="GtkTable_breakoptions"> ++ <xsl:template name="GtkTable_breakoptions2"> + <xsl:param name="string"/> + <xsl:choose> + <xsl:when test="contains($string, '|')"> +- <xsl:call-template name="GtkTable_breakoptions"> ++ <xsl:call-template name="GtkTable_breakoptions2"> + <xsl:with-param name="string" select="substring-before($string, '|')"/> + </xsl:call-template> + <xsl:text>|</xsl:text> +- <xsl:call-template name="GtkTable_breakoptions"> ++ <xsl:call-template name="GtkTable_breakoptions2"> + <xsl:with-param name="string" select="substring-after($string, '|')"/> + </xsl:call-template> + </xsl:when> +Index: libstetic/wrapper/Expander.cs +=================================================================== +--- libstetic/wrapper/Expander.cs (revision 17) ++++ libstetic/wrapper/Expander.cs (working copy) +@@ -21,13 +21,13 @@ + AddPlaceholder (); + } + if (expander.LabelWidget != null) +- ObjectWrapper.Create (proj, expander.LabelWidget); ++ ObjectWrapper.Create (proj, expander.LabelWidget, this); + } + + protected override ObjectWrapper ReadChild (ObjectReader reader, XmlElement child_elem) + { + if ((string)GladeUtils.GetChildProperty (child_elem, "type", "") == "label_item") { +- ObjectWrapper wrapper = reader.ReadObject (child_elem["widget"]); ++ ObjectWrapper wrapper = reader.ReadObject (child_elem["widget"], this); + expander.LabelWidget = (Gtk.Widget)wrapper.Wrapped; + return wrapper; + } else +Index: libstetic/GladeUtils.cs +=================================================================== +--- libstetic/GladeUtils.cs (revision 17) ++++ libstetic/GladeUtils.cs (working copy) +@@ -104,31 +104,31 @@ + return doc; + } + +- public static Stetic.Wrapper.Widget Import (IProject project, XmlDocument doc) +- { +- try { +- doc = XslImportTransform (doc); +- } catch { +- return null; +- } +- +- ObjectReader reader = new ObjectReader (project, FileFormat.Glade); +- +- XmlElement elem = (XmlElement)doc.SelectSingleNode ("glade-interface/widget"); +- if (elem.GetAttribute ("class") != "GtkWindow" || +- elem.GetAttribute ("id") != "glade-dummy-container") { +- // Creating a new toplevel +- Stetic.Wrapper.Widget toplevel = (Stetic.Wrapper.Widget) +- Stetic.ObjectWrapper.ReadObject (reader, elem); +- if (toplevel != null) { +- project.AddWindow ((Gtk.Window)toplevel.Wrapped); +- } +- return toplevel; +- } +- +- return (Stetic.Wrapper.Widget) +- Stetic.ObjectWrapper.ReadObject (reader, (XmlElement)elem.SelectSingleNode ("child/widget")); +- } ++// public static Stetic.Wrapper.Widget Import (IProject project, XmlDocument doc) ++// { ++// try { ++// doc = XslImportTransform (doc); ++// } catch { ++// return null; ++// } ++// ++// ObjectReader reader = new ObjectReader (project, FileFormat.Glade); ++// ++// XmlElement elem = (XmlElement)doc.SelectSingleNode ("glade-interface/widget"); ++// if (elem.GetAttribute ("class") != "GtkWindow" || ++// elem.GetAttribute ("id") != "glade-dummy-container") { ++// // Creating a new toplevel ++// Stetic.Wrapper.Widget toplevel = (Stetic.Wrapper.Widget) ++// Stetic.ObjectWrapper.ReadObject (reader, elem); ++// if (toplevel != null) { ++// project.AddWindow ((Gtk.Window)toplevel.Wrapped); ++// } ++// return toplevel; ++// } ++// ++// return (Stetic.Wrapper.Widget) ++// Stetic.ObjectWrapper.ReadObject (reader, (XmlElement)elem.SelectSingleNode ("child/widget")); ++// } + + public static void Copy (Gtk.Widget widget, Gtk.SelectionData seldata, bool copyAsText) + { +@@ -142,23 +142,23 @@ + seldata.Set (ApplicationXGladeAtom, 8, System.Text.Encoding.UTF8.GetBytes (doc.OuterXml)); + } + +- public static Stetic.Wrapper.Widget Paste (IProject project, Gtk.SelectionData seldata) +- { +- if (seldata.Type != ApplicationXGladeAtom) +- return null; +- string data = System.Text.Encoding.UTF8.GetString (seldata.Data); ++// public static Stetic.Wrapper.Widget Paste (IProject project, Gtk.SelectionData seldata) ++// { ++// if (seldata.Type != ApplicationXGladeAtom) ++// return null; ++// string data = System.Text.Encoding.UTF8.GetString (seldata.Data); ++// ++// XmlDocument doc = new XmlDocument (); ++// doc.PreserveWhitespace = true; ++// try { ++// doc.LoadXml (data); ++// } catch { ++// return null; ++// } ++// ++// return Import (project, doc); ++// } + +- XmlDocument doc = new XmlDocument (); +- doc.PreserveWhitespace = true; +- try { +- doc.LoadXml (data); +- } catch { +- return null; +- } +- +- return Import (project, doc); +- } +- + static object GetProperty (XmlElement elem, string selector, object defaultValue, bool extract) + { + XmlElement prop = (XmlElement)elem.SelectSingleNode (selector); +Index: libstetic/ErrorWidget.cs +=================================================================== +--- libstetic/ErrorWidget.cs (revision 17) ++++ libstetic/ErrorWidget.cs (working copy) +@@ -96,9 +96,9 @@ + ErrorWidget ew = (ErrorWidget) Wrapped; + string msg; + if (ew.Exception != null) +- msg = Project.FileName + ": Could not generate code for an invalid widget. The widget failed to load: " + ew.Exception.Message + ". The generated code may be invalid."; ++ msg = Project.FolderName + ": Could not generate code for an invalid widget. The widget failed to load: " + ew.Exception.Message + ". The generated code may be invalid."; + else +- msg = Project.FileName + ": Could not generate code for widgets of type: " + ew.ClassName + ". The widget could not be found in any referenced library. The generated code may be invalid."; ++ msg = Project.FolderName + ": Could not generate code for widgets of type: " + ew.ClassName + ". The widget could not be found in any referenced library. The generated code may be invalid."; + + if (ctx.Options.FailForUnknownWidgets) { + throw new InvalidOperationException (msg); +Index: libstetic/WidgetUtils.cs +=================================================================== +--- libstetic/WidgetUtils.cs (revision 17) ++++ libstetic/WidgetUtils.cs (working copy) +@@ -37,7 +37,7 @@ + public static Gtk.Widget ImportWidget (IProject project, XmlElement element) + { + ObjectReader reader = new ObjectReader (project, FileFormat.Native); +- ObjectWrapper wrapper = Stetic.ObjectWrapper.ReadObject (reader, element); ++ ObjectWrapper wrapper = Stetic.ObjectWrapper.ReadObject (reader, element, null); + return wrapper.Wrapped as Gtk.Widget; + } + +@@ -126,11 +126,14 @@ + Gtk.Widget widget = (Gtk.Widget) wrapper.Wrapped; + if (widget == null) { + widget = (Gtk.Widget) klass.CreateInstance (wrapper.Project); ++ //set name before binding to ensure ++ //that ObjectWrapper.RootWrapperName will be valid ++ widget.Name = elem.GetAttribute ("id"); + ObjectWrapper.Bind (wrapper.Project, klass, wrapper, widget, true); ++ } else { ++ widget.Name = elem.GetAttribute ("id"); + } + +- widget.Name = elem.GetAttribute ("id"); +- + ReadMembers (klass, wrapper, widget, elem); + + if (!(widget is Gtk.Window)) +Index: MonoDevelop.GtkCore.Commands/GladeCommands.cs +=================================================================== +--- MonoDevelop.GtkCore.Commands/GladeCommands.cs (revision 17) ++++ MonoDevelop.GtkCore.Commands/GladeCommands.cs (working copy) +@@ -36,6 +36,7 @@ + AddNewActionGroup, + ImportGladeFile, + EditIcons, +- GtkSettings ++ GtkSettings, ++ GenerateCode + } + } +Index: MonoDevelop.GtkCore.Commands/ChangeLog +=================================================================== +--- MonoDevelop.GtkCore.Commands/ChangeLog (revision 0) ++++ MonoDevelop.GtkCore.Commands/ChangeLog (revision 124) +@@ -0,0 +1,4 @@ ++2010-08-15 Krzysztof Marecki <freefirma@gmail.com> ++ ++ * GladeCommands.cs: ++ +Index: MonoDevelop.GtkCore/GtkDesignInfo.cs +=================================================================== +--- MonoDevelop.GtkCore/GtkDesignInfo.cs (revision 17) ++++ MonoDevelop.GtkCore/GtkDesignInfo.cs (working copy) +@@ -29,6 +29,8 @@ + + using System; + using System.IO; ++using System.CodeDom; ++using System.CodeDom.Compiler; + using System.Collections.Generic; + using System.Collections.Specialized; + +@@ -51,13 +53,23 @@ + IDotNetLanguageBinding binding; + ProjectResourceProvider resourceProvider; + ReferenceManager referenceManager; ++ string langExtension; + +- [ItemProperty (DefaultValue=true)] ++ [ItemProperty (DefaultValue = true)] + bool generateGettext = true; + +- [ItemProperty (DefaultValue="Mono.Unix.Catalog")] ++ [ItemProperty (DefaultValue = "Mono.Unix.Catalog")] + string gettextClass = "Mono.Unix.Catalog"; + ++ [ItemProperty (DefaultValue = "Stetic")] ++ string steticFolderName = "Stetic"; ++ ++ [ItemProperty (DefaultValue = false)] ++ bool wasConverted; ++ ++ [ItemProperty (DefaultValue = true)] ++ bool hideGtkxFiles = true; ++ + GtkDesignInfo () + { + } +@@ -85,8 +97,15 @@ + referenceManager = null; + } + project = value; ++ + if (project != null) { + binding = LanguageBindingService.GetBindingPerLanguageName (project.LanguageName) as IDotNetLanguageBinding; ++ ++ CodeDomProvider provider = binding.GetCodeDomProvider (); ++ if (provider == null) ++ throw new UserException ("Code generation not supported for language: " + project.LanguageName); ++ langExtension = "." + provider.FileExtension; ++ + project.FileAddedToProject += OnFileEvent; + project.FileChangedInProject += OnFileEvent; + project.FileRemovedFromProject += OnFileEvent; +@@ -120,11 +139,7 @@ + get { + if (builderProject == null) { + if (SupportsDesigner (project)) { +- if (!File.Exists (SteticFile)) { +- UpdateGtkFolder (); +- ProjectNodeBuilder.OnSupportChanged (project); +- } +- builderProject = new GuiBuilderProject (project, SteticFile); ++ builderProject = new GuiBuilderProject (project, SteticFolder.FullPath.FullPath); + } else + builderProject = new GuiBuilderProject (project, null); + } +@@ -156,20 +171,27 @@ + } + } + ++ public bool OldVersion { ++ get { return project.IsFileInProject (SteticFile); } ++ } ++ + FilePath ObjectsFile { +- get { return GtkGuiFolder.Combine ("objects.xml"); } ++ get { return SteticFolder.Combine ("objects.xml"); } + } + ++ [Obsolete] + public FilePath SteticGeneratedFile { +- get { return GtkGuiFolder.Combine (binding.GetFileName ("generated")); } ++ get { return SteticFolder.Combine (binding.GetFileName ("generated")); } + } + ++ [Obsolete] + public FilePath SteticFile { +- get { return GtkGuiFolder.Combine ("gui.stetic"); } ++ get { return SteticFolder.Combine ("gui.stetic"); } + } + +- public FilePath GtkGuiFolder { +- get { return project.BaseDirectory.Combine ("gtk-gui"); } ++ public FilePath SteticFolder { ++// get { return project.BaseDirectory.Combine ("gtk-gui"); } ++ get { return project.BaseDirectory.Combine (!wasConverted ? "gtk-gui" : steticFolderName); } + } + + public bool GenerateGettext { +@@ -187,13 +209,22 @@ + set { gettextClass = value; } + } + ++ public string SteticFolderName { ++ get { return steticFolderName; } ++ set { steticFolderName = value; } ++ } ++ ++ public bool HideGtkxFiles { ++ get { return hideGtkxFiles; } ++ set { hideGtkxFiles = value; } ++ } ++ + public static bool HasDesignedObjects (Project project) + { + if (project == null) + return false; + +- string stetic_file = Path.Combine (Path.Combine (project.BaseDirectory, "gtk-gui"), "gui.stetic"); +- return SupportsDesigner (project) && File.Exists (stetic_file); ++ return SupportsDesigner (project); + } + + public static bool SupportsDesigner (Project project) +@@ -250,7 +281,7 @@ + bool projectModified = false; + + // Remove all project files which are not in the generated list +- foreach (ProjectFile pf in project.Files.GetFilesInPath (GtkGuiFolder)) { ++ foreach (ProjectFile pf in project.Files.GetFilesInPath (SteticFolder)) { + if (remaining_files.Contains (pf.FilePath)) + continue; + +@@ -260,68 +291,218 @@ + } + + if (remaining_files.Count == 0) +- FileService.DeleteDirectory (GtkGuiFolder); ++ FileService.DeleteDirectory (SteticFolder); + + return projectModified; + } + ++ public void ConvertGtkFolder (string guiFolderName, bool makeBackup) ++ { ++ foreach (ProjectFile pf in project.Files.GetFilesInPath (SteticFolder)) { ++ FilePath path = pf.FilePath; ++ ++ if (path != SteticGeneratedFile) { ++ project.Files.Remove (path); ++ ++ if (path != SteticFile) ++ FileService.DeleteFile (path.FullPath); ++ } ++ } ++ ++ string oldGuiFolder = SteticFolder.FullPath; ++ string oldSteticFile = SteticFile; ++ string oldGeneratedFile = SteticGeneratedFile; ++ SteticFolderName = guiFolderName; ++ wasConverted = true; ++ ++ if (!Directory.Exists (SteticFolder)) ++ FileService.CreateDirectory (SteticFolder); ++ ++ if (makeBackup && File.Exists (oldSteticFile)) { ++ string backupFile = SteticFolder.Combine ("old.stetic"); ++ FileService.MoveFile (oldSteticFile, backupFile); ++ } ++ ++ if (File.Exists (oldGeneratedFile)) ++ FileService.DeleteFile (oldGeneratedFile); ++ ++ FileService.DeleteDirectory (oldGuiFolder); ++ } ++ + public bool UpdateGtkFolder () + { + if (!SupportsDesigner (project)) + return false; +- ++ + // This method synchronizes the current gtk project configuration info + // with the needed support files in the gtk-gui folder. + +- FileService.CreateDirectory (GtkGuiFolder); ++ FileService.CreateDirectory (SteticFolder); + bool projectModified = false; +- bool initialGeneration = false; + +- if (!File.Exists (SteticFile)) { +- initialGeneration = true; +- StreamWriter sw = new StreamWriter (SteticFile); +- sw.WriteLine ("<stetic-interface />"); +- sw.Close (); +- FileService.NotifyFileChanged (SteticFile); +- } ++ foreach (string filename in GetComponentsFiles ()) { ++ ProjectFile pf = project.AddFile (filename, BuildAction.EmbeddedResource); ++ pf.ResourceId = Path.GetFileName (filename); ++ ++ string componentFile = GetComponentFileFromGtkx (filename); + +- if (!project.IsFileInProject (SteticFile)) { +- ProjectFile pf = project.AddFile (SteticFile, BuildAction.EmbeddedResource); +- pf.ResourceId = "gui.stetic"; ++ if (componentFile != null && File.Exists (componentFile)) { ++ pf.DependsOn = componentFile; ++ ++ string buildFile = GetBuildFileFromGtkx (filename); ++ if (buildFile != null && File.Exists (buildFile)) { ++ ProjectFile pf2 = project.AddFile (buildFile, BuildAction.Compile); ++ pf2.ResourceId = Path.GetFileName (buildFile); ++ pf2.DependsOn = componentFile; ++ } ++ } ++ + projectModified = true; + } +- +- StringCollection files = GuiBuilderProject.GenerateFiles (GtkGuiFolder); +- DateTime generatedTime = File.GetLastWriteTime (SteticFile).Subtract (TimeSpan.FromSeconds (2)); +- ++ ++ StringCollection files = GuiBuilderProject.GenerateFiles (SteticFolder); + foreach (string filename in files) { +- if (initialGeneration) { +- // Ensure that the generation date of this file is < the date of the .stetic file +- // In this way the code will be properly regenerated when building the project. +- File.SetLastWriteTime (filename, generatedTime); +- } + if (!project.IsFileInProject (filename)) { + project.AddFile (filename, BuildAction.Compile); + projectModified = true; + } ++ + } +- ++ + UpdateObjectsFile (); +- files.Add (ObjectsFile); +- files.Add (SteticFile); +- +- if (CleanGtkFolder (files)) +- projectModified = true; +- ++ + return ReferenceManager.Update () || projectModified; + } + ++// public bool UpdateGtkFolder () ++// { ++// if (!SupportsDesigner (project)) ++// return false; ++// ++// // This method synchronizes the current gtk project configuration info ++// // with the needed support files in the gtk-gui folder. ++// ++// FileService.CreateDirectory (GtkGuiFolder); ++// bool projectModified = false; ++// bool initialGeneration = false; ++// ++// if (!File.Exists (SteticFile)) { ++// initialGeneration = true; ++// StreamWriter sw = new StreamWriter (SteticFile); ++// sw.WriteLine ("<stetic-interface />"); ++// sw.Close (); ++// FileService.NotifyFileChanged (SteticFile); ++// } ++// ++// if (!project.IsFileInProject (SteticFile)) { ++// ProjectFile pf = project.AddFile (SteticFile, BuildAction.EmbeddedResource); ++// pf.ResourceId = "gui.stetic"; ++// projectModified = true; ++// } ++// ++// StringCollection files = GuiBuilderProject.GenerateFiles (GtkGuiFolder); ++// DateTime generatedTime = File.GetLastWriteTime (SteticFile).Subtract (TimeSpan.FromSeconds (2)); ++// ++// foreach (string filename in files) { ++// if (initialGeneration) { ++// // Ensure that the generation date of this file is < the date of the .stetic file ++// // In this way the code will be properly regenerated when building the project. ++// File.SetLastWriteTime (filename, generatedTime); ++// } ++// if (!project.IsFileInProject (filename)) { ++// project.AddFile (filename, BuildAction.Compile); ++// projectModified = true; ++// } ++// } ++// ++// UpdateObjectsFile (); ++// files.Add (ObjectsFile); ++// files.Add (SteticFile); ++// ++// if (CleanGtkFolder (files)) ++// projectModified = true; ++// ++// return ReferenceManager.Update () || projectModified; ++// return true; ++// } ++ ++ ++ public string GetComponentFile (string componentName) ++ { ++ IType type = GuiBuilderProject.FindClass (componentName); ++ ++ if (type != null) { ++ ++ foreach (IType part in type.Parts) { ++ string componentFile = part.CompilationUnit.FileName.FullPath.ToString (); ++// if (!componentFile.Contains (".generated")) ++// return componentFile; ++ if (componentFile.Contains (".generated")) ++ componentFile = componentFile.Replace (".generated", string.Empty); ++ ++ return componentFile; ++ } ++ } ++ ++ return null; ++ } ++ ++ public string GetBuildFile (string componentFile) ++ { ++ if (componentFile != null) { ++ string buildFile = componentFile.Replace ++ (Path.GetExtension (SteticGeneratedFile), ".generated" + langExtension); ++ return buildFile; ++ } ++ ++ return null; ++ } ++ ++ public string GetBuildFileInSteticFolder (string componentName) ++ { ++ string name = string.Format ("{0}.generated{1}", componentName, langExtension); ++ string buildFile = Path.Combine (SteticFolder, name); ++ ++ return buildFile; ++ } ++ ++ public string GetGtkxFile (string componentFile) ++ { ++ if (componentFile != null) { ++ string gtkxFile = componentFile.Replace (langExtension, ".gtkx"); ++ return gtkxFile; ++ } ++ ++ return null; ++ } ++ ++ public string GetComponentFileFromGtkx (string gtkxFile) ++ { ++ if (gtkxFile != null) { ++ string componentFile = gtkxFile.Replace (".gtkx", langExtension); ++ return componentFile; ++ } ++ ++ return null; ++ } ++ ++ public string GetBuildFileFromGtkx (string gtkxFile) ++ { ++ string buildFile = gtkxFile.Replace (".gtkx", ".generated" + langExtension); ++ return buildFile; ++ } ++ ++ + public string GetComponentFolder (string componentName) + { + IType type = GuiBuilderProject.FindClass (componentName); +- FilePath folder = type.CompilationUnit.FileName.ParentDirectory; + +- return folder.FullPath.ToString (); ++ if (type != null) { ++ FilePath folder = type.CompilationUnit.FileName.ParentDirectory; ++ return folder.FullPath.ToString (); ++ } ++ ++ return null; + } + + public string[] GetComponentFolders () +@@ -329,17 +510,54 @@ + List<string> folders = new List<string> (); + ProjectDom ctx = GuiBuilderProject.GetParserContext (); + +- foreach (IType type in ctx.Types) { +- FilePath folder = type.CompilationUnit.FileName.ParentDirectory; +- string folderName = folder.FullPath.ToString (); ++ foreach (IType type in ctx.Types) ++ foreach (IType part in type.Parts) { ++ FilePath folder = part.CompilationUnit.FileName.ParentDirectory; ++ string folderName = folder.FullPath.ToString (); + +- if (!folders.Contains (folderName)) +- folders.Add (folder); ++ if (!folders.Contains (folderName)) ++ folders.Add (folder); + } + + return folders.ToArray (); + } ++ ++ public string[] GetComponentsFiles () ++ { ++ List<string> files = new List<string> (); ++ ++ foreach (string folder in GetComponentFolders ()) { ++ DirectoryInfo dir = new DirectoryInfo (folder); ++ ++ foreach (FileInfo file in dir.GetFiles ()) ++ if (file.Extension == ".gtkx") ++ files.Add (file.ToString ()); ++ } ++ ++ return files.ToArray (); ++ } + ++ public bool HasComponentFile (string componentName) ++ { ++ return (GetComponentFile (componentName) != null); ++ } ++ ++ public bool ComponentNeedsCodeGeneration (string componentName) ++ { ++ string componentFile = GetComponentFile (componentName); ++ string gtkxFile = GetGtkxFile (componentFile); ++ string buildFile = GetBuildFile (componentFile); ++ FileInfo gtkxFileInfo = File.Exists (gtkxFile) ? new FileInfo (gtkxFile) : null; ++ FileInfo buildFileInfo = File.Exists (buildFile) ? new FileInfo (buildFile) : null; ++ Console.WriteLine(gtkxFile); ++ if (gtkxFileInfo == null) ++ return false; ++ if (buildFileInfo == null) ++ //file does not exist ++ return true; ++ return gtkxFileInfo.LastWriteTime > buildFileInfo.LastWriteTime; ++ } ++ + void UpdateObjectsFile () + { + if (!File.Exists (ObjectsFile)) +Index: MonoDevelop.GtkCore/ChangeLog +=================================================================== +--- MonoDevelop.GtkCore/ChangeLog (revision 0) ++++ MonoDevelop.GtkCore/ChangeLog (revision 125) +@@ -0,0 +1,36 @@ ++2010-08-15 Krzysztof Marecki <freefirma@gmail.com> ++ ++ * WidgetFileDescriptionTemplate.cs: ++ ++2010-08-15 Krzysztof Marecki <freefirma@gmail.com> ++ ++ * GtkDesignInfo.cs: ++ ++2010-08-13 Krzysztof Marecki <freefirma@gmail.com> ++ ++ * GtkDesignInfo.cs: ++ ++2010-08-09 Krzysztof Marecki <freefirma@gmail.com> ++ ++ * GtkDesignInfo.cs: Add ComponentNeedsCodeGeneration method, ++ ++2010-08-04 Krzysztof Marecki <freefirma@gmail.com> ++ ++ * WidgetFileDescriptionTemplate.cs: Bump Api ++ ++2010-07-06 Krzysztof Marecki <marecki.krzysztof@gmail.com> ++ ++ * GtkDesignInfo.cs: Remove gtk-gui folder after project conversion ++ ++2010-06-23 Krzysztof Marecki <marecki.krzysztof@gmail.com> ++ ++ * GtkDesignInfo.cs: ++ ++2010-06-16 Krzysztof Marecki <marecki.krzysztof@gmail.com> ++ ++ * GtkDesignInfo.cs: ++ ++2010-06-07 Krzysztof Marecki <marecki.krzysztof@gmail.com> ++ ++ * GtkDesignInfo.cs: Transition from project file name to project folder. ++ +Index: MonoDevelop.GtkCore/WidgetFileDescriptionTemplate.cs +=================================================================== +--- MonoDevelop.GtkCore/WidgetFileDescriptionTemplate.cs (revision 17) ++++ MonoDevelop.GtkCore/WidgetFileDescriptionTemplate.cs (working copy) +@@ -91,7 +91,7 @@ + string fileName = fileTemplate.GetFileName (policyParent, project, language, directory, name); + fileTemplate.AddToProject (policyParent, project, language, directory, name); + +- ProjectDomService.Parse (project, fileName, null); ++ ProjectDomService.Parse (project, fileName); + + DotNetProject netProject = project as DotNetProject; + string ns = netProject != null ? netProject.GetDefaultNamespace (fileName) : ""; +@@ -125,7 +125,8 @@ + XmlDocument doc = new XmlDocument (); + doc.LoadXml (content); + +- gproject.SteticProject.AddNewActionGroup (doc.DocumentElement); ++ Stetic.Project sproject = gproject.SteticProject; ++ sproject.AddNewActionGroup (doc.DocumentElement); + gproject.Save (false); + IdeApp.ProjectOperations.Save (project); + return true; +Index: ChangeLog +=================================================================== +--- ChangeLog (revision 17) ++++ ChangeLog (working copy) +@@ -1,3 +1,117 @@ ++2010-08-15 Krzysztof Marecki <freefirma@gmail.com> ++ ++ * MonoDevelop.GtkCore.addin.xml: ++ ++2010-08-15 Krzysztof Marecki <freefirma@gmail.com> ++ ++ * Makefile.am: ++ * MonoDevelop.GtkCore2.csproj: ++ * MonoDevelop.GtkCore.addin.xml: ++ ++2010-08-09 Krzysztof Marecki <freefirma@gmail.com> ++ ++ * Makefile.am: ++ * MonoDevelop.GtkCore2.csproj: ++ * MonoDevelop.GtkCore.addin.xml: Add GuiFolderBuilderNode extension ++ ++2010-08-07 Krzysztof Marecki <marecki.krzysztof@gmail.com> ++ ++ * MonoDevelop.GtkCore2.csproj: ++ ++2010-08-04 Krzysztof Marecki <freefirma@gmail.com> ++ ++ * MonoDevelop.GtkCore2.csproj: ++ ++2010-07-27 Krzysztof Marecki <freefirma@gmail.com> ++ ++ * MonoDevelop.GtkCore.GuiBuilder/GuiBuilderView.cs: ++ Remove autoCommit argument ++ ++2010-07-05 Krzysztof Marecki <marecki.krzysztof@gmail.com> ++ ++ * Makefile.am: ++ * MonoDevelop.GtkCore2.csproj: ++ * MonoDevelop.GtkCore.addin.xml: ++ ++2010-06-28 Krzysztof Marecki <marecki.krzysztof@gmail.com> ++ ++ * MonoDevelop.GtkCore/GtkDesignInfo.cs: ++ * MonoDevelop.GtkCore.GuiBuilder/GuiBuilderService.cs: ++ * MonoDevelop.GtkCore.GuiBuilder/GuiBuilderProject.cs: ++ * MonoDevelop.GtkCore.NodeBuilders/ProjectNodeBuilder.cs: ++ * MonoDevelop.GtkCore.NodeBuilders/ProjectFileExtension.cs: ++ * MonoDevelop.GtkCore.NodeBuilders/ProjectFileNodeBuilderExtension.cs: ++ Fixes fo better file grouping in the project pad ++ ++ ++2010-06-28 Krzysztof Marecki <marecki.krzysztof@gmail.com> ++ ++ * MonoDevelop.GtkCore2.csproj: ++ ++2010-06-23 Krzysztof Marecki <marecki.krzysztof@gmail.com> ++ Draw action group icon ++ * gtk-gui/gui.stetic: ++ * MonoDevelop.GtkCore2.csproj: ++ * MonoDevelop.GtkCore/GtkDesignInfo.cs: ++ * MonoDevelop.GtkCore.GuiBuilder/GuiBuilderProject.cs: ++ * MonoDevelop.GtkCore.NodeBuilders/ProjectNodeBuilder.cs: ++ * MonoDevelop.GtkCore.NodeBuilders/ProjectFileExtension.cs: ++ * MonoDevelop.GtkCore.NodeBuilders/ProjectFileNodeBuilderExtension.cs: ++ ++2010-06-23 Krzysztof Marecki <marecki.krzysztof@gmail.com> ++ ++ * Makefile.am: ++ * MonoDevelop.GtkCore2.csproj: ++ ++2010-06-22 Krzysztof Marecki <marecki.krzysztof@gmail.com> ++ ++ * Makefile.am: ++ * MonoDevelop.GtkCore2.csproj: ++ * MonoDevelop.GtkCore.addin.xml: ++ * MonoDevelop.GtkCore/GtkDesignInfo.cs: ++ * MonoDevelop.GtkCore.NodeBuilders/ProjectNodeBuilder.cs: ++ * MonoDevelop.GtkCore.NodeBuilders/ProjectFileExtension.cs: ++ * MonoDevelop.GtkCore.NodeBuilders/ProjectFileNodeBuilderExtension.cs: ++ * MonoDevelop.GtkCore.NodeBuilders/ProjectFolderNodeBuilderExtension.cs: ++ ++ ++2010-06-16 Krzysztof Marecki <marecki.krzysztof@gmail.com> ++ ++ * MonoDevelop.GtkCore.addin.xml: ++ ++2010-06-15 Krzysztof Marecki <marecki.krzysztof@gmail.com> ++ Changes in the project pad for displaying grouped component files ++ ++ * Makefile.am: ++ * MonoDevelop.GtkCore2.csproj: ++ * MonoDevelop.GtkCore.addin.xml: ++ * MonoDevelop.GtkCore/GtkDesignInfo.cs: ++ * MonoDevelop.GtkCore.GuiBuilder/GuiBuilderService.cs: ++ * MonoDevelop.GtkCore.NodeBuilders/WindowsFolderNodeBuilder.cs: ++ * MonoDevelop.GtkCore.NodeBuilders/ProjectFileNodeBuilderExtension.cs: ++ ++ ++2010-06-09 Krzysztof Marecki <marecki.krzysztof@gmail.com> ++ ++ * gtk-gui/gui.stetic: ++ * MonoDevelop.GtkCore2.csproj: ++ * MonoDevelop.GtkCore/GtkDesignInfo.cs: Add gtkx files to project ++ * MonoDevelop.GtkCore.GuiBuilder/GuiBuilderProject.cs: ++ ++2010-06-07 Krzysztof Marecki <marecki.krzysztof@gmail.com> ++ ++ * gtk-gui/gui.stetic: ++ * MonoDevelop.GtkCore/GtkDesignInfo.cs: ++ * MonoDevelop.GtkCore.GuiBuilder/GuiBuilderProject.cs: ++ ++2010-06-02 Krzysztof Marecki <marecki.krzysztof@gmail.com> ++ ++ * Makefile.am: ++ * MonoDevelop.GtkCore2.csproj: ++ * MonoDevelop.GtkCore/GtkDesignInfo.cs: ++ * MonoDevelop.GtkCore.GuiBuilder/GuiBuilderService.cs: ++ Move generated partial class for components from gtk-gui. ++ + 2010-04-29 Michael Hutchinson <mhutchinson@novell.com> + + * MonoDevelop.GtkCore.GuiBuilder/GuiBuilderService.cs: Track +Index: MonoDevelop.GtkCore.addin.xml +=================================================================== +--- MonoDevelop.GtkCore.addin.xml (revision 17) ++++ MonoDevelop.GtkCore.addin.xml (working copy) +@@ -1,6 +1,6 @@ + <Addin id = "GtkCore2" + namespace = "MonoDevelop" +- name = "GTK# Visual Designer 2" ++ name = "GTK# Visual Designer (experimental)" + author = "Lluis Sanchez Gual, Krzysztof Marecki" + copyright = "X11" + url = "" +@@ -20,6 +20,7 @@ + <Addin id="Core" version="2.4"/> + <Addin id="Ide" version="2.4"/> + <Addin id="DesignerSupport" version="2.4"/> ++ <Addin id="XmlEditor" version="2.4"/> + </Dependencies> + + <ExtensionPoint path = "/MonoDevelop/GtkCore/ContextMenu/ProjectPad.ActionGroup"> +@@ -43,12 +44,13 @@ + </Extension> + + <Extension path = "/MonoDevelop/Ide/Pads/ProjectPad"> ++ <NodeBuilder class = "MonoDevelop.GtkCore.NodeBuilders.GuiProjectFolderNodeBuilder"/> + <NodeBuilder class = "MonoDevelop.GtkCore.NodeBuilders.ProjectFolderNodeBuilderExtension"/> ++ <NodeBuilder class = "MonoDevelop.GtkCore.NodeBuilders.ProjectFileNodeBuilderExtension"/> + <NodeBuilder class = "MonoDevelop.GtkCore.NodeBuilders.ProjectNodeBuilder"/> +- <NodeBuilder class = "MonoDevelop.GtkCore.NodeBuilders.WidgetNodeBuilder"/> + <NodeBuilder class = "MonoDevelop.GtkCore.NodeBuilders.WindowsFolderNodeBuilder"/> +- <NodeBuilder class = "MonoDevelop.GtkCore.NodeBuilders.ActionGroupNodeBuilder"/> + <NodeBuilder class = "MonoDevelop.GtkCore.NodeBuilders.StockIconsNodeBuilder"/> ++ <NodeBuilder class = "MonoDevelop.GtkCore.NodeBuilders.ProjectFileNodeBuilderExtension" /> + </Extension> + + <Extension path = "/MonoDevelop/Ide/FileTemplates"> +@@ -87,9 +89,13 @@ + <Command id = "MonoDevelop.GtkCore.GtkCommands.ImportGladeFile" + _label = "Import Glade file..." /> + <Command id = "MonoDevelop.GtkCore.GtkCommands.EditIcons" ++ icon = "md-gtkcore-iconfactory" + _label = "Edit Project Icons..." /> + <Command id = "MonoDevelop.GtkCore.GtkCommands.GtkSettings" +- _label = "GTK# support settings..." /> ++ _label = "GTK# support settings..." ++ icon = "md-gtkcore-gtk-logo"/> ++ <Command id = "MonoDevelop.GtkCore.GtkCommands.GenerateCode" ++ _label = "Generate code..."/> + </Category> + </Extension> + +@@ -103,16 +109,16 @@ + </Condition> + </Extension> + +- <Extension path = "/MonoDevelop/GtkCore/ContextMenu/ProjectPad.UserInterfaceFolder"> +- <CommandItem id = "MonoDevelop.GtkCore.GtkCommands.AddNewDialog" /> +- <CommandItem id = "MonoDevelop.GtkCore.GtkCommands.AddNewWindow" /> +- <CommandItem id = "MonoDevelop.GtkCore.GtkCommands.AddNewWidget" /> +- <CommandItem id = "MonoDevelop.GtkCore.GtkCommands.AddNewActionGroup" /> +- <SeparatorItem /> +- <CommandItem id = "MonoDevelop.GtkCore.GtkCommands.EditIcons" /> +- <CommandItem id = "MonoDevelop.GtkCore.GtkCommands.ImportGladeFile" /> +- <SeparatorItem /> +- <CommandItem id = "MonoDevelop.GtkCore.GtkCommands.GtkSettings" /> ++ <Extension path = "/MonoDevelop/Ide/ContextMenu/ProjectPad"> ++ <Condition id="ItemType" value="Project|MonoDevelop.GtkCore.NodeBuilders.GuiProjectFolder"> ++ <CommandItem id = "MonoDevelop.GtkCore.GtkCommands.EditIcons" insertafter="BuildSectionEnd"/> ++ <CommandItem id = "MonoDevelop.GtkCore.GtkCommands.ImportGladeFile" /> ++ <SeparatorItem/> ++ <CommandItem id = "MonoDevelop.GtkCore.GtkCommands.GtkSettings" /> ++ </Condition> ++ <Condition id="ItemType" value="ProjectFile"> ++ <CommandItem id = "MonoDevelop.GtkCore.GtkCommands.GenerateCode" insertafter="BuildSectionEnd"/> ++ </Condition> + </Extension> + + <Extension path = "/MonoDevelop/GtkCore/ContextMenu/ProjectPad.Component"> +@@ -145,7 +151,8 @@ + <Section id = "SteticOptionsPanel" + _label = "GTK# Settings" + fill="true" +- class = "MonoDevelop.GtkCore.Dialogs.WidgetBuilderOptionPanel"/> ++ class = "MonoDevelop.GtkCore.Dialogs.WidgetBuilderOptionPanel" ++ icon = "md-gtkcore-gtk-logo"/> + </Condition> + </Extension> + +@@ -158,8 +165,17 @@ + <StockIcon stockid = "md-gtkcore-dialog" resource = "dialog.png" /> + <StockIcon stockid = "md-gtkcore-widget" resource = "widget.png" /> + <StockIcon stockid = "md-gtkcore-actiongroup" resource = "actiongroup.png" /> ++ <StockIcon stockid = "md-gtkcore-iconfactory" resource = "image-x-generic.png" /> ++ <StockIcon stockid = "md-gtkcore-gtkx" resource = "gtkx.png" /> ++ <StockIcon stockid = "md-gtkcore-gtk-logo" resource = "gtk-logo.png"/> + </Extension> + ++ <Extension path = "/MonoDevelop/Core/MimeTypes"> ++ <MimeType id="text/x-gtkx" _description="Gtk# designer file" icon="gtk-page-setup" isText="true"> ++ <File pattern="*.gtkx" /> ++ </MimeType> ++ </Extension> ++ + <Extension path = "/MonoDevelop/ProjectModel/ProjectServiceExtensions"> + <Class class = "MonoDevelop.GtkCore.GuiBuilder.GtkProjectServiceExtension" insertafter="MidStep"/> + </Extension> +@@ -181,6 +197,10 @@ + </Extension> + + <Extension path = "/MonoDevelop/Ide/GlobalOptionsDialog/Preferences/Style"> +- <Panel _label = "GTK# Designer" class = "MonoDevelop.GtkCore.Dialogs.GtkDesignerOptionPanel" /> ++ <Panel _label = "GTK# Designer" class = "MonoDevelop.GtkCore.Dialogs.GtkDesignerOptionPanel" /> + </Extension> ++ ++ <Extension path = "/MonoDevelop/XmlEditor/XmlFileExtensions"> ++ <XmlFileExtension extension = ".gtkx"/> ++ </Extension> + </Addin> +Index: MonoDevelop.GtkCore.NodeBuilders/ProjectFolderNodeBuilderExtension.cs +=================================================================== +--- MonoDevelop.GtkCore.NodeBuilders/ProjectFolderNodeBuilderExtension.cs (revision 17) ++++ MonoDevelop.GtkCore.NodeBuilders/ProjectFolderNodeBuilderExtension.cs (working copy) +@@ -25,15 +25,15 @@ + // 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 MonoDevelop.Projects; + using MonoDevelop.Ide.Gui.Pads.ProjectPad; + using MonoDevelop.Components.Commands; + using MonoDevelop.GtkCore.GuiBuilder; ++using MonoDevelop.Ide.Gui; + using MonoDevelop.Ide.Gui.Components; + using MonoDevelop.Ide; ++using MonoDevelop.Ide.Commands; + + namespace MonoDevelop.GtkCore.NodeBuilders + { +@@ -41,8 +41,9 @@ + { + public override bool CanBuildNode (Type dataType) + { +- return typeof(ProjectFolder).IsAssignableFrom (dataType) || +- typeof(DotNetProject).IsAssignableFrom (dataType); ++ return typeof(ProjectFolder).IsAssignableFrom (dataType) && !(dataType is GuiProjectFolder); ++// typeof(DotNetProject).IsAssignableFrom (dataType); ++ return false; + } + + public override Type CommandHandlerType { +@@ -51,13 +52,13 @@ + + public override void GetNodeAttributes (ITreeNavigator treeNavigator, object dataObject, ref NodeAttributes attributes) + { +- if (treeNavigator.Options ["ShowAllFiles"]) ++ if (dataObject is GuiProjectFolder) + return; +- ++ + ProjectFolder folder = dataObject as ProjectFolder; + if (folder != null && folder.Project is DotNetProject) { + GtkDesignInfo info = GtkDesignInfo.FromProject (folder.Project); +- if (info.GtkGuiFolder == folder.Path) ++ if (info.SteticFolder == folder.Path) + attributes |= NodeAttributes.Hidden; + } + } +@@ -74,7 +75,7 @@ + [CommandUpdateHandler (MonoDevelop.GtkCore.GtkCommands.AddNewDialog)] + public void UpdateAddNewDialogToProject (CommandInfo cinfo) + { +- cinfo.Visible = CanAddWindow (); ++ cinfo.Visible = CanAddWindow () && !(CurrentNode.DataItem is GuiProjectFolder); + } + + [CommandHandler (MonoDevelop.GtkCore.GtkCommands.AddNewWindow)] +@@ -86,7 +87,7 @@ + [CommandUpdateHandler (MonoDevelop.GtkCore.GtkCommands.AddNewWindow)] + public void UpdateAddNewWindowToProject (CommandInfo cinfo) + { +- cinfo.Visible = CanAddWindow (); ++ cinfo.Visible = CanAddWindow () && !(CurrentNode.DataItem is GuiProjectFolder); + } + + [CommandHandler (MonoDevelop.GtkCore.GtkCommands.AddNewWidget)] +@@ -98,8 +99,8 @@ + [CommandUpdateHandler (MonoDevelop.GtkCore.GtkCommands.AddNewWidget)] + public void UpdateAddNewWidgetToProject (CommandInfo cinfo) + { +- cinfo.Visible = CanAddWindow (); +- } ++ cinfo.Visible = CanAddWindow () && !(CurrentNode.DataItem is GuiProjectFolder); ++ } + + [CommandHandler (MonoDevelop.GtkCore.GtkCommands.AddNewActionGroup)] + public void AddNewActionGroupToProject() +@@ -110,51 +111,20 @@ + [CommandUpdateHandler (MonoDevelop.GtkCore.GtkCommands.AddNewActionGroup)] + public void UpdateAddNewActionGroupToProject(CommandInfo cinfo) + { +- cinfo.Visible = CanAddWindow (); ++ cinfo.Visible = CanAddWindow () && !(CurrentNode.DataItem is GuiProjectFolder); + } + +- [CommandHandler (GtkCommands.ImportGladeFile)] +- protected void OnImportGladeFile () ++ public override bool CanDropMultipleNodes (object[] dataObjects, DragOperation operation, DropPosition position) + { +- Project project = CurrentNode.GetParentDataItem (typeof(Project), true) as Project; +- GuiBuilderService.ImportGladeFile (project); ++ return false; ++ ++ foreach (object dataObject in dataObjects) ++ if (dataObjects is GuiProjectFolder) ++ return false; ++ ++ return base.CanDropMultipleNodes (dataObjects, operation, position); + } +- +- [CommandUpdateHandler (GtkCommands.ImportGladeFile)] +- protected void UpdateImportGladeFile (CommandInfo cinfo) +- { +- cinfo.Visible = CanAddWindow (); +- } +- +- [CommandHandler (GtkCommands.EditIcons)] +- protected void OnEditIcons () +- { +- Project project = CurrentNode.GetParentDataItem (typeof(Project), true) as Project; +- GuiBuilderProject gp = GtkDesignInfo.FromProject (project).GuiBuilderProject; +- Stetic.Project sp = gp.SteticProject; +- sp.EditIcons (); +- gp.Save (true); +- } +- +- [CommandUpdateHandler (GtkCommands.EditIcons)] +- protected void UpdateEditIcons (CommandInfo cinfo) +- { +- cinfo.Visible = CanAddWindow (); +- } +- +- [CommandHandler (GtkCommands.GtkSettings)] +- protected void OnGtkSettings () +- { +- Project project = CurrentNode.GetParentDataItem (typeof(Project), true) as Project; +- IdeApp.ProjectOperations.ShowOptions (project, "SteticOptionsPanel"); +- } +- +- [CommandUpdateHandler (GtkCommands.EditIcons)] +- protected void UpdateGtkSettings (CommandInfo cinfo) +- { +- cinfo.Visible = CanAddWindow (); +- } +- ++ + bool CanAddWindow () + { + DotNetProject project = CurrentNode.GetParentDataItem (typeof(Project), true) as DotNetProject; +Index: MonoDevelop.GtkCore.NodeBuilders/StockIconsNodeBuilder.cs +=================================================================== +--- MonoDevelop.GtkCore.NodeBuilders/StockIconsNodeBuilder.cs (revision 17) ++++ MonoDevelop.GtkCore.NodeBuilders/StockIconsNodeBuilder.cs (working copy) +@@ -70,7 +70,7 @@ + GtkDesignInfo info = GtkDesignInfo.FromProject (node.Project); + GuiBuilderProject gp = info.GuiBuilderProject; + Stetic.Project sp = gp.SteticProject; +- sp.ImagesRootPath = FileService.AbsoluteToRelativePath (info.GtkGuiFolder, gp.Project.BaseDirectory); ++ sp.ImagesRootPath = FileService.AbsoluteToRelativePath (info.SteticFolder, gp.Project.BaseDirectory); + sp.ImportFileCallback = delegate (string file) { + return GuiBuilderService.ImportFile (gp.Project, file); + }; +Index: MonoDevelop.GtkCore.NodeBuilders/ProjectFileNodeBuilderExtension.cs +=================================================================== +--- MonoDevelop.GtkCore.NodeBuilders/ProjectFileNodeBuilderExtension.cs (revision 0) ++++ MonoDevelop.GtkCore.NodeBuilders/ProjectFileNodeBuilderExtension.cs (revision 124) +@@ -0,0 +1,144 @@ ++using System; ++ ++using MonoDevelop.Components.Commands; ++using MonoDevelop.GtkCore.GuiBuilder; ++using MonoDevelop.Ide; ++using MonoDevelop.Ide.Commands; ++using MonoDevelop.Ide.Gui; ++using MonoDevelop.Ide.Gui.Components; ++using MonoDevelop.Ide.Gui.Pads.ProjectPad; ++using MonoDevelop.Projects; ++using MonoDevelop.Projects.Dom; ++ ++namespace MonoDevelop.GtkCore.NodeBuilders ++{ ++ public class ProjectFileBuilder : ProjectFileNodeBuilder ++ { ++ ++ } ++ ++ public class ProjectFileNodeBuilderExtension : NodeBuilderExtension ++ { ++ public override bool CanBuildNode (Type dataType) ++ { ++ return typeof(ProjectFile).IsAssignableFrom (dataType); ++ } ++ ++ public override Type CommandHandlerType { ++ get { return typeof (ComponentCommandHandler); } ++ } ++ ++ public override void GetNodeAttributes (ITreeNavigator treeNavigator, object dataObject, ref NodeAttributes attributes) ++ { ++ if (treeNavigator.Options ["ShowAllFiles"]) ++ return; ++ ++ ProjectFile pf = (ProjectFile) dataObject; ++ GtkDesignInfo info = GtkDesignInfo.FromProject (pf.Project); ++ if (info.HideGtkxFiles && pf.FilePath.Extension == ".gtkx") ++ attributes |= NodeAttributes.Hidden; ++ } ++ ++ ++ public override void BuildNode (ITreeBuilder treeBuilder, object dataObject, ref string label, ref Gdk.Pixbuf icon, ref Gdk.Pixbuf closedIcon) ++ { ++ ProjectFile pf = (ProjectFile) dataObject; ++ ++ //do not show custom icon for generated source files ++ if (pf.DependsOn == null) { ++ GtkComponentType type = pf.GetComponentType (); ++ ++ switch (type) { ++ case GtkComponentType.Dialog : ++ icon = ImageService.GetPixbuf ("md-gtkcore-dialog", Gtk.IconSize.Menu); ++ break; ++ case GtkComponentType.Widget : ++ icon = ImageService.GetPixbuf ("md-gtkcore-widget", Gtk.IconSize.Menu); ++ break; ++ case GtkComponentType.ActionGroup : ++ icon = ImageService.GetPixbuf ("md-gtkcore-actiongroup", Gtk.IconSize.Menu); ++ break; ++ case GtkComponentType.IconFactory : ++ icon = ImageService.GetPixbuf ("md-gtkcore-iconfactory", Gtk.IconSize.Menu); ++ label = "Stock icons"; ++ break; ++ } ++ } ++ } ++ ++ //override ++ public override bool HasChildNodes (ITreeBuilder builder, object dataObject) ++ { ++ return base.HasChildNodes (builder, dataObject); ++ } ++ } ++ ++ public class ComponentCommandHandler : NodeCommandHandler ++ { ++ /*public override void ActivateItem () ++ { ++ ProjectFile pf = (ProjectFile) CurrentNode.DataItem; ++ ++ if (pf.IsComponentFile ()) { ++ Document doc = IdeApp.Workbench.OpenDocument (pf.FilePath, true); ++ ++ if (doc != null) { ++ GuiBuilderView view = doc.GetContent<GuiBuilderView> (); ++ if (view != null) { ++ GtkComponentType type = pf.GetComponentType (); ++ ++ switch (type) { ++ case GtkComponentType.Dialog : ++ case GtkComponentType.Widget : ++ view.ShowDesignerView (); ++ break; ++ case GtkComponentType.ActionGroup : ++ view.ShowActionDesignerView (((Stetic.ActionGroupInfo) CurrentNode.DataItem).Name); ++ break; ++ } ++ } ++ } ++ return; ++ } ++ base.ActivateItem (); ++ } ++ */ ++ ++ [CommandHandler (GtkCommands.GenerateCode)] ++ protected void OnGenerateCode () ++ { ++ ProjectFile pf = CurrentNode.DataItem as ProjectFile; ++ Project project = CurrentNode.GetParentDataItem (typeof(Project), true) as Project; ++ GtkDesignInfo info = GtkDesignInfo.FromProject (project); ++ GuiBuilderProject gproject = info.GuiBuilderProject; ++ ++ gproject.GenerateCode (pf.FilePath); ++ } ++ ++ [CommandUpdateHandler (GtkCommands.GenerateCode)] ++ protected void UpdateGenerateCode (CommandInfo cinfo) ++ { ++ ProjectFile pf = CurrentNode.DataItem as ProjectFile; ++ ++ if (pf.DependsOn == null && pf.HasChildren) ++ cinfo.Visible = pf.IsComponentFile (); ++ else ++ cinfo.Visible = false; ++ } ++ ++ [CommandUpdateHandler (EditCommands.Copy)] ++ [CommandUpdateHandler (EditCommands.Delete)] ++ [CommandUpdateHandler (EditCommands.Rename)] ++ protected void UpdateDisabledCommands (CommandInfo cinfo) ++ { ++ //disable operations for generated files in designer folder ++ cinfo.Visible = false;//(CurrentNode.GetParentDataItem (typeof (GuiProjectFolder), true) == null); ++ } ++ ++ public override DragOperation CanDragNode () ++ { ++ return DragOperation.None; ++ } ++ ++ } ++} +\ No newline at end of file +Index: MonoDevelop.GtkCore.NodeBuilders/ChangeLog +=================================================================== +--- MonoDevelop.GtkCore.NodeBuilders/ChangeLog (revision 0) ++++ MonoDevelop.GtkCore.NodeBuilders/ChangeLog (revision 125) +@@ -0,0 +1,58 @@ ++2010-08-15 Krzysztof Marecki <freefirma@gmail.com> ++ ++ * ProjectNodeBuilder.cs: ++ * GuiProjectFolderNodeBuilder.cs: ++ ++2010-08-15 Krzysztof Marecki <freefirma@gmail.com> ++ ++ * ProjectFileExtension.cs: ++ * GuiProjectFolderNodeBuilder.cs: ++ * ProjectFileNodeBuilderExtension.cs: ++ * ProjectFolderNodeBuilderExtension.cs: ++ ++2010-08-13 Krzysztof Marecki <freefirma@gmail.com> ++ ++ * ProjectNodeBuilder.cs: ++ * StockIconsNodeBuilder.cs: ++ * ProjectFileNodeBuilderExtension.cs: ++ * ProjectFolderNodeBuilderExtension.cs: ++ ++2010-08-09 Krzysztof Marecki <freefirma@gmail.com> ++ ++ * GuiProjectFolder.cs: Put gui project folder directly below References ++ in the project pad ++ * ProjectNodeBuilder.cs: ++ * GuiProjectFolderNodeBuilder.cs: ++ * ProjectFolderNodeBuilderExtension.cs: ++ ++2010-07-06 Krzysztof Marecki <marecki.krzysztof@gmail.com> ++ ++ * ProjectFileExtension.cs: Move cursor in entryFolder to the end. ++ ++2010-07-05 Krzysztof Marecki <marecki.krzysztof@gmail.com> ++ ++ * ProjectFileExtension.cs: Better approach for obtaining GtkComponentType ++ * ProjectFileNodeBuilderExtension.cs: ++ * ProjectFolderNodeBuilderExtension.cs: ++ ++2010-06-28 Krzysztof Marecki <marecki.krzysztof@gmail.com> ++ ++ * ProjectNodeBuilder.cs: ++ * ProjectFileNodeBuilderExtension.cs: ++ * ProjectFolderNodeBuilderExtension.cs: ++ ++2010-06-23 Krzysztof Marecki <marecki.krzysztof@gmail.com> ++ ++ * ProjectNodeBuilder.cs: ++ * ProjectFileNodeBuilderExtension.cs: Show ProjectConversionDialog before ++ conversion ++ ++2010-06-21 Krzysztof Marecki <marecki.krzysztof@gmail.com> ++ ++ * ProjectNodeBuilder.cs: Convert a project file layout on open ++ * ProjectFileNodeBuilderExtension.cs: Group components files ++ ++2010-06-16 Krzysztof Marecki <marecki.krzysztof@gmail.com> ++ ++ * ProjectFileNodeBuilderExtension.cs: ++ +Index: MonoDevelop.GtkCore.NodeBuilders/ProjectNodeBuilder.cs +=================================================================== +--- MonoDevelop.GtkCore.NodeBuilders/ProjectNodeBuilder.cs (revision 17) ++++ MonoDevelop.GtkCore.NodeBuilders/ProjectNodeBuilder.cs (working copy) +@@ -28,14 +28,19 @@ + + using System; + using System.Collections; ++using System.IO; + ++using Gtk; ++ + using MonoDevelop.Projects; + using MonoDevelop.Core; + using MonoDevelop.Ide.Gui.Pads; + using MonoDevelop.Ide.Gui; + using MonoDevelop.Ide.Gui.Components; +- ++using MonoDevelop.Ide.Gui.Pads.ProjectPad; ++using MonoDevelop.GtkCore.Dialogs; + using MonoDevelop.GtkCore.GuiBuilder; ++using MonoDevelop.Ide; + + namespace MonoDevelop.GtkCore.NodeBuilders + { +@@ -48,6 +53,12 @@ + return typeof(DotNetProject).IsAssignableFrom (dataType); + } + ++ public override Type CommandHandlerType { ++ get { ++ return typeof (GuiProjectFolderCommandHandler); ++ } ++ } ++ + protected override void Initialize () + { + lock (typeof (ProjectNodeBuilder)) +@@ -60,10 +71,62 @@ + instance = null; + } + ++ public override void BuildNode (ITreeBuilder treeBuilder, object dataObject, ref string label, ref Gdk.Pixbuf icon, ref Gdk.Pixbuf closedIcon) ++ { ++ Project project = dataObject as Project; ++ ++ if (project is DotNetProject) { ++ GtkDesignInfo info = GtkDesignInfo.FromProject (project); ++ ++ if (info.OldVersion) { ++ ProjectConversionDialog dialog = new ProjectConversionDialog (project, info.SteticFolderName); ++ ++ try ++ { ++ if (dialog.Run () == (int)ResponseType.Yes) { ++ info.GuiBuilderProject.Convert (dialog.GuiFolderName, dialog.MakeBackup); ++ IdeApp.ProjectOperations.Save (project); ++ } ++ } finally { ++ dialog.Destroy (); ++ } ++ } ++ ++ project.FileAddedToProject += HandleProjectFileAddedToProject; ++ } ++ } ++ ++ void HandleProjectFileAddedToProject (object sender, ProjectFileEventArgs e) ++ { ++ Project project = e.Project; ++ ProjectFile pf = e.ProjectFile; ++ string fileName = pf.FilePath.FullPath.ToString (); ++ GtkDesignInfo info = GtkDesignInfo.FromProject (project); ++ ++ string buildFile = info.GetBuildFile (fileName); ++ if (!project.IsFileInProject(buildFile) && File.Exists (buildFile)) { ++ ProjectFile pf2 = project.AddFile (buildFile, BuildAction.Compile); ++ pf2.DependsOn = pf.FilePath.FileName; ++ } ++ ++ string gtkxFile = info.GetGtkxFile (fileName); ++ if (!project.IsFileInProject(gtkxFile) && File.Exists (gtkxFile)) { ++ ProjectFile pf3 = project.AddFile (gtkxFile, BuildAction.EmbeddedResource); ++ pf3.DependsOn = pf.FilePath.FileName; ++ } ++ } ++ + public override void BuildChildNodes (ITreeBuilder builder, object dataObject) + { +- if (GtkDesignInfo.HasDesignedObjects ((Project)dataObject)) +- builder.AddChild (new WindowsFolder ((Project)dataObject)); ++ Project project = (Project)dataObject; ++ GtkDesignInfo info = GtkDesignInfo.FromProject (project); ++ ++ if (GtkDesignInfo.HasDesignedObjects (project)) { ++ GuiProjectFolder folder = new GuiProjectFolder(info.SteticFolder.FullPath, project, null); ++ ++ builder.AddChild (new WindowsFolder (project)); ++ builder.AddChild (folder); ++ } + } + + public static void OnSupportChanged (Project p) +Index: MonoDevelop.GtkCore.NodeBuilders/ProjectFileExtension.cs +=================================================================== +--- MonoDevelop.GtkCore.NodeBuilders/ProjectFileExtension.cs (revision 0) ++++ MonoDevelop.GtkCore.NodeBuilders/ProjectFileExtension.cs (revision 124) +@@ -0,0 +1,52 @@ ++using System; ++using MonoDevelop.GtkCore.GuiBuilder; ++using MonoDevelop.Projects; ++using MonoDevelop.Projects.Dom; ++using MonoDevelop.Projects.Dom.Parser; ++ ++namespace MonoDevelop.GtkCore.NodeBuilders ++{ ++ public enum GtkComponentType ++ { ++ Dialog, ++ Widget, ++ ActionGroup, ++ IconFactory, ++ None ++ } ++ ++ public static class ProjectFileExtension ++ { ++ public static bool IsComponentFile (this ProjectFile pf) ++ { ++ return pf.GetComponentType () != GtkComponentType.None; ++ } ++ ++ public static GtkComponentType GetComponentType (this ProjectFile pf) ++ { ++ GtkDesignInfo info = GtkDesignInfo.FromProject (pf.Project); ++ ParsedDocument doc = ProjectDomService.GetParsedDocument (ProjectDomService.GetProjectDom (pf.Project), pf.Name); ++ //ParsedDocument doc = ProjectDomService.ParseFile (ProjectDomService.GetProjectDom (pf.Project), pf.FilePath.ToString ()); ++ if (doc != null && doc.CompilationUnit != null) { ++ foreach (IType t in doc.CompilationUnit.Types) { ++ string className = t.FullName; ++ if (className != null) { ++ GuiBuilderWindow win = info.GuiBuilderProject.GetWindowForClass (className); ++ if (win != null) ++ return win.RootWidget.IsWindow ? GtkComponentType.Dialog : GtkComponentType.Widget; ++ ++ Stetic.ActionGroupInfo action = info.GuiBuilderProject.GetActionGroup (className); ++ if (action != null) ++ return GtkComponentType.ActionGroup; ++ ++ } ++ } ++ } ++ if (pf.Name.Contains ("IconFactory.gtkx")) ++ return GtkComponentType.IconFactory; ++ ++ return GtkComponentType.None; ++ } ++ } ++} ++ +Index: MonoDevelop.GtkCore.NodeBuilders/GuiProjectFolderNodeBuilder.cs +=================================================================== +--- MonoDevelop.GtkCore.NodeBuilders/GuiProjectFolderNodeBuilder.cs (revision 0) ++++ MonoDevelop.GtkCore.NodeBuilders/GuiProjectFolderNodeBuilder.cs (revision 125) +@@ -0,0 +1,176 @@ ++// ++// GuiProjectFolderNodeBuilder.cs ++// ++// Author: ++// Krzysztof Marecki <marecki.krzysztof@gmail.com> ++// ++// Copyright (c) 2010 KrzysztofMarecki ++// ++// 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 MonoDevelop.Components.Commands; ++using MonoDevelop.Core; ++using MonoDevelop.Ide.Commands; ++using MonoDevelop.Ide; ++using MonoDevelop.Ide.Gui; ++using MonoDevelop.Ide.Gui.Components; ++using MonoDevelop.Ide.Gui.Pads.ProjectPad; ++using MonoDevelop.Projects; ++ ++using MonoDevelop.GtkCore.GuiBuilder; ++ ++namespace MonoDevelop.GtkCore.NodeBuilders ++{ ++ public class GuiProjectFolderNodeBuilder : ProjectFolderNodeBuilder ++ { ++ public override Type NodeDataType { ++ get { return typeof(GuiProjectFolder); } ++ } ++ ++ public override Type CommandHandlerType { ++ get { return typeof(GuiProjectFolderCommandHandler); } ++ } ++ ++ public override string GetNodeName (ITreeNavigator thisNode, object dataObject) ++ { ++ //nodes are sorted alphabetically and we want to have gui folder on the top ++ return string.Empty; ++ } ++ ++ ++ public override void BuildNode (ITreeBuilder treeBuilder, object dataObject, ref string label, ref Gdk.Pixbuf icon, ref Gdk.Pixbuf closedIcon) ++ { ++ GuiProjectFolder folder = (GuiProjectFolder) dataObject; ++ ++ icon = Context.GetIcon (Stock.OpenResourceFolder); ++ closedIcon = Context.GetIcon (Stock.ClosedResourceFolder); ++ label = folder.Name; ++ } ++ } ++ ++ public class GuiProjectFolderCommandHandler : ProjectFolderCommandHandler ++ { ++ [CommandHandler (GtkCommands.ImportGladeFile)] ++ protected void OnImportGladeFile () ++ { ++ Project project = CurrentNode.GetParentDataItem (typeof(Project), true) as Project; ++ GuiBuilderService.ImportGladeFile (project); ++ } ++ ++ [CommandUpdateHandler (GtkCommands.ImportGladeFile)] ++ protected void UpdateImportGladeFile (CommandInfo cinfo) ++ { ++ cinfo.Visible = CanAddWindow (); ++ } ++ ++ [CommandHandler (GtkCommands.EditIcons)] ++ protected void OnEditIcons () ++ { ++ Project project = CurrentNode.GetParentDataItem (typeof(Project), true) as Project; ++ GuiBuilderProject gp = GtkDesignInfo.FromProject (project).GuiBuilderProject; ++ Stetic.Project sp = gp.SteticProject; ++ sp.EditIcons (); ++ gp.Save (true); ++ } ++ ++ [CommandUpdateHandler (GtkCommands.EditIcons)] ++ protected void UpdateEditIcons (CommandInfo cinfo) ++ { ++ cinfo.Visible = CanAddWindow (); ++ } ++ ++ [CommandHandler (GtkCommands.GtkSettings)] ++ protected void OnGtkSettings () ++ { ++ Project project = CurrentNode.GetParentDataItem (typeof(Project), true) as Project; ++ IdeApp.ProjectOperations.ShowOptions (project, "SteticOptionsPanel"); ++ } ++ ++ [CommandUpdateHandler (GtkCommands.EditIcons)] ++ protected void UpdateGtkSettings (CommandInfo cinfo) ++ { ++ //cinfo.Visible = CanAddWindow (); ++ } ++ ++ [CommandUpdateHandler (EditCommands.Delete)] ++ [CommandUpdateHandler (EditCommands.Rename)] ++ [CommandUpdateHandler (ProjectCommands.AddNewFiles)] ++ [CommandUpdateHandler (ProjectCommands.AddFiles)] ++ [CommandUpdateHandler (ProjectCommands.AddSolutionFolder)] ++ [CommandUpdateHandler (ProjectCommands.AddItem)] ++ [CommandUpdateHandler (ProjectCommands.NewFolder)] ++ protected void UpdateDisabledCommands (CommandInfo cinfo) ++ { ++ cinfo.Visible = false; ++ cinfo.Enabled = false; ++ } ++ ++ bool CanAddWindow () ++ { ++ DotNetProject project = CurrentNode.GetParentDataItem (typeof(Project), true) as DotNetProject; ++ return GtkDesignInfo.SupportsDesigner (project); ++ } ++ ++ public override DragOperation CanDragNode () ++ { ++ return DragOperation.None; ++ } ++ ++ public override bool CanDeleteItem () ++ { ++ return false; ++ } ++ ++ public override bool CanDropMultipleNodes (object[] dataObjects, DragOperation operation) ++ { ++ return false; ++ } ++ ++ public override bool CanDropMultipleNodes (object[] dataObjects, DragOperation operation, DropPosition position) ++ { ++ return false; ++ } ++ ++ public override bool CanDeleteMultipleItems () ++ { ++ return false; ++ } ++ ++ public override bool CanDropNode (object dataObject, DragOperation operation) ++ { ++ return false; ++ } ++ ++ public override bool CanDropNode (object dataObject, DragOperation operation, DropPosition position) ++ { ++ return false; ++ } ++ ++ public override void RenameItem (string newName) ++ { ++ Project project = CurrentNode.GetParentDataItem (typeof(Project), true) as Project; ++ GtkDesignInfo info = GtkDesignInfo.FromProject (project); ++ info.SteticFolderName = newName; ++ ++ base.RenameItem (newName); ++ } ++ } ++} ++ +Index: MonoDevelop.GtkCore.NodeBuilders/GuiProjectFolder.cs +=================================================================== +--- MonoDevelop.GtkCore.NodeBuilders/GuiProjectFolder.cs (revision 0) ++++ MonoDevelop.GtkCore.NodeBuilders/GuiProjectFolder.cs (revision 112) +@@ -0,0 +1,42 @@ ++// ++// GuiProjectFolder.cs ++// ++// Author: ++// Krzysztof Marecki <marecki.krzysztof@gmail.com> ++// ++// Copyright (c) 2010 KrzysztofMarecki ++// ++// 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 MonoDevelop.Core; ++using MonoDevelop.Ide.Gui.Pads.ProjectPad; ++using MonoDevelop.Projects; ++using MonoDevelop.Projects.Dom; ++ ++namespace MonoDevelop.GtkCore.NodeBuilders ++{ ++ public class GuiProjectFolder : ProjectFolder ++ { ++ public GuiProjectFolder (FilePath absolutePath, IWorkspaceObject parentWorkspaceObject, object parent) ++ : base (absolutePath, parentWorkspaceObject, parent) ++ { ++ } ++ } ++} ++ +Index: MonoDevelop.GtkCore.NodeBuilders/WindowsFolderNodeBuilder.cs +=================================================================== +--- MonoDevelop.GtkCore.NodeBuilders/WindowsFolderNodeBuilder.cs (revision 17) ++++ MonoDevelop.GtkCore.NodeBuilders/WindowsFolderNodeBuilder.cs (working copy) +@@ -82,10 +82,10 @@ + GtkDesignInfo info = GtkDesignInfo.FromProject (p); + if (!info.GuiBuilderProject.HasError) { + builder.AddChild (new StockIconsNode (p)); +- foreach (GuiBuilderWindow fi in info.GuiBuilderProject.Windows) +- builder.AddChild (fi); +- foreach (Stetic.ActionGroupInfo group in info.GuiBuilderProject.SteticProject.ActionGroups) +- builder.AddChild (group); ++// foreach (GuiBuilderWindow fi in info.GuiBuilderProject.Windows) ++// builder.AddChild (fi); ++// foreach (Stetic.ActionGroupInfo group in info.GuiBuilderProject.SteticProject.ActionGroups) ++// builder.AddChild (group); + } + } + +Index: MonoDevelop.GtkCore.Dialogs/ProjectConversionDialog.cs +=================================================================== +--- MonoDevelop.GtkCore.Dialogs/ProjectConversionDialog.cs (revision 0) ++++ MonoDevelop.GtkCore.Dialogs/ProjectConversionDialog.cs (revision 124) +@@ -0,0 +1,40 @@ ++using System; ++using Gtk; ++ ++using MonoDevelop.Projects; ++ ++namespace MonoDevelop.GtkCore.Dialogs ++{ ++ public partial class ProjectConversionDialog : Gtk.Dialog ++ { ++ public ProjectConversionDialog (IntPtr raw) ++ : base (raw) ++ { ++ } ++ ++ public string GuiFolderName { get; private set; } ++ ++ public bool MakeBackup { get; private set; } ++ ++ ++ public ProjectConversionDialog (Project project, string guiFolderName) ++ { ++ this.Build (); ++ ++ entryFolder.Text = guiFolderName; ++ Title = project.Name; ++ entryFolder.Position = -1; ++ ++ buttonConvert.Clicked += HandleButtonConvertClicked; ++ } ++ ++ void HandleButtonConvertClicked (object sender, EventArgs e) ++ { ++ GuiFolderName = entryFolder.Text; ++ MakeBackup = checkBackup.Active; ++ ++ Respond (ResponseType.Yes); ++ } ++ } ++} ++ +Index: MonoDevelop.GtkCore.Dialogs/ChangeLog +=================================================================== +--- MonoDevelop.GtkCore.Dialogs/ChangeLog (revision 0) ++++ MonoDevelop.GtkCore.Dialogs/ChangeLog (revision 124) +@@ -0,0 +1,18 @@ ++2010-08-15 Krzysztof Marecki <freefirma@gmail.com> ++ ++ * ProjectConversionDialog.cs: ++ ++2010-08-13 Krzysztof Marecki <freefirma@gmail.com> ++ ++ * ProjectConversionDialog.cs: ++ * WidgetBuilderOptionPanel.cs: ++ ++2010-07-06 Krzysztof Marecki <marecki.krzysztof@gmail.com> ++ ++ * ProjectConversionDialog.cs: ++ ++2010-06-23 Krzysztof Marecki <marecki.krzysztof@gmail.com> ++ ++ * ProjectConversionDialog.cs: Initial commit ++ * WidgetBuilderOptionPanel.cs: ++ +Index: MonoDevelop.GtkCore.Dialogs/WidgetBuilderOptionPanel.cs +=================================================================== +--- MonoDevelop.GtkCore.Dialogs/WidgetBuilderOptionPanel.cs (revision 17) ++++ MonoDevelop.GtkCore.Dialogs/WidgetBuilderOptionPanel.cs (working copy) +@@ -43,6 +43,8 @@ + Gtk.CheckButton checkGettext; + Gtk.Entry entryGettext; + Gtk.ComboBox comboVersions; ++ Gtk.Entry entryFolderName; ++ Gtk.CheckButton checkHideFiles; + + DotNetProject project; + +@@ -84,11 +86,23 @@ + box.ShowAll (); + PackStart (box, false, false, 0); + +- checkGettext.Clicked += delegate { +- box.Sensitive = checkGettext.Active; +- if (checkGettext.Active) +- entryGettext.Text = "Mono.Unix.Catalog"; +- }; ++ sep= new HSeparator (); ++ sep.Show (); ++ PackStart (sep, false, false, 0); ++ ++ box = new Gtk.HBox (false, 3); ++ box.PackStart (new Label (GettextCatalog.GetString ("Stetic folder name :")), false, false, 0); ++ entryFolderName = new Gtk.Entry (); ++ entryFolderName.Text = designInfo.SteticFolderName; ++ entryFolderName.Sensitive = false; ++ box.PackStart (entryFolderName, false, false, 0); ++ box.ShowAll (); ++ PackStart (box, false, false, 0); ++ ++ checkHideFiles = new CheckButton (GettextCatalog.GetString ("Hide designer files")); ++ checkHideFiles.Active = designInfo.HideGtkxFiles; ++ checkHideFiles.Show (); ++ PackStart (checkHideFiles, false, false, 0); + } + + public void Store () +@@ -101,6 +115,8 @@ + info.GenerateGettext = checkGettext.Active; + info.GettextClass = entryGettext.Text; + info.GuiBuilderProject.SteticProject.TargetGtkVersion = comboVersions.ActiveText; ++ info.SteticFolderName = entryFolderName.Text; ++ info.HideGtkxFiles = checkHideFiles.Active; + info.GuiBuilderProject.Save (false); + } + refmgr.Dispose (); +Index: MonoDevelop.GtkCore2.csproj +=================================================================== +--- MonoDevelop.GtkCore2.csproj (revision 17) ++++ MonoDevelop.GtkCore2.csproj (working copy) +@@ -59,12 +59,21 @@ + <Reference Include="gtk-sharp, Version=2.12.0.0, Culture=neutral, PublicKeyToken=35e10195dab3c99f"> + <SpecificVersion>False</SpecificVersion> + </Reference> ++ <Reference Include="System.Core" /> ++ <Reference Include="Mono.Cecil, Version=0.6.9.0, Culture=neutral, PublicKeyToken=0738eb9f132ed756"> ++ <Package>monodevelop</Package> ++ </Reference> ++ <Reference Include="NRefactory, Version=2.1.1.0, Culture=neutral, PublicKeyToken=efe927acf176eea2"> ++ <Package>monodevelop</Package> ++ </Reference> ++ <Reference Include="Mono.Debugging, Version=0.0.0.0, Culture=neutral, PublicKeyToken=9307d64546e0580d"> ++ <Package>monodevelop</Package> ++ </Reference> + </ItemGroup> + <ItemGroup> + <ProjectReference Include="..\..\core\MonoDevelop.Core\MonoDevelop.Core.csproj"> + <Project>{7525BB88-6142-4A26-93B9-A30C6983390A}</Project> + <Name>MonoDevelop.Core</Name> +- <Private>False</Private> + </ProjectReference> + <ProjectReference Include="..\..\core\MonoDevelop.Ide\MonoDevelop.Ide.csproj"> + <Project>{27096E7F-C91C-4AC6-B289-6897A701DF21}</Project> +@@ -76,11 +85,6 @@ + <Name>MonoDevelop.DesignerSupport</Name> + <Private>False</Private> + </ProjectReference> +- <ProjectReference Include="..\..\..\contrib\Mono.Cecil\Mono.Cecil.csproj"> +- <Project>{3EC06433-F168-4C5B-A885-99CE4AB617E1}</Project> +- <Name>Mono.Cecil</Name> +- <Private>False</Private> +- </ProjectReference> + <ProjectReference Include="..\Deployment\MonoDevelop.Deployment\MonoDevelop.Deployment.csproj"> + <Project>{9BC670A8-1851-40EC-9685-279F4C98433D}</Project> + <Name>MonoDevelop.Deployment</Name> +@@ -151,6 +155,12 @@ + <EmbeddedResource Include="gtk-gui\gui.stetic"> + <LogicalName>gui.stetic</LogicalName> + </EmbeddedResource> ++ <EmbeddedResource Include="icons\gtkx.png"> ++ <LogicalName>gtkx.png</LogicalName> ++ </EmbeddedResource> ++ <EmbeddedResource Include="icons\gtk-logo.png"> ++ <LogicalName>gtk-logo.png</LogicalName> ++ </EmbeddedResource> + </ItemGroup> + <ItemGroup> + <Compile Include="MonoDevelop.GtkCore.Commands\GladeCommands.cs" /> +@@ -166,7 +176,6 @@ + <Compile Include="MonoDevelop.GtkCore\GtkCoreService.cs" /> + <Compile Include="MonoDevelop.GtkCore.Dialogs\WidgetBuilderOptionPanel.cs" /> + <Compile Include="MonoDevelop.GtkCore.NodeBuilders\ProjectNodeBuilder.cs" /> +- <Compile Include="MonoDevelop.GtkCore.NodeBuilders\WidgetNodeBuilder.cs" /> + <Compile Include="MonoDevelop.GtkCore.NodeBuilders\ProjectFolderNodeBuilderExtension.cs" /> + <Compile Include="MonoDevelop.GtkCore.NodeBuilders\WindowsFolderNodeBuilder.cs" /> + <Compile Include="MonoDevelop.GtkCore.NodeBuilders\WindowsFolder.cs" /> +@@ -176,7 +185,6 @@ + <Compile Include="MonoDevelop.GtkCore.Dialogs\ConfirmWindowDeleteDialog.cs" /> + <Compile Include="MonoDevelop.GtkCore\ProjectResourceProvider.cs" /> + <Compile Include="MonoDevelop.GtkCore.GuiBuilder\ActionGroupView.cs" /> +- <Compile Include="MonoDevelop.GtkCore.NodeBuilders\ActionGroupNodeBuilder.cs" /> + <Compile Include="MonoDevelop.GtkCore.GuiBuilder\ActionGroupDisplayBinding.cs" /> + <Compile Include="MonoDevelop.GtkCore.GuiBuilder\CombinedDesignView.cs" /> + <Compile Include="MonoDevelop.GtkCore.GuiBuilder\CodeBinder.cs" /> +@@ -193,8 +201,15 @@ + <Compile Include="MonoDevelop.GtkCore.Dialogs\GtkDesignerOptionsPanelWidget.cs" /> + <Compile Include="gtk-gui\MonoDevelop.GtkCore.Dialogs.GtkDesignerOptionsPanelWidget.cs" /> + <Compile Include="MonoDevelop.GtkCore\Counters.cs" /> ++ <Compile Include="MonoDevelop.GtkCore.NodeBuilders\ProjectFileNodeBuilderExtension.cs" /> ++ <Compile Include="MonoDevelop.GtkCore.NodeBuilders\ProjectFileExtension.cs" /> ++ <Compile Include="MonoDevelop.GtkCore.Dialogs\ProjectConversionDialog.cs" /> ++ <Compile Include="MonoDevelop.GtkCore.NodeBuilders\GuiProjectFolder.cs" /> ++ <Compile Include="MonoDevelop.GtkCore.NodeBuilders\GuiProjectFolderNodeBuilder.cs" /> ++ <Compile Include="gtk-gui\MonoDevelop.GtkCore.Dialogs.ProjectConversionDialog.cs" /> + </ItemGroup> + <Import Project="$(MSBuildBinPath)\Microsoft.CSharp.targets" /> ++ <Import Project="$(MSBuildExtensionsPath)\Mono.Addins.targets" /> + <ProjectExtensions> + <MonoDevelop> + <Properties> +Index: gtk-gui/MonoDevelop.GtkCore.Dialogs.ProjectConversionDialog.cs +=================================================================== +--- gtk-gui/MonoDevelop.GtkCore.Dialogs.ProjectConversionDialog.cs (revision 0) ++++ gtk-gui/MonoDevelop.GtkCore.Dialogs.ProjectConversionDialog.cs (revision 124) +@@ -0,0 +1,183 @@ ++// ------------------------------------------------------------------------------ ++// <autogenerated> ++// This code was generated by a tool. ++// Mono Runtime Version: 2.0.50727.1433 ++// ++// Changes to this file may cause incorrect behavior and will be lost if ++// the code is regenerated. ++// </autogenerated> ++// ------------------------------------------------------------------------------ ++ ++ ++// This file has been generated by the GUI designer. Do not modify. ++namespace MonoDevelop.GtkCore.Dialogs ++{ ++ public partial class ProjectConversionDialog ++ { ++ private global::Gtk.HBox hbox; ++ ++ private global::Gtk.Alignment alignmentLogo; ++ ++ private global::Gtk.Image imageLogo; ++ ++ private global::Gtk.VBox vbox2; ++ ++ private global::Gtk.Label labelProject; ++ ++ private global::Gtk.Label labelInfo; ++ ++ private global::Gtk.HSeparator hseparator1; ++ ++ private global::Gtk.HBox hbox1; ++ ++ private global::Gtk.Label labelFolder; ++ ++ private global::Gtk.Entry entryFolder; ++ ++ private global::Gtk.CheckButton checkBackup; ++ ++ private global::Gtk.Button buttonConvert; ++ ++ protected virtual void Build () ++ { ++ global::Stetic.Gui.Initialize (this); ++ // Widget MonoDevelop.GtkCore.Dialogs.ProjectConversionDialog ++ this.Name = "MonoDevelop.GtkCore.Dialogs.ProjectConversionDialog"; ++ this.Title = global::Mono.Unix.Catalog.GetString ("Project Name"); ++ this.WindowPosition = ((global::Gtk.WindowPosition)(4)); ++ this.Modal = true; ++ this.SkipTaskbarHint = true; ++ // Internal child MonoDevelop.GtkCore.Dialogs.ProjectConversionDialog.VBox ++ global::Gtk.VBox w1 = this.VBox; ++ w1.Name = "dialog1_VBox"; ++ w1.BorderWidth = ((uint)(2)); ++ // Container child dialog1_VBox.Gtk.Box+BoxChild ++ this.hbox = new global::Gtk.HBox (); ++ this.hbox.Name = "hbox"; ++ this.hbox.Spacing = 6; ++ // Container child hbox.Gtk.Box+BoxChild ++ this.alignmentLogo = new global::Gtk.Alignment (1f, 0.15f, 1f, 0f); ++ this.alignmentLogo.Name = "alignmentLogo"; ++ // Container child alignmentLogo.Gtk.Container+ContainerChild ++ this.imageLogo = new global::Gtk.Image (); ++ this.imageLogo.WidthRequest = 180; ++ this.imageLogo.Name = "imageLogo"; ++ this.imageLogo.Yalign = 0f; ++ this.imageLogo.Pixbuf = global::Gdk.Pixbuf.LoadFromResource ("gtk-logo.png"); ++ this.alignmentLogo.Add (this.imageLogo); ++ this.hbox.Add (this.alignmentLogo); ++ global::Gtk.Box.BoxChild w3 = ((global::Gtk.Box.BoxChild)(this.hbox[this.alignmentLogo])); ++ w3.Position = 0; ++ w3.Expand = false; ++ w3.Fill = false; ++ // Container child hbox.Gtk.Box+BoxChild ++ this.vbox2 = new global::Gtk.VBox (); ++ this.vbox2.Name = "vbox2"; ++ this.vbox2.Spacing = 6; ++ // Container child vbox2.Gtk.Box+BoxChild ++ this.labelProject = new global::Gtk.Label (); ++ this.labelProject.Name = "labelProject"; ++ this.labelProject.LabelProp = global::Mono.Unix.Catalog.GetString ("<b><big>GTK# Project Conversion</big></b>"); ++ this.labelProject.UseMarkup = true; ++ this.vbox2.Add (this.labelProject); ++ global::Gtk.Box.BoxChild w4 = ((global::Gtk.Box.BoxChild)(this.vbox2[this.labelProject])); ++ w4.Position = 0; ++ w4.Expand = false; ++ w4.Fill = false; ++ // Container child vbox2.Gtk.Box+BoxChild ++ this.labelInfo = new global::Gtk.Label (); ++ this.labelInfo.Name = "labelInfo"; ++ this.labelInfo.Xalign = 0f; ++ this.labelInfo.Yalign = 0f; ++ this.labelInfo.LabelProp = global::Mono.Unix.Catalog.GetString ("This project has been created in the previous\nversion of GTK# addin and must be converted. \n\n<b>Following changes will be made :</b>\n\t- split gui.stetic into separate .gtkx files\n\t- split generated.cs into separate helper classes\n\t- remove gtk-gui folder.\n\t- create a designer folder for stock icons\n\t and generated helper classes. "); ++ this.labelInfo.UseMarkup = true; ++ this.labelInfo.Wrap = true; ++ this.vbox2.Add (this.labelInfo); ++ global::Gtk.Box.BoxChild w5 = ((global::Gtk.Box.BoxChild)(this.vbox2[this.labelInfo])); ++ w5.Position = 1; ++ w5.Expand = false; ++ w5.Fill = false; ++ // Container child vbox2.Gtk.Box+BoxChild ++ this.hseparator1 = new global::Gtk.HSeparator (); ++ this.hseparator1.Name = "hseparator1"; ++ this.vbox2.Add (this.hseparator1); ++ global::Gtk.Box.BoxChild w6 = ((global::Gtk.Box.BoxChild)(this.vbox2[this.hseparator1])); ++ w6.Position = 2; ++ w6.Expand = false; ++ w6.Fill = false; ++ // Container child vbox2.Gtk.Box+BoxChild ++ this.hbox1 = new global::Gtk.HBox (); ++ this.hbox1.Name = "hbox1"; ++ this.hbox1.Spacing = 6; ++ // Container child hbox1.Gtk.Box+BoxChild ++ this.labelFolder = new global::Gtk.Label (); ++ this.labelFolder.Name = "labelFolder"; ++ this.labelFolder.LabelProp = global::Mono.Unix.Catalog.GetString ("Designer folder name:"); ++ this.hbox1.Add (this.labelFolder); ++ global::Gtk.Box.BoxChild w7 = ((global::Gtk.Box.BoxChild)(this.hbox1[this.labelFolder])); ++ w7.Position = 0; ++ w7.Expand = false; ++ w7.Fill = false; ++ // Container child hbox1.Gtk.Box+BoxChild ++ this.entryFolder = new global::Gtk.Entry (); ++ this.entryFolder.CanFocus = true; ++ this.entryFolder.Name = "entryFolder"; ++ this.entryFolder.IsEditable = true; ++ this.entryFolder.InvisibleChar = '●'; ++ this.hbox1.Add (this.entryFolder); ++ global::Gtk.Box.BoxChild w8 = ((global::Gtk.Box.BoxChild)(this.hbox1[this.entryFolder])); ++ w8.Position = 1; ++ this.vbox2.Add (this.hbox1); ++ global::Gtk.Box.BoxChild w9 = ((global::Gtk.Box.BoxChild)(this.vbox2[this.hbox1])); ++ w9.Position = 3; ++ w9.Expand = false; ++ w9.Fill = false; ++ // Container child vbox2.Gtk.Box+BoxChild ++ this.checkBackup = new global::Gtk.CheckButton (); ++ this.checkBackup.CanFocus = true; ++ this.checkBackup.Name = "checkBackup"; ++ this.checkBackup.Label = global::Mono.Unix.Catalog.GetString ("Make a backup before converting"); ++ this.checkBackup.Active = true; ++ this.checkBackup.DrawIndicator = true; ++ this.checkBackup.UseUnderline = true; ++ this.vbox2.Add (this.checkBackup); ++ global::Gtk.Box.BoxChild w10 = ((global::Gtk.Box.BoxChild)(this.vbox2[this.checkBackup])); ++ w10.Position = 4; ++ w10.Expand = false; ++ w10.Fill = false; ++ this.hbox.Add (this.vbox2); ++ global::Gtk.Box.BoxChild w11 = ((global::Gtk.Box.BoxChild)(this.hbox[this.vbox2])); ++ w11.Position = 1; ++ w11.Expand = false; ++ w11.Fill = false; ++ w1.Add (this.hbox); ++ global::Gtk.Box.BoxChild w12 = ((global::Gtk.Box.BoxChild)(w1[this.hbox])); ++ w12.Position = 0; ++ w12.Expand = false; ++ w12.Fill = false; ++ // Internal child MonoDevelop.GtkCore.Dialogs.ProjectConversionDialog.ActionArea ++ global::Gtk.HButtonBox w13 = this.ActionArea; ++ w13.Name = "dialog1_ActionArea"; ++ w13.Spacing = 10; ++ w13.BorderWidth = ((uint)(5)); ++ w13.LayoutStyle = ((global::Gtk.ButtonBoxStyle)(4)); ++ // Container child dialog1_ActionArea.Gtk.ButtonBox+ButtonBoxChild ++ this.buttonConvert = new global::Gtk.Button (); ++ this.buttonConvert.CanDefault = true; ++ this.buttonConvert.CanFocus = true; ++ this.buttonConvert.Name = "buttonConvert"; ++ this.buttonConvert.UseUnderline = true; ++ this.buttonConvert.Label = global::Mono.Unix.Catalog.GetString ("_Convert"); ++ this.AddActionWidget (this.buttonConvert, -5); ++ global::Gtk.ButtonBox.ButtonBoxChild w14 = ((global::Gtk.ButtonBox.ButtonBoxChild)(w13[this.buttonConvert])); ++ w14.Expand = false; ++ w14.Fill = false; ++ if ((this.Child != null)) { ++ this.Child.ShowAll (); ++ } ++ this.DefaultWidth = 532; ++ this.DefaultHeight = 292; ++ this.Show (); ++ } ++ } ++} +Index: gtk-gui/ChangeLog +=================================================================== +--- gtk-gui/ChangeLog (revision 0) ++++ gtk-gui/ChangeLog (revision 124) +@@ -0,0 +1,46 @@ ++2010-08-15 Krzysztof Marecki <freefirma@gmail.com> ++ ++ * gui.stetic: ++ * MonoDevelop.GtkCore.Dialogs.ProjectConversionDialog.cs: ++ ++2010-08-13 Krzysztof Marecki <freefirma@gmail.com> ++ ++ * gui.stetic: ++ ++2010-08-09 Krzysztof Marecki <freefirma@gmail.com> ++ ++ * gui.stetic: ++ ++2010-08-07 Krzysztof Marecki <marecki.krzysztof@gmail.com> ++ ++ * gui.stetic: ++ ++2010-08-05 Krzysztof Marecki <freefirma@gmail.com> ++ ++ * gui.stetic: ++ ++2010-08-04 Krzysztof Marecki <freefirma@gmail.com> ++ ++ * gui.stetic: ++ ++2010-08-03 Krzysztof Marecki <marecki.krzysztof@gmail.com> ++ ++ * gui.stetic: ++ ++2010-07-05 Krzysztof Marecki <marecki.krzysztof@gmail.com> ++ ++ * gui.stetic: ++ ++2010-06-23 Krzysztof Marecki <marecki.krzysztof@gmail.com> ++ ++ * gui.stetic: ++ * MonoDevelop.GtkCore.Dialogs.ProjectConversionDialog.cs: ++ ++2010-06-16 Krzysztof Marecki <marecki.krzysztof@gmail.com> ++ ++ * gui.stetic: ++ ++2010-06-07 Krzysztof Marecki <marecki.krzysztof@gmail.com> ++ ++ * gui.stetic: ++ +Index: gtk-gui/gui.stetic +=================================================================== +--- gtk-gui/gui.stetic (revision 17) ++++ gtk-gui/gui.stetic (working copy) +@@ -8,10 +8,11 @@ + <widget-library name="glade-sharp, Version=2.12.0.0, Culture=neutral, PublicKeyToken=35e10195dab3c99f" /> + <widget-library name="../../../../build/bin/MonoDevelop.Ide.dll" /> + <widget-library name="../../../../build/AddIns/MonoDevelop.DesignerSupport/MonoDevelop.DesignerSupport.dll" /> +- <widget-library name="../../../../build/AddIns/MonoDevelop.Deployment/MonoDevelop.Deployment.dll" /> + <widget-library name="../../../../build/bin/Mono.TextEditor.dll" /> + <widget-library name="../../../../build/AddIns/MonoDevelop.GtkCore2/libsteticui2.dll" /> + <widget-library name="../../../../build/AddIns/MonoDevelop.GtkCore2/libstetic2.dll" /> ++ <widget-library name="MonoDevelop.Ide, Version=2.4.0.0, Culture=neutral" /> ++ <widget-library name="Mono.TextEditor, Version=1.0.0.0, Culture=neutral" /> + <widget-library name="../../../../build/AddIns/MonoDevelop.GtkCore2/MonoDevelop.GtkCore2.dll" internal="true" /> + </import> + <widget class="Gtk.Bin" id="MonoDevelop.GtkCore.Dialogs.GtkDesignerOptionsPanelWidget" design-size="503 22"> +@@ -40,4 +41,190 @@ + </widget> + </child> + </widget> ++ <widget class="Gtk.Dialog" id="MonoDevelop.GtkCore.Dialogs.ProjectConversionDialog" design-size="532 308"> ++ <property name="MemberName" /> ++ <property name="Title" translatable="yes">Project Name</property> ++ <property name="WindowPosition">CenterOnParent</property> ++ <property name="Modal">True</property> ++ <property name="SkipTaskbarHint">True</property> ++ <property name="Buttons">1</property> ++ <property name="HelpButton">False</property> ++ <child internal-child="VBox"> ++ <widget class="Gtk.VBox" id="dialog1_VBox"> ++ <property name="MemberName" /> ++ <property name="BorderWidth">2</property> ++ <child> ++ <widget class="Gtk.HBox" id="hbox"> ++ <property name="MemberName" /> ++ <property name="Spacing">6</property> ++ <child> ++ <widget class="Gtk.Alignment" id="alignmentLogo"> ++ <property name="MemberName" /> ++ <property name="Yscale">0</property> ++ <property name="Xalign">1</property> ++ <property name="Yalign">0.15</property> ++ <child> ++ <widget class="Gtk.Image" id="imageLogo"> ++ <property name="MemberName" /> ++ <property name="WidthRequest">180</property> ++ <property name="Yalign">0</property> ++ <property name="Pixbuf">resource:gtk-logo.png</property> ++ </widget> ++ </child> ++ </widget> ++ <packing> ++ <property name="Position">0</property> ++ <property name="AutoSize">True</property> ++ <property name="Expand">False</property> ++ <property name="Fill">False</property> ++ </packing> ++ </child> ++ <child> ++ <widget class="Gtk.VBox" id="vbox2"> ++ <property name="MemberName" /> ++ <property name="Spacing">6</property> ++ <child> ++ <widget class="Gtk.Label" id="labelProject"> ++ <property name="MemberName" /> ++ <property name="LabelProp" translatable="yes"><b><big>GTK# Project Conversion</big></b></property> ++ <property name="UseMarkup">True</property> ++ </widget> ++ <packing> ++ <property name="Position">0</property> ++ <property name="AutoSize">True</property> ++ <property name="Expand">False</property> ++ <property name="Fill">False</property> ++ </packing> ++ </child> ++ <child> ++ <widget class="Gtk.Label" id="labelInfo"> ++ <property name="MemberName" /> ++ <property name="Xalign">0</property> ++ <property name="Yalign">0</property> ++ <property name="LabelProp" translatable="yes">This project has been created in the previous ++version of GTK# addin and must be converted. ++ ++<b>Following changes will be made :</b> ++ - split gui.stetic into separate .gtkx files ++ - split generated.cs into separate helper classes ++ - remove gtk-gui folder. ++ - create a designer folder for stock icons ++ and generated helper classes.</property> ++ <property name="UseMarkup">True</property> ++ <property name="Wrap">True</property> ++ </widget> ++ <packing> ++ <property name="Position">1</property> ++ <property name="AutoSize">True</property> ++ <property name="Expand">False</property> ++ <property name="Fill">False</property> ++ </packing> ++ </child> ++ <child> ++ <widget class="Gtk.HSeparator" id="hseparator1"> ++ <property name="MemberName" /> ++ </widget> ++ <packing> ++ <property name="Position">2</property> ++ <property name="AutoSize">True</property> ++ <property name="Expand">False</property> ++ <property name="Fill">False</property> ++ </packing> ++ </child> ++ <child> ++ <widget class="Gtk.HBox" id="hbox1"> ++ <property name="MemberName" /> ++ <property name="Spacing">6</property> ++ <child> ++ <widget class="Gtk.Label" id="labelFolder"> ++ <property name="MemberName" /> ++ <property name="LabelProp" translatable="yes">Designer folder name:</property> ++ </widget> ++ <packing> ++ <property name="Position">0</property> ++ <property name="AutoSize">True</property> ++ <property name="Expand">False</property> ++ <property name="Fill">False</property> ++ </packing> ++ </child> ++ <child> ++ <widget class="Gtk.Entry" id="entryFolder"> ++ <property name="MemberName" /> ++ <property name="CanFocus">True</property> ++ <property name="IsEditable">True</property> ++ <property name="InvisibleChar">●</property> ++ </widget> ++ <packing> ++ <property name="Position">1</property> ++ <property name="AutoSize">True</property> ++ </packing> ++ </child> ++ </widget> ++ <packing> ++ <property name="Position">3</property> ++ <property name="AutoSize">True</property> ++ <property name="Expand">False</property> ++ <property name="Fill">False</property> ++ </packing> ++ </child> ++ <child> ++ <widget class="Gtk.CheckButton" id="checkBackup"> ++ <property name="MemberName" /> ++ <property name="CanFocus">True</property> ++ <property name="Label" translatable="yes">Make a backup before converting</property> ++ <property name="Active">True</property> ++ <property name="DrawIndicator">True</property> ++ <property name="HasLabel">True</property> ++ <property name="UseUnderline">True</property> ++ </widget> ++ <packing> ++ <property name="Position">4</property> ++ <property name="AutoSize">True</property> ++ <property name="Expand">False</property> ++ <property name="Fill">False</property> ++ </packing> ++ </child> ++ </widget> ++ <packing> ++ <property name="Position">1</property> ++ <property name="AutoSize">True</property> ++ <property name="Expand">False</property> ++ <property name="Fill">False</property> ++ </packing> ++ </child> ++ </widget> ++ <packing> ++ <property name="Position">0</property> ++ <property name="AutoSize">True</property> ++ <property name="Expand">False</property> ++ <property name="Fill">False</property> ++ </packing> ++ </child> ++ </widget> ++ </child> ++ <child internal-child="ActionArea"> ++ <widget class="Gtk.HButtonBox" id="dialog1_ActionArea"> ++ <property name="MemberName" /> ++ <property name="Spacing">10</property> ++ <property name="BorderWidth">5</property> ++ <property name="Size">1</property> ++ <property name="LayoutStyle">End</property> ++ <child> ++ <widget class="Gtk.Button" id="buttonConvert"> ++ <property name="MemberName" /> ++ <property name="CanDefault">True</property> ++ <property name="CanFocus">True</property> ++ <property name="Type">TextOnly</property> ++ <property name="Label" translatable="yes">_Convert</property> ++ <property name="UseUnderline">True</property> ++ <property name="ResponseId">-5</property> ++ </widget> ++ <packing> ++ <property name="Expand">False</property> ++ <property name="Fill">False</property> ++ </packing> ++ </child> ++ </widget> ++ </child> ++ </widget> + </stetic-interface> +\ No newline at end of file +Index: Makefile.am +=================================================================== +--- Makefile.am (revision 17) ++++ Makefile.am (working copy) +@@ -1,14 +1,13 @@ + SUBDIRS = libstetic libsteticui + +-ADDIN_BUILD = $(top_builddir)/build/AddIns/MonoDevelop.GtkCore +-ASSEMBLY = $(ADDIN_BUILD)/MonoDevelop.GtkCore.dll ++ADDIN_BUILD = $(top_builddir)/build/AddIns/MonoDevelop.GtkCore2 ++ASSEMBLY = $(ADDIN_BUILD)/MonoDevelop.GtkCore2.dll + + DEPS = \ + $(top_builddir)/build/AddIns/MonoDevelop.Deployment/MonoDevelop.Deployment.dll \ + $(top_builddir)/build/AddIns/MonoDevelop.DesignerSupport/MonoDevelop.DesignerSupport.dll \ + $(top_builddir)/build/AddIns/MonoDevelop.GtkCore2/libstetic2.dll \ + $(top_builddir)/build/AddIns/MonoDevelop.GtkCore2/libsteticui2.dll \ +- $(top_builddir)/build/bin/Mono.Cecil.dll \ + $(top_builddir)/build/bin/Mono.TextEditor.dll \ + $(top_builddir)/build/bin/MonoDevelop.Core.dll \ + $(top_builddir)/build/bin/MonoDevelop.Ide.dll +@@ -18,19 +17,23 @@ + $(GLIB_SHARP_LIBS) \ + $(GTK_SHARP_LIBS) \ + $(MONO_ADDINS_LIBS) \ ++ -pkg:monodevelop \ + -r:Mono.Posix \ + -r:System \ ++ -r:System.Core \ + -r:System.Xml + + FILES = \ + AssemblyInfo.cs \ + gtk-gui/generated.cs \ + gtk-gui/MonoDevelop.GtkCore.Dialogs.GtkDesignerOptionsPanelWidget.cs \ ++ gtk-gui/MonoDevelop.GtkCore.Dialogs.ProjectConversionDialog.cs \ + MonoDevelop.GtkCore.Commands/GladeCommands.cs \ + MonoDevelop.GtkCore.Dialogs/BindDesignDialog.cs \ + MonoDevelop.GtkCore.Dialogs/ConfirmWindowDeleteDialog.cs \ + MonoDevelop.GtkCore.Dialogs/GtkDesignerOptionsPanelWidget.cs \ + MonoDevelop.GtkCore.Dialogs/GtkFeatureWidget.cs \ ++ MonoDevelop.GtkCore.Dialogs/ProjectConversionDialog.cs \ + MonoDevelop.GtkCore.Dialogs/SelectRenamedClassDialog.cs \ + MonoDevelop.GtkCore.Dialogs/WidgetBuilderOptionPanel.cs \ + MonoDevelop.GtkCore.GuiBuilder/ActionGroupDisplayBinding.cs \ +@@ -48,11 +51,13 @@ + MonoDevelop.GtkCore.GuiBuilder/PropertiesWidget.cs \ + MonoDevelop.GtkCore.GuiBuilder/ToolboxLoader.cs \ + MonoDevelop.GtkCore.GuiBuilder/ToolboxProvider.cs \ +- MonoDevelop.GtkCore.NodeBuilders/ActionGroupNodeBuilder.cs \ ++ MonoDevelop.GtkCore.NodeBuilders/GuiProjectFolder.cs \ ++ MonoDevelop.GtkCore.NodeBuilders/GuiProjectFolderNodeBuilder.cs \ ++ MonoDevelop.GtkCore.NodeBuilders/ProjectFileExtension.cs \ ++ MonoDevelop.GtkCore.NodeBuilders/ProjectFileNodeBuilderExtension.cs \ + MonoDevelop.GtkCore.NodeBuilders/ProjectFolderNodeBuilderExtension.cs \ + MonoDevelop.GtkCore.NodeBuilders/ProjectNodeBuilder.cs \ + MonoDevelop.GtkCore.NodeBuilders/StockIconsNodeBuilder.cs \ +- MonoDevelop.GtkCore.NodeBuilders/WidgetNodeBuilder.cs \ + MonoDevelop.GtkCore.NodeBuilders/WindowsFolder.cs \ + MonoDevelop.GtkCore.NodeBuilders/WindowsFolderNodeBuilder.cs \ + MonoDevelop.GtkCore/Counters.cs \ +@@ -68,6 +73,8 @@ + gtk-gui/gui.stetic \ + gui.glade \ + icons/actiongroup.png \ ++ icons/gtk-logo.png \ ++ icons/gtkx.png \ + icons/image-x-generic.png \ + icons/widget.png \ + MonoDevelop.GtkCore.addin.xml \ +@@ -99,7 +106,7 @@ + $(CSC) $(CSC_FLAGS) -debug -out:$@ -target:library \ + $(build_resources:%=/resource:%) $(build_sources) $(REFS) $(build_deps) + +-assemblydir = $(MD_ADDIN_DIR)/MonoDevelop.GtkCore ++assemblydir = $(MD_ADDIN_DIR)/MonoDevelop.GtkCore2 + assembly_DATA = $(ASSEMBLY) $(ASSEMBLY).mdb + + CLEANFILES = $(ASSEMBLY) $(ASSEMBLY).mdb +Index: icons/gtkx.png +=================================================================== +Cannot display: file marked as a binary type. +svn:mime-type = application/octet-stream + +Property changes on: icons/gtkx.png +___________________________________________________________________ +Added: svn:mime-type + + application/octet-stream + +Index: icons/gtk-logo.png +=================================================================== +Cannot display: file marked as a binary type. +svn:mime-type = application/octet-stream + +Property changes on: icons/gtk-logo.png +___________________________________________________________________ +Added: svn:mime-type + + application/octet-stream + +Index: icons/ChangeLog +=================================================================== +--- icons/ChangeLog (revision 0) ++++ icons/ChangeLog (revision 124) +@@ -0,0 +1,5 @@ ++2010-08-15 Krzysztof Marecki <freefirma@gmail.com> ++ ++ * gtkx.png: ++ * gtk-logo.png: ++ +Index: MonoDevelop.GtkCore.GuiBuilder/ActionGroupDisplayBinding.cs +=================================================================== +--- MonoDevelop.GtkCore.GuiBuilder/ActionGroupDisplayBinding.cs (revision 17) ++++ MonoDevelop.GtkCore.GuiBuilder/ActionGroupDisplayBinding.cs (working copy) +@@ -53,12 +53,17 @@ + { + if (excludeThis) + return false; ++ ++ if (fileName.Contains ("generated")) ++ return false; ++ + if (!IdeApp.Workspace.IsOpen) + return false; + + if (GetActionGroup (fileName) == null) + return false; + ++ + excludeThis = true; + var db = DisplayBindingService.GetDefaultBindingForUri (fileName); + excludeThis = false; +@@ -171,7 +176,7 @@ + IdeApp.ProjectOperations.Save (project); + + // Make sure the database is up-to-date +- ProjectDomService.Parse (project, cls.CompilationUnit.FileName, null); ++ ProjectDomService.Parse (project, cls.CompilationUnit.FileName); + return cls; + } + +Index: MonoDevelop.GtkCore.GuiBuilder/GuiBuilderService.cs +=================================================================== +--- MonoDevelop.GtkCore.GuiBuilder/GuiBuilderService.cs (revision 17) ++++ MonoDevelop.GtkCore.GuiBuilder/GuiBuilderService.cs (working copy) +@@ -34,6 +34,7 @@ + + using MonoDevelop.Ide.Gui; + using MonoDevelop.Projects; ++using MonoDevelop.Projects.Dom; + using MonoDevelop.Projects.Dom.Parser; + using MonoDevelop.Projects.Text; + using MonoDevelop.Core; +@@ -257,12 +258,21 @@ + + public static string GetBuildCodeFileName (Project project, string componentName) + { ++ return GetBuildCodeFileName (project, componentName, string.Empty); ++ } ++ ++ public static string GetBuildCodeFileName (Project project, string componentName, string nameSpace) ++ { + GtkDesignInfo info = GtkDesignInfo.FromProject (project); +-// var type=info.GuiBuilderProject.FindClass(componentName); +- var folder = info.GtkGuiFolder; ++ string componentFile = info.GetComponentFile (componentName); + +-// folder=type.CompilationUnit.FileName.ParentDirectory; +- return Path.Combine (folder, componentName + Path.GetExtension (info.SteticGeneratedFile)); ++ if (componentFile == null) { ++ if (nameSpace == "Stetic") { ++ return info.GetBuildFileInSteticFolder (componentName); ++ } else ++ throw new UserException ("Cannot find component file for " + componentName); ++ } else ++ return info.GetBuildFile (componentFile); + } + + public static string GenerateSteticCodeStructure (DotNetProject project, Stetic.ProjectItemInfo item, bool saveToFile, bool overwrite) +@@ -351,13 +361,12 @@ + FileService.NotifyFileChanged (fileName); + } + else +- ProjectDomService.Parse (project, fileName, "", ((StringWriter)fileStream).ToString ()); ++ ProjectDomService.Parse (project, fileName, ((StringWriter)fileStream).ToString ()); + } + + return fileName; + } + +- + public static Stetic.CodeGenerationResult GenerateSteticCode (IProgressMonitor monitor, DotNetProject project, ConfigurationSelector configuration) + { + if (generating || !GtkDesignInfo.HasDesignedObjects (project)) +@@ -382,8 +391,8 @@ + } + + // Check if generated code is already up to date. +- if (!ref_changed && last_gen_time >= File.GetLastWriteTime (info.SteticFile)) +- return null; ++// if (!ref_changed && last_gen_time >= File.GetLastWriteTime (info.SteticFile)) ++// return null; + + if (info.GuiBuilderProject.HasError) { + monitor.ReportError (GettextCatalog.GetString ("GUI code generation failed for project '{0}'. The file '{1}' could not be loaded.", project.Name, info.SteticFile), null); +@@ -402,8 +411,8 @@ + + info.GuiBuilderProject.UpdateLibraries (); + +- ArrayList projects = new ArrayList (); +- projects.Add (info.GuiBuilderProject.File); ++ ArrayList projectFolders = new ArrayList (); ++ projectFolders.Add (info.SteticFolder.FullPath); + + generating = true; + Stetic.CodeGenerationResult generationResult = null; +@@ -418,7 +427,7 @@ + // Generate the code in another process if stetic is not isolated + CodeGeneratorProcess cob = (CodeGeneratorProcess) Runtime.ProcessService.CreateExternalProcessObject (typeof (CodeGeneratorProcess), false); + using (cob) { +- generationResult = cob.GenerateCode (projects, info.GenerateGettext, info.GettextClass, project.UsePartialTypes, info); ++ generationResult = cob.GenerateCode (projectFolders, info.GenerateGettext, info.GettextClass, project.UsePartialTypes, info); + } + } catch (Exception ex) { + generatedException = ex; +@@ -438,8 +447,6 @@ + Stetic.GenerationOptions options = new Stetic.GenerationOptions (); + options.UseGettext = info.GenerateGettext; + options.GettextClass = info.GettextClass; +- options.UsePartialClasses = project.UsePartialTypes; +- options.GenerateSingleFile = false; + generationResult = SteticApp.GenerateProjectCode (options, info.GuiBuilderProject.SteticProject); + } catch (Exception ex) { + generatedException = ex; +@@ -448,8 +455,23 @@ + } + + if (generatedException != null) { +- LoggingService.LogError ("GUI code generation failed", generatedException); +- throw new UserException ("GUI code generation failed: " + generatedException.Message); ++ string msg = string.Empty; ++ ++ if (generatedException.InnerException != null) { ++ msg = string.Format("{0}\n{1}\nInner Exception {2}\n{3}", ++ generatedException.Message, ++ generatedException.StackTrace, ++ generatedException.InnerException.Message, ++ generatedException.InnerException.StackTrace); ++ } else { ++ msg = string.Format("{0}\n{1}", ++ generatedException.Message, ++ generatedException.StackTrace); ++ } ++ ++// LoggingService.LogError ("GUI code generation failed", generatedException); ++ LoggingService.LogError ("GUI code generation failed: " + msg); ++ throw new UserException ("GUI code generation failed: " + msg); + } + + if (generationResult == null) +@@ -459,15 +481,15 @@ + if (provider == null) + throw new UserException ("Code generation not supported for language: " + project.LanguageName); + +- string basePath = Path.GetDirectoryName (info.SteticGeneratedFile); +- string ext = Path.GetExtension (info.SteticGeneratedFile); +- + foreach (Stetic.SteticCompilationUnit unit in generationResult.Units) { + string fname; + if (unit.Name.Length == 0) + fname = info.SteticGeneratedFile; + else +- fname = Path.Combine (basePath, unit.Name) + ext; ++ fname = GetBuildCodeFileName (project, ++ unit.Name, ++ (unit.Namespace != null) ? unit.Namespace.Name : string.Empty); ++ + StringWriter sw = new StringWriter (); + try { + foreach (CodeNamespace ns in unit.Namespaces) +@@ -476,6 +498,12 @@ + string content = sw.ToString (); + content = FormatGeneratedFile (fname, content, provider); + File.WriteAllText (fname, content); ++// if (File.Exists (fname)) { ++// FileInfo file = new FileInfo (fname); ++// DateTime now = DateTime.Now; ++// file.LastWriteTime = now; ++// file.LastWriteTimeUtc = now; ++// } + } finally { + FileService.NotifyFileChanged (fname); + } +@@ -580,23 +608,21 @@ + + public class CodeGeneratorProcess: RemoteProcessObject + { +- public Stetic.CodeGenerationResult GenerateCode (ArrayList projectFiles, bool useGettext, string gettextClass, bool usePartialClasses, GtkDesignInfo info) ++ public Stetic.CodeGenerationResult GenerateCode (ArrayList projectFolders, bool useGettext, string gettextClass, bool usePartialClasses, GtkDesignInfo info) + { + Gtk.Application.Init (); + + Stetic.Application app = Stetic.ApplicationFactory.CreateApplication (Stetic.IsolationMode.None); + +- Stetic.Project[] projects = new Stetic.Project [projectFiles.Count]; +- for (int n=0; n < projectFiles.Count; n++) { ++ Stetic.Project[] projects = new Stetic.Project [projectFolders.Count]; ++ for (int n=0; n < projectFolders.Count; n++) { + projects [n] = app.CreateProject (info); +- projects [n].Load ((string) projectFiles [n]); ++ projects [n].Load ((string) projectFolders [n]); + } + + Stetic.GenerationOptions options = new Stetic.GenerationOptions (); + options.UseGettext = useGettext; + options.GettextClass = gettextClass; +- options.UsePartialClasses = usePartialClasses; +- options.GenerateSingleFile = false; + + return app.GenerateProjectCode (options, projects); + } +Index: MonoDevelop.GtkCore.GuiBuilder/GuiBuilderDisplayBinding.cs +=================================================================== +--- MonoDevelop.GtkCore.GuiBuilder/GuiBuilderDisplayBinding.cs (revision 17) ++++ MonoDevelop.GtkCore.GuiBuilder/GuiBuilderDisplayBinding.cs (working copy) +@@ -46,6 +46,9 @@ + { + if (excludeThis) return false; + ++ if (fileName.Contains ("generated")) ++ return false; ++ + if (GetWindow (fileName) == null) + return false; + +@@ -81,7 +84,7 @@ + return null; + + GtkDesignInfo info = GtkDesignInfo.FromProject (project); +- if (file.StartsWith (info.GtkGuiFolder)) ++ if (file.StartsWith (info.SteticFolder)) + return null; + + ParsedDocument doc = ProjectDomService.GetParsedDocument (null, file); +Index: MonoDevelop.GtkCore.GuiBuilder/GuiBuilderProject.cs +=================================================================== +--- MonoDevelop.GtkCore.GuiBuilder/GuiBuilderProject.cs (revision 17) ++++ MonoDevelop.GtkCore.GuiBuilder/GuiBuilderProject.cs (working copy) +@@ -44,12 +44,15 @@ + { + public class GuiBuilderProject + { ++ //to save temporarily GuiBuilderWindow while files are being moved between projects ++ static List<GuiBuilderWindow> formInfosRemoved; ++ + internal object MemoryProbe = Counters.GuiProjectsInMemory.CreateMemoryProbe (); + + List<GuiBuilderWindow> formInfos; + Stetic.Project gproject; + DotNetProject project; +- string fileName; ++ string folderName; + bool hasError; + bool needsUpdate = true; + +@@ -64,38 +67,87 @@ + public event EventHandler Reloaded; + public event EventHandler Unloaded; + public event EventHandler Changed; ++ ++ static GuiBuilderProject () ++ { ++ formInfosRemoved = new List<GuiBuilderWindow> (); ++ } + +- public GuiBuilderProject (DotNetProject project, string fileName) ++ public GuiBuilderProject (DotNetProject project, string folderName) + { +- this.fileName = fileName; ++ this.folderName = folderName; + this.project = project; + Counters.GuiProjectsLoaded++; + } + ++ public void Convert (string guiFolderName, bool makeBackup) ++ { ++ GtkDesignInfo info = GtkDesignInfo.FromProject (project); ++ Stetic.Project gproject = GuiBuilderService.SteticApp.CreateProject (info); ++ //Stetic.Project does not implement IDisposable ++ try { ++ string newGuiFolderName = project.BaseDirectory.Combine (guiFolderName); ++ gproject.ConvertProject (info.SteticFile, newGuiFolderName); ++ info.ConvertGtkFolder (guiFolderName, makeBackup); ++ info.UpdateGtkFolder (); ++ folderName = newGuiFolderName; ++ IProgressMonitor monitor = IdeApp.Workbench.ProgressMonitors.GetBuildProgressMonitor (); ++ try { ++ ConfigurationSelector configuration = IdeApp.Workspace.ActiveConfiguration; ++ Generator generator = new Generator (); ++ generator.Run (monitor, project, configuration); ++ monitor.ReportSuccess ("Converting was succesfull"); ++ } finally { ++ monitor.Dispose (); ++ } ++ } finally { ++ gproject.Dispose (); ++ } ++ } ++ ++ public void GenerateCode (string componentFile) ++ { ++ GtkDesignInfo info = GtkDesignInfo.FromProject (project); ++ string gtkxFile = info.GetGtkxFile (componentFile); ++ if (gtkxFile != null && File.Exists (gtkxFile)) { ++ ++ Save (false); ++ FileInfo fi = new FileInfo (gtkxFile); ++ fi.LastWriteTime = DateTime.Now; ++ ++ IProgressMonitor monitor = IdeApp.Workbench.ProgressMonitors.GetBuildProgressMonitor (); ++ try { ++ ConfigurationSelector configuration = IdeApp.Workspace.ActiveConfiguration; ++ Generator generator = new Generator (); ++ generator.Run (monitor, project, configuration); ++ } finally { ++ monitor.Dispose (); ++ } ++ } ++ } ++ + void Load () + { +- if (gproject != null || disposed || fileName == null) ++ if (gproject != null || disposed || folderName == null) + return; + + GtkDesignInfo info = GtkDesignInfo.FromProject (project); + gproject = GuiBuilderService.SteticApp.CreateProject (info); + formInfos = new List<GuiBuilderWindow> (); +- +- if (!System.IO.File.Exists (fileName)) { +- // Regenerate the gtk-gui folder if the stetic project +- // doesn't exist. +- info.UpdateGtkFolder (); +- } ++ ++// TODO : when expanding project, UpdateGtkFolder causes in throwing exception by gtk ++// info.UpdateGtkFolder (); + + try { +- gproject.Load (fileName); ++ gproject.Load (folderName); + } catch (Exception ex) { +- MessageService.ShowException (ex, GettextCatalog.GetString ("The GUI designer project file '{0}' could not be loaded.", fileName)); ++ MessageService.ShowException (ex, GettextCatalog.GetString ("The GUI designer project folder '{0}' could not be loaded.", folderName)); + hasError = true; + } + + Counters.SteticProjectsLoaded++; + gproject.ResourceProvider = GtkDesignInfo.FromProject (project).ResourceProvider; ++// gproject.DesignInfo = info; + gproject.WidgetAdded += OnAddWidget; + gproject.WidgetRemoved += OnRemoveWidget; + gproject.ActionGroupsChanged += OnGroupsChanged; +@@ -108,14 +160,14 @@ + RegisterWindow (ob, false); + + // Monitor changes in the file +- lastSaveTime = System.IO.File.GetLastWriteTime (fileName); +- watcher = new FileSystemWatcher (); +- if (System.IO.File.Exists (fileName)) { +- watcher.Path = Path.GetDirectoryName (fileName); +- watcher.Filter = Path.GetFileName (fileName); +- watcher.Changed += (FileSystemEventHandler) DispatchService.GuiDispatch (new FileSystemEventHandler (OnSteticFileChanged)); +- watcher.EnableRaisingEvents = true; +- } ++// lastSaveTime = System.IO.File.GetLastWriteTime (fileName); ++// watcher = new FileSystemWatcher (); ++// if (System.IO.File.Exists (fileName)) { ++// watcher.Path = Path.GetDirectoryName (fileName); ++// watcher.Filter = Path.GetFileName (fileName); ++// watcher.Changed += (FileSystemEventHandler) DispatchService.GuiDispatch (new FileSystemEventHandler (OnSteticFileChanged)); ++// watcher.EnableRaisingEvents = true; ++// } + } + + void Unload () +@@ -158,7 +210,7 @@ + void OnSteticFileChanged (object s, FileSystemEventArgs args) + { + lock (fileSaveLock) { +- if (lastSaveTime == System.IO.File.GetLastWriteTime (fileName)) ++ if (lastSaveTime == System.IO.File.GetLastWriteTime (folderName)) + return; + } + +@@ -198,8 +250,8 @@ + + if (gproject != null && !hasError) { + lock (fileSaveLock) { +- gproject.Save (fileName); +- lastSaveTime = System.IO.File.GetLastWriteTime (fileName); ++ gproject.Save (folderName); ++ lastSaveTime = System.IO.File.GetLastWriteTime (folderName); + } + } + +@@ -207,14 +259,11 @@ + IdeApp.ProjectOperations.Save (project); + } + +- public string File { +- get { return fileName; } +- } +- + public Stetic.Project SteticProject { + get { + Load (); + return gproject; ++ + } + } + +@@ -256,6 +305,16 @@ + RegisterWindow (c, true); + return c; + } ++ ++ public void AddNewComponent (string fileName) ++ { ++ object ob = SteticProject.AddNewComponent (fileName); ++ ++ if (ob is Stetic.WidgetInfo) { ++ var c = (Stetic.WidgetInfo) ob; ++ RegisterWindow (c, true); ++ } ++ } + + void RegisterWindow (Stetic.WidgetInfo widget, bool notify) + { +@@ -266,6 +325,16 @@ + + GuiBuilderWindow win = new GuiBuilderWindow (this, gproject, widget); + formInfos.Add (win); ++ ++ GuiBuilderWindow winToRemove = null; ++ foreach (GuiBuilderWindow form in formInfosRemoved) ++ if (form.RootWidget == widget) { ++ winToRemove = form; ++ break; ++ } ++ ++ if (winToRemove != null) ++ formInfosRemoved.Remove (winToRemove); + + if (notify) { + if (WindowAdded != null) +@@ -281,6 +350,7 @@ + return; + + formInfos.Remove (win); ++ formInfosRemoved.Add (win); + + if (WindowRemoved != null) + WindowRemoved (this, new WindowEventArgs (win)); +@@ -319,30 +389,18 @@ + } + + void OnFileAdded (object sender, ProjectFileEventArgs args) +- { ++ { ++ FilePath path = args.ProjectFile.FilePath; + +- ParsedDocument doc = ProjectDomService.GetParsedDocument (ProjectDomService.GetProjectDom (args.Project), args.ProjectFile.Name); +- if (doc == null || doc.CompilationUnit == null) +- return; +- +- string dir = Path.Combine (Path.Combine (Environment.GetFolderPath (Environment.SpecialFolder.ApplicationData), "stetic"), "deleted-designs"); +- if (!Directory.Exists (dir) || Directory.GetFiles (dir).Length == 0) +- return; +- +- foreach (IType t in doc.CompilationUnit.Types) { +- string path = Path.Combine (dir, t.FullName + ".xml"); +- if (!System.IO.File.Exists (path)) +- continue; +- XmlDocument xmldoc = new XmlDocument (); +- xmldoc.Load (path); +- AddNewComponent (xmldoc.DocumentElement); +- System.IO.File.Delete (path); ++ if (path.Extension == ".gtkx") { ++ AddNewComponent (path); + } + } + + void OnFileRemoved (object sender, ProjectFileEventArgs args) + { + ArrayList toDelete = new ArrayList (); ++ ArrayList toDeleteGroups = new ArrayList (); + + ParsedDocument doc = ProjectDomService.GetParsedDocument (ProjectDomService.GetProjectDom (args.Project), args.ProjectFile.Name); + if (doc == null || doc.CompilationUnit == null) +@@ -350,12 +408,22 @@ + + foreach (IType t in doc.CompilationUnit.Types) { + GuiBuilderWindow win = GetWindowForClass (t.FullName); +- if (win != null) ++ if (win != null) { + toDelete.Add (win); ++ continue; ++ } ++ ++ Stetic.ActionGroupInfo group = GetActionGroup (t.FullName); ++ if (group != null) { ++ toDeleteGroups.Add (group); ++ } + } +- ++ + foreach (GuiBuilderWindow win in toDelete) + Remove (win); ++ ++ foreach (Stetic.ActionGroupInfo group in toDeleteGroups) ++ RemoveActionGroup (group); + } + + void OnGroupsChanged (object s, EventArgs a) +@@ -424,6 +492,13 @@ + return form; + } + } ++ ++ if (formInfosRemoved != null) { ++ foreach (GuiBuilderWindow form in formInfosRemoved) { ++ if (CodeBinder.GetObjectName (form.RootWidget) == className) ++ return form; ++ } ++ } + return null; + }
+
+@@ -460,7 +535,7 @@ + + public Stetic.ActionGroupInfo GetActionGroup (string name) + { +- return SteticProject.GetActionGroup (name); ++ return (SteticProject != null) ? SteticProject.GetActionGroup (name) : null; + }
+
+ public FilePath GetSourceCodeFile (Stetic.ProjectItemInfo obj) +@@ -489,8 +564,9 @@ + + public IType FindClass (string className, bool getUserClass) + {
+- FilePath gui_folder = GtkDesignInfo.FromProject (project).GtkGuiFolder; ++ FilePath gui_folder = GtkDesignInfo.FromProject (project).SteticFolder; + ProjectDom ctx = GetParserContext (); ++ + if (ctx == null) + return null; + IEnumerable<IType> classes = ctx.Types; +@@ -502,7 +578,9 @@ + // Return this class only if it is declared outside the gtk-gui + // folder. Generated partial classes will be ignored. + foreach (IType part in cls.Parts) { +- if (part.CompilationUnit != null && !part.CompilationUnit.FileName.IsNullOrEmpty && !part.CompilationUnit.FileName.IsChildPathOf (gui_folder)) { ++ if (part.CompilationUnit.FileName.FullPath.IsChildPathOf (gui_folder)) ++ continue; ++ if (part.CompilationUnit != null && !part.CompilationUnit.FileName.IsNullOrEmpty && !part.CompilationUnit.FileName.FileName.Contains ("generated")) { + return part; + } + } +@@ -557,8 +635,10 @@ + + // Make sure the target gtk version is properly set + if (gproject.TargetGtkVersion != target_version) { ++ if (gproject.TargetGtkVersion != string.Empty) { ++ needsSave = true; ++ } + gproject.TargetGtkVersion = target_version; +- needsSave = true; + } + + string outLib = project.GetOutputFileName (IdeApp.Workspace.ActiveConfiguration); +@@ -571,8 +651,11 @@ + + // See if something has changed + if (LibrariesChanged (oldLibs, internalLibs, newLibs)) { ++ // If oldLibs is empty, gproject was uninitialized, so there are no changes to save ++ if (oldLibs.Length > 0) { ++ needsSave = true; ++ } + gproject.SetWidgetLibraries (newLibs, internalLibs); +- needsSave = true; + } else { + GuiBuilderService.SteticApp.UpdateWidgetLibraries (false); + } +@@ -611,24 +694,30 @@ + return files; + + IDotNetLanguageBinding binding = LanguageBindingService.GetBindingPerLanguageName (project.LanguageName) as IDotNetLanguageBinding; +- string path = Path.Combine (guiFolder, binding.GetFileName ("generated")); +- if (!System.IO.File.Exists (path)) { +- // Generate an empty build class +- CodeDomProvider provider = binding.GetCodeDomProvider (); +- if (provider == null) +- throw new UserException ("Code generation not supported for language: " + project.LanguageName); +- GuiBuilderService.SteticApp.GenerateProjectCode (path, "Stetic", provider, null); ++ CodeDomProvider provider = binding.GetCodeDomProvider (); ++ ++ if (provider == null) ++ throw new UserException ("Code generation not supported for language: " + project.LanguageName); ++// string path = Path.Combine (guiFolder, binding.GetFileName ("generated")); ++// if (!System.IO.File.Exists (path)) { ++// GuiBuilderService.SteticApp.GenerateProjectCode (path, "Stetic", provider, null); ++// } ++// files.Add (path); ++// ++// if (Windows != null) { ++// foreach (GuiBuilderWindow win in Windows) ++// files.Add (GuiBuilderService.GenerateSteticCodeStructure (project, win.RootWidget, true, false)); ++// } ++// ++// foreach (Stetic.ActionGroupInfo ag in SteticProject.ActionGroups) ++// files.Add (GuiBuilderService.GenerateSteticCodeStructure (project, ag, true, false)); ++ ++ string extension = "generated." + provider.FileExtension; ++ foreach (string file in Directory.GetFiles (guiFolder)) { ++ if (file.Contains (extension)) ++ files.Add (file); + } +- files.Add (path); + +- if (Windows != null) { +- foreach (GuiBuilderWindow win in Windows) +- files.Add (GuiBuilderService.GenerateSteticCodeStructure (project, win.RootWidget, true, false)); +- } +- +- foreach (Stetic.ActionGroupInfo ag in SteticProject.ActionGroups) +- files.Add (GuiBuilderService.GenerateSteticCodeStructure (project, ag, true, false)); +- + return files; + } + } +Index: MonoDevelop.GtkCore.GuiBuilder/ChangeLog +=================================================================== +--- MonoDevelop.GtkCore.GuiBuilder/ChangeLog (revision 0) ++++ MonoDevelop.GtkCore.GuiBuilder/ChangeLog (revision 125) +@@ -0,0 +1,75 @@ ++2010-08-15 Krzysztof Marecki <freefirma@gmail.com> ++ ++ * GuiBuilderProject.cs: ++ ++2010-08-15 Krzysztof Marecki <freefirma@gmail.com> ++ ++ * GuiBuilderProject.cs: ++ * GuiBuilderService.cs: ++ ++2010-08-13 Krzysztof Marecki <freefirma@gmail.com> ++ ++ * GuiBuilderView.cs: ++ * GuiBuilderProject.cs: ++ * GuiBuilderService.cs: ++ * GuiBuilderDisplayBinding.cs: ++ * ActionGroupDisplayBinding.cs: ++ ++2010-08-09 Krzysztof Marecki <freefirma@gmail.com> ++ ++ * GuiBuilderProject.cs: Generate stetic code after a project converting ++ * GuiBuilderService.cs: ++ * GuiBuilderDisplayBinding.cs: Don't use component display binding for ++ generated partial files ++ ++2010-08-07 Krzysztof Marecki <marecki.krzysztof@gmail.com> ++ ++ * GuiBuilderView.cs: Raise OnDirtyChanged after saving. ++ * CombinedDesignView.cs: Track Api Changes. ++ ++2010-08-05 Krzysztof Marecki <freefirma@gmail.com> ++ ++ * GuiBuilderView.cs: Remove ModifiedChanged handler ++ ++2010-08-04 Krzysztof Marecki <freefirma@gmail.com> ++ ++ * CodeBinder.cs: Bump Api ++ * GuiBuilderWindow.cs: ++ * GuiBuilderService.cs: ++ * CombinedDesignView.cs: ++ * ActionGroupDisplayBinding.cs: ++ ++2010-08-03 Krzysztof Marecki <marecki.krzysztof@gmail.com> ++ ++ * GuiBuilderProject.cs: When Updatinglibraries don't save ++ if Stetic.Project was uninitialized ++ ++2010-07-27 Krzysztof Marecki <marecki.krzysztof@gmail.com> ++ ++ * GuiBuilderView.cs: ++ * CombinedDesignView.cs: ++ ++2010-07-06 Krzysztof Marecki <marecki.krzysztof@gmail.com> ++ ++ * GuiBuilderProject.cs: ++ * GuiBuilderService.cs: ++ ++2010-07-05 Krzysztof Marecki <marecki.krzysztof@gmail.com> ++ ++ * GuiBuilderProject.cs: ++ * CombinedDesignView.cs: ++ ++2010-06-23 Krzysztof Marecki <marecki.krzysztof@gmail.com> ++ ++ * GuiBuilderProject.cs: ++ ++2010-06-21 Krzysztof Marecki <marecki.krzysztof@gmail.com> ++ ++ * GuiBuilderProject.cs: Add Convert method ++ ++2010-06-07 Krzysztof Marecki <marecki.krzysztof@gmail.com> ++ ++ * GuiBuilderProject.cs: ++ * GuiBuilderService.cs: ++ * GtkProjectServiceExtension.cs: ++ +Index: MonoDevelop.GtkCore.GuiBuilder/GuiBuilderWindow.cs +=================================================================== +--- MonoDevelop.GtkCore.GuiBuilder/GuiBuilderWindow.cs (revision 17) ++++ MonoDevelop.GtkCore.GuiBuilder/GuiBuilderWindow.cs (working copy) +@@ -203,7 +203,7 @@ + IdeApp.ProjectOperations.Save (Project.Project); + + // Make sure the database is up-to-date +- ProjectDomService.Parse (Project.Project, cls.CompilationUnit.FileName, null); ++ ProjectDomService.Parse (Project.Project, cls.CompilationUnit.FileName); + } + + void AddSignalsRec (CodeTypeDeclaration type, Stetic.Component comp) +Index: MonoDevelop.GtkCore.GuiBuilder/GuiBuilderView.cs +=================================================================== +--- MonoDevelop.GtkCore.GuiBuilder/GuiBuilderView.cs (revision 17) ++++ MonoDevelop.GtkCore.GuiBuilder/GuiBuilderView.cs (working copy) +@@ -79,7 +79,7 @@ + { + gproject = window.Project; + GtkDesignInfo info = GtkDesignInfo.FromProject (gproject.Project); +- gproject.SteticProject.ImagesRootPath = FileService.AbsoluteToRelativePath (info.GtkGuiFolder, gproject.Project.BaseDirectory); ++ gproject.SteticProject.ImagesRootPath = FileService.AbsoluteToRelativePath (info.SteticFolder, gproject.Project.BaseDirectory); + gproject.UpdateLibraries (); + LoadDesigner (); + } +@@ -121,7 +121,7 @@ + + gproject.Unloaded += OnDisposeProject; + +- designer = gproject.SteticProject.CreateWidgetDesigner (window.RootWidget, false); ++ designer = gproject.SteticProject.CreateWidgetDesigner (window.RootWidget); + + // Designer page + designerPage.ClearChild (); +@@ -138,7 +138,7 @@ + codeBinder = new CodeBinder (gproject.Project, new OpenDocumentFileProvider (), designer.RootComponent); + + designer.BindField += OnBindWidgetField; +- designer.ModifiedChanged += OnWindowModifiedChanged; ++ designer.Changed += OnChanged; + designer.SignalAdded += OnSignalAdded; + designer.SignalRemoved += OnSignalRemoved; + designer.SignalChanged += OnSignalChanged; +@@ -194,7 +194,7 @@ + + gproject.Unloaded -= OnDisposeProject; + designer.BindField -= OnBindWidgetField; +- designer.ModifiedChanged -= OnWindowModifiedChanged; ++ designer.Changed -= OnChanged; + designer.SignalAdded -= OnSignalAdded; + designer.SignalRemoved -= OnSignalRemoved; + designer.SignalChanged -= OnSignalChanged; +@@ -292,7 +292,7 @@ + AddButton (GettextCatalog.GetString ("Actions"), actionsPage); + } + +- void OnWindowModifiedChanged (object s, EventArgs args) ++ void OnChanged (object s, EventArgs args) + { + if (IsDirty) + OnContentChanged (args); +@@ -351,6 +351,7 @@ + } + + gproject.Save (true); ++ OnDirtyChanged (EventArgs.Empty); + } + + public override bool IsDirty { +Index: MonoDevelop.GtkCore.GuiBuilder/CodeBinder.cs +=================================================================== +--- MonoDevelop.GtkCore.GuiBuilder/CodeBinder.cs (revision 17) ++++ MonoDevelop.GtkCore.GuiBuilder/CodeBinder.cs (working copy) +@@ -89,7 +89,7 @@ + if (targetObject == null) + return; + +- ParsedDocument doc = ProjectDomService.Parse (project, fileName, null); ++ ParsedDocument doc = ProjectDomService.Parse (project, fileName); + classFile = fileName; + + if (doc != null && doc.CompilationUnit != null) { +@@ -266,7 +266,7 @@ + ArrayList matches = new ArrayList (); + ICompilationUnit unit = null; + ProjectDom ctx = gproject.GetParserContext (); +- ParsedDocument doc = ProjectDomService.Parse (project, classFile, null); ++ ParsedDocument doc = ProjectDomService.Parse (project, classFile); + if (doc != null && doc.CompilationUnit != null) { + unit = doc.CompilationUnit; + foreach (IType fcls in unit.Types) { +Index: MonoDevelop.GtkCore.GuiBuilder/CombinedDesignView.cs +=================================================================== +--- MonoDevelop.GtkCore.GuiBuilder/CombinedDesignView.cs (revision 17) ++++ MonoDevelop.GtkCore.GuiBuilder/CombinedDesignView.cs (working copy) +@@ -200,6 +200,7 @@ + + public override void Load (string fileName) + { ++ ShowPage (1); + ContentName = fileName; + content.Load (fileName); + } +@@ -257,7 +258,9 @@ + { + } + +- public override object GetContent (Type type) ++// public override object GetContent (Type type) ++// public override T GetContent<T> () ++ public override T GetContent<T> () + { + // if (type == typeof(IEditableTextBuffer)) { + // // Intercept the IPositionable interface, since we need to +@@ -268,18 +271,12 @@ + // return null; + // } + // +- object ob = base.GetContent (type); +- if (ob != null) +- return ob; +- else if (content != null) +- return content.GetContent (type); +- else +- return null; ++ return base.GetContent<T> () ?? content.GetContent<T> (); + } + + public void JumpTo (int line, int column) + { +- IEditableTextBuffer ip = (IEditableTextBuffer) content.GetContent (typeof(IEditableTextBuffer)); ++ IEditableTextBuffer ip = (IEditableTextBuffer) content.GetContent<IEditableTextBuffer> (); + if (ip != null) { + ShowPage (0); + ip.SetCaretTo (line, column); +Index: MonoDevelop.GtkCore.GuiBuilder/GtkProjectServiceExtension.cs +=================================================================== +--- MonoDevelop.GtkCore.GuiBuilder/GtkProjectServiceExtension.cs (revision 17) ++++ MonoDevelop.GtkCore.GuiBuilder/GtkProjectServiceExtension.cs (working copy) +@@ -35,7 +35,9 @@ + + if (gen.Messages != null) { + foreach (string s in gen.Messages) +- res.AddWarning (info.GuiBuilderProject.File, 0, 0, null, s); ++// res.AddWarning (info.GuiBuilderProject.File, 0, 0, null, s); ++// TODO: Add gtkx file name in the Generator ++ res.AddWarning ("", 0, 0, null, s); + + if (gen.Messages.Length > 0) + info.ForceCodeGenerationOnBuild (); diff --git a/main/src/addins/MonoDevelop.GtkCore2/gtk-gui/ChangeLog b/main/src/addins/MonoDevelop.GtkCore2/gtk-gui/ChangeLog new file mode 100644 index 0000000000..3e2aea8cac --- /dev/null +++ b/main/src/addins/MonoDevelop.GtkCore2/gtk-gui/ChangeLog @@ -0,0 +1,50 @@ +2010-08-27 Krzysztof Marecki <freefirma@gmail.com> + + * gui.stetic: + +2010-08-15 Krzysztof Marecki <freefirma@gmail.com> + + * gui.stetic: + * MonoDevelop.GtkCore.Dialogs.ProjectConversionDialog.cs: + +2010-08-13 Krzysztof Marecki <freefirma@gmail.com> + + * gui.stetic: + +2010-08-09 Krzysztof Marecki <freefirma@gmail.com> + + * gui.stetic: + +2010-08-07 Krzysztof Marecki <marecki.krzysztof@gmail.com> + + * gui.stetic: + +2010-08-05 Krzysztof Marecki <freefirma@gmail.com> + + * gui.stetic: + +2010-08-04 Krzysztof Marecki <freefirma@gmail.com> + + * gui.stetic: + +2010-08-03 Krzysztof Marecki <marecki.krzysztof@gmail.com> + + * gui.stetic: + +2010-07-05 Krzysztof Marecki <marecki.krzysztof@gmail.com> + + * gui.stetic: + +2010-06-23 Krzysztof Marecki <marecki.krzysztof@gmail.com> + + * gui.stetic: + * MonoDevelop.GtkCore.Dialogs.ProjectConversionDialog.cs: + +2010-06-16 Krzysztof Marecki <marecki.krzysztof@gmail.com> + + * gui.stetic: + +2010-06-07 Krzysztof Marecki <marecki.krzysztof@gmail.com> + + * gui.stetic: + diff --git a/main/src/addins/MonoDevelop.GtkCore2/gtk-gui/MonoDevelop.GtkCore.Dialogs.GtkDesignerOptionsPanelWidget.cs b/main/src/addins/MonoDevelop.GtkCore2/gtk-gui/MonoDevelop.GtkCore.Dialogs.GtkDesignerOptionsPanelWidget.cs new file mode 100644 index 0000000000..0af9212faa --- /dev/null +++ b/main/src/addins/MonoDevelop.GtkCore2/gtk-gui/MonoDevelop.GtkCore.Dialogs.GtkDesignerOptionsPanelWidget.cs @@ -0,0 +1,40 @@ + +// This file has been generated by the GUI designer. Do not modify. +namespace MonoDevelop.GtkCore.Dialogs +{ + public partial class GtkDesignerOptionsPanelWidget + { + private global::Gtk.VBox vbox2; + + private global::Gtk.CheckButton checkSwitchLayout; + + protected virtual void Build () + { + global::Stetic.Gui.Initialize (this); + // Widget MonoDevelop.GtkCore.Dialogs.GtkDesignerOptionsPanelWidget + global::Stetic.BinContainer.Attach (this); + this.Name = "MonoDevelop.GtkCore.Dialogs.GtkDesignerOptionsPanelWidget"; + // Container child MonoDevelop.GtkCore.Dialogs.GtkDesignerOptionsPanelWidget.Gtk.Container+ContainerChild + this.vbox2 = new global::Gtk.VBox (); + this.vbox2.Name = "vbox2"; + this.vbox2.Spacing = 6; + // Container child vbox2.Gtk.Box+BoxChild + this.checkSwitchLayout = new global::Gtk.CheckButton (); + this.checkSwitchLayout.CanFocus = true; + this.checkSwitchLayout.Name = "checkSwitchLayout"; + this.checkSwitchLayout.Label = global::Mono.Unix.Catalog.GetString ("Automatically switch to the \"GUI Builder\" layout when opening the designer"); + this.checkSwitchLayout.DrawIndicator = true; + this.checkSwitchLayout.UseUnderline = true; + this.vbox2.Add (this.checkSwitchLayout); + global::Gtk.Box.BoxChild w1 = ((global::Gtk.Box.BoxChild)(this.vbox2[this.checkSwitchLayout])); + w1.Position = 0; + w1.Expand = false; + w1.Fill = false; + this.Add (this.vbox2); + if ((this.Child != null)) { + this.Child.ShowAll (); + } + this.Hide (); + } + } +} diff --git a/main/src/addins/MonoDevelop.GtkCore2/gtk-gui/MonoDevelop.GtkCore.Dialogs.ProjectConversionDialog.cs b/main/src/addins/MonoDevelop.GtkCore2/gtk-gui/MonoDevelop.GtkCore.Dialogs.ProjectConversionDialog.cs new file mode 100644 index 0000000000..b7650fd16e --- /dev/null +++ b/main/src/addins/MonoDevelop.GtkCore2/gtk-gui/MonoDevelop.GtkCore.Dialogs.ProjectConversionDialog.cs @@ -0,0 +1,183 @@ +// ------------------------------------------------------------------------------ +// <autogenerated> +// This code was generated by a tool. +// Mono Runtime Version: 2.0.50727.1433 +// +// Changes to this file may cause incorrect behavior and will be lost if +// the code is regenerated. +// </autogenerated> +// ------------------------------------------------------------------------------ + + +// This file has been generated by the GUI designer. Do not modify. +namespace MonoDevelop.GtkCore.Dialogs +{ + public partial class ProjectConversionDialog + { + private global::Gtk.HBox hbox; + + private global::Gtk.Alignment alignmentLogo; + + private global::Gtk.Image imageLogo; + + private global::Gtk.VBox vbox2; + + private global::Gtk.Label labelProject; + + private global::Gtk.Label labelInfo; + + private global::Gtk.HSeparator hseparator1; + + private global::Gtk.HBox hbox1; + + private global::Gtk.Label labelFolder; + + private global::Gtk.Entry entryFolder; + + private global::Gtk.CheckButton checkBackup; + + private global::Gtk.Button buttonConvert; + + protected virtual void Build () + { + global::Stetic.Gui.Initialize (this); + // Widget MonoDevelop.GtkCore.Dialogs.ProjectConversionDialog + this.Name = "MonoDevelop.GtkCore.Dialogs.ProjectConversionDialog"; + this.Title = global::Mono.Unix.Catalog.GetString ("Project Name"); + this.WindowPosition = ((global::Gtk.WindowPosition)(4)); + this.Modal = true; + this.SkipTaskbarHint = true; + // Internal child MonoDevelop.GtkCore.Dialogs.ProjectConversionDialog.VBox + global::Gtk.VBox w1 = this.VBox; + w1.Name = "dialog1_VBox"; + w1.BorderWidth = ((uint)(2)); + // Container child dialog1_VBox.Gtk.Box+BoxChild + this.hbox = new global::Gtk.HBox (); + this.hbox.Name = "hbox"; + this.hbox.Spacing = 6; + // Container child hbox.Gtk.Box+BoxChild + this.alignmentLogo = new global::Gtk.Alignment (1f, 0.15f, 1f, 0f); + this.alignmentLogo.Name = "alignmentLogo"; + // Container child alignmentLogo.Gtk.Container+ContainerChild + this.imageLogo = new global::Gtk.Image (); + this.imageLogo.WidthRequest = 180; + this.imageLogo.Name = "imageLogo"; + this.imageLogo.Yalign = 0f; + this.imageLogo.Pixbuf = global::Gdk.Pixbuf.LoadFromResource ("gtk-logo.png"); + this.alignmentLogo.Add (this.imageLogo); + this.hbox.Add (this.alignmentLogo); + global::Gtk.Box.BoxChild w3 = ((global::Gtk.Box.BoxChild)(this.hbox[this.alignmentLogo])); + w3.Position = 0; + w3.Expand = false; + w3.Fill = false; + // Container child hbox.Gtk.Box+BoxChild + this.vbox2 = new global::Gtk.VBox (); + this.vbox2.Name = "vbox2"; + this.vbox2.Spacing = 6; + // Container child vbox2.Gtk.Box+BoxChild + this.labelProject = new global::Gtk.Label (); + this.labelProject.Name = "labelProject"; + this.labelProject.LabelProp = global::Mono.Unix.Catalog.GetString ("<b><big>GTK# Project Conversion</big></b>"); + this.labelProject.UseMarkup = true; + this.vbox2.Add (this.labelProject); + global::Gtk.Box.BoxChild w4 = ((global::Gtk.Box.BoxChild)(this.vbox2[this.labelProject])); + w4.Position = 0; + w4.Expand = false; + w4.Fill = false; + // Container child vbox2.Gtk.Box+BoxChild + this.labelInfo = new global::Gtk.Label (); + this.labelInfo.Name = "labelInfo"; + this.labelInfo.Xalign = 0f; + this.labelInfo.Yalign = 0f; + this.labelInfo.LabelProp = global::Mono.Unix.Catalog.GetString ("This project has been created in the previous\nversion of GTK# addin and must be converted. \n\n<b>Following changes will be made :</b>\n\t- split gui.stetic into separate .gtkx files\n\t- split generated.cs into separate helper classes\n\t- remove gtk-gui folder.\n\t- create a designer folder for stock icons\n\t and generated helper classes. "); + this.labelInfo.UseMarkup = true; + this.labelInfo.Wrap = true; + this.vbox2.Add (this.labelInfo); + global::Gtk.Box.BoxChild w5 = ((global::Gtk.Box.BoxChild)(this.vbox2[this.labelInfo])); + w5.Position = 1; + w5.Expand = false; + w5.Fill = false; + // Container child vbox2.Gtk.Box+BoxChild + this.hseparator1 = new global::Gtk.HSeparator (); + this.hseparator1.Name = "hseparator1"; + this.vbox2.Add (this.hseparator1); + global::Gtk.Box.BoxChild w6 = ((global::Gtk.Box.BoxChild)(this.vbox2[this.hseparator1])); + w6.Position = 2; + w6.Expand = false; + w6.Fill = false; + // Container child vbox2.Gtk.Box+BoxChild + this.hbox1 = new global::Gtk.HBox (); + this.hbox1.Name = "hbox1"; + this.hbox1.Spacing = 6; + // Container child hbox1.Gtk.Box+BoxChild + this.labelFolder = new global::Gtk.Label (); + this.labelFolder.Name = "labelFolder"; + this.labelFolder.LabelProp = global::Mono.Unix.Catalog.GetString ("Designer folder name:"); + this.hbox1.Add (this.labelFolder); + global::Gtk.Box.BoxChild w7 = ((global::Gtk.Box.BoxChild)(this.hbox1[this.labelFolder])); + w7.Position = 0; + w7.Expand = false; + w7.Fill = false; + // Container child hbox1.Gtk.Box+BoxChild + this.entryFolder = new global::Gtk.Entry (); + this.entryFolder.CanFocus = true; + this.entryFolder.Name = "entryFolder"; + this.entryFolder.IsEditable = true; + + this.hbox1.Add (this.entryFolder); + global::Gtk.Box.BoxChild w8 = ((global::Gtk.Box.BoxChild)(this.hbox1[this.entryFolder])); + w8.Position = 1; + this.vbox2.Add (this.hbox1); + global::Gtk.Box.BoxChild w9 = ((global::Gtk.Box.BoxChild)(this.vbox2[this.hbox1])); + w9.Position = 3; + w9.Expand = false; + w9.Fill = false; + // Container child vbox2.Gtk.Box+BoxChild + this.checkBackup = new global::Gtk.CheckButton (); + this.checkBackup.CanFocus = true; + this.checkBackup.Name = "checkBackup"; + this.checkBackup.Label = global::Mono.Unix.Catalog.GetString ("Make a backup before converting"); + this.checkBackup.Active = true; + this.checkBackup.DrawIndicator = true; + this.checkBackup.UseUnderline = true; + this.vbox2.Add (this.checkBackup); + global::Gtk.Box.BoxChild w10 = ((global::Gtk.Box.BoxChild)(this.vbox2[this.checkBackup])); + w10.Position = 4; + w10.Expand = false; + w10.Fill = false; + this.hbox.Add (this.vbox2); + global::Gtk.Box.BoxChild w11 = ((global::Gtk.Box.BoxChild)(this.hbox[this.vbox2])); + w11.Position = 1; + w11.Expand = false; + w11.Fill = false; + w1.Add (this.hbox); + global::Gtk.Box.BoxChild w12 = ((global::Gtk.Box.BoxChild)(w1[this.hbox])); + w12.Position = 0; + w12.Expand = false; + w12.Fill = false; + // Internal child MonoDevelop.GtkCore.Dialogs.ProjectConversionDialog.ActionArea + global::Gtk.HButtonBox w13 = this.ActionArea; + w13.Name = "dialog1_ActionArea"; + w13.Spacing = 10; + w13.BorderWidth = ((uint)(5)); + w13.LayoutStyle = ((global::Gtk.ButtonBoxStyle)(4)); + // Container child dialog1_ActionArea.Gtk.ButtonBox+ButtonBoxChild + this.buttonConvert = new global::Gtk.Button (); + this.buttonConvert.CanDefault = true; + this.buttonConvert.CanFocus = true; + this.buttonConvert.Name = "buttonConvert"; + this.buttonConvert.UseUnderline = true; + this.buttonConvert.Label = global::Mono.Unix.Catalog.GetString ("_Convert"); + this.AddActionWidget (this.buttonConvert, -5); + global::Gtk.ButtonBox.ButtonBoxChild w14 = ((global::Gtk.ButtonBox.ButtonBoxChild)(w13[this.buttonConvert])); + w14.Expand = false; + w14.Fill = false; + if ((this.Child != null)) { + this.Child.ShowAll (); + } + this.DefaultWidth = 532; + this.DefaultHeight = 292; + this.Show (); + } + } +} diff --git a/main/src/addins/MonoDevelop.GtkCore2/gtk-gui/generated.cs b/main/src/addins/MonoDevelop.GtkCore2/gtk-gui/generated.cs new file mode 100644 index 0000000000..aa96390c4a --- /dev/null +++ b/main/src/addins/MonoDevelop.GtkCore2/gtk-gui/generated.cs @@ -0,0 +1,82 @@ + +// This file has been generated by the GUI designer. Do not modify. +namespace Stetic +{ + internal class Gui + { + private static bool initialized; + + static internal void Initialize (Gtk.Widget iconRenderer) + { + if ((Stetic.Gui.initialized == false)) { + Stetic.Gui.initialized = true; + } + } + } + + internal class BinContainer + { + private Gtk.Widget child; + + private Gtk.UIManager uimanager; + + public static BinContainer Attach (Gtk.Bin bin) + { + BinContainer bc = new BinContainer (); + bin.SizeRequested += new Gtk.SizeRequestedHandler (bc.OnSizeRequested); + bin.SizeAllocated += new Gtk.SizeAllocatedHandler (bc.OnSizeAllocated); + bin.Added += new Gtk.AddedHandler (bc.OnAdded); + return bc; + } + + private void OnSizeRequested (object sender, Gtk.SizeRequestedArgs args) + { + if ((this.child != null)) { + args.Requisition = this.child.SizeRequest (); + } + } + + private void OnSizeAllocated (object sender, Gtk.SizeAllocatedArgs args) + { + if ((this.child != null)) { + this.child.Allocation = args.Allocation; + } + } + + private void OnAdded (object sender, Gtk.AddedArgs args) + { + this.child = args.Widget; + } + + public void SetUiManager (Gtk.UIManager uim) + { + this.uimanager = uim; + this.child.Realized += new System.EventHandler (this.OnRealized); + } + + private void OnRealized (object sender, System.EventArgs args) + { + if ((this.uimanager != null)) { + Gtk.Widget w; + w = this.child.Toplevel; + if (((w != null) && typeof(Gtk.Window).IsInstanceOfType (w))) { + ((Gtk.Window)(w)).AddAccelGroup (this.uimanager.AccelGroup); + this.uimanager = null; + } + } + } + } + + internal class ActionGroups + { + public static Gtk.ActionGroup GetActionGroup (System.Type type) + { + return Stetic.ActionGroups.GetActionGroup (type.FullName); + } + + public static Gtk.ActionGroup GetActionGroup (string name) + { + return null; + } + } +} diff --git a/main/src/addins/MonoDevelop.GtkCore2/gtk-gui/gui.stetic b/main/src/addins/MonoDevelop.GtkCore2/gtk-gui/gui.stetic new file mode 100644 index 0000000000..819d4c1aa8 --- /dev/null +++ b/main/src/addins/MonoDevelop.GtkCore2/gtk-gui/gui.stetic @@ -0,0 +1,231 @@ +<?xml version="1.0" encoding="utf-8"?> +<stetic-interface> + <configuration> + <images-root-path>..</images-root-path> + <target-gtk-version>2.12</target-gtk-version> + </configuration> + <import> + <widget-library name="glade-sharp, Version=2.12.0.0, Culture=neutral, PublicKeyToken=35e10195dab3c99f" /> + <widget-library name="../../../../build/AddIns/MonoDevelop.GtkCore2/libsteticui2.dll" /> + <widget-library name="../../../../build/AddIns/MonoDevelop.GtkCore2/libstetic2.dll" /> + <widget-library name="../../../../build/AddIns/MonoDevelop.Deployment/MonoDevelop.Deployment.dll" /> + <widget-library name="../../../../build/AddIns/MonoDevelop.DesignerSupport/MonoDevelop.DesignerSupport.dll" /> + <widget-library name="../../../../build/bin/MonoDevelop.Ide.dll" /> + <widget-library name="../../../../build/bin/Mono.TextEditor.dll" /> + <widget-library name="MonoDevelop.Ide, Version=2.4.0.0, Culture=neutral" /> + <widget-library name="Mono.TextEditor, Version=1.0.0.0, Culture=neutral" /> + <widget-library name="../../../../build/AddIns/MonoDevelop.GtkCore2/MonoDevelop.GtkCore2.dll" internal="true" /> + </import> + <widget class="Gtk.Bin" id="MonoDevelop.GtkCore.Dialogs.GtkDesignerOptionsPanelWidget" design-size="503 22"> + <property name="MemberName" /> + <property name="Visible">False</property> + <child> + <widget class="Gtk.VBox" id="vbox2"> + <property name="MemberName" /> + <property name="Spacing">6</property> + <child> + <widget class="Gtk.CheckButton" id="checkSwitchLayout"> + <property name="MemberName" /> + <property name="CanFocus">True</property> + <property name="Label" translatable="yes">Automatically switch to the "GUI Builder" layout when opening the designer</property> + <property name="DrawIndicator">True</property> + <property name="HasLabel">True</property> + <property name="UseUnderline">True</property> + </widget> + <packing> + <property name="Position">0</property> + <property name="AutoSize">True</property> + <property name="Expand">False</property> + <property name="Fill">False</property> + </packing> + </child> + </widget> + </child> + </widget> + <widget class="Gtk.Dialog" id="MonoDevelop.GtkCore.Dialogs.ProjectConversionDialog" design-size="532 308"> + <property name="MemberName" /> + <property name="Title" translatable="yes">Project Name</property> + <property name="WindowPosition">CenterOnParent</property> + <property name="Modal">True</property> + <property name="SkipTaskbarHint">True</property> + <property name="Buttons">1</property> + <property name="HelpButton">False</property> + <child internal-child="VBox"> + <widget class="Gtk.VBox" id="dialog1_VBox"> + <property name="MemberName" /> + <property name="BorderWidth">2</property> + <child> + <widget class="Gtk.HBox" id="hbox"> + <property name="MemberName" /> + <property name="Spacing">6</property> + <child> + <widget class="Gtk.Alignment" id="alignmentLogo"> + <property name="MemberName" /> + <property name="Yscale">0</property> + <property name="Xalign">1</property> + <property name="Yalign">0.15</property> + <child> + <widget class="Gtk.Image" id="imageLogo"> + <property name="MemberName" /> + <property name="WidthRequest">180</property> + <property name="Yalign">0</property> + <property name="Pixbuf">resource:gtk-logo.png</property> + </widget> + </child> + </widget> + <packing> + <property name="Position">0</property> + <property name="AutoSize">True</property> + <property name="Expand">False</property> + <property name="Fill">False</property> + </packing> + </child> + <child> + <widget class="Gtk.VBox" id="vbox2"> + <property name="MemberName" /> + <property name="Spacing">6</property> + <child> + <widget class="Gtk.Label" id="labelProject"> + <property name="MemberName" /> + <property name="LabelProp" translatable="yes"><b><big>GTK# Project Conversion</big></b></property> + <property name="UseMarkup">True</property> + </widget> + <packing> + <property name="Position">0</property> + <property name="AutoSize">True</property> + <property name="Expand">False</property> + <property name="Fill">False</property> + </packing> + </child> + <child> + <widget class="Gtk.Label" id="labelInfo"> + <property name="MemberName" /> + <property name="Xalign">0</property> + <property name="Yalign">0</property> + <property name="LabelProp" translatable="yes">This project has been created in the previous +version of GTK# addin and must be converted. + +<b>Following changes will be made :</b> + - split gui.stetic into separate .gtkx files + - split generated.cs into separate helper classes + - remove gtk-gui folder. + - create a designer folder for stock icons + and generated helper classes.</property> + <property name="UseMarkup">True</property> + <property name="Wrap">True</property> + </widget> + <packing> + <property name="Position">1</property> + <property name="AutoSize">True</property> + <property name="Expand">False</property> + <property name="Fill">False</property> + </packing> + </child> + <child> + <widget class="Gtk.HSeparator" id="hseparator1"> + <property name="MemberName" /> + </widget> + <packing> + <property name="Position">2</property> + <property name="AutoSize">True</property> + <property name="Expand">False</property> + <property name="Fill">False</property> + </packing> + </child> + <child> + <widget class="Gtk.HBox" id="hbox1"> + <property name="MemberName" /> + <property name="Spacing">6</property> + <child> + <widget class="Gtk.Label" id="labelFolder"> + <property name="MemberName" /> + <property name="LabelProp" translatable="yes">Designer folder name:</property> + </widget> + <packing> + <property name="Position">0</property> + <property name="AutoSize">True</property> + <property name="Expand">False</property> + <property name="Fill">False</property> + </packing> + </child> + <child> + <widget class="Gtk.Entry" id="entryFolder"> + <property name="MemberName" /> + <property name="CanFocus">True</property> + <property name="IsEditable">True</property> + <property name="InvisibleChar">●</property> + </widget> + <packing> + <property name="Position">1</property> + <property name="AutoSize">True</property> + </packing> + </child> + </widget> + <packing> + <property name="Position">3</property> + <property name="AutoSize">True</property> + <property name="Expand">False</property> + <property name="Fill">False</property> + </packing> + </child> + <child> + <widget class="Gtk.CheckButton" id="checkBackup"> + <property name="MemberName" /> + <property name="CanFocus">True</property> + <property name="Label" translatable="yes">Make a backup before converting</property> + <property name="Active">True</property> + <property name="DrawIndicator">True</property> + <property name="HasLabel">True</property> + <property name="UseUnderline">True</property> + </widget> + <packing> + <property name="Position">4</property> + <property name="AutoSize">True</property> + <property name="Expand">False</property> + <property name="Fill">False</property> + </packing> + </child> + </widget> + <packing> + <property name="Position">1</property> + <property name="AutoSize">True</property> + <property name="Expand">False</property> + <property name="Fill">False</property> + </packing> + </child> + </widget> + <packing> + <property name="Position">0</property> + <property name="AutoSize">True</property> + <property name="Expand">False</property> + <property name="Fill">False</property> + </packing> + </child> + </widget> + </child> + <child internal-child="ActionArea"> + <widget class="Gtk.HButtonBox" id="dialog1_ActionArea"> + <property name="MemberName" /> + <property name="Spacing">10</property> + <property name="BorderWidth">5</property> + <property name="Size">1</property> + <property name="LayoutStyle">End</property> + <child> + <widget class="Gtk.Button" id="buttonConvert"> + <property name="MemberName" /> + <property name="CanDefault">True</property> + <property name="CanFocus">True</property> + <property name="Type">TextOnly</property> + <property name="Label" translatable="yes">_Convert</property> + <property name="UseUnderline">True</property> + <property name="ResponseId">-5</property> + </widget> + <packing> + <property name="Expand">False</property> + <property name="Fill">False</property> + </packing> + </child> + </widget> + </child> + </widget> +</stetic-interface>
\ No newline at end of file diff --git a/main/src/addins/MonoDevelop.GtkCore2/gui.glade b/main/src/addins/MonoDevelop.GtkCore2/gui.glade new file mode 100644 index 0000000000..92f5740b91 --- /dev/null +++ b/main/src/addins/MonoDevelop.GtkCore2/gui.glade @@ -0,0 +1,710 @@ +<?xml version="1.0" standalone="no"?> <!--*- mode: xml -*--> +<!DOCTYPE glade-interface SYSTEM "http://glade.gnome.org/glade-2.0.dtd"> + +<glade-interface> +<requires lib="gnome"/> + +<widget class="GtkDialog" id="SelectRenamedClassDialog"> + <property name="visible">True</property> + <property name="title" translatable="yes">GUI Designer</property> + <property name="type">GTK_WINDOW_TOPLEVEL</property> + <property name="window_position">GTK_WIN_POS_NONE</property> + <property name="modal">False</property> + <property name="resizable">True</property> + <property name="destroy_with_parent">False</property> + <property name="decorated">True</property> + <property name="skip_taskbar_hint">False</property> + <property name="skip_pager_hint">False</property> + <property name="type_hint">GDK_WINDOW_TYPE_HINT_DIALOG</property> + <property name="gravity">GDK_GRAVITY_NORTH_WEST</property> + <property name="focus_on_map">True</property> + <property name="urgency_hint">False</property> + <property name="has_separator">True</property> + + <child internal-child="vbox"> + <widget class="GtkVBox" id="dialog-vbox1"> + <property name="visible">True</property> + <property name="homogeneous">False</property> + <property name="spacing">0</property> + + <child internal-child="action_area"> + <widget class="GtkHButtonBox" id="dialog-action_area1"> + <property name="visible">True</property> + <property name="layout_style">GTK_BUTTONBOX_END</property> + + <child> + <widget class="GtkButton" id="cancelbutton1"> + <property name="visible">True</property> + <property name="can_default">True</property> + <property name="can_focus">True</property> + <property name="label">gtk-cancel</property> + <property name="use_stock">True</property> + <property name="relief">GTK_RELIEF_NORMAL</property> + <property name="focus_on_click">True</property> + <property name="response_id">-6</property> + </widget> + </child> + + <child> + <widget class="GtkButton" id="okbutton1"> + <property name="visible">True</property> + <property name="can_default">True</property> + <property name="can_focus">True</property> + <property name="label">gtk-ok</property> + <property name="use_stock">True</property> + <property name="relief">GTK_RELIEF_NORMAL</property> + <property name="focus_on_click">True</property> + <property name="response_id">-5</property> + </widget> + </child> + </widget> + <packing> + <property name="padding">0</property> + <property name="expand">False</property> + <property name="fill">True</property> + <property name="pack_type">GTK_PACK_END</property> + </packing> + </child> + + <child> + <widget class="GtkVBox" id="vbox2"> + <property name="border_width">6</property> + <property name="visible">True</property> + <property name="homogeneous">False</property> + <property name="spacing">6</property> + + <child> + <widget class="GtkLabel" id="labelMessage"> + <property name="width_request">549</property> + <property name="visible">True</property> + <property name="label" translatable="yes">The class that was bound to the design currently edited could not be found. Please select the class you want to bind to the design:</property> + <property name="use_underline">False</property> + <property name="use_markup">False</property> + <property name="justify">GTK_JUSTIFY_LEFT</property> + <property name="wrap">True</property> + <property name="selectable">False</property> + <property name="xalign">0</property> + <property name="yalign">0.5</property> + <property name="xpad">0</property> + <property name="ypad">0</property> + <property name="ellipsize">PANGO_ELLIPSIZE_NONE</property> + <property name="width_chars">-1</property> + <property name="single_line_mode">False</property> + <property name="angle">0</property> + </widget> + <packing> + <property name="padding">0</property> + <property name="expand">False</property> + <property name="fill">False</property> + </packing> + </child> + + <child> + <widget class="GtkScrolledWindow" id="scrolledwindow2"> + <property name="visible">True</property> + <property name="can_focus">True</property> + <property name="hscrollbar_policy">GTK_POLICY_ALWAYS</property> + <property name="vscrollbar_policy">GTK_POLICY_ALWAYS</property> + <property name="shadow_type">GTK_SHADOW_IN</property> + <property name="window_placement">GTK_CORNER_TOP_LEFT</property> + + <child> + <widget class="GtkTreeView" id="treeClasses"> + <property name="visible">True</property> + <property name="can_focus">True</property> + <property name="headers_visible">False</property> + <property name="rules_hint">False</property> + <property name="reorderable">False</property> + <property name="enable_search">True</property> + <property name="fixed_height_mode">False</property> + <property name="hover_selection">False</property> + <property name="hover_expand">False</property> + </widget> + </child> + </widget> + <packing> + <property name="padding">0</property> + <property name="expand">True</property> + <property name="fill">True</property> + </packing> + </child> + </widget> + <packing> + <property name="padding">0</property> + <property name="expand">True</property> + <property name="fill">True</property> + </packing> + </child> + </widget> + </child> +</widget> + +<widget class="GtkDialog" id="BindDesignDialog"> + <property name="visible">True</property> + <property name="title" translatable="yes">Bind Widget Design</property> + <property name="type">GTK_WINDOW_TOPLEVEL</property> + <property name="window_position">GTK_WIN_POS_NONE</property> + <property name="modal">False</property> + <property name="resizable">True</property> + <property name="destroy_with_parent">False</property> + <property name="decorated">True</property> + <property name="skip_taskbar_hint">False</property> + <property name="skip_pager_hint">False</property> + <property name="type_hint">GDK_WINDOW_TYPE_HINT_DIALOG</property> + <property name="gravity">GDK_GRAVITY_NORTH_WEST</property> + <property name="focus_on_map">True</property> + <property name="urgency_hint">False</property> + <property name="has_separator">True</property> + + <child internal-child="vbox"> + <widget class="GtkVBox" id="dialog-vbox2"> + <property name="visible">True</property> + <property name="homogeneous">False</property> + <property name="spacing">0</property> + + <child internal-child="action_area"> + <widget class="GtkHButtonBox" id="dialog-action_area2"> + <property name="visible">True</property> + <property name="layout_style">GTK_BUTTONBOX_END</property> + + <child> + <widget class="GtkButton" id="cancelbutton2"> + <property name="visible">True</property> + <property name="can_default">True</property> + <property name="can_focus">True</property> + <property name="label">gtk-cancel</property> + <property name="use_stock">True</property> + <property name="relief">GTK_RELIEF_NORMAL</property> + <property name="focus_on_click">True</property> + <property name="response_id">-6</property> + </widget> + </child> + + <child> + <widget class="GtkButton" id="okButton"> + <property name="visible">True</property> + <property name="can_default">True</property> + <property name="can_focus">True</property> + <property name="label">gtk-ok</property> + <property name="use_stock">True</property> + <property name="relief">GTK_RELIEF_NORMAL</property> + <property name="focus_on_click">True</property> + <property name="response_id">-5</property> + </widget> + </child> + </widget> + <packing> + <property name="padding">0</property> + <property name="expand">False</property> + <property name="fill">True</property> + <property name="pack_type">GTK_PACK_END</property> + </packing> + </child> + + <child> + <widget class="GtkVBox" id="vbox3"> + <property name="border_width">6</property> + <property name="visible">True</property> + <property name="homogeneous">False</property> + <property name="spacing">6</property> + + <child> + <widget class="GtkLabel" id="labelMessage"> + <property name="visible">True</property> + <property name="label" translatable="yes">The widget design {0} is not currently bound to a class.</property> + <property name="use_underline">False</property> + <property name="use_markup">False</property> + <property name="justify">GTK_JUSTIFY_LEFT</property> + <property name="wrap">False</property> + <property name="selectable">False</property> + <property name="xalign">0</property> + <property name="yalign">0.5</property> + <property name="xpad">0</property> + <property name="ypad">0</property> + <property name="ellipsize">PANGO_ELLIPSIZE_NONE</property> + <property name="width_chars">-1</property> + <property name="single_line_mode">False</property> + <property name="angle">0</property> + </widget> + <packing> + <property name="padding">0</property> + <property name="expand">False</property> + <property name="fill">False</property> + </packing> + </child> + + <child> + <widget class="GtkRadioButton" id="radioSelect"> + <property name="visible">True</property> + <property name="can_focus">True</property> + <property name="label" translatable="yes">Bind the design to an existing class</property> + <property name="use_underline">True</property> + <property name="relief">GTK_RELIEF_NORMAL</property> + <property name="focus_on_click">True</property> + <property name="active">False</property> + <property name="inconsistent">False</property> + <property name="draw_indicator">True</property> + <signal name="toggled" handler="OnSelectToggled" last_modification_time="Mon, 27 Feb 2006 15:28:25 GMT"/> + </widget> + <packing> + <property name="padding">0</property> + <property name="expand">False</property> + <property name="fill">False</property> + </packing> + </child> + + <child> + <widget class="GtkHBox" id="hbox1"> + <property name="visible">True</property> + <property name="homogeneous">False</property> + <property name="spacing">0</property> + + <child> + <widget class="GtkLabel" id="label8"> + <property name="width_request">24</property> + <property name="visible">True</property> + <property name="label" translatable="yes"></property> + <property name="use_underline">False</property> + <property name="use_markup">False</property> + <property name="justify">GTK_JUSTIFY_LEFT</property> + <property name="wrap">False</property> + <property name="selectable">False</property> + <property name="xalign">0.5</property> + <property name="yalign">0.5</property> + <property name="xpad">0</property> + <property name="ypad">0</property> + <property name="ellipsize">PANGO_ELLIPSIZE_NONE</property> + <property name="width_chars">-1</property> + <property name="single_line_mode">False</property> + <property name="angle">0</property> + </widget> + <packing> + <property name="padding">0</property> + <property name="expand">False</property> + <property name="fill">False</property> + </packing> + </child> + + <child> + <widget class="GtkLabel" id="label7"> + <property name="visible">True</property> + <property name="label" translatable="yes">Select a class: </property> + <property name="use_underline">False</property> + <property name="use_markup">False</property> + <property name="justify">GTK_JUSTIFY_LEFT</property> + <property name="wrap">False</property> + <property name="selectable">False</property> + <property name="xalign">0.5</property> + <property name="yalign">0.5</property> + <property name="xpad">0</property> + <property name="ypad">0</property> + <property name="ellipsize">PANGO_ELLIPSIZE_NONE</property> + <property name="width_chars">-1</property> + <property name="single_line_mode">False</property> + <property name="angle">0</property> + </widget> + <packing> + <property name="padding">0</property> + <property name="expand">False</property> + <property name="fill">False</property> + </packing> + </child> + + <child> + <widget class="GtkComboBox" id="comboClasses"> + <property name="visible">True</property> + <property name="add_tearoffs">False</property> + <property name="focus_on_click">True</property> + </widget> + <packing> + <property name="padding">0</property> + <property name="expand">True</property> + <property name="fill">True</property> + </packing> + </child> + </widget> + <packing> + <property name="padding">0</property> + <property name="expand">False</property> + <property name="fill">False</property> + </packing> + </child> + + <child> + <widget class="GtkRadioButton" id="radioCreate"> + <property name="visible">True</property> + <property name="can_focus">True</property> + <property name="label" translatable="yes">Create a new class</property> + <property name="use_underline">True</property> + <property name="relief">GTK_RELIEF_NORMAL</property> + <property name="focus_on_click">True</property> + <property name="active">False</property> + <property name="inconsistent">False</property> + <property name="draw_indicator">True</property> + <property name="group">radioSelect</property> + <signal name="toggled" handler="OnSelectToggled" last_modification_time="Mon, 27 Feb 2006 15:28:54 GMT"/> + </widget> + <packing> + <property name="padding">0</property> + <property name="expand">False</property> + <property name="fill">False</property> + </packing> + </child> + + <child> + <widget class="GtkTable" id="tableNewClass"> + <property name="visible">True</property> + <property name="n_rows">3</property> + <property name="n_columns">3</property> + <property name="homogeneous">False</property> + <property name="row_spacing">6</property> + <property name="column_spacing">6</property> + + <child> + <widget class="GtkLabel" id="label4"> + <property name="visible">True</property> + <property name="label" translatable="yes">Name:</property> + <property name="use_underline">False</property> + <property name="use_markup">False</property> + <property name="justify">GTK_JUSTIFY_LEFT</property> + <property name="wrap">False</property> + <property name="selectable">False</property> + <property name="xalign">0</property> + <property name="yalign">0.5</property> + <property name="xpad">0</property> + <property name="ypad">0</property> + <property name="ellipsize">PANGO_ELLIPSIZE_NONE</property> + <property name="width_chars">-1</property> + <property name="single_line_mode">False</property> + <property name="angle">0</property> + </widget> + <packing> + <property name="left_attach">1</property> + <property name="right_attach">2</property> + <property name="top_attach">0</property> + <property name="bottom_attach">1</property> + <property name="x_options">fill</property> + <property name="y_options"></property> + </packing> + </child> + + <child> + <widget class="GtkLabel" id="label5"> + <property name="visible">True</property> + <property name="label" translatable="yes">Namespace:</property> + <property name="use_underline">False</property> + <property name="use_markup">False</property> + <property name="justify">GTK_JUSTIFY_LEFT</property> + <property name="wrap">False</property> + <property name="selectable">False</property> + <property name="xalign">0</property> + <property name="yalign">0.5</property> + <property name="xpad">0</property> + <property name="ypad">0</property> + <property name="ellipsize">PANGO_ELLIPSIZE_NONE</property> + <property name="width_chars">-1</property> + <property name="single_line_mode">False</property> + <property name="angle">0</property> + </widget> + <packing> + <property name="left_attach">1</property> + <property name="right_attach">2</property> + <property name="top_attach">1</property> + <property name="bottom_attach">2</property> + <property name="x_options">fill</property> + <property name="y_options"></property> + </packing> + </child> + + <child> + <widget class="GtkLabel" id="label6"> + <property name="visible">True</property> + <property name="label" translatable="yes">Location:</property> + <property name="use_underline">False</property> + <property name="use_markup">False</property> + <property name="justify">GTK_JUSTIFY_LEFT</property> + <property name="wrap">False</property> + <property name="selectable">False</property> + <property name="xalign">0</property> + <property name="yalign">0.5</property> + <property name="xpad">0</property> + <property name="ypad">0</property> + <property name="ellipsize">PANGO_ELLIPSIZE_NONE</property> + <property name="width_chars">-1</property> + <property name="single_line_mode">False</property> + <property name="angle">0</property> + </widget> + <packing> + <property name="left_attach">1</property> + <property name="right_attach">2</property> + <property name="top_attach">2</property> + <property name="bottom_attach">3</property> + <property name="x_options">fill</property> + <property name="y_options"></property> + </packing> + </child> + + <child> + <widget class="GtkLabel" id="label9"> + <property name="width_request">24</property> + <property name="visible">True</property> + <property name="label" translatable="yes"></property> + <property name="use_underline">False</property> + <property name="use_markup">False</property> + <property name="justify">GTK_JUSTIFY_LEFT</property> + <property name="wrap">False</property> + <property name="selectable">False</property> + <property name="xalign">0</property> + <property name="yalign">0.5</property> + <property name="xpad">0</property> + <property name="ypad">0</property> + <property name="ellipsize">PANGO_ELLIPSIZE_NONE</property> + <property name="width_chars">-1</property> + <property name="single_line_mode">False</property> + <property name="angle">0</property> + </widget> + <packing> + <property name="left_attach">0</property> + <property name="right_attach">1</property> + <property name="top_attach">0</property> + <property name="bottom_attach">1</property> + <property name="x_options">fill</property> + <property name="y_options"></property> + </packing> + </child> + + <child> + <widget class="GtkEntry" id="entryClassName"> + <property name="visible">True</property> + <property name="can_focus">True</property> + <property name="editable">True</property> + <property name="visibility">True</property> + <property name="max_length">0</property> + <property name="text" translatable="yes"></property> + <property name="has_frame">True</property> + <property name="invisible_char">*</property> + <property name="activates_default">False</property> + <signal name="changed" handler="OnEntryChanged" last_modification_time="Mon, 27 Feb 2006 18:53:06 GMT"/> + </widget> + <packing> + <property name="left_attach">2</property> + <property name="right_attach">3</property> + <property name="top_attach">0</property> + <property name="bottom_attach">1</property> + <property name="y_options"></property> + </packing> + </child> + + <child> + <widget class="GtkEntry" id="entryNamespace"> + <property name="visible">True</property> + <property name="can_focus">True</property> + <property name="editable">True</property> + <property name="visibility">True</property> + <property name="max_length">0</property> + <property name="text" translatable="yes"></property> + <property name="has_frame">True</property> + <property name="invisible_char">*</property> + <property name="activates_default">False</property> + <signal name="changed" handler="OnEntryChanged" last_modification_time="Mon, 27 Feb 2006 18:53:28 GMT"/> + </widget> + <packing> + <property name="left_attach">2</property> + <property name="right_attach">3</property> + <property name="top_attach">1</property> + <property name="bottom_attach">2</property> + <property name="y_options"></property> + </packing> + </child> + + <child> + <widget class="GtkEventBox" id="fileEntryBox"> + <property name="visible">True</property> + <property name="visible_window">True</property> + <property name="above_child">False</property> + + <child> + <placeholder/> + </child> + </widget> + <packing> + <property name="left_attach">2</property> + <property name="right_attach">3</property> + <property name="top_attach">2</property> + <property name="bottom_attach">3</property> + <property name="x_options">fill</property> + <property name="y_options">fill</property> + </packing> + </child> + </widget> + <packing> + <property name="padding">0</property> + <property name="expand">True</property> + <property name="fill">True</property> + </packing> + </child> + </widget> + <packing> + <property name="padding">0</property> + <property name="expand">True</property> + <property name="fill">True</property> + </packing> + </child> + </widget> + </child> +</widget> + +<widget class="GtkDialog" id="ConfirmWindowDeleteDialog"> + <property name="visible">True</property> + <property name="title" translatable="yes">MonoDevelop</property> + <property name="type">GTK_WINDOW_TOPLEVEL</property> + <property name="window_position">GTK_WIN_POS_NONE</property> + <property name="modal">False</property> + <property name="resizable">True</property> + <property name="destroy_with_parent">False</property> + <property name="decorated">True</property> + <property name="skip_taskbar_hint">False</property> + <property name="skip_pager_hint">False</property> + <property name="type_hint">GDK_WINDOW_TYPE_HINT_DIALOG</property> + <property name="gravity">GDK_GRAVITY_NORTH_WEST</property> + <property name="focus_on_map">True</property> + <property name="urgency_hint">False</property> + <property name="has_separator">True</property> + + <child internal-child="vbox"> + <widget class="GtkVBox" id="dialog-vbox3"> + <property name="visible">True</property> + <property name="homogeneous">False</property> + <property name="spacing">0</property> + + <child internal-child="action_area"> + <widget class="GtkHButtonBox" id="dialog-action_area3"> + <property name="visible">True</property> + <property name="layout_style">GTK_BUTTONBOX_END</property> + + <child> + <widget class="GtkButton" id="cancelbutton3"> + <property name="visible">True</property> + <property name="can_default">True</property> + <property name="can_focus">True</property> + <property name="label">gtk-no</property> + <property name="use_stock">True</property> + <property name="relief">GTK_RELIEF_NORMAL</property> + <property name="focus_on_click">True</property> + <property name="response_id">-9</property> + </widget> + </child> + + <child> + <widget class="GtkButton" id="okbutton2"> + <property name="visible">True</property> + <property name="can_default">True</property> + <property name="can_focus">True</property> + <property name="label">gtk-yes</property> + <property name="use_stock">True</property> + <property name="relief">GTK_RELIEF_NORMAL</property> + <property name="focus_on_click">True</property> + <property name="response_id">-8</property> + </widget> + </child> + </widget> + <packing> + <property name="padding">0</property> + <property name="expand">False</property> + <property name="fill">True</property> + <property name="pack_type">GTK_PACK_END</property> + </packing> + </child> + + <child> + <widget class="GtkHBox" id="hbox2"> + <property name="border_width">12</property> + <property name="visible">True</property> + <property name="homogeneous">False</property> + <property name="spacing">12</property> + + <child> + <widget class="GtkImage" id="image1"> + <property name="visible">True</property> + <property name="stock">gtk-dialog-question</property> + <property name="icon_size">6</property> + <property name="xalign">0.5</property> + <property name="yalign">0</property> + <property name="xpad">0</property> + <property name="ypad">0</property> + </widget> + <packing> + <property name="padding">0</property> + <property name="expand">False</property> + <property name="fill">False</property> + </packing> + </child> + + <child> + <widget class="GtkVBox" id="vbox4"> + <property name="visible">True</property> + <property name="homogeneous">False</property> + <property name="spacing">6</property> + + <child> + <widget class="GtkLabel" id="label"> + <property name="visible">True</property> + <property name="label">Are you sure you want to delete the window '{0}'?</property> + <property name="use_underline">False</property> + <property name="use_markup">False</property> + <property name="justify">GTK_JUSTIFY_LEFT</property> + <property name="wrap">True</property> + <property name="selectable">False</property> + <property name="xalign">0</property> + <property name="yalign">0.5</property> + <property name="xpad">0</property> + <property name="ypad">0</property> + <property name="ellipsize">PANGO_ELLIPSIZE_NONE</property> + <property name="width_chars">-1</property> + <property name="single_line_mode">False</property> + <property name="angle">0</property> + </widget> + <packing> + <property name="padding">0</property> + <property name="expand">False</property> + <property name="fill">False</property> + </packing> + </child> + + <child> + <widget class="GtkCheckButton" id="checkbox"> + <property name="visible">True</property> + <property name="can_focus">True</property> + <property name="label" translatable="yes">Also remove the file '{0}'</property> + <property name="use_underline">True</property> + <property name="relief">GTK_RELIEF_NORMAL</property> + <property name="focus_on_click">True</property> + <property name="active">False</property> + <property name="inconsistent">False</property> + <property name="draw_indicator">True</property> + </widget> + <packing> + <property name="padding">0</property> + <property name="expand">False</property> + <property name="fill">False</property> + </packing> + </child> + </widget> + <packing> + <property name="padding">0</property> + <property name="expand">True</property> + <property name="fill">True</property> + </packing> + </child> + </widget> + <packing> + <property name="padding">0</property> + <property name="expand">True</property> + <property name="fill">True</property> + </packing> + </child> + </widget> + </child> +</widget> + +</glade-interface> diff --git a/main/src/addins/MonoDevelop.GtkCore2/icons/ChangeLog b/main/src/addins/MonoDevelop.GtkCore2/icons/ChangeLog new file mode 100644 index 0000000000..86f901e6a8 --- /dev/null +++ b/main/src/addins/MonoDevelop.GtkCore2/icons/ChangeLog @@ -0,0 +1,5 @@ +2010-08-15 Krzysztof Marecki <freefirma@gmail.com> + + * gtkx.png: + * gtk-logo.png: + diff --git a/main/src/addins/MonoDevelop.GtkCore2/icons/actiongroup.png b/main/src/addins/MonoDevelop.GtkCore2/icons/actiongroup.png Binary files differnew file mode 100644 index 0000000000..de43e0a5c4 --- /dev/null +++ b/main/src/addins/MonoDevelop.GtkCore2/icons/actiongroup.png diff --git a/main/src/addins/MonoDevelop.GtkCore2/icons/dialog.png b/main/src/addins/MonoDevelop.GtkCore2/icons/dialog.png Binary files differnew file mode 100644 index 0000000000..6e81b2fd60 --- /dev/null +++ b/main/src/addins/MonoDevelop.GtkCore2/icons/dialog.png diff --git a/main/src/addins/MonoDevelop.GtkCore2/icons/gtk-logo-orig.png b/main/src/addins/MonoDevelop.GtkCore2/icons/gtk-logo-orig.png Binary files differnew file mode 100644 index 0000000000..9809fa4e09 --- /dev/null +++ b/main/src/addins/MonoDevelop.GtkCore2/icons/gtk-logo-orig.png diff --git a/main/src/addins/MonoDevelop.GtkCore2/icons/gtk-logo.png b/main/src/addins/MonoDevelop.GtkCore2/icons/gtk-logo.png Binary files differnew file mode 100644 index 0000000000..5ebee707d9 --- /dev/null +++ b/main/src/addins/MonoDevelop.GtkCore2/icons/gtk-logo.png diff --git a/main/src/addins/MonoDevelop.GtkCore2/icons/gtkx.png b/main/src/addins/MonoDevelop.GtkCore2/icons/gtkx.png Binary files differnew file mode 100644 index 0000000000..87a1d7946d --- /dev/null +++ b/main/src/addins/MonoDevelop.GtkCore2/icons/gtkx.png diff --git a/main/src/addins/MonoDevelop.GtkCore2/icons/image-x-generic.png b/main/src/addins/MonoDevelop.GtkCore2/icons/image-x-generic.png Binary files differnew file mode 100644 index 0000000000..68da5027cf --- /dev/null +++ b/main/src/addins/MonoDevelop.GtkCore2/icons/image-x-generic.png diff --git a/main/src/addins/MonoDevelop.GtkCore2/icons/widget.png b/main/src/addins/MonoDevelop.GtkCore2/icons/widget.png Binary files differnew file mode 100644 index 0000000000..7f5844bbfc --- /dev/null +++ b/main/src/addins/MonoDevelop.GtkCore2/icons/widget.png diff --git a/main/src/addins/MonoDevelop.GtkCore2/icons/window.png b/main/src/addins/MonoDevelop.GtkCore2/icons/window.png Binary files differnew file mode 100644 index 0000000000..8f82250f04 --- /dev/null +++ b/main/src/addins/MonoDevelop.GtkCore2/icons/window.png diff --git a/main/src/addins/MonoDevelop.GtkCore2/libstetic/ChangeLog b/main/src/addins/MonoDevelop.GtkCore2/libstetic/ChangeLog new file mode 100644 index 0000000000..4d98b372cf --- /dev/null +++ b/main/src/addins/MonoDevelop.GtkCore2/libstetic/ChangeLog @@ -0,0 +1,1793 @@ +2010-10-28 Krzysztof Marecki <marecki.krzysztof@gmail.com> + + * Makefile.am: + +2010-10-04 Krzysztof Marecki <marecki.krzysztof@gmail.com> + + * TypedClassDescriptor.cs: + +2010-09-30 Krzysztof Marecki <marecki.krzysztof@gmail.com> + + * Registry.cs: + +2010-09-30 Krzysztof Marecki <marecki.krzysztof@gmail.com> + + * Registry.cs: + * TypedClassDescriptor.cs: + +2010-09-21 Krzysztof Marecki <marecki.krzysztof@gmail.com> + + * wrapper/Bin.cs: Set RootWrapperName + +2010-08-15 Krzysztof Marecki <freefirma@gmail.com> + + * DND.cs: + * IProject.cs: + +2010-08-13 Krzysztof Marecki <freefirma@gmail.com> + + * GeneratorContext.cs: + +2010-08-07 Krzysztof Marecki <marecki.krzysztof@gmail.com> + + * IProject.cs: Remove Modified property, add WasModified method which check state of a given top level + +2010-08-03 Krzysztof Marecki <marecki.krzysztof@gmail.com> + + * GladeUtils.cs: Set ObjectWrapper.RootWrapperName when reading from xml + * WidgetUtils.cs: + * ObjectReader.cs: + * ObjectWrapper.cs: + * wrapper/Frame.cs: + * wrapper/Window.cs: + * wrapper/MenuItem.cs: + * wrapper/Expander.cs: + * undo/UndoManager.cs: + * wrapper/Notebook.cs: + * wrapper/Container.cs: + * wrapper/OptionMenu.cs: + +2010-08-03 Krzysztof Marecki <marecki.krzysztof@gmail.com> + + * ObjectWrapper.cs: Save a root wrapper name + +2010-06-07 Krzysztof Marecki <marecki.krzysztof@gmail.com> + + * IProject.cs: + * ErrorWidget.cs: + +2010-04-30 Lluis Sanchez Gual <lluis@novell.com> + + * editor/ActionMenu.cs: Explicit destroy of children should + not be required. + +2010-04-30 Mike Krüger <mkrueger@novell.com> + + * editor/ActionMenu.cs: moved code from dispose -> destroy. + +2010-04-29 Mike Krüger <mkrueger@novell.com> + + * editor/ActionMenu.cs: + * editor/ActionToolbar.cs: + * editor/ActionMenuBar.cs: Destroy gtk components instead of + disposing them. + +2010-04-16 Lluis Sanchez Gual <lluis@novell.com> + + * GladeUtils.cs: Fix glade import. GtkWindow and GtkDialog + need to be special cased, since we are not creating real + Gtk.Window objects anymore. + +2010-04-08 Lluis Sanchez Gual <lluis@novell.com> + + * wrapper/Misc.cs: Show alignment buttons as toggles. + +2010-03-30 Lluis Sanchez Gual <lluis@novell.com> + + * wrapper/Widget.cs: + * wrapper/Container.cs: When setting the name of a widget, + make sure the old name field is also set. Fixes bug #549463 + - Forms designer renames variables it shouldn't. + +2010-01-19 Lluis Sanchez Gual <lluis@novell.com> + + * TypedPropertyDescriptor.cs: Don't translate property names + in the property grid. See bug #571351. + +2010-01-19 Lluis Sanchez Gual <lluis@novell.com> + + * GeneratorContext.cs: When loading an icon, don't hardcode + the required size. Instead, call SizeLookup to get the + correct size for the current theme. + +2010-01-18 Lluis Sanchez Gual <lluis@novell.com> + + * Makefile.am: + * ImageInfo.cs: + * wrapper/Bin.cs: + * WidgetUtils.cs: + * libstetic.csproj: + * ObjectWrapper.cs: + * wrapper/Action.cs: + * wrapper/Widget.cs: + * wrapper/VScale.cs: + * wrapper/HScale.cs: + * wrapper/MenuBar.cs: + * wrapper/Expander.cs: + * GeneratorContext.cs: + * wrapper/Notebook.cs: + * wrapper/ComboBox.cs: + * wrapper/Container.cs: + * RadioGroupManager.cs: + * wrapper/VScrollbar.cs: + * ProjectIconFactory.cs: + * wrapper/HScrollbar.cs: + * wrapper/ToolButton.cs: + * wrapper/ActionTree.cs: + * wrapper/ActionGroup.cs: + * wrapper/ComboBoxEntry.cs: + * wrapper/ActionToolbarWrapper.cs: + * wrapper/RadioActionGroupManager.cs: Use global:: for type + references in generated code. + + * Placeholder.cs: + * editor/Flags.cs: + * editor/Enumeration.cs: + * editor/ActionMenuItem.cs: + * editor/ActionToolItem.cs: Fix warnings. + +2009-12-17 Lluis Sanchez Gual <lluis@novell.com> + + * libstetic.csproj: Flush. + +2009-12-11 Lluis Sanchez Gual <lluis@novell.com> + + * wrapper/Table.cs: Fix table creation issue. Sync call has no + effect while loading a widget. + +2009-12-01 Lluis Sanchez Gual <lluis@novell.com> + + * wrapper/Widget.cs: Fix check for top level window. + +2009-11-19 Lluis Sanchez Gual <lluis@novell.com> + + * Makefile.am: + * wrapper/MenuBar.cs: + * wrapper/ActionToolbarWrapper.cs: Propagate the menu name to + the action tree. Fixes bug #540512. + +2009-11-06 Lluis Sanchez Gual <lluis@novell.com> + + * ObjectReader.cs: + * ObjectWrapper.cs: + * ClassDescriptor.cs: Ensure the Loading flag is set when + loading internal children of a widget. + +2009-11-05 Mike Kestner <mkestner@novell.com> + + * wrapper/*.cs: improper new keyword warning cleanup. + +2009-10-29 Lluis Sanchez Gual <lluis@novell.com> + + * Makefile.am: + * libstetic.csproj: Reference mono-cairo package. + +2009-10-21 Lluis Sanchez Gual <lluis@novell.com> + + * wrapper/Widget.cs: Don't fire the name changed event while + loading. + + * wrapper/Container.cs: Set the loading flag when loading. + +2009-10-16 Mike Krüger <mkrueger@novell.com> + + * DND.cs: + * WidgetUtils.cs: + * CommandDescriptor.cs: + * editor/Translatable.cs: + * editor/ActionMenuItem.cs: Handled icon loading failures. + +2009-09-29 Lluis Sanchez Gual <lluis@novell.com> + + * wrapper/Paned.cs: Avoid unnecessary Changed event. + +2009-09-29 Lluis Sanchez Gual <lluis@novell.com> + + * wrapper\Paned.cs: Restore the paned position after + realizing. It may have been reset during the realization. + Fixes bug #542227. + +2009-09-21 Lluis Sanchez Gual <lluis@novell.com> + + * wrapper/Widget.cs: Fire name change event when name changes. + Fixes bug #540512 - NullReferenceException in stetic + generated code. + +2009-09-10 Christian Hergert <chris@dronelabs.com> + + * libstetic/libstetic.dll.config: Use quartz on osx. + +2009-09-02 Lluis Sanchez Gual <lluis@novell.com> + + * wrapper/Action.cs: For stock gtk and gnome icons, use the + stock id as base name for the action identifier. Fixes bug + #525571. + +2009-08-26 Lluis Sanchez Gual <lluis@novell.com> + + * libstetic.csproj: Updated dependencies. We now depend on + gtk# 2.12.8, Mono 2.4, and Mono.Addins 0.4. + +2009-08-25 Lluis Sanchez Gual <lluis@novell.com> + + * wrapper/Container.cs: Properly validate widget ids when + pasting a child. If there is a conflict, the child has to be + modified. Fixes bug #530086 - When copy/pasting widgets in + stetic, the original is renamed. + +2009-08-04 Lluis Sanchez Gual <lluis@novell.com> + + * wrapper/Notebook.cs: Fix issue with adding a widget with + ShowScrollbars=true to a notebook. Fixes bug 526434 - + Notebook Tab Labels Revert Back to "Page 1". + +2009-08-04 Lluis Sanchez Gual <lluis@novell.com> + + * wrapper/ComboBox.cs: + * wrapper/ComboBoxEntry.cs: Changed the sensitivity mode to + 'always on'. Since gtk+ 2.14, empty combos are disabled by + default. + +2009-07-31 Lluis Sanchez Gual <lluis@novell.com> + + * wrapper/objects.xml: Fix invalid xml. + +2009-07-31 Lluis Sanchez Gual <lluis@novell.com> + + * wrapper/objects.xml: Fix some default values. + +2009-07-31 Lluis Sanchez Gual <lluis@novell.com> + + * wrapper/objects.xml: Make sure the default value for + HasSeparator is true. + +2009-07-21 Lluis Sanchez Gual <lluis@novell.com> + + * wrapper/objects.xml: Removed Version=2.6.0.0 specification + from Pango.EllipsizeMode type. This allows other GTK + versions to work. Patch by Daniel Newton. + + +2009-07-02 Lluis Sanchez Gual <lluis@novell.com> + + * ClassDescriptor.cs: When creating a widget instance, + initialize the properties after creating the wrapper, since + some properties may be implemented in the wrapper. This + should fix bug #505083 - hbuttonbox1.cs file being created + in gtk-gui causing problems with compilation. + +2009-05-25 Lluis Sanchez Gual <lluis@novell.com> + + * Makefile.am: + * Placeholder.cs: + * libstetic.csproj: Improved the look of placeholders. + +2009-05-07 Lluis Sanchez Gual <lluis@novell.com> + + * ItemDescriptor.cs: Added missing BindingFlags.Instance flag. + + * wrapper/Container.cs: Fix bug when showing the selection + box. + + * TopLevelWindow.cs: + * TopLevelDialog.cs: + * wrapper/Dialog.cs: + * wrapper/Window.cs: + * wrapper/objects.xml: Top level windows are not represented + using a Gtk.Window anymore at design time. Instead they are + represented by TopLevelWindow. This is a regular widget, so + window embedding hacks are not required anymore. The same + has been done for Gtk.Dialog/TopLevelDialog. + + * libstetic.csproj: Added new files. + + * Makefile.am: Updated. + + * DND.cs: Accept copy as drop target. Fixed the target list. + + * TypedClassDescriptor.cs: Invocation of a constructor does + not need an instance reference. + +2009-05-04 Lluis Sanchez Gual <lluis@novell.com> + + * Registry.cs: Make sure GetType can find the type when the + provided assembly name does not have version info. + + * libstetic.csproj: Copy the config file to the output dir. + + * TypedPropertyDescriptor.cs: Catch ambiguous match exception + when looking for properties. + +2009-04-29 Lluis Sanchez Gual <lluis@novell.com> + + * libstetic.csproj: Don't require a specific gtk# version. + +2009-03-03 Lluis Sanchez Gual <lluis@novell.com> + + * Registry.cs: + * WidgetLibrary.cs: Flush cached data when closing a change + set. + +2009-02-19 Lluis Sanchez Gual <lluis@novell.com> + + * wrapper/Table.cs: + * wrapper/objects.xml: A better fix for the default row/column + issue. + +2009-02-10 Michael Hutchinson <mhutchinson@novell.com> + + * libstetic.csproj: Don't build with make, since MD can build + these just fine. + +2009-02-07 Mike Krüger <mkrueger@novell.com> + + * GladeUtils.cs: fixed compiler warning. + +2009-02-06 Lluis Sanchez Gual <lluis@novell.com> + + * libstetic.mdp: + * libstetic.csproj: Migrated to MSBuild file format. + +2009-01-26 Michael Hutchinson <mhutchinson@novell.com> + + * libstetic.mdp: Flush project format changes. + +2009-01-20 Lluis Sanchez Gual <lluis@novell.com> + + * wrapper/objects.xml: Added some defaults. + +2008-12-12 Lluis Sanchez Gual <lluis@novell.com> + + * libstetic.mdp: All projects now require fx 3.5. + +2008-09-17 Lluis Sanchez Gual <lluis@novell.com> + + * PropertyDescriptor.cs: Use invariant culture when converting types. + +2008-07-27 Mike Krüger <mkrueger@novell.com> + + + +2008-02-23 Mike Krüger <mkrueger@novell.com> + + * MonoDevelop.GtkCore.mdp, lib/libsteticui.mdp: Removed some unused glade + and gnome-sharp references (only the unused). But I'll continue to + remove glade, we need to lower the dependency tree a bit. + +2008-02-22 Mike Krüger <mkrueger@novell.com> + + * MonoDevelop.GtkCore.GuiBuilder/CombinedDesignView.cs: Added IViewContent + switching logic (but should be done centrally using the secondaryview + paradigmn). + +2008-02-21 Lluis Sanchez Gual <lluis@novell.com> + + * MonoDevelop.GtkCore/GtkDesignInfo.cs: Workaround for mono bug + #350432. + +2008-02-20 Lluis Sanchez Gual <lluis@novell.com> + + * MonoDevelop.GtkCore.NodeBuilders/ActionGroupNodeBuilder.cs, + MonoDevelop.GtkCore.NodeBuilders/WidgetNodeBuilder.cs: Handle the delete + key in TreeViewPad, so it will work event if the shortcut is not + defined. + +2008-01-29 Lluis Sanchez Gual <lluis@novell.com> + + * MonoDevelop.GtkCore.addin.xml, MonoDevelop.GtkCore.mdp, Makefile.am, + icons/pad-widget-tree-16.png: Added widget tree icon. + +2008-01-25 Lluis Sanchez Gual <lluis@novell.com> + + * MonoDevelop.GtkCore.addin.xml: Update MD version. + +2008-01-23 Lluis Sanchez Gual <lluis@novell.com> + + * MonoDevelop.GtkCore.Dialogs/BindDesignDialog.cs, + MonoDevelop.GtkCore.Dialogs/ConfirmWindowDeleteDialog.cs, + MonoDevelop.GtkCore.Dialogs/WidgetBuilderOptionPanel.cs: Made internal + some classes that don't need to be public. + +2008-01-21 Lluis Sanchez Gual <lluis@novell.com> + + * MonoDevelop.GtkCore/GtkDesignInfo.cs, + MonoDevelop.GtkCore.GuiBuilder/GuiBuilderService.cs: Notify file changes + through the FileService. + +2008-01-16 Lluis Sanchez Gual <lluis@novell.com> + + * MonoDevelop.GtkCore.GuiBuilder/GuiBuilderService.cs: Stetic code must be + generated in the GUI thread. Should fix bug #349505. + +2008-01-15 Michael Hutchinson <mhutchinson@novell.com> + + * MonoDevelop.GtkCore.GuiBuilder/GuiBuilderService.cs: Feed default layout + name to Gettext for translation. + +2008-01-15 Michael Hutchinson <mhutchinson@novell.com> + + * templates/WidgetPartial.xft.xml, templates/Widget.xft.xml, + templates/WindowPartial.xft.xml, templates/ActionGroupPartial.xft.xml, + templates/Window.xft.xml, templates/ActionGroup.xft.xml, + templates/DialogPartial.xft.xml, templates/Dialog.xft.xml: Make template + categories translatable. + +2008-01-08 Lluis Sanchez Gual <lluis@novell.com> + + * MonoDevelop.GtkCore.GuiBuilder/CodeBinder.cs: Added null check on the + result of UpdateFile. Should fix bug #352194. + +2008-01-08 Lluis Sanchez Gual <lluis@novell.com> + + * MonoDevelop.GtkCore.NodeBuilders/ProjectFolderNodeBuilderExtension.cs, + MonoDevelop.GtkCore.NodeBuilders/ProjectNodeBuilder.cs, + MonoDevelop.GtkCore/GtkDesignInfo.cs, + MonoDevelop.GtkCore/GtkCoreService.cs, + MonoDevelop.GtkCore/WidgetFileDescriptionTemplate.cs, + MonoDevelop.GtkCore.Dialogs/WidgetBuilderOptionPanel.cs, + MonoDevelop.GtkCore.GuiBuilder/ActionGroupDisplayBinding.cs, + MonoDevelop.GtkCore.GuiBuilder/GuiBuilderService.cs, + MonoDevelop.GtkCore.GuiBuilder/GuiBuilderDisplayBinding.cs, + MonoDevelop.GtkCore.GuiBuilder/GuiBuilderProject.cs, + MonoDevelop.GtkCore.GuiBuilder/GtkProjectServiceExtension.cs: Handle + projects which don't support the GTK# designer. Window and widget + generation options are hidden, and code is never generated. Fixes bug + #350632. + +2007-12-14 Lluis Sanchez Gual <lluis@novell.com> + + * MonoDevelop.GtkCore.GuiBuilder/CodeBinder.cs: Don't update bindings if the + file has syntax errors. May fix bug #347590. + +2007-12-12 Lluis Sanchez Gual <lluis@novell.com> + + * MonoDevelop.GtkCore.addin.xml: Bump add-in versions. + +2007-12-12 Lluis Sanchez Gual <lluis@novell.com> + + * Makefile.am: Update after build reorg. + +2007-12-06 Geoff Norton <gnorton@novell.com> + + * Makefile.am: Only build the GtkCore addin if we have gnome-sharp + available. + +2007-12-04 Lluis Sanchez Gual <lluis@novell.com> + + * MonoDevelop.GtkCore.mdp, lib/libsteticui.mdp, lib/libstetic.mdp, + Makefile.am: Directory reorganization. + +2007-11-20 Lluis Sanchez Gual <lluis@novell.com> + + * gui.glade, MonoDevelop.GtkCore.Dialogs/BindDesignDialog.cs: Removed + Gnome.FileEntry. + +2007-11-09 Michael Hutchinson <mhutchinson@novell.com> + + * MonoDevelop.GtkCore.GuiBuilder/GuiBuilderService.cs, + MonoDevelop.GtkCore.GuiBuilder/GtkProjectServiceExtension.cs: Track + LoggingService API changes. + +2007-11-02 Lluis Sanchez Gual <lluis@novell.com> + + * MonoDevelop.GtkCore.GuiBuilder/ActionGroupDisplayBinding.cs, + MonoDevelop.GtkCore.GuiBuilder/CodeBinder.cs, + MonoDevelop.GtkCore.GuiBuilder/GuiBuilderWindow.cs: Use RootCombine + instead of CurrentOpenCombine when possible. + +2007-10-29 Lluis Sanchez Gual <lluis@novell.com> + + * MonoDevelop.GtkCore.addin.xml: Bump MD version. + +2007-10-29 Lluis Sanchez Gual <lluis@novell.com> + + * MonoDevelop.GtkCore.GuiBuilder/GuiBuilderView.cs: Fix nullref. Happens + when removing a project from a solution while one of the windows of that + project is open. + +2007-10-25 Lluis Sanchez Gual <lluis@novell.com> + + * templates/ActionGroup.xft.xml, templates/ActionGroupPartial.xft.xml, + templates/Dialog.xft.xml, templates/DialogPartial.xft.xml, + templates/Widget.xft.xml, templates/WidgetPartial.xft.xml, + templates/Window.xft.xml, templates/WindowPartial.xft.xml: Use tango + file icons. Removed obsolete icons. + +2007-10-23 Lluis Sanchez Gual <lluis@novell.com> + + * MonoDevelop.GtkCore.Dialogs/GtkFeatureWidget.cs: Track api changes. Added + Description property. + +2007-10-23 Lluis Sanchez Gual <lluis@novell.com> + + * lib/libsteticui.mdp, lib/libstetic.mdp: Project file names updated by + change in MD path functions. + +2007-10-22 Lluis Sanchez Gual <lluis@novell.com> + + * MonoDevelop.GtkCore.mds, Makefile.am: Added custom command for updating + the Stetic sources. + +2007-10-22 Lluis Sanchez Gual <lluis@novell.com> + + * MonoDevelop.GtkCore.addin.xml: Set a more meaningful category name for + addin commands. + * MonoDevelop.GtkCore.mdp, MonoDevelop.GtkCore.mds: Updated. + +2007-10-16 Lluis Sanchez Gual <lluis@novell.com> + + * MonoDevelop.GtkCore.GuiBuilder/GuiBuilderView.cs: If the current selection + can't be deleted, just ignore the delete command, so the default handler + will be executed. Fixes bug #325440. + +2007-10-16 Lluis Sanchez Gual <lluis@novell.com> + + * lib/libstetic.mdp: Fix required gtk# version. + +2007-10-12 Mike Krüger <mkrueger@novell.com> + + * MonoDevelop.GtkCore.NodeBuilders/StockIconsNodeBuilder.cs, + MonoDevelop.GtkCore.NodeBuilders/WidgetNodeBuilder.cs, + MonoDevelop.GtkCore/GtkDesignInfo.cs, + MonoDevelop.GtkCore/GtkCoreService.cs, + MonoDevelop.GtkCore.GuiBuilder/ActionGroupView.cs, + MonoDevelop.GtkCore.GuiBuilder/GuiBuilderView.cs, + MonoDevelop.GtkCore.GuiBuilder/ToolboxProvider.cs: Applied changes that + were neccassary for to the new FileService. + +2007-10-11 Mike Krüger <mkrueger@novell.com> + + * MonoDevelop.GtkCore/WidgetFileDescriptionTemplate.cs: Changed calls for + the new StringParser. + +2007-10-10 Lluis Sanchez Gual <lluis@novell.com> + + * MonoDevelop.GtkCore/GtkDesignInfo.cs: In Bind(), don't subscribe the + NameChanged event at every call. + * MonoDevelop.GtkCore.GuiBuilder/ActionGroupView.cs, + MonoDevelop.GtkCore.GuiBuilder/GuiBuilderView.cs: The designer needs to + be explicitely destroyed. + +2007-10-03 Michael Hutchinson <mhutchinson@novell.com> + + * MonoDevelop.GtkCore.GuiBuilder/ToolboxProvider.cs: No need to implement + IComparable; it's done in the base class now. + +2007-09-27 Lluis Sanchez Gual <lluis@novell.com> + + * MonoDevelop.GtkCore.Dialogs/GtkFeatureWidget.cs: Assign the selected + target gtk# version to the new project. + +2007-09-21 Michael Hutchinson <mhutchinson@novell.com> + + * MonoDevelop.GtkCore/GtkDesignInfo.cs: Use ProjectReference.StoredReference + rather than ProjectReference.Reference, in order to refer to the actual + stored reference string rather than a temporarily bumped version. + +2007-09-21 Lluis Sanchez Gual <lluis@novell.com> + + * MonoDevelop.GtkCore.addin.xml: Bump MD version. + +2007-09-20 Lluis Sanchez Gual <lluis@novell.com> + + * MonoDevelop.GtkCore.GuiBuilder/GuiBuilderService.cs, + MonoDevelop.GtkCore.GuiBuilder/GuiBuilderProject.cs: Implemented an + assembly resolver for the stetic app, so assembly widgets registered + with .pc files can be found. + * MonoDevelop.GtkCore.GuiBuilder/ToolboxLoader.cs: If a widget dll belongs + to a package, store it as a package reference in the toolbox index. + +2007-09-19 Michael Hutchinson <mhutchinson@novell.com> + + * MonoDevelop.GtkCore/GtkDesignInfo.cs: Allow setting TargetGtkVersion to + DefaultGtkVersion when current value is null. + +2007-09-19 Michael Hutchinson <mhutchinson@novell.com> + + * MonoDevelop.GtkCore/GtkDesignInfo.cs: Don't touch GTK# assembly versions + when a target version is not set. Don't use gtkVersion=null to represent + default version. + * MonoDevelop.GtkCore/GtkCoreService.cs: Set TargetGtkVersion on new + projects. Bump default version to 2.8. + +2007-09-17 Michael Hutchinson <mhutchinson@novell.com> + + * MonoDevelop.GtkCore.mdp, lib/libsteticui.mdp, lib/libstetic.mdp, + lib/Makefile.am, MonoDevelop.GtkCore.mds, Makefile.am: Use projects for + imported stetic libraries. + +2007-09-17 Lluis Sanchez Gual <lluis@novell.com> + + * MonoDevelop.GtkCore.GuiBuilder/GuiBuilderService.cs: Removed access to + Component object. + * MonoDevelop.GtkCore.GuiBuilder/GuiBuilderProject.cs: Remove unused method. + +2007-09-13 Lluis Sanchez Gual <lluis@novell.com> + + * MonoDevelop.GtkCore.Dialogs/SelectRenamedClassDialog.cs, + MonoDevelop.GtkCore.Dialogs/WidgetBuilderOptionPanel.cs, + MonoDevelop.GtkCore.Dialogs/BindDesignDialog.cs, + MonoDevelop.GtkCore.Dialogs/ConfirmWindowDeleteDialog.cs: Fix warnings. + +2007-09-13 Michael Hutchinson <mhutchinson@novell.com> + + * lib/stetic, Makefile.am, lib/Makefile.am: Build stetic from + svn:externals. + * lib/libsteticui.dll.config, lib/libstetic.dll.config, + lib/libstetic.dll, lib/libsteticui.dll: Removed. + +2007-09-10 Michael Hutchinson <mhutchinson@novell.com> + + * templates/WidgetPartial.xft.xml, templates/Widget.xft.xml, + templates/WindowPartial.xft.xml, templates/Window.xft.xml, + templates/ActionGroupPartial.xft.xml, templates/ActionGroup.xft.xml, + templates/DialogPartial.xft.xml, templates/Dialog.xft.xml: Remove + deprecated FileOptions element from templates. + +2007-09-10 Lluis Sanchez Gual <lluis@novell.com> + + * lib/libsteticui.dll, lib/libstetic.dll, + MonoDevelop.GtkCore.GuiBuilder/GuiBuilderService.cs, + MonoDevelop.GtkCore.GuiBuilder/GuiBuilderProject.cs, + MonoDevelop.GtkCore.GuiBuilder/ActionGroupView.cs, + MonoDevelop.GtkCore.GuiBuilder/GuiBuilderView.cs, + MonoDevelop.GtkCore.GuiBuilder/CombinedDesignView.cs: Changed the way to + set the active designer (the api changed). Fixed some renaming issues. + * MonoDevelop.GtkCore.GuiBuilder/GuiBuilderProjectPad.cs: Track api changes. + +2007-09-07 Michael Hutchinson <mhutchinson@novell.com> + + * templates/Window.xft.xml: Oops, PartialTypeSupport should be set to + Disabled for non-partial window. + +2007-09-07 Michael Hutchinson <mhutchinson@novell.com> + + * MonoDevelop.GtkCore.mdp, Makefile.am: Updated. + * MonoDevelop.GtkCore/GtkDesignInfo.cs, + MonoDevelop.GtkCore/GtkCoreService.cs: Use DotNetProject.UsePartialTypes + instead of custom setting. + * MonoDevelop.GtkCore/WidgetFileTemplatePartialClass.cs, + MonoDevelop.GtkCore/WidgetFileTemplateFullClass.cs: No longer needed. + * templates/WidgetPartial.xft.xml, templates/Widget.xft.xml, + templates/WindowPartial.xft.xml, templates/Window.xft.xml, + templates/ActionGroupPartial.xft.xml, templates/ActionGroup.xft.xml, + templates/DialogPartial.xft.xml, templates/Dialog.xft.xml: Use + PartialTypes condition instead of custom file template. + +2007-09-04 Lluis Sanchez Gual <lluis@novell.com> + + * lib/libsteticui.dll, lib/libstetic.dll: Updated from stetic module. + Includes fixes for bugs #82671, #82527, #82476, #81763 and #81238. + +2007-08-31 Mike Krüger <mkrueger@novell.com> + + * MonoDevelop.GtkCore.Dialogs/WidgetBuilderOptionPanel.cs, + MonoDevelop.GtkCore.GuiBuilder/GuiBuilderService.cs, + MonoDevelop.GtkCore.GuiBuilder/PropertiesWidget.cs: Changes due to new + property infrastructure. + +2007-08-16 Lluis Sanchez Gual <lluis@novell.com> + + * MonoDevelop.GtkCore/GtkDesignInfo.cs, + MonoDevelop.GtkCore/GtkCoreService.cs: By default use the project name + as category name for new custom widgets. + * lib/libsteticui.dll, lib/libstetic.dll: Updated from stetic module. + * MonoDevelop.GtkCore.GuiBuilder/ToolboxProvider.cs: Don't show the full + name of widgets in the toolbar. + +2007-08-16 Lluis Sanchez Gual <lluis@novell.com> + + * MonoDevelop.GtkCore.GuiBuilder/GuiBuilderProject.cs: In FindClass, make + sure the getUserClass parameter is taken into account when the found + class is not a multi-part class. Fixes bug #82258. + +2007-08-09 Lluis Sanchez Gual <lluis@novell.com> + + * MonoDevelop.GtkCore.addin.xml: Removed the CommandService class. + Everything is done directly with CommandManager. Moved all extension + node types to MD.Components. + +2007-08-09 Lluis Sanchez Gual <lluis@novell.com> + + * MonoDevelop.GtkCore.addin.xml, + MonoDevelop.GtkCore.NodeBuilders/StockIconsNodeBuilder.cs, + MonoDevelop.GtkCore.NodeBuilders/WidgetNodeBuilder.cs, + MonoDevelop.GtkCore.NodeBuilders/WindowsFolderNodeBuilder.cs, + MonoDevelop.GtkCore.NodeBuilders/ActionGroupNodeBuilder.cs, + MonoDevelop.GtkCore.mdp, Makefile.am: Reorganized the extension point + hierarchy. Embedded all add-in manifests as resources. + * lib/libstetic.dll: Updated from stetic module. + +2007-08-08 Lluis Sanchez Gual <lluis@novell.com> + + * MonoDevelop.GtkCore.GuiBuilder/GuiBuilderService.cs: Improved error + reporting. + +2007-08-02 Lluis Sanchez Gual <lluis@novell.com> + + * MonoDevelop.GtkCore.NodeBuilders/WindowsFolderNodeBuilder.cs, + MonoDevelop.GtkCore.GuiBuilder/GuiBuilderService.cs, + MonoDevelop.GtkCore.GuiBuilder/GuiBuilderProject.cs: Converted + DispatchService to a static class. + +2007-08-01 Lluis Sanchez Gual <lluis@novell.com> + + * lib/libstetic.dll: Updated. + +2007-07-31 Lluis Sanchez Gual <lluis@novell.com> + + * lib/libsteticui.dll, lib/libstetic.dll, + MonoDevelop.GtkCore.GuiBuilder/GuiBuilderProject.cs: Fixed some + problems with the target gtk version. It was not assigned to the + stetic project. Also fixed some stock icon rendering issues in + Stetic. + +2007-07-31 Lluis Sanchez Gual <lluis@novell.com> + + * lib/libsteticui.dll, lib/libstetic.dll: Updated from stetic module. + Includes a nullref fix. + +2007-07-30 Lluis Sanchez Gual <lluis@novell.com> + + * lib/libsteticui.dll, lib/libstetic.dll: Updated. + * MonoDevelop.GtkCore.GuiBuilder/GuiBuilderService.cs: Layout switch + delay is not needed anymore. + +2007-07-25 Lluis Sanchez Gual <lluis@novell.com> + + * MonoDevelop.GtkCore.Dialogs/WidgetBuilderOptionPanel.cs: Fix nullref + when gtk support is not enabled. Patch by Chris Howie. + +2007-07-20 Lluis Sanchez Gual <lluis@novell.com> + + * MonoDevelop.GtkCore.NodeBuilders/ProjectFolderNodeBuilderExtension.cs: + Don't try to use the CurrentNode property after adding the file, + since it may have changed. Should fix bug #82123. + * lib/libsteticui.dll, lib/libstetic.dll: Updated from Stetic module. + Fixes bugs #81846 and #82144. + * MonoDevelop.GtkCore.GuiBuilder/GuiBuilderProject.cs: Fix window + source file lookup. + * MonoDevelop.GtkCore.GuiBuilder/GuiBuilderView.cs: Use the new methods + for checking clipboard operations on the current selection. + * MonoDevelop.GtkCore.GuiBuilder/ToolboxProvider.cs: Include the + current project in the list of libraries to show in the toolbox. + Fixes bug #82125. + +2007-07-10 Lluis Sanchez Gual <lluis@novell.com> + + * lib/libsteticui.dll, lib/libstetic.dll: Updated. Fixes bugs 81977, + 81810 and 82052. + +2007-07-10 Lluis Sanchez Gual <lluis@novell.com> + + * MonoDevelop.GtkCore.GuiBuilder/GuiBuilderService.cs, + MonoDevelop.GtkCore.GuiBuilder/GuiBuilderProject.cs, + MonoDevelop.GtkCore.GuiBuilder/ActionGroupView.cs, + MonoDevelop.GtkCore.GuiBuilder/GuiBuilderView.cs, + MonoDevelop.GtkCore.GuiBuilder/CodeBinder.cs: Properly rename + fields when the widget name is changed. Fixes bug #81976. + +2007-07-09 Lluis Sanchez Gual <lluis@novell.com> + + * MonoDevelop.GtkCore.GuiBuilder/GuiBuilderProjectPad.cs: Update the + properties pad when the focus is on the widget tree pad. Fixes bug + #81971. + +2007-07-05 Lluis Sanchez Gual <lluis@novell.com> + + * lib/libsteticui.dll, lib/libstetic.dll: Updated from Stetic module. + * MonoDevelop.GtkCore.GuiBuilder/GuiBuilderService.cs: Added null + check. + * MonoDevelop.GtkCore.GuiBuilder/GuiBuilderView.cs: Track api changes + in DesignerSupport. When adding a project reference to a widget + library, take into account that widgets may be implemented in a + library different from the one providing the widget list. + * MonoDevelop.GtkCore.GuiBuilder/ToolboxProvider.cs: In + GetDynamicItems, only return widgets provided by libraries + referenced by the project. Don't return widgets from libstetic + since those are already included by default in the toolbox. + Implemented IToolboxDefaultProvider. + +2007-07-03 Mike Krüger <mkrueger@novell.com> + + * MonoDevelop.GtkCore.GuiBuilder/GuiBuilderService.cs: Changed a bit + because of the removal of custom collections in the Ide project. + +2007-06-30 Jacob Ilsø Christensen <jacobilsoe@gmail.com> + + * gui.glade: Fixed capitalization. + +2007-06-27 Lluis Sanchez Gual <lluis@novell.com> + + * MonoDevelop.GtkCore.GuiBuilder/ToolboxLoader.cs: Don't show windows + in the toolbox. + * lib/libstetic.dll, lib/libsteticui.dll: Updated from Stetic module. + +2007-06-22 Lluis Sanchez Gual <lluis@novell.com> + + * lib/libsteticui.dll, lib/libstetic.dll: Updated from Stetic module. + +2007-06-20 Lluis Sanchez Gual <lluis@novell.com> + + * gui.glade, MonoDevelop.GtkCore/GtkDesignInfo.cs, + MonoDevelop.GtkCore/GtkCoreService.cs, + MonoDevelop.GtkCore.Dialogs/WidgetBuilderOptionPanel.cs, + MonoDevelop.GtkCore.Dialogs/GtkFeatureWidget.cs: Allow selecting + the target GTK# version of the project. + * MonoDevelop.GtkCore.addin.xml, MonoDevelop.GtkCore.mdp, Makefile.am, + MonoDevelop.GtkCore.GuiBuilder/ToolboxLoader.cs, + MonoDevelop.GtkCore.GuiBuilder/GuiBuilderView.cs, + MonoDevelop.GtkCore.GuiBuilder/ToolboxProvider.cs: Implemented a + toolbox loader, which allows registering assemblies in the toolbox. + When a widget from a toolbox is dropped to a window, MD will now + add a reference to the required assembly. + * lib/libsteticui.dll, lib/libstetic.dll: Updated from stetic module. + +2007-06-11 Lluis Sanchez Gual <lluis@novell.com> + + * lib/libsteticui.dll: One last update. + +2007-06-11 Lluis Sanchez Gual <lluis@novell.com> + + * lib/libsteticui.dll, lib/libstetic.dll: Updated from Stetic module. + +2007-06-11 Lluis Sanchez Gual <lluis@novell.com> + + * MonoDevelop.GtkCore.NodeBuilders/StockIconsNodeBuilder.cs, + MonoDevelop.GtkCore.GuiBuilder/GuiBuilderService.cs, + MonoDevelop.GtkCore.GuiBuilder/GuiBuilderView.cs: Set the import + file callback when editing project stock icons. + * MonoDevelop.GtkCore/ProjectResourceProvider.cs: The GetResources + method only returns resource files now. + * lib/libsteticui.dll, lib/libstetic.dll: Updated from stetic module. + +2007-06-06 Lluis Sanchez Gual <lluis@novell.com> + + * MonoDevelop.GtkCore.addin.xml, + MonoDevelop.GtkCore.GuiBuilder/GuiBuilderProjectPad.cs: Default pad + placement is now specified in the xml file. + +2007-05-31 Lluis Sanchez Gual <lluis@novell.com> + + * MonoDevelop.GtkCore/GtkCoreService.cs: In GetBaseType, use + Project.GetWidgetTypes to get all registered wiget types, including + base widget types (which were not provided by GetComponentTypes). + * lib/libsteticui.dll, lib/libstetic.dll: Updated from stetic module. + Includes fix for bug #81785. + +2007-05-31 Lluis Sanchez Gual <lluis@novell.com> + + * MonoDevelop.GtkCore/GtkCoreService.cs: Don't include non-public + members to the objects.xml file. + +2007-05-30 Lluis Sanchez Gual <lluis@novell.com> + + * MonoDevelop.GtkCore.mdp: Updated. + * MonoDevelop.GtkCore.Dialogs/GtkFeatureWidget.cs: Fix feature message. + * lib/libsteticui.dll, lib/libstetic.dll: Updated from Stetic module. + Includes fixes for bugs #81761, #81758 and #81762. + * MonoDevelop.GtkCore.GuiBuilder/GuiBuilderProject.cs: + (UpdateLibraries) Properly check for library changes. + +2007-05-23 Lluis Sanchez Gual <lluis@novell.com> + + * lib/libsteticui.dll, lib/libstetic.dll: Updated from stetic module. + Fixes bugs #80783 and #81683. + +2007-05-19 Lluis Sanchez Gual <lluis@novell.com> + + * MonoDevelop.GtkCore.mdp, Makefile.am: Added new dependency. + * lib/libsteticui.dll, lib/libstetic.dll: Updated from svn. Fixes bug + #81590. + * MonoDevelop.GtkCore.GuiBuilder/GuiBuilderView.cs: When selecting an + image file in the widget designer, import the file into the + project. + +2007-05-18 Lluis Sanchez Gual <lluis@novell.com> + + * MonoDevelop.GtkCore.GuiBuilder/GuiBuilderService.cs: Added some delay + in the code that changes the workbench layout when selecting the + designer. Fixes bug #80963. + +2007-05-17 Lluis Sanchez Gual <lluis@novell.com> + + * MonoDevelop.GtkCore.addin.xml, MonoDevelop.GtkCore.mdp, Makefile.am, + MonoDevelop.GtkCore.GuiBuilder/GuiBuilderPalettePad.cs: Removed old + palette pad. + * MonoDevelop.GtkCore/GtkCoreService.cs: Set the 'internal' flag for + widgets implemented by private classes. + * lib/libsteticui.dll, lib/libstetic.dll: Updated from svn module. + Fixes bugs #80875, #81261, #81365. + * MonoDevelop.GtkCore.GuiBuilder/GuiBuilderProject.cs: If the project + is a library, add itself as an internal widget library, so widgets + with internal visibility will be shown. + * MonoDevelop.GtkCore.GuiBuilder/CodeBinder.cs: When saving a window, + use the visibility of the class to set the visibility of the + component. Together with all changes done in stetic, fixes bug + #80875. + +2007-05-15 Lluis Sanchez Gual <lluis@novell.com> + + * MonoDevelop.GtkCore.NodeBuilders/WidgetNodeBuilder.cs, + MonoDevelop.GtkCore.NodeBuilders/WindowsFolderNodeBuilder.cs, + MonoDevelop.GtkCore.NodeBuilders/ActionGroupNodeBuilder.cs, + MonoDevelop.GtkCore/GtkDesignInfo.cs, + MonoDevelop.GtkCore/WidgetFileDescriptionTemplate.cs, + MonoDevelop.GtkCore.Dialogs/ConfirmWindowDeleteDialog.cs, + MonoDevelop.GtkCore.GuiBuilder/ActionGroupDisplayBinding.cs, + MonoDevelop.GtkCore.GuiBuilder/GuiBuilderService.cs, + MonoDevelop.GtkCore.GuiBuilder/GuiBuilderProject.cs, + MonoDevelop.GtkCore.GuiBuilder/GuiBuilderWindow.cs, + MonoDevelop.GtkCore.GuiBuilder/ActionGroupView.cs, + MonoDevelop.GtkCore.GuiBuilder/GuiBuilderView.cs, + MonoDevelop.GtkCore.GuiBuilder/CodeBinder.cs: Track api changes in + Stetic. + * MonoDevelop.GtkCore.Dialogs/WidgetBuilderOptionPanel.cs: Delay + library updating until really necessary. + * lib/libsteticui.dll, lib/libstetic.dll: Updated from stetic module. + +2007-05-11 Lluis Sanchez Gual <lluis@novell.com> + + * MonoDevelop.GtkCore.mdp: Copy the .addins.xml file to the output dir. + +2007-05-11 Lluis Sanchez Gual <lluis@novell.com> + + * MonoDevelop.GtkCore.mdp: Copy stetic dlls together with the assembly. + * lib/libsteticui.dll, lib/libstetic.dll: Updated. + +2007-05-09 Lluis Sanchez Gual <lluis@novell.com> + + * MonoDevelop.GtkCore.mdp, Makefile.am: Reference shared assemblies + from the correct location. + +2007-05-04 Wade Berrier <wberrier@novell.com> + * lib/libstetic.dll.config: + * lib/libsteticui.dll.config: + Fix os attribute formats (mono-config.c separates oses by comma, + and ignores or includes the whole string.) + +2007-05-04 Lluis Sanchez Gual <lluis@novell.com> + + * MonoDevelop.GtkCore.addin.xml, MonoDevelop.GtkCore.mdp, Makefile.am: + Migration to Mono.Addins. + +2007-04-26 Lluis Sanchez Gual <lluis@novell.com> + + * MonoDevelop.GtkCore.addin.xml, MonoDevelop.GtkCore.mdp, + MonoDevelop.GtkCore.Dialogs/GtkFeatureWidget.cs, Makefile.am: + Implemented project feature for enabling gtk# support in new + projects. + * MonoDevelop.GtkCore.NodeBuilders/WidgetNodeBuilder.cs, + MonoDevelop.GtkCore.NodeBuilders/ActionGroupNodeBuilder.cs: Use + Menu icon size in the project pad. + * lib/libsteticui.dll, lib/libstetic.dll: Updated from stetic module. + +2007-04-18 Lluis Sanchez Gual <lluis@novell.com> + + * MonoDevelop.GtkCore.NodeBuilders/WidgetNodeBuilder.cs: Show a + relative path in the window delete confirm dialog, since the + absolute path may take too much space. + * MonoDevelop.GtkCore.mdp: Updated. + * lib/libsteticui.dll, lib/libstetic.dll: Updated from stetic module. + * templates/DialogPartial.xft.xml, templates/Dialog.xft.xml: Add + Ok/Cancel buttons by default in new dialogs. + +2007-03-28 Lluis Sanchez Gual <lluis@novell.com> + + * lib/libsteticui.dll, lib/libstetic.dll: Updated from stetic module. + Includes fixes for bugs 81033, 81086, 81239, 81143, 81014 and + 81015. + * MonoDevelop.GtkCore.GuiBuilder/GuiBuilderView.cs: Allow pasting when + a placeholder is selected. Fixes bug #81246. + +2007-03-28 Lluis Sanchez Gual <lluis@novell.com> + + * MonoDevelop.GtkCore.addin.xml, + MonoDevelop.GtkCore.NodeBuilders/StockIconsNodeBuilder.cs, + MonoDevelop.GtkCore.NodeBuilders/WindowsFolderNodeBuilder.cs, + MonoDevelop.GtkCore.mdp, Makefile.am, icons/image-x-generic.png: + Show a "Stock Icons" node in the User Interface folder. It's easier + to discover than the context menu option. + * MonoDevelop.GtkCore.NodeBuilders/ProjectFolderNodeBuilderExtension.cs, + MonoDevelop.GtkCore.Commands/GladeCommands.cs: Added menu option + for opening the gtk# settings. + * MonoDevelop.GtkCore.GuiBuilder/GuiBuilderProject.cs: Don't crash if + the gtk-gui folder doesn't exist. Fixes bug #81152. + * MonoDevelop.GtkCore.GuiBuilder/CombinedDesignView.cs: Hide the border + of the combined view notebook. + +2007-03-08 Lluis Sanchez Gual <lluis@novell.com> + + * lib/libstetic.dll: Updated from stetic module. Fixes NRE crash. + +2007-03-08 Lluis Sanchez Gual <lluis@novell.com> + + * lib/libsteticui.dll, lib/libstetic.dll: Updated from stetic module. + * MonoDevelop.GtkCore.GuiBuilder/CodeBinder.cs: Fix null ref. + +2007-03-06 Lluis Sanchez Gual <lluis@novell.com> + + * MonoDevelop.GtkCore.addin.xml: Register a new toolbox loader. Removed + old properties pads. + * MonoDevelop.GtkCore.mdp, Makefile.am: Added reference to + MonoDevelop.DesignerSupport. + * lib/libsteticui.dll, lib/libstetic.dll: Updated from svn module. + * MonoDevelop.GtkCore.GuiBuilder/GuiBuilderService.cs, + MonoDevelop.GtkCore.GuiBuilder/GuiBuilderView.cs, + MonoDevelop.GtkCore.GuiBuilder/PropertiesWidget.cs, + MonoDevelop.GtkCore.GuiBuilder/ToolboxProvider.cs: Integrate Stetic + widgets in the main toolbox. + * MonoDevelop.GtkCore.GuiBuilder/ActionGroupView.cs: Implement + ICustomPropertyPadProvider and return the Stetic property pad. + * MonoDevelop.GtkCore.GuiBuilder/GuiBuilderPropertiesPad.cs: Renamed. + * MonoDevelop.GtkCore.GuiBuilder/CombinedDesignView.cs: Fix warning. + +2007-02-20 Lluis Sanchez Gual <lluis@novell.com> + + Updated from Stetic module. Includes fix for bug #80864. + +2007-02-20 Lluis Sanchez Gual <lluis@novell.com> + + * lib/libsteticui.dll, lib/libstetic.dll: Updated from SVN. Fixes some + memory leaks and bug #79453. + * MonoDevelop.GtkCore.GuiBuilder/CombinedDesignView.cs: Explicitely + destroy notebook children, since notebook doesnt do it because of a + gtk bug. + * MonoDevelop.GtkCore.GuiBuilder/GuiBuilderView.cs: Some fixes in the + dispose code. + +2007-02-16 Lluis Sanchez Gual <lluis@novell.com> + + * MonoDevelop.GtkCore.NodeBuilders/ProjectFolderNodeBuilderExtension.cs, + MonoDevelop.GtkCore.GuiBuilder/ActionGroupDisplayBinding.cs, + MonoDevelop.GtkCore.GuiBuilder/GuiBuilderWindow.cs: Use + ProjectOperations.SaveProject to save projects. + +2007-02-16 Lluis Sanchez Gual <lluis@novell.com> + + * MonoDevelop.GtkCore.addin.xml: Change add-in versions to 0.13. + +2007-02-15 Lluis Sanchez Gual <lluis@novell.com> + + * MonoDevelop.GtkCore.GuiBuilder/GuiBuilderProject.cs: Fix nullref. + * MonoDevelop.GtkCore.GuiBuilder/GtkProjectServiceExtension.cs: Log + error message. + * Makefile.am, MonoDevelop.GtkCore.mdp: Synchronized MD project and + makefile. + +2007-02-15 Lluis Sanchez Gual <lluis@novell.com> + + * MonoDevelop.GtkCore.GuiBuilder/GuiBuilderProject.cs: Avoid throwing + delayed events after the project has been disposed. + +2007-02-14 Lluis Sanchez Gual <lluis@novell.com> + + * MonoDevelop.GtkCore.GuiBuilder/GuiBuilderProject.cs: Added missing + null check. + +2007-02-14 Lluis Sanchez Gual <lluis@novell.com> + + * MonoDevelop.GtkCore.GuiBuilder/GuiBuilderService.cs, + MonoDevelop.GtkCore.GuiBuilder/GuiBuilderProject.cs: Ask for user + confirmation when reloading a designer only when the designer has + unsaved changes. + +2007-02-14 Lluis Sanchez Gual <lluis@novell.com> + + * MonoDevelop.GtkCore.NodeBuilders/ProjectFolderNodeBuilderExtension.cs, + MonoDevelop.GtkCore.NodeBuilders/WindowsFolderNodeBuilder.cs, + MonoDevelop.GtkCore.NodeBuilders/WindowsFolder.cs, + MonoDevelop.GtkCore/GtkDesignInfo.cs, + MonoDevelop.GtkCore.GuiBuilder/GuiBuilderService.cs, + MonoDevelop.GtkCore.GuiBuilder/GuiBuilderProject.cs, + MonoDevelop.GtkCore.GuiBuilder/ActionGroupView.cs, + MonoDevelop.GtkCore.GuiBuilder/GuiBuilderView.cs: Detect external + changes in the gui.stetic files, and reload it when it changes. + Take into account that the load of gui.stetic can fail. Added + several workarounds for this case. + +2007-02-13 Lluis Sanchez Gual <lluis@novell.com> + + * lib/libsteticui.dll, lib/libstetic.dll: Updated from SVN. Includes + fixes for bugs #80722, #79427 and #80127. + * MonoDevelop.GtkCore.GuiBuilder/GuiBuilderService.cs, + MonoDevelop.GtkCore.GuiBuilder/GuiBuilderProject.cs: Store some + Stetic configuration in the MD properties. + +2007-02-09 Lluis Sanchez Gual <lluis@novell.com> + + * gui.glade, MonoDevelop.GtkCore.Dialogs/WidgetBuilderOptionPanel.cs, + MonoDevelop.GtkCore.GuiBuilder/GuiBuilderService.cs: Added options + for enabling/disabling gtk support, and for gettext support. + * MonoDevelop.GtkCore.addin.xml: Change options panel name. + * MonoDevelop.GtkCore.NodeBuilders/ProjectFolderNodeBuilderExtension.cs, + MonoDevelop.GtkCore.GuiBuilder/CodeBinder.cs, + MonoDevelop.GtkCore.GuiBuilder/GuiBuilderWindow.cs: Make sure the + MD project is saved together with the stetic project, if necessary. + * MonoDevelop.GtkCore.NodeBuilders/WidgetNodeBuilder.cs, + MonoDevelop.GtkCore.NodeBuilders/ActionGroupNodeBuilder.cs, + MonoDevelop.GtkCore/WidgetFileDescriptionTemplate.cs: Avoid saving + the MD project twice. + * MonoDevelop.GtkCore.NodeBuilders/ProjectNodeBuilder.cs: If gtk + integration status changes for a project, refresh the tree. + * MonoDevelop.GtkCore.NodeBuilders/WindowsFolder.cs: Null check. + * MonoDevelop.GtkCore/GtkDesignInfo.cs: Added support for gettext and + gettext class options for generated code. + * MonoDevelop.GtkCore/GtkCoreService.cs: Added events for notifying + when the gtk integration status changes for a project. + * lib/libsteticui.dll, lib/libstetic.dll: Updated from stetic module. + * Makefile.am: distcheck fixes + * MonoDevelop.GtkCore.GuiBuilder/GuiBuilderProject.cs, + MonoDevelop.GtkCore.GuiBuilder/ActionGroupView.cs, + MonoDevelop.GtkCore.GuiBuilder/CombinedDesignView.cs, + MonoDevelop.GtkCore.GuiBuilder/GuiBuilderView.cs: When a designer + project is disposed, hide the designer view in the editor. + * MonoDevelop.GtkCore.GuiBuilder/GtkProjectServiceExtension.cs: + Factorized some code into GtkDesignInfo. + +2007-02-07 Lluis Sanchez Gual <lluis@novell.com> + + * MonoDevelop.GtkCore.addin.xml: Make sure the code generation + extension is executed before the last step. + * MonoDevelop.GtkCore.NodeBuilders/ProjectFolderNodeBuilderExtension.cs: + Hide the add window commands when the project is not DotNet + * MonoDevelop.GtkCore.mdp, lib/libsteticui.dll, lib/libstetic.dll: + Updated. + +2007-02-02 Lluis Sanchez Gual <lluis@novell.com> + + * MonoDevelop.GtkCore.GuiBuilder/CombinedDesignView.cs: Intercept calls + to the IPositionable interface, and show the editor page when + jumping to a line. + +2007-02-02 Lluis Sanchez Gual <lluis@novell.com> + + * MonoDevelop.GtkCore.GuiBuilder/GuiBuilderProject.cs: When looking for + the window class, avoid returning the generated partial class. + * MonoDevelop.GtkCore.GuiBuilder/GuiBuilderView.cs: Show the editor + page when jumping to a signal handler. + +2007-02-02 Lluis Sanchez Gual <lluis@novell.com> + + * MonoDevelop.GtkCore.GuiBuilder/GuiBuilderService.cs: Warn the user if + the gtk-sharp-2 package can't be found. Some distros don't include + the .pc file in the gtk# package, only in the -devel package. + +2007-02-02 Lluis Sanchez Gual <lluis@novell.com> + + * lib/libsteticui.dll, lib/libstetic.dll: Updated from Stetic module. + +2007-01-31 Lluis Sanchez Gual <lluis@novell.com> + + * lib/libstetic.dll.config, lib/libsteticui.dll, lib/libstetic.dll, + lib/libsteticui.dll.config: Updated from Stetic module. + +2007-01-29 Lluis Sanchez Gual <lluis@novell.com> + + * MonoDevelop.GtkCore.NodeBuilders/WidgetNodeBuilder.cs, + MonoDevelop.GtkCore.NodeBuilders/ActionGroupNodeBuilder.cs, + MonoDevelop.GtkCore.GuiBuilder/GuiBuilderService.cs, + MonoDevelop.GtkCore.GuiBuilder/CodeBinder.cs, + MonoDevelop.GtkCore.GuiBuilder/GuiBuilderWindow.cs: Track api + changes in Document class. + * lib/libsteticui.dll, lib/libstetic.dll: Updated form Stetic module. + * MonoDevelop.GtkCore.GuiBuilder/CombinedDesignView.cs: Removed + implementation of all text editor interfaces. Now the view + overrides GetContent and calls editor.GetContent when a requested + interface is not found. + +2007-01-22 Lluis Sanchez Gual <lluis@novell.com> + + * MonoDevelop.GtkCore.mdp: Updated. + * MonoDevelop.GtkCore/GtkDesignInfo.cs: Removed unused namespace. + * MonoDevelop.GtkCore/GtkCoreService.cs: Use the new base-type property + to describe custom widgets. When looking for properties and events, + look in the base classes as well as in the widget class. + * lib/libsteticui.dll, lib/libstetic.dll: Updated from stetic module. + * Makefile.am, + MonoDevelop.GtkCore.WidgetLibrary/ProjectClassDescriptor.cs, + MonoDevelop.GtkCore.WidgetLibrary/ProjectSignalDescriptor.cs, + MonoDevelop.GtkCore.WidgetLibrary/BaseWidgetLibrary.cs, + MonoDevelop.GtkCore.WidgetLibrary/AssemblyReferenceWidgetLibrary.cs, + MonoDevelop.GtkCore.WidgetLibrary/ProjectPropertyDescriptor.cs: + Removed unused files. All widget library functionality has been + moved to stetic. + * MonoDevelop.GtkCore.GuiBuilder/GuiBuilderService.cs: Removed all + widget library management, which has been moved to Stetic. + * MonoDevelop.GtkCore.GuiBuilder/CodeBinder.cs: Added some null checks. + * MonoDevelop.GtkCore.GuiBuilder/GuiBuilderProject.cs: Use the new way + of managing dependencies in projects. + * MonoDevelop.GtkCore.GuiBuilder/GuiBuilderWindow.cs, + templates/WindowPartial.xft.xml, templates/Window.xft.xml: The + window constructor now takes the window type. + * MonoDevelop.GtkCore.GuiBuilder/GuiBuilderView.cs: Some gui + improvements and added some null checks. + +2007-01-17 Lluis Sanchez Gual <lluis@novell.com> + + * MonoDevelop.GtkCore.GuiBuilder/GuiBuilderView.cs: Don't crash if the + designer can't be loaded for some reason. + +2007-01-15 Lluis Sanchez Gual <lluis@novell.com> + + * MonoDevelop.GtkCore.addin.xml, + MonoDevelop.GtkCore.NodeBuilders/ProjectFolderNodeBuilderExtension.cs, + MonoDevelop.GtkCore/GtkCoreService.cs, + MonoDevelop.GtkCore/WidgetFileTemplatePartialClass.cs, + MonoDevelop.GtkCore/WidgetFileTemplateFullClass.cs, + MonoDevelop.GtkCore.GuiBuilder/CodeBinder.cs, + MonoDevelop.GtkCore.GuiBuilder/GuiBuilderWindow.cs, + MonoDevelop.GtkCore.GuiBuilder/CombinedDesignView.cs, + templates/WidgetPartial.xft.xml, templates/Widget.xft.xml, + templates/WindowPartial.xft.xml, templates/Window.xft.xml, + templates/ActionGroupPartial.xft.xml, + templates/ActionGroup.xft.xml, templates/DialogPartial.xft.xml, + templates/Dialog.xft.xml: Implemented support for generating code + in partial classes. + * MonoDevelop.GtkCore.NodeBuilders/WidgetNodeBuilder.cs: Use the + correct method for saving the project. + * MonoDevelop.GtkCore.NodeBuilders/WindowsFolder.cs: Refresh the user + interface folder when the gui project is reloaded. + * MonoDevelop.GtkCore.mdp: Updated. + * MonoDevelop.GtkCore/GtkDesignInfo.cs: Added support for partial + classes. In the GuiBuilderProject property, don't update the + gtk-gui folder since this call may change the contents of the + project, and weird things happen when called by the project pad to + fill the tree. + * lib/libsteticui.dll, lib/libstetic.dll: Updated from stetic module. + * Makefile.am: Added new files. + * MonoDevelop.GtkCore.WidgetLibrary/BaseWidgetLibrary.cs, + MonoDevelop.GtkCore.WidgetLibrary/AssemblyReferenceWidgetLibrary.cs: + Make it work even when the assembly it references has been deleted + (maybe as a result of cleaning a project). In this case the widget + library is shown as empty. + * MonoDevelop.GtkCore.GuiBuilder/GuiBuilderService.cs, + MonoDevelop.GtkCore.GuiBuilder/GuiBuilderProject.cs: Added support + for Loading/Unloading a project, to optimize use of memory for + solutions with many gui projects. Implemented support for + generating code in partial classes. + * MonoDevelop.GtkCore.GuiBuilder/ActionGroupView.cs, + MonoDevelop.GtkCore.GuiBuilder/GuiBuilderView.cs: Implemented + support for generating code in partial classes. Implemented support + for UNDO/REDO. + * MonoDevelop.GtkCore.GuiBuilder/GtkProjectServiceExtension.cs: + Generation of gui code is now done from the Build method of a + project service extension. Fixes some issues when building a + project which contains custom components. + +2006-12-17 Lluis Sanchez Gual <lluis@novell.com> + + * MonoDevelop.GtkCore/GtkCoreService.cs: Track API changes in + FileService. + +2006-12-13 Jacob Ilsø Christensen <jacobilsoe@gmail.com> + + * MonoDevelop.GtkCore.GuiBuilder/GuiBuilderService.cs: Don't + generate stetic code if CurrentOpenCombine is null. + +2006-12-07 Jacob Ilsø Christensen <jacobilsoe@gmail.com> + + * MonoDevelop.GtkCore.mdp: Updated to it can be + built from MonoDevelop. + +2006-11-16 Lluis Sanchez Gual <lluis@novell.com> + + * MonoDevelop.GtkCore.GuiBuilder/GuiBuilderService.cs: Simplified the + code by using global events from the Ide, instead of combine + events. + +2006-10-18 Lluis Sanchez Gual <lluis@novell.com> + + * MonoDevelop.GtkCore/GtkDesignInfo.cs: Added RemoveExportedWidget method. + * MonoDevelop.GtkCore.Dialogs/WidgetBuilderOptionPanel.cs: track + API changes. + * MonoDevelop.GtkCore.GuiBuilder/GuiBuilderView.cs: If the name of a + widget changes and it is being exported, update it in the objects.xml + file. Fixes bug #79656. + +2006-09-23 Lluis Sanchez Gual <lluis@novell.com> + + * lib/*: Updated from Stetic module. It provides a redesigned API + which will allow running designers in a separate process. + + * MonoDevelop.GtkCore/WidgetFileDescriptionTemplate.cs: + * MonoDevelop.GtkCore.NodeBuilders/WidgetNodeBuilder.cs: + * MonoDevelop.GtkCore.NodeBuilders/WindowsFolderNodeBuilder.cs: + * MonoDevelop.GtkCore.NodeBuilders/WindowsFolder.cs: + * MonoDevelop.GtkCore.NodeBuilders/ActionGroupNodeBuilder.cs: + * MonoDevelop.GtkCore.NodeBuilders/ProjectFolderNodeBuilderExtension.cs: + * MonoDevelop.GtkCore.Dialogs/WidgetBuilderOptionPanel.cs: + * MonoDevelop.GtkCore.Dialogs/ConfirmWindowDeleteDialog.cs: + * MonoDevelop.GtkCore.WidgetLibrary/AssemblyReferenceWidgetLibrary.cs: + * MonoDevelop.GtkCore.GuiBuilder/ActionGroupDisplayBinding.cs: + * MonoDevelop.GtkCore.GuiBuilder/GuiBuilderService.cs: + * MonoDevelop.GtkCore.GuiBuilder/GuiBuilderProject.cs: + * MonoDevelop.GtkCore.GuiBuilder/GuiBuilderWindow.cs: + * MonoDevelop.GtkCore.GuiBuilder/ActionGroupView.cs: + * MonoDevelop.GtkCore.GuiBuilder/GuiBuilderView.cs: + * MonoDevelop.GtkCore.GuiBuilder/GuiBuilderPropertiesPad.cs: + * MonoDevelop.GtkCore.GuiBuilder/CodeBinder.cs: + * MonoDevelop.GtkCore.GuiBuilder/GuiBuilderPalettePad.cs: + * MonoDevelop.GtkCore.GuiBuilder/GuiBuilderProjectPad.cs: + Track api changes. + + * MonoDevelop.GtkCore.WidgetLibrary/BaseWidgetLibrary.cs: Make sure + parse information is up to date before loading an assembly library. + * MonoDevelop.GtkCore/ProjectResourceProvider.cs: Make sure this object + is always alive when remoted. + * MonoDevelop.GtkCore.GuiBuilder/CombinedDesignView.cs: Added null check. + * MonoDevelop.GtkCore.GuiBuilder/GuiBuilderEditSession.cs: Not needed anymore. + * MonoDevelop.GtkCore.addin.xml: Removed build step. Code generation + is done now before compiling. + + * MonoDevelop.GtkCore.WidgetLibrary/ProjectWidgetLibrary.cs: + * MonoDevelop.GtkCore.WidgetLibrary/CachedProjectWidgetLibrary.cs: + * MonoDevelop.GtkCore/GtkDesignInfo.cs: ProjectWidgetLibrary is not used + anymore. All libraries are now handled by AssemblyReferenceWidgetLibrary. + + * MonoDevelop.GtkCore.GuiBuilder/MonoDevelopWidgetActionBar.cs: + * MonoDevelop.GtkCore.GuiBuilder/MonoDevelopActionGroupToolbar.cs: + Moved to Stetic. + + * Makefile.am: + * MonoDevelop.GtkCore.mdp: Updated. + +2006-09-23 Lluis Sanchez Gual <lluis@novell.com> + + * MonoDevelop.GtkCore.GuiBuilder/GuiBuilderService.cs: Track api changes. + +2006-09-19 Jacob Ilsø Christensen <jacobilsoe@gmail.com> + + * .: Added svn:ignore for MonoDevelop.GtkCore.pidb + +2006-09-01 Lluis Sanchez Gual <lluis@novell.com> + + * lib/*: Updated from stetic module. Includes fix for bug #79247. + +2006-09-01 Lluis Sanchez Gual <lluis@novell.com> + + * lib/*: Updated from stetic module. + * MonoDevelop.GtkCore.NodeBuilders/ProjectFolderNodeBuilderExtension.cs: + Save the project after editing the icons. + * MonoDevelop.GtkCore.GuiBuilder/GuiBuilderProject.cs: Set the + ResourceProvider for the main stetic project. Added null check. + +2006-08-30 Lluis Sanchez Gual <lluis@novell.com> + + * MonoDevelop.GtkCore.GuiBuilder/GuiBuilderView.cs: Fixed bug about + adding the wrong widget as action designer page. + +2006-08-30 Lluis Sanchez Gual <lluis@novell.com> + + * MonoDevelop.GtkCore/GtkCoreService.cs: Only export properties which + return primitive types. Fixes bug #79195. + * lib/*: Updated from stetic module. + * MonoDevelop.GtkCore.Dialogs/BindDesignDialog.cs: Unsubscribe close + event when done. + * MonoDevelop.GtkCore.GuiBuilder/GuiBuilderView.cs: Handle designer + commands in its own tab page. + + * MonoDevelop.GtkCore.GuiBuilder/CombinedDesignView.cs: + * MonoDevelop.GtkCore.GuiBuilder/GuiBuilderEditSession.cs: + * MonoDevelop.GtkCore.GuiBuilder/ActionGroupView.cs: Explicitely dispose + custom widgets to avoid memory leaks. + + * MonoDevelop.GtkCore.GuiBuilder/GuiBuilderWindow.cs: + * MonoDevelop.GtkCore.GuiBuilder/GuiBuilderProject.cs: Track api changes. + + * MonoDevelop.GtkCore.mdp: Updated. + +2006-08-18 Lluis Sanchez Gual <lluis@novell.com> + + * gui.glade: Minor fix. + * MonoDevelop.GtkCore.NodeBuilders/WidgetNodeBuilder.cs: Track api + changes. + * MonoDevelop.GtkCore/GtkDesignInfo.cs: Stetic files don't need + to be added as resource to projects. + * MonoDevelop.GtkCore.Dialogs/ConfirmWindowDeleteDialog.cs: Make it + work for action groups. + * lib/*: several fixes. + * MonoDevelop.GtkCore.GuiBuilder/GuiBuilderProject.cs: Added method + for removing an action group. + + * MonoDevelop.GtkCore.GuiBuilder/GuiBuilderEditSession.cs: + * MonoDevelop.GtkCore.GuiBuilder/ActionGroupView.cs: + * MonoDevelop.GtkCore.GuiBuilder/GuiBuilderView.cs: Track API changes + in Stetic. Properly bound edit commands from the main menu. + + * MonoDevelop.GtkCore.NodeBuilders/ActionGroupNodeBuilder.cs: + * MonoDevelop.GtkCore.addin.xml: Implemented Open and Delete + commands for global action groups. + + * MonoDevelop.GtkCore.mdp: Updated. + +2006-08-11 Lluis Sanchez Gual <lluis@novell.com> + + * lib/*: Updated from Stetic module. Includes fixes for + bugs #79043, #79044 and #79045 + * MonoDevelop.GtkCore.GuiBuilder/GuiBuilderWindow.cs: Don't + crash if something goes wrong when binding a class. + Fixed nullref. + +2006-08-04 Lluis Sanchez Gual <lluis@novell.com> + + * MonoDevelop.GtkCore.GuiBuilder/GuiBuilderDisplayBinding.cs: + * MonoDevelop.GtkCore.GuiBuilder/ActionGroupDisplayBinding.cs: + CreateContentForFile should not load the file, just create + the view. + + * MonoDevelop.GtkCore.GuiBuilder/CombinedDesignView.cs: Add + support for IEncodedTextContent. + +2006-08-01 Lluis Sanchez Gual <lluis@novell.com> + + * MonoDevelop.GtkCore.GuiBuilder/GuiBuilderEditSession.cs: + Set the resource provider before loading the project. + Fixes bug #78966. + + * libs/*: Updated from Stetic module. Fixes several bugs: + 78938, 78916, 78909, 78956, and 78867. + +2006-07-27 Lluis Sanchez Gual <lluis@novell.com> + + * MonoDevelop.GtkCore.WidgetLibrary/ProjectClassDescriptor.cs: + Added null check. + + * MonoDevelop.GtkCore.WidgetLibrary/AssemblyReferenceWidgetLibrary.cs: + Get the parser context using the assembly file name, not the full + assembly name. + +2006-07-25 Lluis Sanchez Gual <lluis@novell.com> + + * MonoDevelop.GtkCore/GtkDesignInfo.cs: + * MonoDevelop.GtkCore.GuiBuilder/ActionGroupDisplayBinding.cs: + * MonoDevelop.GtkCore.GuiBuilder/GuiBuilderService.cs: + * MonoDevelop.GtkCore.GuiBuilder/GuiBuilderDisplayBinding.cs: + * MonoDevelop.GtkCore.GuiBuilder/GuiBuilderProject.cs: + * MonoDevelop.GtkCore.GuiBuilder/GuiBuilderWindow.cs: + * MonoDevelop.GtkCore.GuiBuilder/CodeBinder.cs: Factorized several + more or less duplicate methods into GuiBuilderProject, specially + methods for locating the class bound to a window. GuiBuilderProject + now will explicitelly update the parser database the first time it + needs to locate a class, so it will work even if the parser service + is busy parsing assemblies. + +2006-07-24 Lluis Sanchez Gual <lluis@novell.com> + + * lib/libstetic.dll: Updated from stetic module. Fixes a bug + in the table wrapper which may cause an endless loop. + +2006-07-05 Matej Urbas <matej.urbas@gmail.com> + + * MonoDevelop.GtkCore/GtkCoreService.cs: + * MonoDevelop.GtkCore.GuiBuilder/ActionGroupDisplayBinding.cs: + * MonoDevelop.GtkCore.GuiBuilder/CodeBinder: + * MonoDevelop.GtkCore.GuiBuilder/GuiBuilderWindow.cs: + * MonoDevelop.GtkCore.WidgetLibrary/BaseWidgetLibrary.cs: Updated to use + ReturnType as BaseTypes in IClass instances. + +2006-07-03 Lluis Sanchez Gual <lluis@novell.com> + + * lib/*: Updated from Stetic module. + * MonoDevelop.GtkCore.GuiBuilder/GuiBuilderService.cs: Fixed automatic + layout switch policy. + * MonoDevelop.GtkCore.GuiBuilder/GuiBuilderView.cs: Fix showing of + action group view. + * MonoDevelop.GtkCore.GuiBuilder/GuiBuilderEditSession.cs: Properly + bind actions when pressing "BindToField". + + * MonoDevelop.GtkCore.addin.xml: Updated versions. + +2006-06-29 Michael Hutchinson <m.j.hutchinson@gmail.com> + + * MonoDevelop.GtkCore.addin.xml: Only display WidgetBuilderOptionPanel + for "DotNet" projects. + +2006-06-19 Lluis Sanchez Gual <lluis@novell.com> + + * lib/*: Updated from Stetic module. + * MonoDevelop.GtkCore.GuiBuilder/GuiBuilderService.cs: Switch to the + designer workbench layout when selecting an action group file. + * MonoDevelop.GtkCore.GuiBuilder/ActionGroupView.cs: Support jumping + to signal hanlder when double-clicking it in the signals editor. + * MonoDevelop.GtkCore.GuiBuilder/CodeBinder.cs: Removed debug code. + + * templates/ActionGroup.xft.xml: + * MonoDevelop.GtkCore.GuiBuilder/ActionGroupDisplayBinding.cs: + Fix code generation of action groups. + +2006-06-12 Lluis Sanchez Gual <lluis@novell.com> + + * MonoDevelop.GtkCore/GtkCoreService.cs: If a member has a [Browsable(false)] + attribute, don't add it to the objects.xml file. Also don't add + read-only properties. + * lib/*: Updated from stetic module. Fixes bugs #78622 and #78620. + Adds an icon for expander and fixes a bug in ColorButton (fix by ml) + +2006-06-11 Lluis Sanchez Gual <lluis@novell.com> + + * lib/libsteticui.dll: + * MonoDevelop.GtkCore.GuiBuilder/MonoDevelopWidgetActionBar.cs: + Track changes in the api. + +2006-06-09 Lluis Sanchez Gual <lluis@novell.com> + + * libs/*: Updated from stetic module. Several improvements. + Also fixes bug #78160. + +2006-05-30 Lluis Sanchez Gual <lluis@novell.com> + + * MonoDevelop.GtkCore.GuiBuilder/ActionGroupDisplayBinding.cs: + * MonoDevelop.GtkCore.GuiBuilder/GuiBuilderDisplayBinding.cs: + Added DisplayName property. + +2006-05-29 David Makovský (Yakeen) <yakeen@sannyas-on.net> + + * MonoDevelop.GtkCore.GuiBuilder/CombinedDesignView.cs: reverted interface changes - missing file change + +2006-05-29 David Makovský (Yakeen) <yakeen@sannyas-on.net> + + * MonoDevelop.GtkCore.GuiBuilder/CombinedDesignView.cs: reverted interface changes + +2006-05-26 Lluis Sanchez Gual <lluis@novell.com> + + * libs/*: Updated from stetic module. Adds support for toolbars. + +2006-05-23 David Makovský (Yakeen) <yakeen@sannyas-on.net> + + * MonoDevelop.GtkCore.GuiBuilder/CombinedDesignView.cs: track api changes + +2006-05-19 Lluis Sanchez Gual <lluis@novell.com> + + * MonoDevelop.GtkCore.Commands/GladeCommands.cs: + * MonoDevelop.GtkCore.NodeBuilders/ProjectFolderNodeBuilderExtension.cs: + * MonoDevelop.GtkCore.addin.xml: Added commands for creating + an action group and editing the project icons. + + * MonoDevelop.GtkCore.NodeBuilders/WidgetNodeBuilder.cs: Show local + action groups as children of the window node. + + * MonoDevelop.GtkCore.NodeBuilders/WindowsFolder.cs: + * MonoDevelop.GtkCore.NodeBuilders/WindowsFolderNodeBuilder.cs: Moved + some event subscriptions to WindowsFolder.cs + + * MonoDevelop.GtkCore.GuiBuilder/GuiBuilderService.cs: + * MonoDevelop.GtkCore.NodeBuilders/ActionGroupNodeBuilder.cs: Open the + corresponding file when clicking on local action groups. + + * Makefile.am: + * MonoDevelop.GtkCore.mdp: Added action group template. + + * MonoDevelop.GtkCore/WidgetFileDescriptionTemplate.cs: Added support for + action group file templates. + * MonoDevelop.GtkCore.GuiBuilder/GuiBuilderWindow.cs: Notify changes in + local action groups. + * MonoDevelop.GtkCore.GuiBuilder/GuiBuilderView.cs: Don't show the actions + tab until there is at least one action group. + * MonoDevelop.GtkCore.GuiBuilder/GuiBuilderPropertiesPad.cs: Don't show + properties or signals for global actions. + * MonoDevelop.GtkCore.GuiBuilder/CombinedDesignView.cs: Added virtual method + OnActiveDocumentChanged, which is called when the view is brought to front. + + * MonoDevelop.GtkCore.GuiBuilder/GuiBuilderEditSession.cs: + * MonoDevelop.GtkCore.GuiBuilder/CodeBinder.cs: Use the new MemberName + field when binding fields. + + * MonoDevelop.GtkCore.GuiBuilder/MonoDevelopActionGroupToolbar.cs: + * MonoDevelop.GtkCore.GuiBuilder/ActionGroupView.cs: Several minor fixes. + + * lib/*: Updated. + + +2006-05-12 Lluis Sanchez Gual <lluis@novell.com> + + * Initial support for the menu editor. Still very unstable!! + + * lib/*: Updated from Stetic module. + * MonoDevelop.GtkCore.addin.xml: Register a node builder and and + display binding for action groups. + * MonoDevelop.GtkCore.NodeBuilders/WindowsFolderNodeBuilder.cs: Update + the folder when action groups change. + * MonoDevelop.GtkCore/GtkCoreService.cs: Fix nullref. + + * MonoDevelop.GtkCore.GuiBuilder/GuiBuilderEditSession.cs: Factorized + some code into CodeBinder.cs + * MonoDevelop.GtkCore.GuiBuilder/GuiBuilderView.cs: Factorized some + code into CombinedDesignView.cs. + + * MonoDevelop.GtkCore.NodeBuilders/ActionGroupNodeBuilder.cs: New node + builder for action groups. + * MonoDevelop.GtkCore.GuiBuilder/ActionGroupDisplayBinding.cs: New display + binding for editing global action groups. + * MonoDevelop.GtkCore.GuiBuilder/MonoDevelopWidgetActionBar.cs: Moved from + GuiBuilderView.cs. + * MonoDevelop.GtkCore.GuiBuilder/MonoDevelopActionGroupToolbar.cs: A new + toolbar for the action group designer. + * MonoDevelop.GtkCore.GuiBuilder/ActionGroupView.cs: A view for editing + global action groups. + * MonoDevelop.GtkCore.GuiBuilder/CodeBinder.cs: Moved here some code + from GuiBuilderEditSession.cs. + * MonoDevelop.GtkCore.GuiBuilder/CombinedDesignView.cs: Moved here some + code from GuiBuilderView.cs. + + * Makefile.am: + * MonoDevelop.GtkCore.mdp: Added new files. + + * MonoDevelop.GtkCore.GuiBuilder/GuiBuilderService.cs: Track api changes. + +2006-05-05 Lluis Sanchez Gual <lluis@novell.com> + + * lib/libstetic.dll: Updated from Stetic module. Includes + a fix for bug #78307. + +2006-05-04 Lluis Sanchez Gual <lluis@novell.com> + + * MonoDevelop.GtkCore.addin.xml: Updated versions. + * MonoDevelop.GtkCore.mdp: Updated. + +2006-05-03 Lluis Sanchez Gual <lluis@novell.com> + + * lib/*: Updated from Stetic module. Includes fixes for + bugs #78266, #78240 and #78276. + + * MonoDevelop.GtkCore.GuiBuilder/GuiBuilderWindow.cs: + * MonoDevelop.GtkCore.GuiBuilder/GuiBuilderEditSession.cs: + * MonoDevelop.GtkCore.GuiBuilder/GuiBuilderView.cs: + * MonoDevelop.GtkCore.GuiBuilder/GuiBuilderService.cs: Track changes + in the Stetic API. + +2006-04-24 Lluis Sanchez Gual <lluis@novell.com> + + * MonoDevelop.GtkCore.GuiBuilder/GuiBuilderProject.cs: Don't + crash if a stetic project can't be loaded. Fixes bug #78169. + * lib/libstetic.dll: Updated from Stetic module. Fixes bug #78167. + +2006-04-18 Lluis Sanchez Gual <lluis@novell.com> + + * libs/*: Updated from stetic module. Fixed construction of + scales and scrollbars. + +2006-04-19 Lluis Sanchez Gual <lluis@novell.com> + + * MonoDevelop.GtkCore.WidgetLibrary/ProjectClassDescriptor.cs: When + creating a widget from a widget design, remove the signals since + those signals reference handlers in the widget class, not the + widget container class. + +2006-04-18 Lluis Sanchez Gual <lluis@novell.com> + + * libs/*: Fix nullref in some themes. + +2006-04-10 Lluis Sanchez Gual <lluis@novell.com> + + * MonoDevelop.GtkCore/WidgetFileDescriptionTemplate.cs: Fix typo. + * libs/*: Fix for #78111, #78092 and #78090. + +2006-04-04 Lluis Sanchez Gual <lluis@novell.com> + + * MonoDevelop.GtkCore/ProjectResourceProvider.cs: Save the project + after adding or removing a resource. + +2006-04-03 Lluis Sanchez Gual <lluis@novell.com> + + * lib/*: Updated. + +2006-03-31 Lluis Sanchez Gual <lluis@novell.com> + + * MonoDevelop.GtkCore.GuiBuilder/GuiBuilderService.cs: Get open + combine events in the GUI thread. + * MonoDevelop.GtkCore.GuiBuilder/GuiBuilderEditSession.cs: Properly + delete signals for which there isn't a handler. Half fixed field + renaming. + * lib/*: Updated. + +2006-03-31 Lluis Sanchez Gual <lluis@novell.com> + + * MonoDevelop.GtkCore/MonoDevelop.GtkCore.addin.xml: Fix ID and + description. Added stetic config files to add-in package. + +2006-03-30 Lluis Sanchez Gual <lluis@novell.com> + + * MonoDevelop.GtkCore.addin.xml: Updated references. + +2006-03-29 Lluis Sanchez Gual <lluis@novell.com> + + * MonoDevelop.GtkCore.GuiBuilder/GuiBuilderEditSession.cs: + Don't crash if no parse info is available for the file + being edited. Should fix #77885. + * MonoDevelop.GtkCore.GuiBuilder/GuiBuilderView.cs: Don't show + the bind to field button for the root container. + * lib/*: Updated. + +2006-03-24 Lluis Sanchez Gual <lluis@novell.com> + + * Makefile.am: Use an unified format. Patch by Matze Braun. + * MonoDevelop.GtkCore.addin.xml: Updated add-in versions. + +2006-03-22 Lluis Sanchez Gual <lluis@novell.com> + + * MonoDevelop.GtkCore.addin.xml: + * MonoDevelop.GtkCore.mdp: Removed GladeFileDisplayBinding. + * lib/*: Updated. + * Makefile.am: Updated. Some files have been moved to Stetic. + + * MonoDevelop.GtkCore.GuiBuilder/GuiBuilderService.cs: Fixed + layout switching. Don't show the widget tree pad by default, + since it is already available as a combo in the designer. + * MonoDevelop.GtkCore.GuiBuilder/GladeFileDisplayBinding.cs: Removed. + * MonoDevelop.GtkCore.GuiBuilder/GuiBuilderPropertiesPad.cs: use + the new property tree instead of the grid. + * MonoDevelop.GtkCore.GuiBuilder/GuiBuilderView.cs: The designer + toolbar has been moved to Stetic. + * MonoDevelop.GtkCore.GuiBuilder/GuiBuilderProjectPad.cs: Changed + default placement. + +2006-03-19 Jacob Ilsø Christensen <jacobilsoe@gmail.com> + + * .: Added Makefile.in and Makefile to svn:ignore. + +2006-03-15 Lluis Sanchez Gual <lluis@novell.com> + + * Makefile.am: + * MonoDevelop.GtkCore.mdp: Updated. + + * MonoDevelop.GtkCore.GuiBuilder/GuiBuilderEditSession.cs: + * MonoDevelop.GtkCore/GtkDesignInfo.cs: Added support for using + resource images in the designer. + + * MonoDevelop.GtkCore/GtkCoreService.cs: Check if the objects.xml + file exists before loading it. + * MonoDevelop.GtkCore/GeneratorBuildStep.cs: Don't generate code + if the stetic file has not been modified since the last + generation. + * MonoDevelop.GtkCore.Dialogs/WidgetBuilderOptionPanel.cs: If Gtk + support is not enabled, don't enable it if no widgets have + been selected. + * lib/libstetic.dll: Updated. + * MonoDevelop.GtkCore.GuiBuilder/GuiBuilderView.cs: Mapped some + commands. + * templates/Window.xft.xml: The constructor of Gtk.Window requires + the title of the window. + +2006-03-04 Lluis Sanchez Gual <lluis@novell.com> + + * MonoDevelop.GtkCore.mdp, Makefile.am: Updated. + * MonoDevelop.GtkCore/GeneratorBuildStep.cs: When generating + code for a project that exports widgets, include the own + project library to the generation, since there can be + widgets that contain other widgets defined in the project. + * MonoDevelop.GtkCore.WidgetLibrary/ProjectClassDescriptor.cs: + removed some IdeApp dependencies. + * MonoDevelop.GtkCore.WidgetLibrary/ProjectWidgetLibrary.cs: + added method for getting the class information from + a project. + * CachedProjectWidgetLibrary.cs: New widget library class + which takes class information from a collection of + ProjectClassInfo objects. + * MonoDevelop.GtkCore.WidgetLibrary/ProjectPropertyDescriptor.cs: + Consider all properties runtime-properties, since they have + been created from class properties. + * lib/*: Updated. + +2006-03-03 Lluis Sanchez Gual <lluis@novell.com> + + * Makefile.am: removed debug files. + +2006-03-02 Lluis Sanchez Gual <lluis@novell.com> + + * MonoDevelop.GtkCore.GuiBuilder/GuiBuilderView.cs: Propagate + project changes to the editor. + +2006-03-02 Lluis Sanchez Gual <lluis@novell.com> + + Initial implementation of the Stetic add-in. diff --git a/main/src/addins/MonoDevelop.GtkCore2/libstetic/ClassDescriptor.cs b/main/src/addins/MonoDevelop.GtkCore2/libstetic/ClassDescriptor.cs new file mode 100644 index 0000000000..29a1f9a593 --- /dev/null +++ b/main/src/addins/MonoDevelop.GtkCore2/libstetic/ClassDescriptor.cs @@ -0,0 +1,344 @@ +using System; +using System.Collections; +using System.Reflection; +using System.Runtime.InteropServices; +using System.Xml; + +namespace Stetic { + + + 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 (); + + protected int importantGroups; + protected ItemGroup contextMenu; + protected ItemGroup internalChildren; + protected string baseType; + protected bool isInternal; + protected string targetGtkVersion; + + WidgetLibrary library; + PropertyDescriptor[] initializationProperties; + static PropertyDescriptor[] emptyPropArray = new PropertyDescriptor[0]; + + int counter; + + protected void Load (XmlElement elem) + { + if (elem.HasAttribute ("cname")) + cname = elem.GetAttribute ("cname"); + else if (cname == null) + cname = elem.GetAttribute ("type"); + + label = elem.GetAttribute ("label"); + if (label == "") { + label = WrappedTypeName; + int i = label.LastIndexOf ('.'); + if (i != -1) + label = label.Substring (i+1); + } + + if (elem.HasAttribute ("allow-children")) + allowChildren = elem.GetAttribute ("allow-children") == "yes" || elem.GetAttribute ("allow-children") == "true"; + + category = elem.GetAttribute ("palette-category"); + + if (elem.HasAttribute ("deprecated")) + deprecated = true; + if (elem.HasAttribute ("hexpandable")) + hexpandable = true; + if (elem.HasAttribute ("vexpandable")) + vexpandable = true; + if (elem.GetAttribute ("internal") == "true") + isInternal = true; + + contextMenu = ItemGroup.Empty; + + baseType = elem.GetAttribute ("base-type"); + if (baseType.Length > 0) { + ClassDescriptor basec = Registry.LookupClassByName (baseType); + if (basec == null) + throw new InvalidOperationException ("Base type '" + baseType + "' not found."); + foreach (ItemGroup group in basec.ItemGroups) + groups.Add (group); + foreach (ItemGroup group in basec.SignalGroups) + signals.Add (group); + contextMenu = basec.ContextMenu; + } else + baseType = null; + + XmlElement groupsElem = elem["itemgroups"]; + if (groupsElem != null) { + foreach (XmlElement groupElem in groupsElem.SelectNodes ("itemgroup")) { + ItemGroup itemgroup; + + if (groupElem.HasAttribute ("ref")) { + string refname = groupElem.GetAttribute ("ref"); + itemgroup = Registry.LookupItemGroup (refname); + } else + itemgroup = new ItemGroup (groupElem, this); + groups.Add (itemgroup); + + if (groupElem.HasAttribute ("important")) { + if (groupElem.GetAttribute ("important") == "true") + importantGroups++; + } else if (groups.Count == 1) + importantGroups++; + } + } + + XmlElement signalsElem = elem["signals"]; + if (signalsElem != null) { + foreach (XmlElement groupElem in signalsElem.SelectNodes ("itemgroup")) { + ItemGroup itemgroup; + if (groupElem.HasAttribute ("ref")) { + string refname = groupElem.GetAttribute ("ref"); + itemgroup = Registry.LookupSignalGroup (refname); + } else + itemgroup = new ItemGroup (groupElem, this); + signals.Add (itemgroup); + } + } + + XmlElement contextElem = elem["contextmenu"]; + if (contextElem != null) { + if (contextElem.HasAttribute ("ref")) { + string refname = contextElem.GetAttribute ("ref"); + contextMenu = Registry.LookupContextMenu (refname); + } else + contextMenu = new ItemGroup (contextElem, this); + } + + XmlElement ichildElem = elem["internal-children"]; + if (ichildElem != null) + internalChildren = new ItemGroup (ichildElem, this); + else + internalChildren = ItemGroup.Empty; + + 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)); + } else + initializationProperties = emptyPropArray; + + targetGtkVersion = elem.GetAttribute ("gtk-version"); + if (targetGtkVersion.Length == 0) + targetGtkVersion = null; + } + + public virtual string Name { + get { + return WrappedTypeName; + } + } + + public virtual bool IsInternal { + get { return isInternal; } + } + + public abstract string WrappedTypeName { + get; + } + + public string CName { + get { + return cname; + } + } + + public bool Deprecated { + get { + return deprecated; + } + } + + public bool HExpandable { + get { + return hexpandable; + } + } + + public bool VExpandable { + get { + return vexpandable; + } + } + + public string Label { + get { + return label; + } + } + + public abstract Gdk.Pixbuf Icon { + get; + } + + public string Category { + get { + return category; + } + } + + public virtual string TargetGtkVersion { + get { + if (targetGtkVersion == null) + return library.TargetGtkVersion; + else + return targetGtkVersion; + } + } + + public bool SupportsGtkVersion (string targetVersion) + { + return WidgetUtils.CompareVersions (TargetGtkVersion, targetVersion) >= 0; + } + + public PropertyDescriptor[] InitializationProperties { + get { return initializationProperties; } + } + + public object NewInstance (IProject proj) + { + return NewInstance (proj, true); + } + + public object NewInstance (IProject proj, bool initialize) + { + object ob = CreateInstance (proj); + + string name = WrappedTypeName.ToLower () + (++counter).ToString (); + int i = name.LastIndexOf ('.'); + if (i != -1) { + if (i < name.Length) + name = name.Substring (i+1); + else + name = name.Replace (".", ""); + } + + ObjectWrapper ow = CreateWrapper ();
+ try {
+ ow.Loading = true;
+ ObjectWrapper.Bind (proj, this, ow, ob, !initialize); + + // Initialize the properties after creating the wrapper, since some properties + // may be implemented in the wrapper
+
+ foreach (ItemGroup group in groups) {
+ foreach (ItemDescriptor item in group) {
+ PropertyDescriptor prop = item as PropertyDescriptor;
+ if (prop != null && prop.InitWithName) {
+ prop.SetValue (ob, name);
+ }
+ }
+ }
+ }
+ finally {
+ ow.Loading = false;
+ } + + return ob; + } + + // Sets the default values for an instance + public virtual void ResetInstance (object obj) + { + foreach (ItemGroup group in groups) { + foreach (ItemDescriptor item in group) { + PropertyDescriptor prop = item as PropertyDescriptor; + if (prop != null) { + try { + prop.ResetValue (obj); + } catch (Exception ex) { + // Ignore. ResetInstance should never crash since it can + // leave a widget half initialized + Console.WriteLine (ex); + } + } + } + } + } + + public abstract object CreateInstance (IProject proj); + + public abstract ObjectWrapper CreateWrapper (); + + public ItemDescriptor this[string name] { + get { + if (groups != null) { + foreach (ItemGroup group in groups) { + ItemDescriptor item = group[name]; + if (item != null) + return item; + } + } + + return null; + } + } + + public ItemGroupCollection ItemGroups { + get { + return groups; + } + } + + public ItemGroupCollection SignalGroups { + get { + return signals; + } + } + + public int ImportantGroups { + get { + return importantGroups; + } + } + + public ItemGroup ContextMenu { + get { + return contextMenu; + } + } + + public ItemGroup InternalChildren { + get { + return internalChildren; + } + } + + public WidgetLibrary Library { + get { return library; } + } + + 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); + } + + internal void SetLibrary (WidgetLibrary library) + { + this.library = library; + } + } +} diff --git a/main/src/addins/MonoDevelop.GtkCore2/libstetic/Clipboard.cs b/main/src/addins/MonoDevelop.GtkCore2/libstetic/Clipboard.cs new file mode 100644 index 0000000000..9c27ceec40 --- /dev/null +++ b/main/src/addins/MonoDevelop.GtkCore2/libstetic/Clipboard.cs @@ -0,0 +1,91 @@ +using Gtk; +using System; +using System.Xml; + +namespace Stetic { + + internal static class Clipboard { + + const int SteticType = 0; + const int TextType = 1; + + static Gtk.TargetEntry[] targets; + static Gtk.TargetEntry[] Targets { + get { + if (targets == null) { +#if GTK_SHARP_2_6 + Gtk.TargetList list = new Gtk.TargetList (); + list.Add ((string)WidgetUtils.ApplicationXSteticAtom, 0, SteticType); + list.AddTextTargets (TextType); + targets = (Gtk.TargetEntry[])list; +#else + targets = new Gtk.TargetEntry[] { + new Gtk.TargetEntry ((string)WidgetUtils.ApplicationXSteticAtom, 0, SteticType) + }; +#endif + } + return targets; + } + } + + static Gtk.Clipboard MainClipboard { + get { + return Gtk.Clipboard.Get (Gdk.Selection.Clipboard); + } + } + + static XmlElement selection; + + static void ClipboardGet (Gtk.Clipboard clipboard, Gtk.SelectionData seldata, uint info) + { + if (selection == null) + return; + + if (info == TextType) + seldata.Text = selection.OuterXml; + else + seldata.Set (WidgetUtils.ApplicationXSteticAtom, 8, System.Text.Encoding.UTF8.GetBytes (selection.OuterXml)); + } + + static void ClipboardClear (Gtk.Clipboard clipboard) + { + selection = null; + } + + public static void Copy (Gtk.Widget widget) + { + MainClipboard.SetWithData (Targets, ClipboardGet, ClipboardClear); + selection = widget != null ? WidgetUtils.ExportWidget (widget) : null; + } + + public static void Cut (Gtk.Widget widget) + { + Copy (widget); + Stetic.Wrapper.Widget wrapper = Stetic.Wrapper.Widget.Lookup (widget); + if (wrapper != null) + wrapper.Delete (); + } + + static Placeholder target; + + static void ClipboardPaste (Gtk.Clipboard clipboard, Gtk.SelectionData seldata) + { + Stetic.Wrapper.Container parent = Stetic.Wrapper.Container.LookupParent (target); + if (parent == null) + return; + + Stetic.Wrapper.Widget wrapper = WidgetUtils.Paste (parent.Project, seldata); + if (wrapper == null) + return; + + parent.PasteChild (target, wrapper.Wrapped); + target = null; + } + + public static void Paste (Placeholder target) + { + Clipboard.target = target; + MainClipboard.RequestContents (WidgetUtils.ApplicationXSteticAtom, ClipboardPaste); + } + } +} diff --git a/main/src/addins/MonoDevelop.GtkCore2/libstetic/CommandDescriptor.cs b/main/src/addins/MonoDevelop.GtkCore2/libstetic/CommandDescriptor.cs new file mode 100644 index 0000000000..eadd8b3970 --- /dev/null +++ b/main/src/addins/MonoDevelop.GtkCore2/libstetic/CommandDescriptor.cs @@ -0,0 +1,152 @@ +using System; +using System.Collections; +using System.Reflection; +using System.Xml; + +namespace Stetic { + + public class CommandDescriptor : ItemDescriptor { + + string name, checkName, label, description, icon; + + const BindingFlags flags = BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.Instance; + + public CommandDescriptor (XmlElement elem, ItemGroup group, ClassDescriptor klass) : base (elem, group, klass) + { + name = elem.GetAttribute ("name"); + label = elem.GetAttribute ("label"); + description = elem.GetAttribute ("description"); + checkName = elem.GetAttribute ("check"); + icon = elem.GetAttribute ("icon"); + } + + public override string Name { + get { + return name; + } + } + + public string Label { + get { + return label; + } + } + + public string Description { + get { + return description; + } + } + + public bool IsToggleCommand (object obj) + { + object target; + return (FindBoolProperty (obj, out target) != null); + } + + public bool IsToogled (object obj) + { + object target; + PropertyInfo prop = FindBoolProperty (obj, out target); + return prop != null && (bool) prop.GetValue (target, null); + } + + PropertyInfo FindBoolProperty (object obj, out object target) + { + PropertyInfo prop = obj.GetType().GetProperty (name, flags); + if (prop != null && prop.PropertyType == typeof(bool)) { + target = obj; + return prop; + } + + ObjectWrapper wrap = ObjectWrapper.Lookup (obj); + if (wrap != null) { + prop = wrap.GetType().GetProperty (name, flags); + if (prop != null && prop.PropertyType == typeof(bool)) { + target = wrap; + return prop; + } + } + target = null; + return null; + } + + public Gtk.Image GetImage () + { + if (icon == null || icon.Length == 0) + return null; + if (icon.StartsWith ("res:")) { + System.IO.Stream s = this.ClassDescriptor.Library.GetResource (icon.Substring (4)); + if (s == null) + return null; + using (s) { + Gdk.Pixbuf pixbuf; + try { + pixbuf = new Gdk.Pixbuf (s); + } catch (Exception e) { + Console.WriteLine ("Error while loading pixbuf '" + icon.Substring (4) + "': " + e); + return null; + } + return new Gtk.Image (pixbuf); + } + } else { + return new Gtk.Image (icon, Gtk.IconSize.Menu); + } + } + + public bool Enabled (object obj) + { + if (checkName == "") + return EnabledFor (obj); + else + return (bool) InvokeMethod (ObjectWrapper.Lookup (obj), checkName, null, false); + } + + public bool Enabled (object obj, Gtk.Widget context) + { + if (checkName == "") + return EnabledFor (obj); + + ObjectWrapper wrapper = ObjectWrapper.Lookup (obj); + return (bool) InvokeMethod (wrapper, checkName, context, true); + } + + public void Run (object obj) + { + ObjectWrapper ww = ObjectWrapper.Lookup (obj); + using (ww.UndoManager.AtomicChange) { + InvokeMethod (ww, name, null, false); + } + } + + public void Run (object obj, Gtk.Widget context) + { + ObjectWrapper ww = ObjectWrapper.Lookup (obj); + using (ww.UndoManager.AtomicChange) { + InvokeMethod (ww, name, context, true); + } + } + + object InvokeMethod (object target, string name, object context, bool withContext) + { + object ptarget; + PropertyInfo prop = FindBoolProperty (target, out ptarget); + if (prop != null) { + prop.SetValue (ptarget, !(bool)prop.GetValue (ptarget, null), null); + return null; + } + + 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() + "'"); + } + } +} diff --git a/main/src/addins/MonoDevelop.GtkCore2/libstetic/CustomWidget.cs b/main/src/addins/MonoDevelop.GtkCore2/libstetic/CustomWidget.cs new file mode 100644 index 0000000000..f9f3934343 --- /dev/null +++ b/main/src/addins/MonoDevelop.GtkCore2/libstetic/CustomWidget.cs @@ -0,0 +1,27 @@ + +using System; + +namespace Stetic +{ + // This widget is used at design-time to represent a Gtk.Bin container. + // Gtk.Bin is the base class for custom widgets. + + public class CustomWidget: Gtk.EventBox + { + public CustomWidget (IntPtr ptr): base (ptr) + { + } + + public CustomWidget () + { + this.VisibleWindow = false; + this.Events |= Gdk.EventMask.ButtonPressMask; + } + + protected override bool OnButtonPressEvent (Gdk.EventButton ev) + { + // Avoid forwarding event to parent widget + return true; + } + } +} diff --git a/main/src/addins/MonoDevelop.GtkCore2/libstetic/DND.cs b/main/src/addins/MonoDevelop.GtkCore2/libstetic/DND.cs new file mode 100644 index 0000000000..a1e58fc21a --- /dev/null +++ b/main/src/addins/MonoDevelop.GtkCore2/libstetic/DND.cs @@ -0,0 +1,630 @@ +using System; +using System.Collections; + +namespace Stetic { + + public static class DND { + static Gtk.TargetEntry[] targets; + static Gtk.TargetList targetList; + static Gdk.Atom steticWidgetType; + static Gdk.Pixbuf widgetIcon; + + const int SteticType = 0; + const int GladeType = 1; + + static DND () + { + try { + widgetIcon = Gdk.Pixbuf.LoadFromResource ("widget.png"); + } catch (Exception e) { + Console.WriteLine ("Error while loading pixbuf 'widget.png': " + e); + } + + steticWidgetType = Gdk.Atom.Intern ("application/x-stetic-widget", false); + + targets = new Gtk.TargetEntry[2]; + targets[0] = new Gtk.TargetEntry (steticWidgetType, 0, SteticType); + targets[1] = new Gtk.TargetEntry ((string) GladeUtils.ApplicationXGladeAtom, 0, GladeType); + + targetList = new Gtk.TargetList (targets); + targets = (Gtk.TargetEntry[]) targetList; + } + + public static Gtk.TargetEntry[] Targets { + get { return targets; } + } + + public static void SourceSet (Gtk.Widget source) + { + Gtk.Drag.SourceSet (source, Gdk.ModifierType.Button1Mask, + targets, Gdk.DragAction.Move); + } + + public static void SourceUnset (Gtk.Widget source) + { + Gtk.Drag.SourceUnset (source); + } + + public static void DestSet (Gtk.Widget dest, bool automatic) + { + Gtk.Drag.DestSet (dest, automatic ? Gtk.DestDefaults.All : 0, + targets, Gdk.DragAction.Move | Gdk.DragAction.Copy); + } + + public static void DestUnset (Gtk.Widget dest) + { + Gtk.Drag.DestUnset (dest); + } + + static Gtk.Widget dragWidget; + static WidgetDropCallback dropCallback; + static int dragHotX; + static int dragHotY; + + // Drag function for non-automatic sources, called from MotionNotifyEvent + public static void Drag (Gtk.Widget source, Gdk.Event evt, Gtk.Widget dragWidget) + { + Gdk.DragContext ctx; + + ctx = Gtk.Drag.Begin (source, targetList, Gdk.DragAction.Move, + 1 /* button */, evt); + Drag (source, ctx, dragWidget); + } + + // Drag function for automatic sources, called from DragBegin + public static void Drag (Gtk.Widget source, Gdk.DragContext ctx, WidgetDropCallback dropCallback, string label) + { + Gtk.Frame fr = new Gtk.Frame (); + fr.ShadowType = Gtk.ShadowType.Out; + Gtk.HBox box = new Gtk.HBox (); + box.Spacing = 3; + box.BorderWidth = 3; + box.PackStart (new Gtk.Image (widgetIcon), false, false, 0); + Gtk.Label lab = new Gtk.Label (label); + lab.Xalign = 0; + box.PackStart (lab, true, true, 0); + fr.Add (box); + fr.ShowAll (); + Drag (source, ctx, dropCallback, fr); + } + + // Drag function for automatic sources, called from DragBegin + public static void Drag (Gtk.Widget source, Gdk.DragContext ctx, Gtk.Widget dragWidget) + { + Drag (source, ctx, null, dragWidget); + } + + // Drag function for automatic sources, called from DragBegin + static void Drag (Gtk.Widget source, Gdk.DragContext ctx, WidgetDropCallback dropCallback, Gtk.Widget dragWidget) + { + if (ctx == null) + return; + + Gtk.Window dragWin; + Gtk.Requisition req; + + ShowFaults (); + DND.dragWidget = dragWidget; + DND.dropCallback = dropCallback; + + dragWin = new Gtk.Window (Gtk.WindowType.Popup); + dragWin.Add (dragWidget); + + req = dragWidget.SizeRequest (); + if (req.Width < 20 && req.Height < 20) + dragWin.SetSizeRequest (20, 20); + else if (req.Width < 20) + dragWin.SetSizeRequest (20, -1); + else if (req.Height < 20) + dragWin.SetSizeRequest (-1, 20); + + req = dragWin.SizeRequest (); + + int px, py, rx, ry; + Gdk.ModifierType pmask; + ctx.SourceWindow.GetPointer (out px, out py, out pmask); + ctx.SourceWindow.GetRootOrigin (out rx, out ry); + + dragWin.Move (rx + px, ry + py); + dragWin.Show (); + + dragHotX = req.Width / 2; + dragHotY = -3; + + Gtk.Drag.SetIconWidget (ctx, dragWin, dragHotX, dragHotY); + + if (source != null) { + source.DragDataGet += DragDataGet; + source.DragEnd += DragEnded; + } + } + + public static Gtk.Widget DragWidget { + get { + return dragWidget; + } + } + + public static int DragHotX { + get { + return dragHotX; + } + } + + public static int DragHotY { + get { + return dragHotY; + } + } + + // Call this from a DragDrop event to receive the dragged widget + public static void Drop (Gdk.DragContext ctx, uint time, ObjectWrapper targetWrapper, string dropData) + { + if (dropCallback == null) { + Gtk.Widget w = Drop (ctx, (Gtk.Widget) targetWrapper.Wrapped, time); + targetWrapper.DropObject (dropData, w); + return; + } + + Cancel (); + Gtk.Drag.Finish (ctx, true, true, time); + + Gtk.Application.Invoke (delegate { + IProject project = targetWrapper.Project; + string uid = targetWrapper.UndoId; + string tname = ((Wrapper.Widget)targetWrapper).GetTopLevel ().Wrapped.Name; + + // This call may cause the project to be reloaded + dragWidget = dropCallback (); + if (dragWidget == null) + return; + + if (targetWrapper.IsDisposed) { + // The project has been reloaded. Find the wrapper again. + Gtk.Widget twidget = project.GetWidget (tname); + ObjectWrapper ow = ObjectWrapper.Lookup (twidget); + if (ow != null) + targetWrapper = ow.FindObjectByUndoId (uid); + else + targetWrapper = null; + + if (targetWrapper == null) { + // Target wrapper not found. Just ignore the drop. + return; + } + } + + targetWrapper.DropObject (dropData, dragWidget); + }); + } + + public static Gtk.Widget Drop (Gdk.DragContext ctx, Gtk.Widget target, uint time) + { + if (dropCallback != null) { + dragWidget = dropCallback (); + } + + if (dragWidget == null) { + Gtk.Drag.GetData (target, ctx, GladeUtils.ApplicationXGladeAtom, time); + return null; + } + + Gtk.Widget w = Cancel (); + Gtk.Drag.Finish (ctx, true, true, time); + return w; + } + + // Call this from a DragEnd event to check if the widget wasn't dropped + public static Gtk.Widget Cancel () + { + if (dragWidget == null) + return null; + + Gtk.Widget w = dragWidget; + dragWidget = null; + + // Remove the widget from its dragWindow + Gtk.Container parent = w.Parent as Gtk.Container; + if (parent != null) { + parent.Remove (w); + parent.Destroy (); + } + return w; + } + + static void DragEnded (object obj, Gtk.DragEndArgs args) + { + dragWidget = null; + HideFaults (); + + ((Gtk.Widget)obj).DragEnd -= DragEnded; + ((Gtk.Widget)obj).DragDataGet -= DragDataGet; + } + + static void DragDataGet (object obj, Gtk.DragDataGetArgs args) + { + if (args.Info == GladeType) { + Gtk.Widget w = Cancel (); + if (w != null) + WidgetUtils.Copy (w, args.SelectionData, false); + } + } + + class Fault { + public Stetic.Wrapper.Widget Owner; + public object Id; + public Gtk.Orientation Orientation; + public Gdk.Window Window; + + public Fault (Stetic.Wrapper.Widget owner, object id, + Gtk.Orientation orientation, Gdk.Window window) + { + Owner = owner; + Id = id; + Orientation = orientation; + Window = window; + } + } + + static Hashtable faultGroups = new Hashtable (); + const int FaultOverlap = 3; + + public static void AddFault (Stetic.Wrapper.Widget owner, object faultId, + Gtk.Orientation orientation, Gdk.Rectangle fault) + { + AddFault (owner, faultId, orientation, + fault.X, fault.Y, fault.Width, fault.Height); + } + + public static void AddFault (Stetic.Wrapper.Widget owner, object faultId, + Gtk.Orientation orientation, + int x, int y, int width, int height) + { + Gtk.Widget widget = owner.Wrapped; + if (!widget.IsRealized) + return; + + Gdk.Window win = NewWindow (widget, Gdk.WindowClass.InputOnly); + win.MoveResize (x, y, width, height); + + Hashtable widgetFaults = faultGroups[widget] as Hashtable; + if (widgetFaults == null) { + faultGroups[widget] = widgetFaults = new Hashtable (); + widget.Destroyed += FaultWidgetDestroyed; + widget.DragMotion += FaultDragMotion; + widget.DragLeave += FaultDragLeave; + widget.DragDrop += FaultDragDrop; + widget.DragDataReceived += FaultDragDataReceived; + DND.DestSet (widget, false); + } + widgetFaults[win] = new Fault (owner, faultId, orientation, win); + } + + public static void AddFault (Stetic.Wrapper.Widget owner, object faultId, + Gtk.Orientation orientation, + Gtk.Widget before, Gtk.Widget after) + { + if (orientation == Gtk.Orientation.Horizontal) + AddHFault (owner, faultId, before, after); + else + AddVFault (owner, faultId, before, after); + } + + public static void AddHFault (Stetic.Wrapper.Widget owner, object faultId, + Gtk.Widget above, Gtk.Widget below) + { + Gtk.Widget widget = owner.Wrapped; + if (!widget.IsRealized) + return; + + Gdk.Rectangle aboveAlloc, belowAlloc; + int x1, y1, x2, y2; + + if (above != null && below != null) { + aboveAlloc = above.Allocation; + belowAlloc = below.Allocation; + + x1 = Math.Min (aboveAlloc.X, belowAlloc.X); + x2 = Math.Max (aboveAlloc.X + aboveAlloc.Width, belowAlloc.X + belowAlloc.Width); + y1 = aboveAlloc.Y + aboveAlloc.Height; + y2 = belowAlloc.Y; + + while (y2 - y1 < FaultOverlap * 2) { + y1--; + y2++; + } + } else if (above == null) { + belowAlloc = below.Allocation; + + x1 = belowAlloc.X; + x2 = belowAlloc.X + belowAlloc.Width; + y1 = 0; + y2 = Math.Max (belowAlloc.Y, FaultOverlap); + } else { + aboveAlloc = above.Allocation; + + x1 = aboveAlloc.X; + x2 = aboveAlloc.X + aboveAlloc.Width; + y1 = Math.Min (aboveAlloc.Y + aboveAlloc.Height, widget.Allocation.Height - FaultOverlap); + y2 = widget.Allocation.Height; + } + + AddFault (owner, faultId, Gtk.Orientation.Horizontal, + x1, y1, x2 - x1, y2 - y1); + } + + public static void AddVFault (Stetic.Wrapper.Widget owner, object faultId, + Gtk.Widget left, Gtk.Widget right) + { + Gtk.Widget widget = owner.Wrapped; + if (!widget.IsRealized) + return; + + Gdk.Rectangle leftAlloc, rightAlloc; + int x1, y1, x2, y2; + + if (left != null && right != null) { + leftAlloc = left.Allocation; + rightAlloc = right.Allocation; + + x1 = leftAlloc.X + leftAlloc.Width; + x2 = rightAlloc.X; + + y1 = Math.Min (leftAlloc.Y, rightAlloc.Y); + y2 = Math.Max (leftAlloc.Y + leftAlloc.Height, rightAlloc.Y + rightAlloc.Height); + + while (x2 - x1 < FaultOverlap * 2) { + x1--; + x2++; + } + } else if (left == null) { + rightAlloc = right.Allocation; + + x1 = 0; + x2 = Math.Max (rightAlloc.X, FaultOverlap); + + y1 = rightAlloc.Y; + y2 = rightAlloc.Y + rightAlloc.Height; + } else { + leftAlloc = left.Allocation; + + x1 = Math.Min (leftAlloc.X + leftAlloc.Width, widget.Allocation.Width - FaultOverlap); + x2 = widget.Allocation.Width; + + y1 = leftAlloc.Y; + y2 = leftAlloc.Y + leftAlloc.Height; + } + + AddFault (owner, faultId, Gtk.Orientation.Vertical, + x1, y1, x2 - x1, y2 - y1); + } + + public static void AddFault (Stetic.Wrapper.Widget owner, object faultId, + Gtk.SideType side, Gtk.Widget widget) + { + Gdk.Rectangle fault; + Gtk.Orientation orientation; + + if (widget == null) { + fault = owner.Wrapped.Allocation; + int border = (int)((Gtk.Container)owner.Wrapped).BorderWidth; + fault.Inflate (-border, -border); + } else + fault = widget.Allocation; + + switch (side) { + case Gtk.SideType.Top: + fault.Y -= FaultOverlap; + fault.Height = 2 * FaultOverlap; + orientation = Gtk.Orientation.Horizontal; + break; + case Gtk.SideType.Bottom: + fault.Y += fault.Height - FaultOverlap; + fault.Height = 2 * FaultOverlap; + orientation = Gtk.Orientation.Horizontal; + break; + case Gtk.SideType.Left: + fault.X -= FaultOverlap; + fault.Width = 2 * FaultOverlap; + orientation = Gtk.Orientation.Vertical; + break; + case Gtk.SideType.Right: + fault.X += fault.Width - FaultOverlap; + fault.Width = 2 *FaultOverlap; + orientation = Gtk.Orientation.Vertical; + break; + default: + throw new Exception ("not reached"); + } + + AddFault (owner, faultId, orientation, fault); + } + + static void FaultWidgetDestroyed (object widget, EventArgs args) + { + ClearFaults ((Gtk.Widget)widget); + } + + public static void ClearFaults (Stetic.Wrapper.Widget owner) + { + ClearFaults (owner.Wrapped); + } + + static void ClearFaults (Gtk.Widget widget) + { + Hashtable widgetFaults = faultGroups[widget] as Hashtable; + if (widgetFaults == null) + return; + faultGroups.Remove (widget); + + foreach (Gdk.Window win in widgetFaults.Keys) + win.Destroy (); + widgetFaults.Clear (); + DND.DestUnset (widget); + } + + static void ShowFaults () + { + foreach (Hashtable widgetFaults in faultGroups.Values) { + foreach (Gdk.Window win in widgetFaults.Keys) + win.Show (); + } + } + + static void HideFaults () + { + foreach (Hashtable widgetFaults in faultGroups.Values) { + foreach (Gdk.Window win in widgetFaults.Keys) + win.Hide (); + } + DestroySplitter (); + dragFault = null; + } + + static Fault dragFault; + static Gdk.Window splitter; + + static void DestroySplitter () + { + if (splitter != null) { + splitter.Hide (); + splitter.Destroy (); + splitter = null; + } + } + + static Fault FindFault (int x, int y, Gtk.Widget w) + { + int wx, wy, width, height, depth; + + Hashtable widgetFaults = (Hashtable) faultGroups [w]; + if (widgetFaults == null) + return null; + + foreach (Fault f in widgetFaults.Values) { + f.Window.GetGeometry (out wx, out wy, out width, out height, out depth); + if (x >= wx && y >= wy && x <= wx + width && y <= wy + height) { + return f; + } + } + return null; + } + + static void FaultDragMotion (object obj, Gtk.DragMotionArgs args) + { + int wx, wy, width, height, depth; + + Gtk.Widget widget = (Gtk.Widget) obj; + int px = args.X + widget.Allocation.X; + int py = args.Y + widget.Allocation.Y; + + Fault fault = FindFault (px, py, widget); + + // If there's a splitter visible, and we're not currently dragging + // in the fault that owns that splitter, hide it + if (splitter != null && dragFault != fault) + DestroySplitter (); + + if (dragFault != fault) { + dragFault = fault; + if (dragFault == null) + return; + + splitter = NewWindow (fault.Owner.Wrapped, Gdk.WindowClass.InputOutput); + fault.Window.GetGeometry (out wx, out wy, out width, out height, out depth); + if (fault.Orientation == Gtk.Orientation.Horizontal) { + splitter.MoveResize (wx, wy + height / 2 - FaultOverlap, + width, 2 * FaultOverlap); + } else { + splitter.MoveResize (wx + width / 2 - FaultOverlap, wy, + 2 * FaultOverlap, height); + } + splitter.ShowUnraised (); + fault.Window.Lower (); + } else if (dragFault == null) + return; + + Gdk.Drag.Status (args.Context, Gdk.DragAction.Move, args.Time); + args.RetVal = true; + } + + static void FaultDragLeave (object obj, Gtk.DragLeaveArgs args) + { + DestroySplitter (); + dragFault = null; + } + + static void FaultDrop (Stetic.Wrapper.Widget wrapper, int x, int y, Gtk.Widget targetWidget) + { + Fault fault = FindFault (x, y, targetWidget); + if (fault != null) { + fault.Owner.Drop (wrapper.Wrapped, fault.Id); + wrapper.Select (); + } + } + + static void FaultDragDrop (object obj, Gtk.DragDropArgs args) + { + Gtk.Widget w = DND.Drop (args.Context, (Gtk.Widget)obj, args.Time); + Stetic.Wrapper.Widget dropped = Stetic.Wrapper.Widget.Lookup (w); + if (dropped != null) { + Gtk.Widget targetWidget = (Gtk.Widget) obj; + int px = args.X + targetWidget.Allocation.X; + int py = args.Y + targetWidget.Allocation.Y; + + FaultDrop (dropped, px, py, targetWidget); + args.RetVal = true; + } + } + + static void FaultDragDataReceived (object obj, Gtk.DragDataReceivedArgs args) + { + Stetic.Wrapper.Widget dropped = null; + + Stetic.Wrapper.Widget faultOwner = Stetic.Wrapper.Widget.Lookup ((Gtk.Widget)obj); + if (faultOwner != null) + dropped = WidgetUtils.Paste (faultOwner.Project, args.SelectionData); + Gtk.Drag.Finish (args.Context, dropped != null, + dropped != null, args.Time); + if (dropped != null) { + Gtk.Widget targetWidget = (Gtk.Widget) obj; + int px = args.X + targetWidget.Allocation.X; + int py = args.Y + targetWidget.Allocation.Y; + FaultDrop (dropped, px, py, targetWidget); + } + } + + static Gdk.Window NewWindow (Gtk.Widget parent, Gdk.WindowClass wclass) + { + Gdk.WindowAttr attributes; + Gdk.WindowAttributesType attributesMask; + Gdk.Window win; + + attributes = new Gdk.WindowAttr (); + attributes.WindowType = Gdk.WindowType.Child; + attributes.Wclass = wclass ; + attributes.Visual = parent.Visual; + attributes.Colormap = parent.Colormap; + attributes.Mask = (Gdk.EventMask.ButtonPressMask | + Gdk.EventMask.ButtonMotionMask | + Gdk.EventMask.ButtonReleaseMask | + Gdk.EventMask.ExposureMask | + Gdk.EventMask.EnterNotifyMask | + Gdk.EventMask.LeaveNotifyMask); + + attributesMask = + Gdk.WindowAttributesType.Visual | + Gdk.WindowAttributesType.Colormap; + + win = new Gdk.Window (parent.GdkWindow, attributes, attributesMask); + win.UserData = parent.Handle; + + if (wclass == Gdk.WindowClass.InputOutput) + parent.Style.Attach (win); + + return win; + } + } + + public delegate Gtk.Widget WidgetDropCallback (); +} diff --git a/main/src/addins/MonoDevelop.GtkCore2/libstetic/EnumDescriptor.cs b/main/src/addins/MonoDevelop.GtkCore2/libstetic/EnumDescriptor.cs new file mode 100644 index 0000000000..79ee48b3c9 --- /dev/null +++ b/main/src/addins/MonoDevelop.GtkCore2/libstetic/EnumDescriptor.cs @@ -0,0 +1,86 @@ +using System; +using System.Collections; +using System.Reflection; +using System.Xml; + +namespace Stetic { + public class EnumValue { + public Enum Value; + public string Label; + public string Description; + + internal EnumValue (Enum value, string label, string description) + { + Value = value; + Label = label; + Description = description; + } + } + + public class EnumDescriptor { + + Type enumType; + Hashtable values; + Enum[] values_array; + string name; + + public EnumDescriptor (XmlElement elem) + { + string cls = elem.GetAttribute ("type"); + enumType = Registry.GetType (cls, true); + this.name = enumType.FullName; + + values = new Hashtable (); + + // This gets the list of enum names and gets the value of each of them. + // This is not done the other way (get the values, and then the names from them) + // because it won't work if two different enum members have the same value + ArrayList list = new ArrayList (); + Hashtable evalues = new Hashtable (); + foreach (string name in Enum.GetNames (enumType)) { + object value = Enum.Parse (enumType, name); + list.Add (value); + evalues[name] = value; + } + + foreach (XmlElement valueElem in elem.SelectNodes ("value")) { + string name = valueElem.GetAttribute ("name"); + if (!evalues.Contains (name)) + throw new ArgumentException ("<enum> node for " + enumType.FullName + " contains extra element " + name); + Enum value = (Enum)evalues[name]; + values[value] = new EnumValue (value, + valueElem.GetAttribute ("label"), + valueElem.GetAttribute ("description")); + evalues.Remove (name); + } + + // Remove from the array the values not declared in the xml file + foreach (object val in evalues.Values) + list.Remove (val); + + values_array = (Enum[]) list.ToArray (typeof(Enum)); + } + + public string Name { + get { return name; } + } + + public Type EnumType { + get { + return enumType; + } + } + + public Enum[] Values { + get { + return values_array; + } + } + + public EnumValue this[Enum value] { + get { + return (EnumValue)values[value]; + } + } + } +} diff --git a/main/src/addins/MonoDevelop.GtkCore2/libstetic/ErrorWidget.cs b/main/src/addins/MonoDevelop.GtkCore2/libstetic/ErrorWidget.cs new file mode 100644 index 0000000000..82ec4ecc50 --- /dev/null +++ b/main/src/addins/MonoDevelop.GtkCore2/libstetic/ErrorWidget.cs @@ -0,0 +1,111 @@ +using System; +using System.Xml; +using System.CodeDom; +using Mono.Unix; + +namespace Stetic +{ + // This widget is shown in place of widgets with unknown classes. + + public class ErrorWidget: Gtk.Frame + { + readonly string className; + readonly Exception exc; + + public ErrorWidget (Exception ex, string id) + { + exc = ex; + Init (Catalog.GetString ("Load Error:") + " " + ex.Message, id); + } + + public ErrorWidget (string className, string id) + { + this.className = className; + Init (Catalog.GetString ("Unknown widget:") + " " + className, id); + } + + public ErrorWidget (string className, string minGtkVersion, string foundGtkVersion, string id) + { + this.className = className; + Init (string.Format (Catalog.GetString ("Widget '{0}' not available in GTK# {1}"), className, foundGtkVersion), id); + } + + void Init (string message, string id) + { + Gtk.Label lab = new Gtk.Label (); + lab.Markup = "<b><span foreground='red'>" + message + "</span></b>"; + this.CanFocus = false; + Add (lab); + this.ShadowType = Gtk.ShadowType.In; + ShowAll (); + if (id != null && id.Length > 0) + Name = id; + } + + public string ClassName { + get { return className; } + } + + public Exception Exception { + get { return exc; } + } + } + + internal class ErrorWidgetWrapper: Wrapper.Widget + { + XmlElement elementData; + FileFormat format; + + public override void Read (ObjectReader reader, XmlElement elem) + { + elementData = elem; + this.format = reader.Format; + } + + public override XmlElement Write (ObjectWriter writer) + { + if (writer.Format != this.format) { + ErrorWidget ew = (ErrorWidget) Wrapped; + XmlElement elem = writer.XmlDocument.CreateElement ("widget"); + elem.SetAttribute ("class", "Gtk.Label"); + elem.SetAttribute ("id", Wrapped.Name); + XmlElement ce = writer.XmlDocument.CreateElement ("property"); + string msg; + if (ew.Exception != null) + msg = "Invalid widget"; + else + msg = "Unknown widget: " + ew.ClassName; + ce.SetAttribute ("name", "LabelProp"); + ce.InnerText = msg; + elem.AppendChild (ce); + return elem; + } + else + return (XmlElement) writer.XmlDocument.ImportNode (elementData, true); + } + + public override string WrappedTypeName { + get { + ErrorWidget ew = (ErrorWidget) Wrapped; + return ew.ClassName; + } + } + + internal protected override CodeExpression GenerateObjectCreation (GeneratorContext ctx) + { + ErrorWidget ew = (ErrorWidget) Wrapped; + string msg; + if (ew.Exception != null) + msg = Project.FolderName + ": Could not generate code for an invalid widget. The widget failed to load: " + ew.Exception.Message + ". The generated code may be invalid."; + else + msg = Project.FolderName + ": Could not generate code for widgets of type: " + ew.ClassName + ". The widget could not be found in any referenced library. The generated code may be invalid."; + + if (ctx.Options.FailForUnknownWidgets) { + throw new InvalidOperationException (msg); + } else { + ctx.ReportWarning (msg); + return new CodePrimitiveExpression (null); + } + } + } +} diff --git a/main/src/addins/MonoDevelop.GtkCore2/libstetic/GeneratorContext.cs b/main/src/addins/MonoDevelop.GtkCore2/libstetic/GeneratorContext.cs new file mode 100644 index 0000000000..65b6daa416 --- /dev/null +++ b/main/src/addins/MonoDevelop.GtkCore2/libstetic/GeneratorContext.cs @@ -0,0 +1,546 @@ +using System; +using System.CodeDom; +using System.Collections; + +namespace Stetic +{ + public class GeneratorContext + { + CodeNamespace cns; + int n; + string idPrefix; + Hashtable vars = new Hashtable (); + ArrayList generatedWrappers = new ArrayList (); + WidgetMap map; + CodeStatementCollection statements; + GenerationOptions options; + ArrayList warnings = new ArrayList (); + CodeExpression rootObject; + + public GeneratorContext (CodeNamespace cns, string idPrefix, CodeStatementCollection statements, GenerationOptions options) + { + this.cns = cns; + this.idPrefix = idPrefix; + this.statements = statements; + this.options = options; + map = new WidgetMap (vars); + } + + public CodeNamespace GlobalCodeNamespace { + get { return cns; } + } + + public CodeStatementCollection Statements { + get { return statements; } + } + + public GenerationOptions Options { + get { return options; } + } + + public string[] Warnings { + get { return (string[]) warnings.ToArray (typeof(string)); } + } + + public void ReportWarning (string s) + { + warnings.Add (s); + } + + public string NewId () + { + return idPrefix + (++n); + } + + public CodeExpression GenerateNewInstanceCode (Wrapper.Widget widget) + { + CodeExpression exp = widget.GenerateObjectCreation (this); + CodeExpression var = GenerateInstanceExpression (widget, exp); + GenerateBuildCode (widget, var); + return var; + } + + public virtual CodeExpression GenerateInstanceExpression (ObjectWrapper wrapper, CodeExpression newObject) + { + string varName = NewId (); + CodeVariableDeclarationStatement varDec = new CodeVariableDeclarationStatement (wrapper.WrappedTypeName.ToGlobalTypeRef (), varName); + varDec.InitExpression = newObject; + statements.Add (varDec); + return new CodeVariableReferenceExpression (varName); + } + + public virtual void GenerateCreationCode (ObjectWrapper wrapper, CodeExpression varExp) + { + rootObject = varExp; + wrapper.GenerateInitCode (this, varExp); + GenerateBuildCode (wrapper, varExp); + } + + public virtual void GenerateBuildCode (ObjectWrapper wrapper, CodeExpression var) + { + vars [wrapper] = var; + wrapper.GenerateBuildCode (this, var); + generatedWrappers.Add (wrapper); + } + + public virtual void GenerateCreationCode (Wrapper.ActionGroup agroup, CodeExpression var) + { + rootObject = var; + vars [agroup] = var; + agroup.GenerateBuildCode (this, var); + } + + public CodeExpression GenerateValue (object value, Type type) + { + return GenerateValue (value, type, false); + } + + public CodeExpression GenerateValue (object value, Type type, bool translatable) + { + if (value == null) + return new CodePrimitiveExpression (value); + + if (value.GetType ().IsEnum) { + if (!type.IsEnum) { + object ival = Convert.ChangeType (value, type); + return new CodePrimitiveExpression (ival); + } else { + long ival = (long) Convert.ChangeType (value, typeof(long)); + return new CodeCastExpression ( + value.GetType ().ToGlobalTypeRef (), + new CodePrimitiveExpression (ival) + ); + } + } + + if (value is Gtk.Adjustment) { + Gtk.Adjustment adj = value as Gtk.Adjustment; + return new CodeObjectCreateExpression ( + typeof(Gtk.Adjustment).ToGlobalTypeRef (), + 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 ( + value.GetType ().ToGlobalTypeRef (), + new CodePrimitiveExpression (Convert.ChangeType (value, typeof(long)))); + } + if (value is ulong) { + return new CodeMethodInvokeExpression ( + new CodeTypeReferenceExpression (value.GetType ()), + "Parse", + new CodePrimitiveExpression (value.ToString ())); + } + + if (value is ImageInfo && typeof(Gdk.Pixbuf).IsAssignableFrom (type)) + return ((ImageInfo)value).ToCodeExpression (this); + + if (value is Wrapper.ActionGroup) { + return new CodeMethodInvokeExpression ( + new CodeMethodReferenceExpression ( + new CodeTypeReferenceExpression (new CodeTypeReference (GlobalCodeNamespace.Name + ".ActionGroups", CodeTypeReferenceOptions.GlobalReference)), + "GetActionGroup" + ), + new CodePrimitiveExpression (((Wrapper.ActionGroup)value).Name) + ); + } + + if (value is Array) { + ArrayList list = new ArrayList (); + foreach (object val in (Array)value) + list.Add (GenerateValue (val, val != null ? val.GetType() : null, translatable)); + return new CodeArrayCreateExpression (value.GetType().GetElementType(), (CodeExpression[]) list.ToArray(typeof(CodeExpression))); + } + + if (value is DateTime) { + return new CodeObjectCreateExpression ( + typeof(DateTime).ToGlobalTypeRef (), + new CodePrimitiveExpression (((DateTime)value).Ticks) + ); + } + + if (value is TimeSpan) { + return new CodeObjectCreateExpression ( + typeof(TimeSpan).ToGlobalTypeRef (), + new CodePrimitiveExpression (((TimeSpan)value).Ticks) + ); + } + + string str = value as string; + if (translatable && str != null && str.Length > 0 && options.UseGettext) { + return new CodeMethodInvokeExpression ( + new CodeTypeReferenceExpression (new CodeTypeReference (options.GettextClass, CodeTypeReferenceOptions.GlobalReference)), + "GetString", + new CodePrimitiveExpression (str) + ); + } + + return new CodePrimitiveExpression (value); + } + + public WidgetMap WidgetMap { + get { return map; } + } + + public System.CodeDom.CodeExpression RootObject { + get { + return rootObject; + } + set { + rootObject = value; + } + } + + public void EndGeneration () + { + foreach (ObjectWrapper w in generatedWrappers) { + CodeExpression var = (CodeExpression) vars [w]; + w.GeneratePostBuildCode (this, var); + } + } + + public void Reset () + { + vars.Clear (); + generatedWrappers.Clear (); + map = new WidgetMap (vars); + n = 0; + } + + public CodeExpression GenerateLoadPixbuf (string name, Gtk.IconSize size) + { + bool found = false; + foreach (CodeTypeDeclaration t in cns.Types) { + if (t.Name == "IconLoader") { + found = true; + break; + } + } + + if (!found) + { + CodeTypeDeclaration cls = new CodeTypeDeclaration ("IconLoader"); + cls.Attributes = MemberAttributes.Private; + cls.TypeAttributes = System.Reflection.TypeAttributes.NestedAssembly; + cns.Types.Add (cls); + + CodeMemberMethod met = new CodeMemberMethod (); + cls.Members.Add (met); + met.Attributes = MemberAttributes.Public | MemberAttributes.Static; + met.Name = "LoadIcon"; + met.Parameters.Add (new CodeParameterDeclarationExpression (typeof(Gtk.Widget), "widget")); + met.Parameters.Add (new CodeParameterDeclarationExpression (typeof(string), "name")); + met.Parameters.Add (new CodeParameterDeclarationExpression (typeof(Gtk.IconSize), "size")); + met.ReturnType = new CodeTypeReference (typeof(Gdk.Pixbuf)); + + CodeExpression widgetExp = new CodeVariableReferenceExpression ("widget"); + CodeExpression nameExp = new CodeVariableReferenceExpression ("name"); + CodeExpression sizeExp = new CodeVariableReferenceExpression ("size"); + CodeExpression szExp = new CodeVariableReferenceExpression ("sz"); + CodeExpression mgExp = new CodeBinaryOperatorExpression (szExp, CodeBinaryOperatorType.Divide, new CodePrimitiveExpression (4)); + CodeExpression pmapExp = new CodeVariableReferenceExpression ("pmap"); + CodeExpression gcExp = new CodeVariableReferenceExpression ("gc"); + CodeExpression szM1Exp = new CodeBinaryOperatorExpression (szExp, CodeBinaryOperatorType.Subtract, new CodePrimitiveExpression (1)); + CodeExpression zeroExp = new CodePrimitiveExpression (0); + CodeExpression resExp = new CodeVariableReferenceExpression ("res"); + + met.Statements.Add ( + new CodeVariableDeclarationStatement (typeof(Gdk.Pixbuf), "res", + new CodeMethodInvokeExpression ( + widgetExp, + "RenderIcon", + nameExp, + sizeExp, + new CodePrimitiveExpression (null) + ) + ) + ); + + CodeConditionStatement nullcheck = new CodeConditionStatement (); + met.Statements.Add (nullcheck); + nullcheck.Condition = new CodeBinaryOperatorExpression ( + resExp, + CodeBinaryOperatorType.IdentityInequality, + new CodePrimitiveExpression (null) + ); + nullcheck.TrueStatements.Add (new CodeMethodReturnStatement (resExp)); + + // int sz, h; + // Gtk.Icon.SizeLookup (size, out sz, out h); + + nullcheck.FalseStatements.Add (new CodeVariableDeclarationStatement (typeof(int), "sz")); + nullcheck.FalseStatements.Add (new CodeVariableDeclarationStatement (typeof(int), "sy")); + nullcheck.FalseStatements.Add (new CodeMethodInvokeExpression ( + new CodeTypeReferenceExpression (typeof(Gtk.Icon).ToGlobalTypeRef ()), + "SizeLookup", + sizeExp, + new CodeDirectionExpression (FieldDirection.Out, szExp), + new CodeDirectionExpression (FieldDirection.Out, new CodeVariableReferenceExpression ("sy")) + )); + + CodeTryCatchFinallyStatement trycatch = new CodeTryCatchFinallyStatement (); + nullcheck.FalseStatements.Add (trycatch); + trycatch.TryStatements.Add ( + new CodeMethodReturnStatement ( + new CodeMethodInvokeExpression ( + new CodePropertyReferenceExpression ( + new CodeTypeReferenceExpression (new CodeTypeReference (typeof(Gtk.IconTheme))), + "Default" + ), + "LoadIcon", + nameExp, + szExp, + zeroExp + ) + ) + ); + + CodeCatchClause ccatch = new CodeCatchClause (); + trycatch.CatchClauses.Add (ccatch); + + CodeConditionStatement cond = new CodeConditionStatement (); + ccatch.Statements.Add (cond); + + cond.Condition = new CodeBinaryOperatorExpression ( + nameExp, + CodeBinaryOperatorType.IdentityInequality, + new CodePrimitiveExpression ("gtk-missing-image") + ); + + cond.TrueStatements.Add ( + new CodeMethodReturnStatement ( + new CodeMethodInvokeExpression ( + new CodeTypeReferenceExpression (cns.Name + "." + cls.Name), + "LoadIcon", + widgetExp, + new CodePrimitiveExpression ("gtk-missing-image"), + sizeExp + ) + ) + ); + + CodeStatementCollection stms = cond.FalseStatements; + + stms.Add ( + new CodeVariableDeclarationStatement (typeof(Gdk.Pixmap), "pmap", + new CodeObjectCreateExpression ( + typeof(Gdk.Pixmap), + new CodePropertyReferenceExpression ( + new CodePropertyReferenceExpression ( + new CodeTypeReferenceExpression (typeof(Gdk.Screen)), + "Default" + ), + "RootWindow" + ), + szExp, + szExp + ) + ) + ); + stms.Add ( + new CodeVariableDeclarationStatement (typeof(Gdk.GC), "gc", + new CodeObjectCreateExpression (typeof(Gdk.GC), pmapExp) + ) + ); + stms.Add ( + new CodeAssignStatement ( + new CodePropertyReferenceExpression ( + gcExp, + "RgbFgColor" + ), + new CodeObjectCreateExpression ( + typeof(Gdk.Color), + new CodePrimitiveExpression (255), + new CodePrimitiveExpression (255), + new CodePrimitiveExpression (255) + ) + ) + ); + stms.Add ( + new CodeMethodInvokeExpression ( + pmapExp, + "DrawRectangle", + gcExp, + new CodePrimitiveExpression (true), + zeroExp, + zeroExp, + szExp, + szExp + ) + ); + stms.Add ( + new CodeAssignStatement ( + new CodePropertyReferenceExpression ( + gcExp, + "RgbFgColor" + ), + new CodeObjectCreateExpression ( + typeof(Gdk.Color), + zeroExp, zeroExp, zeroExp + ) + ) + ); + stms.Add ( + new CodeMethodInvokeExpression ( + pmapExp, + "DrawRectangle", + gcExp, + new CodePrimitiveExpression (false), + zeroExp, + zeroExp, + szM1Exp, + szM1Exp + ) + ); + stms.Add ( + new CodeMethodInvokeExpression ( + gcExp, + "SetLineAttributes", + new CodePrimitiveExpression (3), + new CodeFieldReferenceExpression (new CodeTypeReferenceExpression (typeof(Gdk.LineStyle)), "Solid"), + new CodeFieldReferenceExpression (new CodeTypeReferenceExpression (typeof(Gdk.CapStyle)), "Round"), + new CodeFieldReferenceExpression (new CodeTypeReferenceExpression (typeof(Gdk.JoinStyle)), "Round") + ) + ); + stms.Add ( + new CodeAssignStatement ( + new CodePropertyReferenceExpression ( + gcExp, + "RgbFgColor" + ), + new CodeObjectCreateExpression ( + typeof(Gdk.Color), + new CodePrimitiveExpression (255), + zeroExp, + zeroExp + ) + ) + ); + stms.Add ( + new CodeMethodInvokeExpression ( + pmapExp, + "DrawLine", + gcExp, + mgExp, + mgExp, + new CodeBinaryOperatorExpression (szM1Exp, CodeBinaryOperatorType.Subtract, mgExp), + new CodeBinaryOperatorExpression (szM1Exp, CodeBinaryOperatorType.Subtract, mgExp) + ) + ); + stms.Add ( + new CodeMethodInvokeExpression ( + pmapExp, + "DrawLine", + gcExp, + new CodeBinaryOperatorExpression (szM1Exp, CodeBinaryOperatorType.Subtract, mgExp), + mgExp, + mgExp, + new CodeBinaryOperatorExpression (szM1Exp, CodeBinaryOperatorType.Subtract, mgExp) + ) + ); + stms.Add ( + new CodeMethodReturnStatement ( + new CodeMethodInvokeExpression ( + new CodeTypeReferenceExpression (typeof(Gdk.Pixbuf)), + "FromDrawable", + pmapExp, + new CodePropertyReferenceExpression (pmapExp, "Colormap"), + zeroExp, zeroExp, zeroExp, zeroExp, szExp, szExp + ) + ) + ); + } + + int sz, h; + Gtk.Icon.SizeLookup (size, out sz, out h); + + return new CodeMethodInvokeExpression ( + new CodeTypeReferenceExpression (new CodeTypeReference (cns.Name + ".IconLoader", CodeTypeReferenceOptions.GlobalReference)), + "LoadIcon", + rootObject, + new CodePrimitiveExpression (name), + new CodeFieldReferenceExpression ( + new CodeTypeReferenceExpression (new CodeTypeReference (typeof(Gtk.IconSize), CodeTypeReferenceOptions.GlobalReference)), + size.ToString () + ) + ); + } + } + + public class WidgetMap + { + Hashtable vars; + + internal WidgetMap (Hashtable vars) + { + this.vars = vars; + } + + public CodeExpression GetWidgetExp (ObjectWrapper wrapper) + { + return (CodeExpression) vars [wrapper]; + } + + public CodeExpression GetWidgetExp (object wrapped) + { + ObjectWrapper w = ObjectWrapper.Lookup (wrapped); + if (w != null) + return GetWidgetExp (w); + else + return null; + } + } + + [Serializable] + public class GenerationOptions + { + bool useGettext; + bool partialClasses; + bool generateEmptyBuildMethod; + bool generateSingleFile = true; + bool failForUnknownWidgets = false; + string path; + string globalNamespace = "Stetic"; + string gettextClass; + + public bool UseGettext { + get { return useGettext; } + set { useGettext = value; } + } + + public string GettextClass { + get { + if (gettextClass == null || gettextClass.Length == 0) + return "Mono.Unix.Catalog"; + else + return gettextClass; + } + set { gettextClass = value; } + } + + public string Path { + get { return path; } + set { path = value; } + } + + public bool GenerateEmptyBuildMethod { + get { return generateEmptyBuildMethod; } + set { generateEmptyBuildMethod = value; } + } + + public string GlobalNamespace { + get { return globalNamespace; } + set { globalNamespace = value; } + } + + public bool FailForUnknownWidgets { + get { return failForUnknownWidgets; } + set { failForUnknownWidgets = value; } + } + } +} + diff --git a/main/src/addins/MonoDevelop.GtkCore2/libstetic/GladeException.cs b/main/src/addins/MonoDevelop.GtkCore2/libstetic/GladeException.cs new file mode 100644 index 0000000000..504dab9823 --- /dev/null +++ b/main/src/addins/MonoDevelop.GtkCore2/libstetic/GladeException.cs @@ -0,0 +1,59 @@ +using System; + +namespace Stetic { + + public class GladeException : ApplicationException { + + public GladeException (string message) : base (message) { } + + public GladeException (string message, string className) : + this (message + " (class " + className + ")") + { + this.className = className; + } + + public GladeException (string message, string className, + bool childprop, string propName) : + this (message + " (class " + className + ", " + (childprop ? "child " : "") + "property " + propName + ")") + { + this.childprop = childprop; + this.propName = propName; + } + + public GladeException (string message, string className, + bool childprop, string propName, string propVal) : + this (message + " (class " + className + ", " + (childprop ? "child " : "") + "property " + propName + ", value " + propVal + ")") + { + this.childprop = childprop; + this.propName = propName; + this.propVal = propVal; + } + + string className, propName, propVal; + bool childprop; + + public string ClassName { + get { + return className; + } + } + + public bool ChildProp { + get { + return childprop; + } + } + + public string PropName { + get { + return propName; + } + } + + public string PropVal { + get { + return propVal; + } + } + } +} diff --git a/main/src/addins/MonoDevelop.GtkCore2/libstetic/GladeUtils.cs b/main/src/addins/MonoDevelop.GtkCore2/libstetic/GladeUtils.cs new file mode 100644 index 0000000000..bb02c0e198 --- /dev/null +++ b/main/src/addins/MonoDevelop.GtkCore2/libstetic/GladeUtils.cs @@ -0,0 +1,773 @@ +using System; +using System.Reflection; +using System.Collections; +using System.Runtime.InteropServices; +using System.Xml; +using Stetic.Wrapper; + +namespace Stetic { + + public static class GladeUtils { + + public const string Glade20SystemId = "http://glade.gnome.org/glade-2.0.dtd"; + + static Gdk.Atom gladeAtom; + public static Gdk.Atom ApplicationXGladeAtom { + get { + if (gladeAtom == null) + gladeAtom = Gdk.Atom.Intern ("application/x-glade", false); + return gladeAtom; + } + } + + public static XmlDocument XslImportTransform (XmlDocument doc) + { +/* XmlDocumentType doctype = doc.DocumentType; + if (doctype == null || + doctype.Name != "glade-interface" || + doctype.SystemId != Glade20SystemId) + throw new GladeException ("Not a glade file according to doctype"); +*/ + XmlReader reader = Registry.GladeImportXsl.Transform (doc, null, (XmlResolver)null); + doc = new XmlDocument (); + doc.PreserveWhitespace = true; + doc.Load (reader); + + return doc; + } + + public static XmlDocument XslExportTransform (XmlDocument doc) + { + XmlReader reader = Registry.GladeExportXsl.Transform (doc, null, (XmlResolver)null); + doc = new XmlDocument (); + doc.PreserveWhitespace = true; + doc.Load (reader); + + XmlDocumentType doctype = doc.CreateDocumentType ("glade-interface", null, Glade20SystemId, null); + doc.PrependChild (doctype); + + return doc; + } + + public static XmlDocument Export (Gtk.Widget widget) + { + Stetic.Wrapper.Widget wrapper = Stetic.Wrapper.Widget.Lookup (widget); + if (wrapper == null) + return null; + + XmlDocument doc = new XmlDocument (); + doc.PreserveWhitespace = true; + + XmlElement toplevel = doc.CreateElement ("glade-interface"); + doc.AppendChild (toplevel); + + // For toplevel widgets, glade just saves it as-is. For + // non-toplevels, it puts the widget into a dummy GtkWindow, + // but using the packing attributes of the widget's real + // container (so as to preserve expand/fill settings and the + // like). + + XmlElement elem; + Stetic.Wrapper.Container parent = wrapper.ParentWrapper; + ObjectWriter writer = new ObjectWriter (doc, FileFormat.Glade); + + if (parent == null) { + elem = wrapper.Write (writer); + if (elem == null) + return null; + if (!(widget is Gtk.Window)) { + XmlElement window = doc.CreateElement ("widget"); + window.SetAttribute ("class", "GtkWindow"); + window.SetAttribute ("id", "glade-dummy-container"); + XmlElement child = doc.CreateElement ("child"); + window.AppendChild (child); + child.AppendChild (elem); + elem = window; + } + } else { + elem = doc.CreateElement ("widget"); + // Set the class correctly (temporarily) so the XSL + // transforms will work correctly. + ClassDescriptor klass = parent.ClassDescriptor; + elem.SetAttribute ("class", klass.CName); + elem.AppendChild (parent.WriteContainerChild (writer, wrapper)); + } + toplevel.AppendChild (elem); + + doc = XslExportTransform (doc); + + if (parent != null) { + elem = (XmlElement)doc.SelectSingleNode ("glade-interface/widget"); + elem.SetAttribute ("class", "GtkWindow"); + elem.SetAttribute ("id", "glade-dummy-container"); + } + return doc; + } + +// public static Stetic.Wrapper.Widget Import (IProject project, XmlDocument doc) +// { +// try { +// doc = XslImportTransform (doc); +// } catch { +// return null; +// } +// +// ObjectReader reader = new ObjectReader (project, FileFormat.Glade); +// +// XmlElement elem = (XmlElement)doc.SelectSingleNode ("glade-interface/widget"); +// if (elem.GetAttribute ("class") != "GtkWindow" || +// elem.GetAttribute ("id") != "glade-dummy-container") { +// // Creating a new toplevel +// Stetic.Wrapper.Widget toplevel = (Stetic.Wrapper.Widget) +// Stetic.ObjectWrapper.ReadObject (reader, elem); +// if (toplevel != null) { +// project.AddWindow ((Gtk.Window)toplevel.Wrapped); +// } +// return toplevel; +// } +// +// return (Stetic.Wrapper.Widget) +// Stetic.ObjectWrapper.ReadObject (reader, (XmlElement)elem.SelectSingleNode ("child/widget")); +// } + + public static void Copy (Gtk.Widget widget, Gtk.SelectionData seldata, bool copyAsText) + { + XmlDocument doc = Export (widget); + if (doc == null) + return; + + if (copyAsText) + seldata.Text = doc.OuterXml; + else + seldata.Set (ApplicationXGladeAtom, 8, System.Text.Encoding.UTF8.GetBytes (doc.OuterXml)); + } + +// public static Stetic.Wrapper.Widget Paste (IProject project, Gtk.SelectionData seldata) +// { +// if (seldata.Type != ApplicationXGladeAtom) +// return null; +// string data = System.Text.Encoding.UTF8.GetString (seldata.Data); +// +// XmlDocument doc = new XmlDocument (); +// doc.PreserveWhitespace = true; +// try { +// doc.LoadXml (data); +// } catch { +// return null; +// } +// +// return Import (project, doc); +// } + + static object GetProperty (XmlElement elem, string selector, object defaultValue, bool extract) + { + XmlElement prop = (XmlElement)elem.SelectSingleNode (selector); + if (prop == null) + return defaultValue; + if (extract) + prop.ParentNode.RemoveChild (prop); + return ParseProperty (null, defaultValue.GetType (), prop.InnerText).Val; + } + + public static object GetProperty (XmlElement elem, string name, object defaultValue) + { + return GetProperty (elem, "./property[@name='" + name + "']", defaultValue, false); + } + + public static object ExtractProperty (XmlElement elem, string name, object defaultValue) + { + return GetProperty (elem, "./property[@name='" + name + "']", defaultValue, true); + } + + public static object GetChildProperty (XmlElement elem, string name, object defaultValue) + { + return GetProperty (elem, "./packing/property[@name='" + name + "']", defaultValue, false); + } + + public static object ExtractChildProperty (XmlElement elem, string name, object defaultValue) + { + return GetProperty (elem, "./packing/property[@name='" + name + "']", defaultValue, true); + } + + public static void SetProperty (XmlElement elem, string name, string value) + { + XmlElement prop_elem = elem.OwnerDocument.CreateElement ("property"); + prop_elem.SetAttribute ("name", name); + prop_elem.InnerText = value; + elem.AppendChild (prop_elem); + } + + public static void SetChildProperty (XmlElement elem, string name, string value) + { + XmlElement packing_elem = elem["packing"]; + if (packing_elem == null) { + packing_elem = elem.OwnerDocument.CreateElement ("packing"); + elem.AppendChild (packing_elem); + } + SetProperty (packing_elem, name, value); + } + + static GLib.Value ParseBasicType (GLib.TypeFundamentals type, string strval) + { + switch (type) { + case GLib.TypeFundamentals.TypeChar: + return new GLib.Value (SByte.Parse (strval)); + case GLib.TypeFundamentals.TypeUChar: + return new GLib.Value (Byte.Parse (strval)); + case GLib.TypeFundamentals.TypeBoolean: + return new GLib.Value (strval == "True"); + case GLib.TypeFundamentals.TypeInt: + return new GLib.Value (Int32.Parse (strval)); + case GLib.TypeFundamentals.TypeUInt: + return new GLib.Value (UInt32.Parse (strval)); + case GLib.TypeFundamentals.TypeInt64: + return new GLib.Value (Int64.Parse (strval)); + case GLib.TypeFundamentals.TypeUInt64: + return new GLib.Value (UInt64.Parse (strval)); + case GLib.TypeFundamentals.TypeFloat: + return new GLib.Value (Single.Parse (strval, System.Globalization.CultureInfo.InvariantCulture)); + case GLib.TypeFundamentals.TypeDouble: + return new GLib.Value (Double.Parse (strval, System.Globalization.CultureInfo.InvariantCulture)); + case GLib.TypeFundamentals.TypeString: + return new GLib.Value (strval); + default: + throw new GladeException ("Could not parse"); + } + } + + static GLib.Value ParseEnum (IntPtr gtype, string strval) + { + IntPtr enum_class = g_type_class_ref (gtype); + try { + IntPtr enum_value = g_enum_get_value_by_name (enum_class, strval); + if (enum_value == IntPtr.Zero) + throw new GladeException ("Could not parse"); + + int eval = Marshal.ReadInt32 (enum_value); + return new GLib.Value (Enum.ToObject (GLib.GType.LookupType (gtype), eval)); + } finally { + g_type_class_unref (enum_class); + } + } + + static GLib.Value ParseFlags (IntPtr gtype, string strval) + { + IntPtr flags_class = g_type_class_ref (gtype); + uint fval = 0; + + try { + foreach (string flag in strval.Split ('|')) { + if (flag == "") + continue; + IntPtr flags_value = g_flags_get_value_by_name (flags_class, flag); + if (flags_value == IntPtr.Zero) + throw new GladeException ("Could not parse"); + + int bits = Marshal.ReadInt32 (flags_value); + fval |= (uint)bits; + } + + return new GLib.Value (Enum.ToObject (GLib.GType.LookupType (gtype), fval)); + } finally { + g_type_class_unref (flags_class); + } + } + + static GLib.Value ParseAdjustment (string strval) + { + string[] vals = strval.Split (' '); + double deflt, min, max, step, page_inc, page_size; + + deflt = Double.Parse (vals[0], System.Globalization.CultureInfo.InvariantCulture); + min = Double.Parse (vals[1], System.Globalization.CultureInfo.InvariantCulture); + max = Double.Parse (vals[2], System.Globalization.CultureInfo.InvariantCulture); + step = Double.Parse (vals[3], System.Globalization.CultureInfo.InvariantCulture); + page_inc = Double.Parse (vals[4], System.Globalization.CultureInfo.InvariantCulture); + page_size = Double.Parse (vals[5], System.Globalization.CultureInfo.InvariantCulture); + return new GLib.Value (new Gtk.Adjustment (deflt, min, max, step, page_inc, page_size)); + } + + /* static GLib.Value ParseUnichar (string strval) + { + return new GLib.Value (strval.Length == 1 ? (uint)strval[0] : 0U); + }*/ + + static GLib.Value ParseProperty (ParamSpec pspec, Type propType, string strval) + { + 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"); + + GLib.TypeFundamentals typef = (GLib.TypeFundamentals)(int)g_type_fundamental (gtype); + + if (gtype == Gtk.Adjustment.GType.Val) + return ParseAdjustment (strval); + else if (typef == GLib.TypeFundamentals.TypeEnum) + return ParseEnum (gtype, strval); + else if (typef == GLib.TypeFundamentals.TypeFlags) + return ParseFlags (gtype, 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 + pspec = ParamSpec.LookupObjectProperty (type, name); + if (pspec == null) + throw new GladeException ("Unknown property", type.ToString (), childprop, name, strval); + + try { + return ParseProperty (pspec, pi.PropertyType, strval); + } catch { + throw new GladeException ("Could not parse property", type.ToString (), childprop, name, strval); + } + } + + static void ParseProperties (Type type, bool childprops, IEnumerable props, + out string[] propNames, out GLib.Value[] propVals) + { + ArrayList names = new ArrayList (); + ArrayList values = new ArrayList (); + + foreach (XmlElement prop in props) { + string name = prop.GetAttribute ("name").Replace ("_","-"); + string strval = prop.InnerText; + + // Skip translation context + if (prop.GetAttribute ("context") == "yes" && + strval.IndexOf ('|') != -1) + strval = strval.Substring (strval.IndexOf ('|') + 1); + + GLib.Value value; + try { + value = ParseProperty (type, childprops, name, strval); + names.Add (name); + values.Add (value); + } catch (GladeException ge) { + Console.Error.WriteLine (ge.Message); + } + } + + propNames = (string[])names.ToArray (typeof (string)); + propVals = (GLib.Value[])values.ToArray (typeof (GLib.Value)); + } + + 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) { + TypedPropertyDescriptor prop = item as TypedPropertyDescriptor; + if (prop == null) + continue; + prop = prop.GladeProperty; + if (prop.GladeName == null) + continue; + + XmlNode prop_node = elem.SelectSingleNode ("property[@name='" + prop.GladeName + "']"); + if (prop_node == null) + continue; + + if (prop.GladeOverride) + overrideProps[prop] = prop_node; + else + rawProps[prop] = prop_node; + } + } + } + + 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 (TypedSignalDescriptor signal in group) { + if (signal.GladeName == null) + continue; + + XmlElement signal_elem = elem.SelectSingleNode ("signal[@name='" + signal.GladeName + "']") 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 public void ImportWidget (ObjectWrapper wrapper, XmlElement elem) + { + string className = elem.GetAttribute ("class"); + if (className == null) + throw new GladeException ("<widget> node with no class name"); + + 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; + ExtractProperties (klass, elem, out rawProps, out overrideProps); + + string[] propNames; + GLib.Value[] propVals; + ParseProperties (klass.WrappedType, false, rawProps.Values, + out propNames, out propVals); + + Gtk.Widget widget; + + if (wrapper.Wrapped == null) { + if (className == "GtkWindow" || className == "GtkDialog") { + widget = (Gtk.Widget) klass.CreateInstance (wrapper.Project); + ObjectWrapper.Bind (wrapper.Project, klass, wrapper, widget, true); + SetProperties (klass, widget, propNames, propVals); + } else { + IntPtr raw = gtksharp_object_newv (klass.GType.Val, propNames.Length, propNames, propVals); + if (raw == IntPtr.Zero) + throw new GladeException ("Could not create widget", className); + widget = (Gtk.Widget)GLib.Object.GetObject (raw, true); + if (widget == null) { + gtk_object_sink (raw); + throw new GladeException ("Could not create gtk# wrapper", className); + } + ObjectWrapper.Bind (wrapper.Project, klass, wrapper, widget, true); + } + } else { + widget = (Gtk.Widget)wrapper.Wrapped; + for (int i = 0; i < propNames.Length; i++) + g_object_set_property (widget.Handle, propNames[i], ref propVals[i]); + } + MarkTranslatables (widget, rawProps); + + widget.Name = elem.GetAttribute ("id"); + + SetOverrideProperties (wrapper, overrideProps); + MarkTranslatables (widget, overrideProps); + } + + static void SetProperties (TypedClassDescriptor klass, Gtk.Widget widget, string[] propNames, GLib.Value[] propVals) + { + for (int n=0; n<propNames.Length; n++) { + foreach (ItemGroup grp in klass.ItemGroups) { + foreach (ItemDescriptor it in grp) { + if (it is TypedPropertyDescriptor) { + TypedPropertyDescriptor prop = (TypedPropertyDescriptor)it; + if (prop.GladeName == propNames[n]) { + prop.SetValue (widget, propVals[n].Val); + } + } + } + } + } + } + + + static void SetOverrideProperties (ObjectWrapper wrapper, Hashtable overrideProps) + { + foreach (TypedPropertyDescriptor prop in overrideProps.Keys) { + XmlElement prop_elem = overrideProps[prop] as XmlElement; + + try { + GLib.Value value = ParseProperty (prop.ParamSpec, prop.PropertyType, prop_elem.InnerText); + prop.SetValue (wrapper.Wrapped, value.Val); + } catch { + throw new GladeException ("Could not parse property", wrapper.GetType ().ToString (), wrapper is Stetic.Wrapper.Container.ContainerChild, prop.GladeName, prop_elem.InnerText); + } + } + } + + static void MarkTranslatables (object obj, Hashtable props) + { + foreach (PropertyDescriptor prop in props.Keys) { + if (!prop.Translatable) + continue; + + XmlElement prop_elem = props[prop] as XmlElement; + if (prop_elem.GetAttribute ("translatable") != "yes") { + prop.SetTranslated (obj, false); + continue; + } + + prop.SetTranslated (obj, true); + if (prop_elem.GetAttribute ("context") == "yes") { + string strval = prop_elem.InnerText; + int bar = strval.IndexOf ('|'); + if (bar != -1) + prop.SetTranslationContext (obj, strval.Substring (0, bar)); + } + + if (prop_elem.HasAttribute ("comments")) + prop.SetTranslationComment (obj, prop_elem.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; + + TypedClassDescriptor klass = wrapper.ClassDescriptor as TypedClassDescriptor; + if (klass == null) + throw new GladeException ("The widget class " + cc.GetType () + " is not supported by Glade"); + + Hashtable rawProps, overrideProps; + ExtractProperties (klass, packing, out rawProps, out overrideProps); + + string[] propNames; + GLib.Value[] propVals; + ParseProperties (cc.Parent.GetType (), true, rawProps.Values, + out propNames, out propVals); + + for (int i = 0; i < propNames.Length; i++) + cc.Parent.ChildSetProperty (cc.Child, propNames[i], propVals[i]); + MarkTranslatables (cc, rawProps); + + SetOverrideProperties (wrapper, overrideProps); + MarkTranslatables (cc, overrideProps); + } + + internal static XmlElement CreatePacking (XmlDocument doc, Stetic.Wrapper.Container.ContainerChild childwrapper) + { + XmlElement packing_elem = doc.CreateElement ("packing"); + GetProps (childwrapper, packing_elem); + return packing_elem; + } + + static string PropToString (ObjectWrapper wrapper, TypedPropertyDescriptor prop) + { + object value; + + if (!prop.GladeOverride) { + Stetic.Wrapper.Container.ContainerChild ccwrap = wrapper as Stetic.Wrapper.Container.ContainerChild; + GLib.Value gval; + + if (ccwrap != null) { + Gtk.Container.ContainerChild cc = (Gtk.Container.ContainerChild)ccwrap.Wrapped; + 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; + gval = new GLib.Value (widget, prop.GladeName); + g_object_get_property (widget.Handle, prop.GladeName, ref gval); + } + value = gval.Val; + } else + value = prop.GetValue (wrapper.Wrapped); + if (value == null) + return null; + + // If the property has its default value, we don't need to write it + if (prop.HasDefault && prop.ParamSpec.IsDefaultValue (value)) + return null; + + if (value is Gtk.Adjustment) { + Gtk.Adjustment adj = value as Gtk.Adjustment; + return String.Format ("{0:G} {1:G} {2:G} {3:G} {4:G} {5:G}", + adj.Value, adj.Lower, adj.Upper, + adj.StepIncrement, adj.PageIncrement, + adj.PageSize); + } else if (value is Enum && prop.ParamSpec != null) { + 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 (); + uint val = (uint)System.Convert.ChangeType (value, typeof (uint)); + + while (val != 0) { + IntPtr flags_value = g_flags_get_first_value (klass, val); + if (flags_value == IntPtr.Zero) + break; + IntPtr fval = Marshal.ReadIntPtr (flags_value); + val &= ~(uint)fval; + + IntPtr name = Marshal.ReadIntPtr (flags_value, Marshal.SizeOf (typeof (IntPtr))); + if (name != IntPtr.Zero) { + if (sb.Length != 0) + sb.Append ('|'); + sb.Append (GLib.Marshaller.Utf8PtrToString (name)); + } + } + + g_type_class_unref (klass); + return sb.ToString (); + } else { + int val = (int)System.Convert.ChangeType (value, typeof (int)); + IntPtr enum_value = g_enum_get_value (klass, val); + g_type_class_unref (klass); + + IntPtr name = Marshal.ReadIntPtr (enum_value, Marshal.SizeOf (typeof (IntPtr))); + return GLib.Marshaller.Utf8PtrToString (name); + } + } else if (value is bool) + return (bool)value ? "True" : "False"; + else + return value.ToString (); + } + + static public XmlElement ExportWidget (ObjectWrapper wrapper, XmlDocument doc) + { + XmlElement elem = doc.CreateElement ("widget"); + elem.SetAttribute ("class", wrapper.ClassDescriptor.CName); + elem.SetAttribute ("id", ((Gtk.Widget)wrapper.Wrapped).Name); + + GetProps (wrapper, elem); + GetSignals (wrapper, elem); + return elem; + } + + static public void GetProps (ObjectWrapper wrapper, XmlElement parent_elem) + { + ClassDescriptor klass = wrapper.ClassDescriptor; + + foreach (ItemGroup group in klass.ItemGroups) { + foreach (ItemDescriptor item in group) { + TypedPropertyDescriptor prop = item as TypedPropertyDescriptor; + if (prop == null) + continue; + prop = prop.GladeProperty; + if (prop.GladeName == null) + continue; + if (!prop.VisibleFor (wrapper.Wrapped)) + continue; + + string val = PropToString (wrapper, prop); + if (val == null) + continue; + + XmlElement prop_elem = parent_elem.OwnerDocument.CreateElement ("property"); + prop_elem.SetAttribute ("name", prop.GladeName); + 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 public 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 (((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", ((TypedSignalDescriptor)signal.SignalDescriptor).GladeName); + signal_elem.SetAttribute ("handler", signal.Handler); + if (signal.After) + signal_elem.SetAttribute ("after", "yes"); + parent_elem.AppendChild (signal_elem); + } + } + + [DllImport("libgobject-2.0-0.dll")] + static extern IntPtr g_type_fundamental (IntPtr gtype); + + [DllImport("libgobject-2.0-0.dll")] + static extern IntPtr g_type_class_ref (IntPtr gtype); + + [DllImport("libgobject-2.0-0.dll")] + static extern IntPtr g_type_class_unref (IntPtr klass); + + [DllImport("glibsharpglue-2")] + static extern IntPtr gtksharp_object_newv (IntPtr gtype, int n_params, string[] names, GLib.Value[] vals); + + [DllImport("libgtk-win32-2.0-0.dll")] + static extern void gtk_object_sink (IntPtr raw); + + [DllImport("libgobject-2.0-0.dll")] + static extern void g_object_get_property (IntPtr obj, string name, ref GLib.Value val); + + [DllImport("libgobject-2.0-0.dll")] + static extern void g_object_set_property (IntPtr obj, string name, ref GLib.Value val); + + [DllImport("libgtk-win32-2.0-0.dll")] + static extern void gtk_container_child_get_property (IntPtr parent, IntPtr child, string name, ref GLib.Value val); + + [DllImport("libgobject-2.0-0.dll")] + static extern IntPtr g_enum_get_value_by_name (IntPtr enum_class, string name); + + [DllImport("libgobject-2.0-0.dll")] + static extern IntPtr g_enum_get_value (IntPtr enum_class, int val); + + [DllImport("libgobject-2.0-0.dll")] + static extern IntPtr g_flags_get_value_by_name (IntPtr flags_class, string nick); + + [DllImport("libgobject-2.0-0.dll")] + static extern IntPtr g_flags_get_first_value (IntPtr flags_class, uint val); + } +} diff --git a/main/src/addins/MonoDevelop.GtkCore2/libstetic/IDesignArea.cs b/main/src/addins/MonoDevelop.GtkCore2/libstetic/IDesignArea.cs new file mode 100644 index 0000000000..7fb86f1beb --- /dev/null +++ b/main/src/addins/MonoDevelop.GtkCore2/libstetic/IDesignArea.cs @@ -0,0 +1,39 @@ + +using System; + +namespace Stetic +{ + public interface IDesignArea + { + IObjectSelection SetSelection (Gtk.Widget widget, object selectedInstance); + IObjectSelection SetSelection (Gtk.Widget widget, object selectedInstance, bool allowDrag); + void ResetSelection (Gtk.Widget widget); + bool IsSelected (Gtk.Widget widget); + IObjectSelection GetSelection (); + IObjectSelection GetSelection (Gtk.Widget widget); + + void AddWidget (Gtk.Widget w, int x, int y); + void RemoveWidget (Gtk.Widget w); + void MoveWidget (Gtk.Widget w, int x, int y); + Gdk.Rectangle GetCoordinates (Gtk.Widget w); + + event EventHandler SelectionChanged; + } + + public delegate void DragDelegate (Gdk.EventMotion evt, int dx, int dy); + + public interface IObjectViewer + { + object TargetObject { get; set; } + } + + public interface IObjectSelection: IDisposable + { + Gtk.Widget Widget { get; } + object DataObject { get; } + bool AllowDrag {get; set; } + + event DragDelegate Drag; + event EventHandler Disposed; + } +} diff --git a/main/src/addins/MonoDevelop.GtkCore2/libstetic/IEditableObject.cs b/main/src/addins/MonoDevelop.GtkCore2/libstetic/IEditableObject.cs new file mode 100644 index 0000000000..dd2e54c5df --- /dev/null +++ b/main/src/addins/MonoDevelop.GtkCore2/libstetic/IEditableObject.cs @@ -0,0 +1,18 @@ + +using System; + +namespace Stetic +{ + public interface IEditableObject + { + bool CanCopy { get; } + bool CanCut { get; } + bool CanPaste { get; } + bool CanDelete { get; } + + void Copy (); + void Cut (); + void Paste (); + void Delete (); + } +} diff --git a/main/src/addins/MonoDevelop.GtkCore2/libstetic/IProject.cs b/main/src/addins/MonoDevelop.GtkCore2/libstetic/IProject.cs new file mode 100644 index 0000000000..03e1c4c477 --- /dev/null +++ b/main/src/addins/MonoDevelop.GtkCore2/libstetic/IProject.cs @@ -0,0 +1,33 @@ +using System; + +namespace Stetic +{ + public interface IProject + { + //string FileName { get; } + string FolderName { get; } + Gtk.Widget[] Toplevels { get; } + Gtk.Widget GetWidget (string name); + Gtk.Widget Selection { get; set; } + Wrapper.ActionGroupCollection ActionGroups { get; } + ProjectIconFactory IconFactory { get; } + string ImagesRootPath { get; } + string TargetGtkVersion { get; } +// bool Modified { get; set; } + IResourceProvider ResourceProvider { get; set; } + + void PopupContextMenu (Stetic.Wrapper.Widget wrapper); + void PopupContextMenu (Placeholder ph); + void AddWindow (Gtk.Window window); + string ImportFile (string filePath); + + event Wrapper.WidgetEventHandler SelectionChanged; + + void NotifyObjectChanged (ObjectWrapperEventArgs args); + void NotifyNameChanged (Stetic.Wrapper.WidgetNameChangedArgs args); + void NotifySignalAdded (SignalEventArgs args); + void NotifySignalRemoved (SignalEventArgs args); + void NotifySignalChanged (SignalChangedEventArgs args); + void NotifyWidgetContentsChanged (Wrapper.Widget w); + } +} diff --git a/main/src/addins/MonoDevelop.GtkCore2/libstetic/IPropertyEditor.cs b/main/src/addins/MonoDevelop.GtkCore2/libstetic/IPropertyEditor.cs new file mode 100644 index 0000000000..f0cb14a48b --- /dev/null +++ b/main/src/addins/MonoDevelop.GtkCore2/libstetic/IPropertyEditor.cs @@ -0,0 +1,23 @@ +using System; + +namespace Stetic +{ + // Property editors must be Gtk Widgets and implement this interface + + public interface IPropertyEditor: IDisposable + { + // Called once to initialize the editor. + void Initialize (PropertyDescriptor descriptor); + + // Called when the object to be edited changes. + void AttachObject (object obj); + + // Gets/Sets the value of the editor. If the editor supports + // several value types, it is the responsibility of the editor + // to return values with the expected type. + object Value { get; set; } + + // To be fired when the edited value changes. + event EventHandler ValueChanged; + } +} diff --git a/main/src/addins/MonoDevelop.GtkCore2/libstetic/IRadioGroupManager.cs b/main/src/addins/MonoDevelop.GtkCore2/libstetic/IRadioGroupManager.cs new file mode 100644 index 0000000000..fe0cdec704 --- /dev/null +++ b/main/src/addins/MonoDevelop.GtkCore2/libstetic/IRadioGroupManager.cs @@ -0,0 +1,21 @@ + +using System; +using System.Collections; + +namespace Stetic +{ + public delegate void GroupsChangedDelegate (); + + public interface IRadioGroupManagerProvider + { + IRadioGroupManager GetGroupManager (); + } + + public interface IRadioGroupManager + { + event GroupsChangedDelegate GroupsChanged; + IEnumerable GroupNames { get; } + void Rename (string oldName, string newName); + void Add (string group); + } +} diff --git a/main/src/addins/MonoDevelop.GtkCore2/libstetic/IResourceProvider.cs b/main/src/addins/MonoDevelop.GtkCore2/libstetic/IResourceProvider.cs new file mode 100644 index 0000000000..3394cf77a6 --- /dev/null +++ b/main/src/addins/MonoDevelop.GtkCore2/libstetic/IResourceProvider.cs @@ -0,0 +1,72 @@ + +using System; +using System.IO; + +namespace Stetic +{ + public interface IResourceProvider + { + ResourceInfo[] GetResources (); + Stream GetResourceStream (string resourceName); + ResourceInfo AddResource (string fileName); + void RemoveResource (string resourceName); + } + + public delegate string MimeResolverDelegate (string url); + + [Serializable] + public class ResourceInfo + { + public static MimeResolverDelegate MimeResolver; + + string name; + string fileName; + string mimeType; + + public ResourceInfo (string name, string fileName): this (name, fileName, null) + { + } + + public ResourceInfo (string name, string fileName, string mimeType) + { + this.name = name; + this.fileName = fileName; + this.mimeType = mimeType; + } + + public string Name { + get { return name; } + } + + public string FileName { + get { return fileName; } + } + + public string MimeType { + get { + if (mimeType == null) { + if (MimeResolver == null) + return null; + + if (File.Exists (fileName)) { + mimeType = MimeResolver (fileName); + } else { + // Guess the mime type creating a temp file with the same extension + string fn = Path.GetTempFileName (); + string ext = Path.GetExtension (fileName); + int n=0; + while (File.Exists (fn + n + ext)) + n++; + string tname = fn + n + ext; + File.Move (fn, tname); + mimeType = MimeResolver (tname); + File.Delete (tname); + } + if (mimeType == null || mimeType == "") + mimeType = "text"; + } + return mimeType; + } + } + } +} diff --git a/main/src/addins/MonoDevelop.GtkCore2/libstetic/ImageInfo.cs b/main/src/addins/MonoDevelop.GtkCore2/libstetic/ImageInfo.cs new file mode 100644 index 0000000000..d21e46c0f5 --- /dev/null +++ b/main/src/addins/MonoDevelop.GtkCore2/libstetic/ImageInfo.cs @@ -0,0 +1,215 @@ + +using System; +using System.IO; +using System.CodeDom; + +namespace Stetic +{ + public enum ImageSource + { + Theme, + Resource, + File + } + + public class ImageInfo + { + ImageSource source; + string name; + Gtk.IconSize size; + Gdk.Pixbuf image; + + private ImageInfo () + { + } + + public string Label { + get { + if (source == ImageSource.File) + return Path.GetFileName (name); + else + return name; + } + } + + public string Name { + get { return name; } + } + + public Gtk.IconSize ThemeIconSize { + get { return size; } + } + + public ImageSource Source { + get { return source; } + } + + public override string ToString () + { + if (source == ImageSource.Theme) + return "stock:" + name + " " + size; + else if (source == ImageSource.Resource) + return "resource:" + name; + else + return "file:" + name; + } + + public static ImageInfo FromResource (string resourceName) + { + ImageInfo info = new ImageInfo (); + info.name = resourceName; + info.source = ImageSource.Resource; + return info; + } + + public static ImageInfo FromTheme (string iconId, Gtk.IconSize size) + { + ImageInfo info = new ImageInfo (); + info.name = iconId; + info.size = size; + info.source = ImageSource.Theme; + return info; + } + + public static ImageInfo FromFile (string file) + { + ImageInfo info = new ImageInfo (); + info.name = file; + info.source = ImageSource.File; + return info; + } + + public static ImageInfo FromString (string str) + { + ImageInfo info = new ImageInfo (); + if (str.StartsWith ("resource:")) { + info.source = ImageSource.Resource; + info.name = str.Substring (9); + } else if (str.StartsWith ("stock:")) { + info.source = ImageSource.Theme; + string[] s = str.Substring (6).Split (' '); + if (s.Length != 2) + return null; + info.name = s[0]; + info.size = (Gtk.IconSize) Enum.Parse (typeof(Gtk.IconSize), s[1]); + } else if (str.StartsWith ("file:")) { + info.source = ImageSource.File; + info.name = str.Substring (5); + } else + return null; + return info; + } + + public Gdk.Pixbuf GetImage (IProject project) + { + if (image != null) + return image; + + switch (source) { + case ImageSource.Resource: + if (project.ResourceProvider == null) + return null; + System.IO.Stream s = project.ResourceProvider.GetResourceStream (name); + if (s == null) + return null; + try { + return image = new Gdk.Pixbuf (s); + } catch { + // Not a valid image + return WidgetUtils.MissingIcon; + } + + case ImageSource.Theme: + return image = WidgetUtils.LoadIcon (name, size); + + case ImageSource.File: + try { + string file = Path.Combine (project.ImagesRootPath, name); + return image = new Gdk.Pixbuf (file); + } catch { + return WidgetUtils.MissingIcon; + } + } + return null; + } + + public Gdk.Pixbuf GetThumbnail (IProject project, int thumbnailSize) + { + Gdk.Pixbuf pix = GetImage (project); + if (pix == null) + return null; + + if (pix.Width >= pix.Height && pix.Width > thumbnailSize) { + return ScaleImage (pix, thumbnailSize, thumbnailSize); + } else if (pix.Height > pix.Width && pix.Height > thumbnailSize) { + return ScaleImage (pix, thumbnailSize, thumbnailSize); + } + return pix; + } + + public Gdk.Pixbuf GetScaledImage (IProject project, Gtk.IconSize size) + { + int w, h; + Gtk.Icon.SizeLookup (size, out w, out h); + return GetScaledImage (project, w, h); + } + + public Gdk.Pixbuf GetScaledImage (IProject project, int width, int height) + { + Gdk.Pixbuf pix = GetImage (project); + if (pix == null) + return null; + else + return ScaleImage (pix, width, height); + } + + Gdk.Pixbuf ScaleImage (Gdk.Pixbuf pix, int width, int height) + { + if ((pix.Width - width) > (pix.Height - height)) { + if (pix.Width != width) { + float prop = (float) pix.Height / (float) pix.Width; + return pix.ScaleSimple (width, (int)(width * prop), Gdk.InterpType.Bilinear); + } + } else { + if (pix.Height != height) { + float prop = (float) pix.Width / (float) pix.Height; + return pix.ScaleSimple ((int)(height * prop), height, Gdk.InterpType.Bilinear); + } + } + return pix; + } + + public CodeExpression ToCodeExpression (GeneratorContext ctx) + { + switch (source) { + case ImageSource.Resource: + return new CodeMethodInvokeExpression ( + new CodeTypeReferenceExpression (new CodeTypeReference (typeof(Gdk.Pixbuf), CodeTypeReferenceOptions.GlobalReference)), + "LoadFromResource", + new CodePrimitiveExpression (name) + ); + + case ImageSource.Theme: + return ctx.GenerateLoadPixbuf (name, size); + + case ImageSource.File: + return new CodeObjectCreateExpression ( + typeof(Gdk.Pixbuf).ToGlobalTypeRef (), + new CodeMethodInvokeExpression ( + new CodeTypeReferenceExpression (new CodeTypeReference (typeof(System.IO.Path), CodeTypeReferenceOptions.GlobalReference)), + "Combine", + new CodePropertyReferenceExpression ( + new CodePropertyReferenceExpression ( + new CodeTypeReferenceExpression (new CodeTypeReference (typeof(AppDomain), CodeTypeReferenceOptions.GlobalReference)), + "CurrentDomain" + ), + "BaseDirectory" + ), + new CodePrimitiveExpression (name) + ) + ); + } + return new CodePrimitiveExpression (null); + } + } +} diff --git a/main/src/addins/MonoDevelop.GtkCore2/libstetic/ItemDescriptor.cs b/main/src/addins/MonoDevelop.GtkCore2/libstetic/ItemDescriptor.cs new file mode 100644 index 0000000000..a64644eb06 --- /dev/null +++ b/main/src/addins/MonoDevelop.GtkCore2/libstetic/ItemDescriptor.cs @@ -0,0 +1,158 @@ +using System; +using System.Collections; +using System.Xml; +using System.Reflection; + +namespace Stetic +{ + [Serializable] + public abstract class ItemDescriptor + { + [NonSerialized] + ArrayList deps; + + [NonSerialized] + ArrayList visdeps; + + [NonSerialized] + bool isInternal; + + [NonSerialized] + ClassDescriptor klass; + + protected string targetGtkVersion; + + protected ItemDescriptor () {} + + protected ItemDescriptor (XmlElement elem, ItemGroup group, ClassDescriptor klass) + { + this.klass = klass; + isInternal = elem.HasAttribute ("internal"); + deps = AddSubprops (elem.SelectNodes ("./disabled-if"), group, klass); + visdeps = AddSubprops (elem.SelectNodes ("./invisible-if"), group, klass); + targetGtkVersion = elem.GetAttribute ("gtk-version"); + if (targetGtkVersion.Length == 0) + targetGtkVersion = null; + } + + ArrayList AddSubprops (XmlNodeList nodes, ItemGroup group, ClassDescriptor klass) + { + ArrayList list = null; + + // Sub-properties can have a name+value (which checks for the value of a + // property) or a method name, which should return true if the item has + // to be disabled/hidden. + + foreach (XmlElement elem in nodes) { + string name = elem.GetAttribute ("name"); + if (name.Length > 0) { + string value = elem.GetAttribute ("value"); + + PropertyDescriptor prop = (PropertyDescriptor)group[name]; + if (prop == null) + prop = (PropertyDescriptor)klass[name]; + if (prop == null) + throw new ArgumentException ("Bad sub-prop " + name); + if (list == null) + list = new ArrayList (); + + DepInfo info = new DepInfo (); + info.Property = prop; + info.Value = prop.StringToValue (value); + list.Add (info); + } else if ((name = elem.GetAttribute ("check")).Length > 0) { + DepInfo info = new DepInfo (); + info.CheckName = name; + if (list == null) + list = new ArrayList (); + list.Add (info); + } else { + throw new ArgumentException ("Bad sub-prop"); + } + } + return list; + } + + // The property's display name + public abstract string Name { get; } + + public virtual string TargetGtkVersion { + get { + if (targetGtkVersion == null) + return klass.TargetGtkVersion; + else + return targetGtkVersion; + } + } + + public bool SupportsGtkVersion (string targetVersion) + { + return WidgetUtils.CompareVersions (TargetGtkVersion, targetVersion) >= 0; + } + + public bool HasDependencies { + get { + return deps != null || visdeps != null; + } + } + + public bool EnabledFor (object obj) + { + if (deps == null) + return true; + + foreach (DepInfo dep in deps) { + if (dep.Check (obj)) + return false; + } + return true; + } + + public bool HasVisibility { + get { + return visdeps != null; + } + } + + public bool VisibleFor (object obj) + { + if (visdeps == null) + return true; + + foreach (DepInfo dep in visdeps) { + if (dep.Check (obj)) + return false; + } + return true; + } + + public bool IsInternal { + get { + return isInternal; + } + } + + public ClassDescriptor ClassDescriptor { + get { return klass; } + } + + class DepInfo + { + public string CheckName; + public PropertyDescriptor Property; + public object Value; + + public bool Check (object obj) + { + if (Property != null) { + object depValue = Property.GetValue (obj); + return Value.Equals (depValue); + } else { + object wrapper = ObjectWrapper.Lookup (obj); + object res = wrapper.GetType ().InvokeMember (CheckName, BindingFlags.InvokeMethod | BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.Instance, null, wrapper, null); + return !(bool) res; + } + } + } + } +} diff --git a/main/src/addins/MonoDevelop.GtkCore2/libstetic/ItemGroup.cs b/main/src/addins/MonoDevelop.GtkCore2/libstetic/ItemGroup.cs new file mode 100644 index 0000000000..f66a9d5603 --- /dev/null +++ b/main/src/addins/MonoDevelop.GtkCore2/libstetic/ItemGroup.cs @@ -0,0 +1,78 @@ +using System; +using System.Collections; +using System.Collections.Specialized; +using System.Xml; + +namespace Stetic { + public class ItemGroup : IEnumerable + { + public static ItemGroup Empty; + + string label, name; + ListDictionary items = new ListDictionary (); + ClassDescriptor declaringType; + + static ItemGroup () + { + Empty = new ItemGroup (); + } + + private ItemGroup () + { + } + + public ItemGroup (XmlElement elem, ClassDescriptor klass) + { + declaringType = klass; + label = elem.GetAttribute ("label"); + name = elem.GetAttribute ("name"); + + XmlNodeList nodes = elem.SelectNodes ("property | command | signal"); + for (int i = 0; i < nodes.Count; i++) { + XmlElement item = (XmlElement)nodes[i]; + string refname = item.GetAttribute ("ref"); + if (refname != "") { + if (refname.IndexOf ('.') != -1) { + ItemDescriptor desc = (ItemDescriptor) Registry.LookupItem (refname); + items.Add (desc.Name, desc); + } else { + ItemDescriptor desc = (ItemDescriptor) klass[refname]; + items.Add (desc.Name, desc); + } + continue; + } + + ItemDescriptor idesc = klass.CreateItemDescriptor ((XmlElement)item, this); + if (idesc != null) + items.Add (idesc.Name, idesc); + } + } + + public string Label { + get { + return label; + } + } + + public string Name { + get { + return name; + } + } + + public IEnumerator GetEnumerator () + { + return items.Values.GetEnumerator (); + } + + public ItemDescriptor this [string name] { + get { + return (ItemDescriptor) items [name]; + } + } + + public ClassDescriptor DeclaringType { + get { return declaringType; } + } + } +} diff --git a/main/src/addins/MonoDevelop.GtkCore2/libstetic/ItemGroupCollection.cs b/main/src/addins/MonoDevelop.GtkCore2/libstetic/ItemGroupCollection.cs new file mode 100644 index 0000000000..9fb9296315 --- /dev/null +++ b/main/src/addins/MonoDevelop.GtkCore2/libstetic/ItemGroupCollection.cs @@ -0,0 +1,42 @@ + +using System; +using System.Collections; + +namespace Stetic +{ + public class ItemGroupCollection: CollectionBase + { + public void Add (ItemGroup group) + { + List.Add (group); + } + + public ItemGroup this [int n] + { + get { + return (ItemGroup) List [n]; + } + } + + public ItemGroup this [string name] + { + get { + for (int n=0; n<List.Count; n++) { + if (((ItemGroup) List [n]).Name == name) + return (ItemGroup) List [n]; + } + return null; + } + } + + public ItemDescriptor GetItem (string name) + { + for (int n=0; n<List.Count; n++) { + ItemDescriptor item = ((ItemGroup) List [n])[name]; + if (item != null) + return item; + } + return null; + } + } +} diff --git a/main/src/addins/MonoDevelop.GtkCore2/libstetic/Makefile.am b/main/src/addins/MonoDevelop.GtkCore2/libstetic/Makefile.am new file mode 100644 index 0000000000..c90eb8c78b --- /dev/null +++ b/main/src/addins/MonoDevelop.GtkCore2/libstetic/Makefile.am @@ -0,0 +1,269 @@ +ADDIN_BUILD = $(top_builddir)/build/AddIns/MonoDevelop.GtkCore +ASSEMBLY = $(ADDIN_BUILD)/libstetic.dll +assemblydir = $(MD_ADDIN_DIR)/MonoDevelop.GtkCore +assembly_DATA = $(ASSEMBLY) $(ASSEMBLY).mdb $(build_dll_config) + +FILES = \ + ClassDescriptor.cs \ + Clipboard.cs \ + CommandDescriptor.cs \ + CustomWidget.cs \ + DND.cs \ + editor/Accelerator.cs \ + editor/ActionGroupEditor.cs \ + editor/ActionItem.cs \ + editor/ActionMenu.cs \ + editor/ActionMenuBar.cs \ + editor/ActionMenuItem.cs \ + editor/ActionToolbar.cs \ + editor/ActionToolItem.cs \ + editor/Boolean.cs \ + editor/CellRendererComboBox.cs \ + editor/Char.cs \ + editor/Color.cs \ + editor/DateTimeEditor.cs \ + editor/EditIconDialog.cs \ + editor/EditIconFactoryDialog.cs \ + editor/Enumeration.cs \ + editor/Flags.cs \ + editor/FlagsSelectorDialog.cs \ + editor/FloatRange.cs \ + editor/GroupPicker.cs \ + editor/IconList.cs \ + editor/IconSelectorItem.cs \ + editor/IconSelectorMenu.cs \ + editor/IconSelectorMenuItem.cs \ + editor/Identifier.cs \ + editor/Image.cs \ + editor/ImageFile.cs \ + editor/ImageSelector.cs \ + editor/IntRange.cs \ + editor/NonContainerWarningDialog.cs \ + editor/OptIntRange.cs \ + editor/ProjectIconList.cs \ + editor/ProjectIconSelectorItem.cs \ + editor/ResponseId.cs \ + editor/SelectIconDialog.cs \ + editor/SelectImageDialog.cs \ + editor/StockIconList.cs \ + editor/StockIconSelectorItem.cs \ + editor/StockItem.cs \ + editor/String.cs \ + editor/StringArray.cs \ + editor/Text.cs \ + editor/TextBox.cs \ + editor/TextEditor.cs \ + editor/TextEditorDialog.cs \ + editor/ThemedIcon.cs \ + editor/ThemedIconList.cs \ + editor/TimeSpanEditor.cs \ + editor/Translatable.cs \ + editor/TreeViewCellContainer.cs \ + editor/WidgetSelector.cs \ + EnumDescriptor.cs \ + ErrorWidget.cs \ + GeneratorContext.cs \ + GladeException.cs \ + GladeUtils.cs \ + IDesignArea.cs \ + IEditableObject.cs \ + ImageInfo.cs \ + IProject.cs \ + IPropertyEditor.cs \ + IRadioGroupManager.cs \ + IResourceProvider.cs \ + ItemDescriptor.cs \ + ItemGroup.cs \ + ItemGroupCollection.cs \ + NoGuiDispatchAttribute.cs \ + ObjectReader.cs \ + ObjectWrapper.cs \ + ObjectWrapperEventHandler.cs \ + ObjectWriter.cs \ + ParamSpec.cs \ + Placeholder.cs \ + ProjectIconFactory.cs \ + PropertyDescriptor.cs \ + PropertyEditorAttribute.cs \ + PropertyEditorCell.cs \ + RadioGroupManager.cs \ + Registry.cs \ + Set.cs \ + SignalDescriptor.cs \ + TopLevelDialog.cs \ + TopLevelWindow.cs \ + TranslatableAttribute.cs \ + TypedClassDescriptor.cs \ + TypedPropertyDescriptor.cs \ + TypedSignalDescriptor.cs \ + undo/ActionDiffAdaptor.cs \ + undo/DiffGenerator.cs \ + undo/IDiffAdaptor.cs \ + undo/UndoManager.cs \ + undo/XmlDiffAdaptor.cs \ + WidgetLibrary.cs \ + WidgetUtils.cs \ + wrapper/Action.cs \ + wrapper/ActionGroup.cs \ + wrapper/ActionToolbarWrapper.cs \ + wrapper/ActionTree.cs \ + wrapper/Bin.cs \ + wrapper/Box.cs \ + wrapper/Button.cs \ + wrapper/ButtonBox.cs \ + wrapper/CheckButton.cs \ + wrapper/ColorButton.cs \ + wrapper/ComboBox.cs \ + wrapper/ComboBoxEntry.cs \ + wrapper/Container.cs \ + wrapper/Custom.cs \ + wrapper/Dialog.cs \ + wrapper/Entry.cs \ + wrapper/Expander.cs \ + wrapper/Fixed.cs \ + wrapper/FontButton.cs \ + wrapper/FontSelectionDialog.cs \ + wrapper/Frame.cs \ + wrapper/HScale.cs \ + wrapper/HScrollbar.cs \ + wrapper/IconView.cs \ + wrapper/Image.cs \ + wrapper/ImageMenuItem.cs \ + wrapper/Label.cs \ + wrapper/MenuBar.cs \ + wrapper/MenuItem.cs \ + wrapper/MessageDialog.cs \ + wrapper/Misc.cs \ + wrapper/Notebook.cs \ + wrapper/Object.cs \ + wrapper/OptionMenu.cs \ + wrapper/Paned.cs \ + wrapper/RadioActionGroupManager.cs \ + wrapper/RadioButton.cs \ + wrapper/RadioMenuItem.cs \ + wrapper/RadioToolButton.cs \ + wrapper/Range.cs \ + wrapper/Scale.cs \ + wrapper/ScrolledWindow.cs \ + wrapper/Signal.cs \ + wrapper/SignalChangedEventHandler.cs \ + wrapper/SignalCollection.cs \ + wrapper/SignalEventHandler.cs \ + wrapper/SpinButton.cs \ + wrapper/Table.cs \ + wrapper/TextView.cs \ + wrapper/ToggleToolButton.cs \ + wrapper/Toolbar.cs \ + wrapper/ToolButton.cs \ + wrapper/TreeView.cs \ + wrapper/Viewport.cs \ + wrapper/VScale.cs \ + wrapper/VScrollbar.cs \ + wrapper/Widget.cs \ + wrapper/WidgetEventHandler.cs \ + wrapper/WidgetNameChangedHandler.cs \ + wrapper/Window.cs + +RES = \ + stetic.glade \ + wrapper/objects.xml \ + wrapper/pixmaps/accellabel.png \ + wrapper/pixmaps/actiongroup.png \ + wrapper/pixmaps/add-check-label.png \ + wrapper/pixmaps/add-menu.png \ + wrapper/pixmaps/alignment.png \ + wrapper/pixmaps/arrow.png \ + wrapper/pixmaps/box-expand.png \ + wrapper/pixmaps/box-fill.png \ + wrapper/pixmaps/button.png \ + wrapper/pixmaps/calendar.png \ + wrapper/pixmaps/cell-expand-h.png \ + wrapper/pixmaps/cell-expand-v.png \ + wrapper/pixmaps/cell-fill-h.png \ + wrapper/pixmaps/cell-fill-v.png \ + wrapper/pixmaps/checkbutton.png \ + wrapper/pixmaps/colorbutton.png \ + wrapper/pixmaps/colorselection.png \ + wrapper/pixmaps/colorselectiondialog.png \ + wrapper/pixmaps/combo.png \ + wrapper/pixmaps/comboentry.png \ + wrapper/pixmaps/custom.png \ + wrapper/pixmaps/dec-border.png \ + wrapper/pixmaps/dialog.png \ + wrapper/pixmaps/drawingarea.png \ + wrapper/pixmaps/entry.png \ + wrapper/pixmaps/eventbox.png \ + wrapper/pixmaps/expander.png \ + wrapper/pixmaps/fileselection.png \ + wrapper/pixmaps/fixed.png \ + wrapper/pixmaps/fontbutton.png \ + wrapper/pixmaps/fontselection.png \ + wrapper/pixmaps/fontselectiondialog.png \ + wrapper/pixmaps/frame.png \ + wrapper/pixmaps/globe.png \ + wrapper/pixmaps/globe-not.png \ + wrapper/pixmaps/handlebox.png \ + wrapper/pixmaps/hbox.png \ + wrapper/pixmaps/hbuttonbox.png \ + wrapper/pixmaps/hpaned.png \ + wrapper/pixmaps/hscale.png \ + wrapper/pixmaps/hscrollbar.png \ + wrapper/pixmaps/hseparator.png \ + wrapper/pixmaps/iconview.png \ + wrapper/pixmaps/image.png \ + wrapper/pixmaps/inc-border.png \ + wrapper/pixmaps/label.png \ + wrapper/pixmaps/menu.png \ + wrapper/pixmaps/menubar.png \ + wrapper/pixmaps/messagedialog.png \ + wrapper/pixmaps/missing.png \ + wrapper/pixmaps/notebook.png \ + wrapper/pixmaps/optionmenu.png \ + wrapper/pixmaps/progressbar.png \ + wrapper/pixmaps/radiobutton.png \ + wrapper/pixmaps/remove-check-label.png \ + wrapper/pixmaps/remove-menu.png \ + wrapper/pixmaps/scrolledwindow.png \ + wrapper/pixmaps/spinbutton.png \ + wrapper/pixmaps/statusbar.png \ + wrapper/pixmaps/table.png \ + wrapper/pixmaps/textview.png \ + wrapper/pixmaps/togglebutton.png \ + wrapper/pixmaps/toolbar.png \ + wrapper/pixmaps/treeview.png \ + wrapper/pixmaps/vbox.png \ + wrapper/pixmaps/vbuttonbox.png \ + wrapper/pixmaps/viewport.png \ + wrapper/pixmaps/vpaned.png \ + wrapper/pixmaps/vscale.png \ + wrapper/pixmaps/vscrollbar.png \ + wrapper/pixmaps/vseparator.png \ + wrapper/pixmaps/widget.png \ + wrapper/pixmaps/window.png + +REFS = \ + $(GLADE_SHARP_LIBS) \ + $(GLIB_SHARP_LIBS) \ + $(GTK_SHARP_LIBS) \ + $(MONO_CAIRO_LIBS) \ + -r:Mono.Posix \ + -r:System \ + -r:System.Core \ + -r:System.Xml + +dll_config = libstetic.dll.config +build_dll_config = $(ADDIN_BUILD)/$(dll_config) + +EXTRA_DIST = $(FILES) $(RES) $(dll_config) wrapper/pixmaps/COPIED + +$(ASSEMBLY): $(build_sources) $(build_resources) $(DEPS) + mkdir -p $(ADDIN_BUILD) + $(CSC) $(CSC_FLAGS) -debug -out:$@ -target:library $(build_resources:%=/resource:%) $(build_sources) $(REFS) + +$(build_dll_config): $(srcdir)/$(dll_config) + mkdir -p $(ADDIN_BUILD) + cp $(srcdir)/$(dll_config) $@ + +CLEANFILES = $(ASSEMBLY) $(ASSEMBLY).mdb $(build_dll_config) + +include $(top_srcdir)/Makefile.include diff --git a/main/src/addins/MonoDevelop.GtkCore2/libstetic/NoGuiDispatchAttribute.cs b/main/src/addins/MonoDevelop.GtkCore2/libstetic/NoGuiDispatchAttribute.cs new file mode 100644 index 0000000000..e1ad777512 --- /dev/null +++ b/main/src/addins/MonoDevelop.GtkCore2/libstetic/NoGuiDispatchAttribute.cs @@ -0,0 +1,9 @@ + +using System; + +namespace Stetic +{ + public class NoGuiDispatchAttribute: Attribute + { + } +} diff --git a/main/src/addins/MonoDevelop.GtkCore2/libstetic/ObjectReader.cs b/main/src/addins/MonoDevelop.GtkCore2/libstetic/ObjectReader.cs new file mode 100644 index 0000000000..2f463d1d52 --- /dev/null +++ b/main/src/addins/MonoDevelop.GtkCore2/libstetic/ObjectReader.cs @@ -0,0 +1,38 @@ + +using System; +using System.Collections; +using System.Xml; + +namespace Stetic +{ + public class ObjectReader + { + FileFormat format; + IProject proj; + internal ArrayList GladeChildStack = new ArrayList (); + + public ObjectReader (IProject proj, FileFormat format) + { + this.format = format; + this.proj = proj; + } + + public FileFormat Format { + get { return format; } + } + + public IProject Project { + get { return proj; } + } + + public virtual ObjectWrapper ReadObject (XmlElement elem, ObjectWrapper root) + { + return Stetic.ObjectWrapper.ReadObject (this, elem, root); + } + + public virtual void ReadExistingObject (ObjectWrapper wrapper, XmlElement elem) + {
+ Stetic.ObjectWrapper.ReadExistingObject (this, elem, wrapper);
+ } + } +} diff --git a/main/src/addins/MonoDevelop.GtkCore2/libstetic/ObjectWrapper.cs b/main/src/addins/MonoDevelop.GtkCore2/libstetic/ObjectWrapper.cs new file mode 100644 index 0000000000..6225267e24 --- /dev/null +++ b/main/src/addins/MonoDevelop.GtkCore2/libstetic/ObjectWrapper.cs @@ -0,0 +1,482 @@ +using System; +using System.Collections; +using System.CodeDom; +using System.Reflection; +using System.Runtime.InteropServices; +using System.Xml; + +namespace Stetic { + + public enum FileFormat { + Native, + Glade + } + + public abstract class ObjectWrapper : MarshalByRefObject, IDisposable + { + static Hashtable wrappers = new Hashtable (); + + protected IProject proj; + protected object wrapped; + protected ClassDescriptor classDescriptor; + SignalCollection signals; + internal Hashtable translationInfo; + Hashtable extendedData; + bool loading; + IObjectFrontend frontend; + bool disposed; + + // This id is used by the undo methods to identify an object. + // This id is not stored, since it's used only while the widget is being + // edited in the designer + string undoId = WidgetUtils.GetUndoId (); + + UndoManager undoManager; + static UndoManager defaultUndoManager = new UndoManager (true); + + public ObjectWrapper () + { + undoManager = defaultUndoManager; + } + + public SignalCollection Signals { + get { + if (signals == null) + signals = new SignalCollection (this); + return signals; + } + } + + public UndoManager UndoManager { + get { return GetUndoManagerInternal (); } + internal set { undoManager = value; } + } + + // Called the get a diff of changes since the last call to GetUndoDiff(). + // The returned object can be used to restore the object status by calling + // ApplyUndoRedoDiff. The implementation can use the UndoManager object to + // store status information. + public virtual object GetUndoDiff () + { + return null; + } + + // Called to apply a set of changes to the object. It returns + // a set of changes which can be used to reverse the operation. + public virtual object ApplyUndoRedoDiff (object diff) + { + return null; + } + + public string UndoId { + get { return undoId; } + internal set { undoId = value; } + } + + public virtual ObjectWrapper FindObjectByUndoId (string id) + { + if (undoId == id) + return this; + else + return null; + } + + internal virtual UndoManager GetUndoManagerInternal () + { + return undoManager; + } + + internal protected bool Loading { + get { return loading; } + set { loading = value; } + } + + public IObjectFrontend Frontend { + [NoGuiDispatch] + get { return frontend; } + [NoGuiDispatch] + set { + if (disposed) + throw new InvalidOperationException ("Can't bind component to disposed wrapper"); + if (frontend != null) + frontend.Dispose (); + frontend = value; + } + } + + public IDictionary ExtendedData { + get { + if (extendedData == null) + extendedData = new Hashtable (); + return extendedData; + } + } + + public void AttachDesigner (IDesignArea designer) + { + OnDesignerAttach (designer); + } + + public void DetachDesigner (IDesignArea designer) + { + OnDesignerDetach (designer); + } + + public virtual void Wrap (object obj, bool initialized) + { + this.wrapped = obj; + wrappers [GetIndentityObject (obj)] = this; + } + + public virtual void Dispose () + { + if (IsDisposed) + return; + + if (Disposed != null) + Disposed (this, EventArgs.Empty); + disposed = true; + if (frontend != null) + frontend.Dispose (); + frontend = null; + if (wrapped != null) + wrappers.Remove (GetIndentityObject (wrapped)); + System.Runtime.Remoting.RemotingServices.Disconnect (this); + } + + public bool IsDisposed { + [NoGuiDispatch] + get { return disposed; } + } + + public static ObjectWrapper Create (IProject proj, object wrapped, ObjectWrapper root) + { + ClassDescriptor klass = Registry.LookupClassByName (wrapped.GetType ().FullName); + ObjectWrapper wrapper = klass.CreateWrapper (); + if (root != null) { + wrapper.RootWrapperName = (root.RootWrapperName != null) ? root.RootWrapperName : root.Name; + } + wrapper.Loading = true; + wrapper.proj = proj; + wrapper.classDescriptor = klass; + wrapper.Wrap (wrapped, true); + wrapper.OnWrapped (); + wrapper.Loading = false; + return wrapper; + } + + internal static void Bind (IProject proj, ClassDescriptor klass, ObjectWrapper wrapper, object wrapped, bool initialized) + { + wrapper.proj = proj; + wrapper.classDescriptor = klass; + wrapper.Wrap (wrapped, initialized); + wrapper.OnWrapped (); + } + + public virtual void Read (ObjectReader reader, XmlElement element) + { + throw new System.NotImplementedException (); + } + + public virtual XmlElement Write (ObjectWriter writer) + { + throw new System.NotImplementedException (); + } + + public static ObjectWrapper ReadObject (ObjectReader reader, XmlElement elem, ObjectWrapper root) + { + string className = elem.GetAttribute ("class"); + ClassDescriptor klass; + if (reader.Format == FileFormat.Native) + klass = Registry.LookupClassByName (className); + else + klass = Registry.LookupClassByCName (className); + + if (klass == null) { + ErrorWidget we = new ErrorWidget (className, elem.GetAttribute ("id")); + ErrorWidgetWrapper wrap = (ErrorWidgetWrapper) Create (reader.Project, we, null); + wrap.Read (reader, elem); + return wrap; + } + if (!klass.SupportsGtkVersion (reader.Project.TargetGtkVersion)) { + ErrorWidget we = new ErrorWidget (className, klass.TargetGtkVersion, reader.Project.TargetGtkVersion, elem.GetAttribute ("id")); + ErrorWidgetWrapper wrap = (ErrorWidgetWrapper) Create (reader.Project, we, null); + wrap.Read (reader, elem); + return wrap; + } + + ObjectWrapper wrapper = klass.CreateWrapper (); + if (root != null) { + if (root.RootWrapperName != null) { + wrapper.RootWrapperName = root.RootWrapperName; + } + } + wrapper.classDescriptor = klass; + wrapper.proj = reader.Project;
+ return ReadExistingObject (reader, elem, wrapper); + }
+
+ public static ObjectWrapper ReadExistingObject (ObjectReader reader, XmlElement elem, ObjectWrapper wrapper)
+ {
+ try {
+ wrapper.OnBeginRead (reader.Format);
+ wrapper.Read (reader, elem);
+ return wrapper;
+ }
+ catch (Exception ex) {
+ Console.WriteLine (ex);
+ ErrorWidget we = new ErrorWidget (ex, elem.GetAttribute ("id"));
+ ErrorWidgetWrapper wrap = (ErrorWidgetWrapper) Create (reader.Project, we, null);
+ wrap.Read (reader, elem);
+ return wrap;
+ }
+ finally {
+ wrapper.OnEndRead (reader.Format);
+ }
+ } + + internal void GenerateInitCode (GeneratorContext ctx, CodeExpression var) + { + // Set the value for initialization properties. The value for those properties is + // usually set in the constructor, but top levels are created by the user, so + // those properties need to be explicitely set in the Gui.Build method. + foreach (PropertyDescriptor prop in ClassDescriptor.InitializationProperties) { + GeneratePropertySet (ctx, var, prop); + } + } + + internal protected virtual void GenerateBuildCode (GeneratorContext ctx, CodeExpression var) + { + // Write the widget properties + foreach (ItemGroup group in ClassDescriptor.ItemGroups) { + foreach (ItemDescriptor item in group) { + if (!item.SupportsGtkVersion (Project.TargetGtkVersion)) + continue; + PropertyDescriptor prop = item as PropertyDescriptor; + if (prop == null || !prop.IsRuntimeProperty) + continue; + if (ClassDescriptor.InitializationProperties != null && Array.IndexOf (ClassDescriptor.InitializationProperties, prop) != -1) + continue; + GeneratePropertySet (ctx, var, prop); + } + } + } + + internal protected virtual void GeneratePostBuildCode (GeneratorContext ctx, CodeExpression var) + { + } + + internal protected virtual CodeExpression GenerateObjectCreation (GeneratorContext ctx) + { + if (ClassDescriptor.InitializationProperties != null) { + CodeExpression[] paramters = new CodeExpression [ClassDescriptor.InitializationProperties.Length]; + for (int n=0; n < paramters.Length; n++) { + PropertyDescriptor prop = ClassDescriptor.InitializationProperties [n]; + paramters [n] = ctx.GenerateValue (prop.GetValue (Wrapped), prop.RuntimePropertyType, prop.Translatable && prop.IsTranslated (Wrapped)); + } + return new CodeObjectCreateExpression (WrappedTypeName.ToGlobalTypeRef (), paramters); + } else + return new CodeObjectCreateExpression (WrappedTypeName.ToGlobalTypeRef ()); + } + + protected virtual void GeneratePropertySet (GeneratorContext ctx, CodeExpression var, PropertyDescriptor prop) + { + object oval = prop.GetValue (Wrapped); + if (oval == null || (prop.HasDefault && prop.IsDefaultValue (oval))) + return; + + CodeExpression val = ctx.GenerateValue (oval, prop.RuntimePropertyType, prop.Translatable && prop.IsTranslated (Wrapped)); + CodeExpression cprop; + + TypedPropertyDescriptor tprop = prop as TypedPropertyDescriptor; + if (tprop == null || tprop.GladeProperty == prop) { + cprop = new CodePropertyReferenceExpression (var, prop.Name); + } else { + cprop = new CodePropertyReferenceExpression (var, tprop.GladeProperty.Name); + cprop = new CodePropertyReferenceExpression (cprop, prop.Name); + } + ctx.Statements.Add (new CodeAssignStatement (cprop, val)); + } + + public static ObjectWrapper Lookup (object obj) + { + if (obj == null) + return null; + else + return wrappers [GetIndentityObject (obj)] as Stetic.ObjectWrapper; + } + + public object Wrapped { + get { + return wrapped; + } + } + + public IProject Project { + get { + return proj; + } + } + + public ClassDescriptor ClassDescriptor { + get { return classDescriptor; } + } + + public virtual string WrappedTypeName { + get { return classDescriptor.WrappedTypeName; } + } + + public void NotifyChanged () + { + if (UndoManager.CanNotifyChanged (this)) + OnObjectChanged (new ObjectWrapperEventArgs (this)); + } + + internal void FireObjectChangedEvent () + { + OnObjectChanged (new ObjectWrapperEventArgs (this)); + } + + public abstract string Name { get; set; } + + public string RootWrapperName { get; protected set; } + + static object GetIndentityObject (object ob) + { + if (ob is Gtk.Container.ContainerChild) { + // We handle ContainerChild in a special way here since + // the Gtk.Container indexer always returns a new ContainerChild + // instance. We register its wrapper using ContainerChildHashItem + // to make sure that two different instance of the same ContainerChild + // can be found equal. + ContainerChildHashItem p = new ContainerChildHashItem (); + p.ContainerChild = (Gtk.Container.ContainerChild) ob; + return p; + } + else + return ob; + } + + public delegate void WrapperNotificationDelegate (object obj, string propertyName); + + public event WrapperNotificationDelegate Notify; + public event SignalEventHandler SignalAdded; + public event SignalEventHandler SignalRemoved; + public event SignalChangedEventHandler SignalChanged; + public event EventHandler Disposed; + + // Fired when any information of the object changes. + public event ObjectWrapperEventHandler ObjectChanged; + + protected virtual void OnBeginRead (FileFormat format) + { + loading = true; + } + + protected virtual void OnEndRead (FileFormat format) + { + loading = false; + } + + internal protected virtual void OnObjectChanged (ObjectWrapperEventArgs args) + { + if (frontend != null) + frontend.NotifyChanged (); + if (!Loading) { + if (proj != null) + proj.NotifyObjectChanged (args); + if (ObjectChanged != null) + ObjectChanged (this, args); + } + } + + protected virtual void EmitNotify (string propertyName) + { + if (!Loading) { + NotifyChanged (); + if (!Loading && Notify != null) + Notify (this, propertyName); + } + } + + internal protected virtual void OnSignalAdded (SignalEventArgs args) + { + OnObjectChanged (args); + if (!Loading) { + if (proj != null) + proj.NotifySignalAdded (args); + if (SignalAdded != null) + SignalAdded (this, args); + } + } + + internal protected virtual void OnSignalRemoved (SignalEventArgs args) + { + OnObjectChanged (args); + if (!Loading) { + if (proj != null) + proj.NotifySignalRemoved (args); + if (SignalRemoved != null) + SignalRemoved (this, args); + } + } + + internal protected virtual void OnSignalChanged (SignalChangedEventArgs args) + { + OnObjectChanged (args); + if (!Loading) { + if (proj != null) + proj.NotifySignalChanged (args); + if (SignalChanged != null) + SignalChanged (this, args); + } + } + + internal protected virtual void OnDesignerAttach (IDesignArea designer) + { + } + + internal protected virtual void OnDesignerDetach (IDesignArea designer) + { + } + + internal protected virtual void OnWrapped () + { + } + + internal protected virtual void DropObject (string data, Gtk.Widget obj) + { + // Called by DND.Drop + } + + public override object InitializeLifetimeService () + { + // Will be disconnected when calling Dispose + return null; + } + } + + // Wraps a ContainerChild, and properly implements GetHashCode() and Equals() + struct ContainerChildHashItem + { + public Gtk.Container.ContainerChild ContainerChild; + + public override int GetHashCode () + { + return ContainerChild.Parent.GetHashCode () + ContainerChild.Child.GetHashCode (); + } + + public override bool Equals (object ob) + { + if (!(ob is ContainerChildHashItem)) + return false; + ContainerChildHashItem ot = (ContainerChildHashItem) ob; + return ot.ContainerChild.Child == ContainerChild.Child && ot.ContainerChild.Parent == ContainerChild.Parent; + } + } + + public interface IObjectFrontend: IDisposable + { + void NotifyChanged (); + } +} diff --git a/main/src/addins/MonoDevelop.GtkCore2/libstetic/ObjectWrapperEventHandler.cs b/main/src/addins/MonoDevelop.GtkCore2/libstetic/ObjectWrapperEventHandler.cs new file mode 100644 index 0000000000..a9645e3384 --- /dev/null +++ b/main/src/addins/MonoDevelop.GtkCore2/libstetic/ObjectWrapperEventHandler.cs @@ -0,0 +1,20 @@ +using System; + +namespace Stetic +{ + public delegate void ObjectWrapperEventHandler (object sender, ObjectWrapperEventArgs args); + + public class ObjectWrapperEventArgs: EventArgs + { + ObjectWrapper objectWrapper; + + public ObjectWrapperEventArgs (ObjectWrapper objectWrapper) + { + this.objectWrapper = objectWrapper; + } + + public ObjectWrapper Wrapper { + get { return objectWrapper; } + } + } +} diff --git a/main/src/addins/MonoDevelop.GtkCore2/libstetic/ObjectWriter.cs b/main/src/addins/MonoDevelop.GtkCore2/libstetic/ObjectWriter.cs new file mode 100644 index 0000000000..cb2e7fd41f --- /dev/null +++ b/main/src/addins/MonoDevelop.GtkCore2/libstetic/ObjectWriter.cs @@ -0,0 +1,38 @@ + +using System; +using System.Xml; +using Stetic.Wrapper; + +namespace Stetic +{ + public class ObjectWriter + { + XmlDocument doc; + FileFormat format; + bool createUndo; + + public ObjectWriter (XmlDocument doc, FileFormat format) + { + this.doc = doc; + this.format = format; + } + + public FileFormat Format { + get { return format; } + } + + public XmlDocument XmlDocument { + get { return doc; } + } + + public bool CreateUndoInfo { + get { return createUndo; } + set { createUndo = value; } + } + + public virtual XmlElement WriteObject (ObjectWrapper wrapper) + { + return wrapper.Write (this); + } + } +} diff --git a/main/src/addins/MonoDevelop.GtkCore2/libstetic/ParamSpec.cs b/main/src/addins/MonoDevelop.GtkCore2/libstetic/ParamSpec.cs new file mode 100644 index 0000000000..c244285f22 --- /dev/null +++ b/main/src/addins/MonoDevelop.GtkCore2/libstetic/ParamSpec.cs @@ -0,0 +1,225 @@ +using GLib; +using Gtk; +using System; +using System.Collections; +using System.Runtime.InteropServices; + +namespace Stetic { + + public class ParamSpec : IDisposable { + IntPtr _obj; + + public ParamSpec (IntPtr raw) + { + Raw = raw; + } + + ~ParamSpec () + { + Dispose (); + } + + public void Dispose () + { + Raw = IntPtr.Zero; + GC.SuppressFinalize (this); + } + + IntPtr Raw { + get { + return _obj; + } + set { + if (_obj != IntPtr.Zero) + g_param_spec_unref (_obj); + _obj = value; + if (_obj != IntPtr.Zero) { + g_param_spec_ref (_obj); + g_param_spec_sink (_obj); + } + } + } + + public string Name { + get { + return GLib.Marshaller.Utf8PtrToString (g_param_spec_get_name (_obj)); + } + } + + public string Nick { + get { + return GLib.Marshaller.Utf8PtrToString (g_param_spec_get_nick (_obj)); + } + } + + public string Blurb { + get { + return GLib.Marshaller.Utf8PtrToString (g_param_spec_get_blurb (_obj)); + } + } + +/* [DllImport("libsteticglue")] + static extern bool stetic_param_spec_get_minimum (IntPtr pspec, ref GLib.Value value); + + public object Minimum { + get { + GLib.Value value = new GLib.Value (); + + if (stetic_param_spec_get_minimum (Raw, ref value)) + return value.Val; + else + return null; + } + } +*/ + public object Minimum { + get { + return null; + } + } + +/* [DllImport("libsteticglue")] + static extern bool stetic_param_spec_get_maximum (IntPtr pspec, ref GLib.Value value); + + public object Maximum { + get { + GLib.Value value = new GLib.Value (); + + if (stetic_param_spec_get_maximum (Raw, ref value)) + return value.Val; + else + return null; + } + } +*/ + public object Maximum { + get { + return null; + } + } + + 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 { + GLib.Value value = new GLib.Value (); + + if (stetic_param_spec_get_default (Raw, ref value)) + return value.Val; + else + return null; + } + } + + [DllImport("libsteticglue")] + static extern IntPtr stetic_param_spec_get_value_type (IntPtr obj); + + public IntPtr ValueType { + get { + return stetic_param_spec_get_value_type (_obj); + } + } +*/ + +/* [DllImport("libsteticglue")] + static extern bool stetic_param_spec_is_unichar (IntPtr pspec); + + public bool IsUnichar { + get { + return stetic_param_spec_is_unichar (_obj); + } + } +*/ + static Hashtable props = new Hashtable (), childProps = new Hashtable (); + + private class ParamSpecTypeHack : GLib.Object { + private ParamSpecTypeHack () : base (IntPtr.Zero) {} + + static Hashtable classes = new Hashtable (); + + public static IntPtr LookupGTypeClass (System.Type t) + { + if (classes[t] == null) { + GType gtype = GLib.Object.LookupGType (t); + classes[t] = g_type_class_ref (gtype.Val); + } + + return (IntPtr)classes[t]; + } + } + + public static ParamSpec LookupObjectProperty (Type type, string name) + { + string key = type.FullName + ":" + name; + if (props[key] != null) + return (ParamSpec)props[key]; + + IntPtr klass = ParamSpecTypeHack.LookupGTypeClass (type); + if (klass == IntPtr.Zero) + return null; + + IntPtr pspec_raw = g_object_class_find_property (klass, name); + if (pspec_raw == IntPtr.Zero) + return null; + + ParamSpec pspec = new ParamSpec (pspec_raw); + props[key] = pspec; + return pspec; + } + + public static ParamSpec LookupChildProperty (Type type, string name) + { + string key = type.FullName + ":" + name; + if (childProps[key] != null) + return (ParamSpec)childProps[key]; + + IntPtr klass = ParamSpecTypeHack.LookupGTypeClass (type); + if (klass == IntPtr.Zero) + return null; + + IntPtr pspec_raw = gtk_container_class_find_child_property (klass, name); + if (pspec_raw == IntPtr.Zero) + return null; + + ParamSpec pspec = new ParamSpec (pspec_raw); + childProps[key] = pspec; + return pspec; + } + + [DllImport("libgobject-2.0-0.dll")] + static extern void g_param_spec_ref (IntPtr obj); + + [DllImport("libgobject-2.0-0.dll")] + static extern void g_param_spec_unref (IntPtr obj); + + [DllImport("libgobject-2.0-0.dll")] + static extern void g_param_spec_sink (IntPtr obj); + + [DllImport("libgobject-2.0-0.dll")] + static extern IntPtr g_param_spec_get_name (IntPtr obj); + + [DllImport("libgobject-2.0-0.dll")] + static extern IntPtr g_param_spec_get_nick (IntPtr obj); + + [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); + + [DllImport("libgobject-2.0-0.dll")] + static extern IntPtr g_object_class_find_property (IntPtr klass, string name); + + [DllImport("libgtk-win32-2.0-0.dll")] + static extern IntPtr gtk_container_class_find_child_property (IntPtr klass, string name); + } +} diff --git a/main/src/addins/MonoDevelop.GtkCore2/libstetic/Placeholder.cs b/main/src/addins/MonoDevelop.GtkCore2/libstetic/Placeholder.cs new file mode 100644 index 0000000000..d5a6b69bec --- /dev/null +++ b/main/src/addins/MonoDevelop.GtkCore2/libstetic/Placeholder.cs @@ -0,0 +1,149 @@ +using Gtk; +using System; + +namespace Stetic { + + public class Placeholder : Gtk.DrawingArea, IEditableObject + { + // This id is used by the undo methods to identify a child of a container. + string undoId; + + public Placeholder () + { + undoId = WidgetUtils.GetUndoId (); + DND.DestSet (this, true); + Events |= Gdk.EventMask.ButtonPressMask; + WidgetFlags |= WidgetFlags.AppPaintable; + } + + internal string UndoId { + get { return undoId; } + set { undoId = value; } + } + + const int minSize = 10; + + protected override void OnSizeRequested (ref Requisition req) + { + base.OnSizeRequested (ref req); + if (req.Width <= 0) + req.Width = minSize; + if (req.Height <= 0) + req.Height = minSize; + } + + protected override void OnRealized () + { + base.OnRealized (); + } + + protected override bool OnExposeEvent (Gdk.EventExpose evt) + { + if (!IsDrawable) + return false; + + int width, height; + GdkWindow.GetSize (out width, out height); + + Gdk.Rectangle a = new Gdk.Rectangle (0,0,width,height); + + byte b2 = 210; + + int ssLT = 12; + int ssRB = 7; + double grey = 0.6; + double greyb1 = 0.9; + double greyb2 = 0.6; + + Gdk.Rectangle rect = a; + Cairo.Color back1 = new Cairo.Color (greyb1, greyb1, greyb1); + Cairo.Color back2 = new Cairo.Color (greyb2, greyb2, greyb2); + Cairo.Color cdark = new Cairo.Color (grey, grey, grey, 1); + Cairo.Color clight = new Cairo.Color (grey, grey, grey, 0); + using (Cairo.Context cr = Gdk.CairoHelper.Create (evt.Window)) { + + DrawGradient (cr, rect, 0, 0, 1, 1, back1, back2); + + rect.X = a.X; + rect.Y = a.Y; + rect.Height = ssLT; + rect.Width = a.Width; + DrawGradient (cr, rect, 0, 0, 0, 1, cdark, clight); + + rect.Y = a.Bottom - ssRB; + rect.Height = ssRB; + DrawGradient (cr, rect, 0, 0, 0, 1, clight, cdark); + + rect.X = a.X; + rect.Y = a.Y; + rect.Width = ssLT; + rect.Height = a.Height; + DrawGradient (cr, rect, 0, 0, 1, 0, cdark, clight); + + rect.X = a.Right - ssRB; + rect.Width = ssRB; + DrawGradient (cr, rect, 0, 0, 1, 0, clight, cdark); + + Gdk.GC gc = new Gdk.GC (GdkWindow); + gc.RgbBgColor = new Gdk.Color (b2,b2,b2); + gc.RgbFgColor = new Gdk.Color (b2,b2,b2); + GdkWindow.DrawRectangle (gc, false, a.X, a.Y, a.Width, a.Height); + gc.Dispose (); + } + + return base.OnExposeEvent (evt); + } + + void DrawGradient (Cairo.Context cr, Gdk.Rectangle rect, int fx, int fy, int fw, int fh, Cairo.Color c1, Cairo.Color c2) + { + cr.NewPath (); + cr.MoveTo (rect.X, rect.Y); + cr.RelLineTo (rect.Width, 0); + cr.RelLineTo (0, rect.Height); + cr.RelLineTo (-rect.Width, 0); + cr.RelLineTo (0, -rect.Height); + cr.ClosePath (); + Cairo.LinearGradient pat = new Cairo.LinearGradient (rect.X + rect.Width*fx, rect.Y + rect.Height*fy, rect.X + rect.Width*fw, rect.Y + rect.Height*fh); + pat.AddColorStop (0, c1); + pat.AddColorStop (1, c2); + cr.Pattern = pat; + cr.FillPreserve (); + } + + bool IEditableObject.CanDelete { + get { return true; } + } + + bool IEditableObject.CanPaste { + get { return true; } + } + + bool IEditableObject.CanCut { + get { return false; } + } + + bool IEditableObject.CanCopy { + get { return false; } + } + + void IEditableObject.Delete () + { + Stetic.Wrapper.Container wc = Stetic.Wrapper.Container.LookupParent (this); + if (wc != null) + wc.Delete (this); + } + + void IEditableObject.Paste () + { + Clipboard.Paste (this); + } + + void IEditableObject.Cut () + { + } + + void IEditableObject.Copy () + { + } + } +} diff --git a/main/src/addins/MonoDevelop.GtkCore2/libstetic/ProjectIconFactory.cs b/main/src/addins/MonoDevelop.GtkCore2/libstetic/ProjectIconFactory.cs new file mode 100644 index 0000000000..79d6918625 --- /dev/null +++ b/main/src/addins/MonoDevelop.GtkCore2/libstetic/ProjectIconFactory.cs @@ -0,0 +1,335 @@ + +using System; +using System.CodeDom; +using System.Xml; +using System.Collections; + +namespace Stetic +{ + public class ProjectIconFactory + { + ProjectIconSetCollection icons = new ProjectIconSetCollection (); + + public ProjectIconFactory() + { + } + + public ProjectIconSetCollection Icons { + get { return icons; } + } + + public ProjectIconSet GetIcon (string name) + { + foreach (ProjectIconSet icon in icons) + if (icon.Name == name) + return icon; + return null; + } + + public XmlElement Write (XmlDocument doc) + { + XmlElement elem = doc.CreateElement ("icon-factory"); + foreach (ProjectIconSet icon in icons) + elem.AppendChild (icon.Write (doc)); + return elem; + } + + public void Read (IProject project, XmlElement elem) + { + icons.Clear (); + foreach (XmlElement child in elem.SelectNodes ("icon-set")) { + ProjectIconSet icon = new ProjectIconSet (); + icon.Read (project, child); + icons.Add (icon); + } + } + + public void GenerateBuildCode (GeneratorContext ctx) + { + string varName = ctx.NewId (); + CodeVariableDeclarationStatement varDec = new CodeVariableDeclarationStatement (typeof(Gtk.IconFactory).ToGlobalTypeRef (), varName); + varDec.InitExpression = new CodeObjectCreateExpression (typeof(Gtk.IconFactory).ToGlobalTypeRef ()); + ctx.Statements.Add (varDec); + + CodeVariableReferenceExpression var = new CodeVariableReferenceExpression (varName); + foreach (ProjectIconSet icon in icons) { + + CodeExpression exp = new CodeMethodInvokeExpression ( + var, + "Add", + new CodePrimitiveExpression (icon.Name), + icon.GenerateObjectBuild (ctx) + ); + ctx.Statements.Add (exp); + } + + CodeExpression addd = new CodeMethodInvokeExpression ( + var, + "AddDefault" + ); + ctx.Statements.Add (addd); + } + + public Gdk.Pixbuf RenderIcon (IProject project, string name, Gtk.IconSize size) + { + ProjectIconSet icon = GetIcon (name); + if (icon == null) + return null; + + foreach (ProjectIconSource src in icon.Sources) { + if (src.SizeWildcarded || src.Size == size) + return src.Image.GetScaledImage (project, size); + } + + return icon.Sources [0].Image.GetScaledImage (project, size); + } + + public Gdk.Pixbuf RenderIcon (IProject project, string name, int size) + { + ProjectIconSet icon = GetIcon (name); + if (icon == null) + return null; + + return icon.Sources [0].Image.GetScaledImage (project, size, size); + } + } + + public class ProjectIconSet + { + ProjectIconSourceCollection sources = new ProjectIconSourceCollection (); + string name; + + public string Name { + get { return name; } + set { name = value; } + } + + public ProjectIconSourceCollection Sources { + get { return sources; } + } + + public XmlElement Write (XmlDocument doc) + { + XmlElement elem = doc.CreateElement ("icon-set"); + elem.SetAttribute ("id", name); + foreach (ProjectIconSource src in sources) + elem.AppendChild (src.Write (doc)); + return elem; + } + + public void Read (IProject project, XmlElement elem) + { + sources.Clear (); + name = elem.GetAttribute ("id"); + if (name.Length == 0) + throw new InvalidOperationException ("Name attribute not found"); + + foreach (XmlElement child in elem.SelectNodes ("source")) { + ProjectIconSource src = new ProjectIconSource (); + src.Read (project, child); + sources.Add (src); + } + } + + internal CodeExpression GenerateObjectBuild (GeneratorContext ctx) + { + string varName = ctx.NewId (); + CodeVariableDeclarationStatement varDec = new CodeVariableDeclarationStatement (typeof(Gtk.IconSet).ToGlobalTypeRef (), varName); + ctx.Statements.Add (varDec); + + CodeVariableReferenceExpression var = new CodeVariableReferenceExpression (varName); + + if (sources.Count == 1 && sources[0].AllWildcarded) { + varDec.InitExpression = new CodeObjectCreateExpression ( + typeof(Gtk.IconSet).ToGlobalTypeRef (), + sources[0].Image.ToCodeExpression (ctx) + ); + } else { + varDec.InitExpression = new CodeObjectCreateExpression (typeof(Gtk.IconSet).ToGlobalTypeRef ()); + foreach (ProjectIconSource src in sources) { + CodeExpression exp = new CodeMethodInvokeExpression ( + var, + "AddSource", + src.GenerateObjectBuild (ctx) + ); + ctx.Statements.Add (exp); + } + } + return var; + } + } + + public class ProjectIconSource: Gtk.IconSource + { + ImageInfo imageInfo; + + public ImageInfo Image { + get { return imageInfo; } + set { imageInfo = value; } + } + + public bool AllWildcarded { + get { + return DirectionWildcarded && SizeWildcarded && StateWildcarded; + } + set { + DirectionWildcarded = SizeWildcarded = StateWildcarded = true; + } + } + + public XmlElement Write (XmlDocument doc) + { + XmlElement elem = doc.CreateElement ("source"); + + XmlElement prop = doc.CreateElement ("property"); + prop.SetAttribute ("name", "Image"); + prop.InnerText = imageInfo.ToString (); + elem.AppendChild (prop); + + if (!SizeWildcarded) { + prop = doc.CreateElement ("property"); + prop.SetAttribute ("name", "Size"); + prop.InnerText = Size.ToString (); + elem.AppendChild (prop); + } + + if (!StateWildcarded) { + prop = doc.CreateElement ("property"); + prop.SetAttribute ("name", "State"); + prop.InnerText = State.ToString (); + elem.AppendChild (prop); + } + + if (!DirectionWildcarded) { + prop = doc.CreateElement ("property"); + prop.SetAttribute ("name", "Direction"); + prop.InnerText = Direction.ToString (); + elem.AppendChild (prop); + } + + return elem; + } + + public void Read (IProject project, XmlElement elem) + { + XmlElement prop = elem.SelectSingleNode ("property[@name='Image']") as XmlElement; + if (prop != null) + imageInfo = ImageInfo.FromString (prop.InnerText); + + prop = elem.SelectSingleNode ("property[@name='Size']") as XmlElement; + if (prop != null && prop.InnerText != "*") { + SizeWildcarded = false; + Size = (Gtk.IconSize) Enum.Parse (typeof(Gtk.IconSize), prop.InnerText); + } else + SizeWildcarded = true; + + prop = elem.SelectSingleNode ("property[@name='State']") as XmlElement; + if (prop != null && prop.InnerText != "*") { + StateWildcarded = false; + State = (Gtk.StateType) Enum.Parse (typeof(Gtk.StateType), prop.InnerText); + } else + StateWildcarded = true; + + prop = elem.SelectSingleNode ("property[@name='Direction']") as XmlElement; + if (prop != null && prop.InnerText != "*") { + DirectionWildcarded = false; + Direction = (Gtk.TextDirection) Enum.Parse (typeof(Gtk.TextDirection), prop.InnerText); + } else + DirectionWildcarded = true; + } + + internal CodeExpression GenerateObjectBuild (GeneratorContext ctx) + { + string varName = ctx.NewId (); + CodeVariableDeclarationStatement varDec = new CodeVariableDeclarationStatement (typeof(Gtk.IconSource).ToGlobalTypeRef (), varName); + varDec.InitExpression = new CodeObjectCreateExpression (typeof(Gtk.IconSource).ToGlobalTypeRef ()); + ctx.Statements.Add (varDec); + + CodeVariableReferenceExpression var = new CodeVariableReferenceExpression (varName); + + ctx.Statements.Add (new CodeAssignStatement ( + new CodePropertyReferenceExpression (var, "Pixbuf"), + imageInfo.ToCodeExpression (ctx) + )); + + if (!SizeWildcarded) { + ctx.Statements.Add (new CodeAssignStatement ( + new CodePropertyReferenceExpression (var, "SizeWildcarded"), + new CodePrimitiveExpression (false) + )); + ctx.Statements.Add (new CodeAssignStatement ( + new CodePropertyReferenceExpression (var, "Size"), + new CodeFieldReferenceExpression ( + new CodeTypeReferenceExpression (new CodeTypeReference ("Gtk.IconSize", CodeTypeReferenceOptions.GlobalReference)), + Size.ToString () + ) + )); + } + + if (!StateWildcarded) { + ctx.Statements.Add (new CodeAssignStatement ( + new CodePropertyReferenceExpression (var, "StateWildcarded"), + new CodePrimitiveExpression (false) + )); + ctx.Statements.Add (new CodeAssignStatement ( + new CodePropertyReferenceExpression (var, "State"), + new CodeFieldReferenceExpression ( + new CodeTypeReferenceExpression (new CodeTypeReference ("Gtk.StateType", CodeTypeReferenceOptions.GlobalReference)), + State.ToString () + ) + )); + } + + if (!DirectionWildcarded) { + ctx.Statements.Add (new CodeAssignStatement ( + new CodePropertyReferenceExpression (var, "DirectionWildcarded"), + new CodePrimitiveExpression (false) + )); + ctx.Statements.Add (new CodeAssignStatement ( + new CodePropertyReferenceExpression (var, "Direction"), + new CodeFieldReferenceExpression ( + new CodeTypeReferenceExpression (new CodeTypeReference ("Gtk.TextDirection", CodeTypeReferenceOptions.GlobalReference)), + Direction.ToString () + ) + )); + } + + return var; + } + } + + public class ProjectIconSetCollection: CollectionBase + { + public ProjectIconSet this [int n] { + get { return (ProjectIconSet) List [n]; } + } + + public void Add (ProjectIconSet icon) + { + List.Add (icon); + } + + public void Remove (ProjectIconSet icon) + { + List.Remove (icon); + } + } + + public class ProjectIconSourceCollection: CollectionBase + { + public void AddRange (ICollection c) + { + foreach (ProjectIconSource s in c) + List.Add (s); + } + + public ProjectIconSource this [int n] { + get { return (ProjectIconSource) List [n]; } + } + + public void Add (ProjectIconSource source) + { + List.Add (source); + } + } +} diff --git a/main/src/addins/MonoDevelop.GtkCore2/libstetic/PropertyDescriptor.cs b/main/src/addins/MonoDevelop.GtkCore2/libstetic/PropertyDescriptor.cs new file mode 100644 index 0000000000..3a4a5e9ffb --- /dev/null +++ b/main/src/addins/MonoDevelop.GtkCore2/libstetic/PropertyDescriptor.cs @@ -0,0 +1,310 @@ +using System; +using System.ComponentModel; +using System.Collections; +using System.Reflection; +using System.Xml; + +namespace Stetic { + + class TranslationInfo { + public bool Translated; + public string Context, Comment; + } + + public abstract class PropertyDescriptor : ItemDescriptor + { + protected string label, description, gladeName; + protected bool gladeOverride; + + protected bool isRuntimeProperty, hasDefault, initWithName; + protected Type editorType; + protected object minimum, maximum; + protected object defaultValue; + protected TypeConverter typeConverter; + protected bool translatable; + + protected PropertyDescriptor () + { + } + + 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"); + + if (label == null) + label = elem.GetAttribute ("name"); + + if (elem.HasAttribute ("description")) + description = elem.GetAttribute ("description"); + + if (elem.HasAttribute ("min")) + minimum = StringToValue (elem.GetAttribute ("min")); + + if (elem.HasAttribute ("max")) + maximum = StringToValue (elem.GetAttribute ("max")); + + if (elem.HasAttribute ("glade-override")) + gladeOverride = true; + + if (elem.HasAttribute ("glade-name")) + gladeName = elem.GetAttribute ("glade-name"); + + if (elem.HasAttribute ("init-with-name")) + initWithName = true; + + if (elem.HasAttribute ("translatable")) + translatable = true; + + if (elem.HasAttribute ("default")) { + defaultValue = StringToValue (elem.GetAttribute ("default")); + hasDefault = true; + } + + string convTypeName = elem.GetAttribute ("type-converter"); + if (convTypeName.Length > 0) { + Type type = Registry.GetType (convTypeName, true); + typeConverter = (TypeConverter) Activator.CreateInstance (type); + } + } + + // The property's user-visible name + public virtual string Label { + get { + return label; + } + } + + // The property's type + public abstract Type PropertyType { + get ; + } + + // The property's user-visible description + public virtual string Description { + get { + return description; + } + } + + // The property's GUI editor type, if overridden + public virtual Type EditorType { + get { + return editorType; + } + } + + // The property's minimum value, if declared + public virtual object Minimum { + get { + return minimum; + } + } + + // The property's maximum value, if declared + public virtual object Maximum { + get { + return maximum; + } + } + + public virtual string InternalChildId { + get { return null; } + } + + // Whether or not the property has a default value + public virtual bool HasDefault { + get { + return hasDefault; + } + set { + hasDefault = value; + } + } + + public virtual bool IsDefaultValue (object value) + { + if (value == null) + return true; + if (defaultValue != null) + return value.Equals (defaultValue); + return false; + } + + public virtual void ResetValue (object instance) + { + if (HasDefault) + SetValue (instance, defaultValue); + } + + // The property's type at run time + public virtual Type RuntimePropertyType { + get { return PropertyType; } + } + + // Gets the value of the property on @obj + public abstract object GetValue (object obj); + + // Gets the value of the property on @obj, bypassing the wrapper. + public virtual object GetRuntimeValue (object obj) + { + return GetValue (obj); + } + + // Whether or not the property is writable + public virtual bool CanWrite { + get { return true; } + } + + // Sets the value of the property on @obj + public abstract void SetValue (object obj, object value); + + // Sets the value of the property on @obj, bypassing the wrapper. + public virtual void SetRuntimeValue (object obj, object value) + { + SetValue (obj, value); + } + + // Parses a string an returns a value valid for this property + public virtual object StringToValue (string value) + { + if (typeConverter != null && typeConverter.CanConvertFrom (typeof(string))) + return typeConverter.ConvertFromString (value); + else if (PropertyType.IsEnum) + return Enum.Parse (PropertyType, value); + else if (PropertyType == typeof(ImageInfo)) + return ImageInfo.FromString (value); + else if (PropertyType == typeof(string[])) + return string.IsNullOrEmpty (value) ? null : value.Split ('\n'); + else if (PropertyType == typeof(DateTime)) + return new DateTime (long.Parse (value)); + else if (PropertyType == typeof(TimeSpan)) + return new TimeSpan (long.Parse (value)); + else if (PropertyType == typeof(double)) { + try { + return Convert.ChangeType (value, PropertyType); + } + catch (InvalidCastException) { + return Convert.ChangeType (value, PropertyType, System.Globalization.CultureInfo.InvariantCulture); + } + } else + return Convert.ChangeType (value, PropertyType, System.Globalization.CultureInfo.InvariantCulture); + } + + // Returns a string representation of the provided property value + public virtual string ValueToString (object value) + { + if (typeConverter != null && typeConverter.CanConvertTo (typeof(string))) + return typeConverter.ConvertToString (value); + else if (PropertyType == typeof(string[])) + return value == null ? string.Empty : string.Join ("\n", (string[])value); + else if (PropertyType == typeof(DateTime)) + return ((DateTime)value).Ticks.ToString (); + else if (PropertyType == typeof(TimeSpan)) + return ((TimeSpan)value).Ticks.ToString (); + else if (PropertyType == typeof(double)) + return ((double)value).ToString (System.Globalization.CultureInfo.InvariantCulture); + else + return value.ToString (); + } + + public virtual bool InitWithName { + get { + return initWithName; + } + } + + public virtual bool IsRuntimeProperty { + get { return isRuntimeProperty; } + } + + public virtual bool Translatable { + get { + return translatable; + } + } + + public virtual bool IsTranslated (object obj) + { + if (!translatable) + return false; + + ObjectWrapper wrapper = ObjectWrapper.Lookup (obj); + if (wrapper == null) + return false; + + // Since translatable properties are assumed to be translated + // by default, we return true if there is no TranslationInfo + // for the object + + if (wrapper.translationInfo == null) + return true; + + TranslationInfo info = (TranslationInfo)wrapper.translationInfo[obj]; + return (info == null || info.Translated == true); + } + + public virtual void SetTranslated (object obj, bool translated) + { + ObjectWrapper wrapper = ObjectWrapper.Lookup (obj); + if (wrapper == null) return; + + if (wrapper.translationInfo == null) + wrapper.translationInfo = new Hashtable (); + + TranslationInfo info = (TranslationInfo)wrapper.translationInfo[obj]; + if (info == null) { + info = new TranslationInfo (); + wrapper.translationInfo[obj] = info; + } + + if (translated) + info.Translated = true; + else + info.Translated = false; + // We leave the old Context and Comment around, so that if + // you toggle Translated off and then back on, the old info + // is still there. + } + + public virtual string TranslationContext (object obj) + { + ObjectWrapper wrapper = ObjectWrapper.Lookup (obj); + if (wrapper == null || wrapper.translationInfo == null) return null; + + TranslationInfo info = (TranslationInfo)wrapper.translationInfo[obj]; + return info != null ? info.Context : null; + } + + public virtual void SetTranslationContext (object obj, string context) + { + SetTranslated (obj, true); + + ObjectWrapper wrapper = ObjectWrapper.Lookup (obj); + if (wrapper == null) return; + ((TranslationInfo)wrapper.translationInfo[obj]).Context = context; + } + + public virtual string TranslationComment (object obj) + { + ObjectWrapper wrapper = ObjectWrapper.Lookup (obj); + if (wrapper == null || wrapper.translationInfo == null) return null; + + TranslationInfo info = (TranslationInfo)wrapper.translationInfo[obj]; + return info != null ? info.Comment : null; + } + + public virtual void SetTranslationComment (object obj, string comment) + { + SetTranslated (obj, true); + + ObjectWrapper wrapper = ObjectWrapper.Lookup (obj); + if (wrapper == null) return; + ((TranslationInfo)wrapper.translationInfo[obj]).Comment = comment; + } + } +} diff --git a/main/src/addins/MonoDevelop.GtkCore2/libstetic/PropertyEditorAttribute.cs b/main/src/addins/MonoDevelop.GtkCore2/libstetic/PropertyEditorAttribute.cs new file mode 100644 index 0000000000..05c2bb720b --- /dev/null +++ b/main/src/addins/MonoDevelop.GtkCore2/libstetic/PropertyEditorAttribute.cs @@ -0,0 +1,36 @@ +using System; + +namespace Stetic { + + [AttributeUsage (AttributeTargets.Class)] + public sealed class PropertyEditorAttribute : Attribute { + + public PropertyEditorAttribute (string property, string evt) + { + this.property = property; + this.evt = evt; + } + + public PropertyEditorAttribute (string property) : this (property, property + "Changed") {} + + string property; + public string Property { + get { + return property; + } + set { + property = value; + } + } + + string evt; + public string Event { + get { + return evt; + } + set { + evt = value; + } + } + } +} diff --git a/main/src/addins/MonoDevelop.GtkCore2/libstetic/PropertyEditorCell.cs b/main/src/addins/MonoDevelop.GtkCore2/libstetic/PropertyEditorCell.cs new file mode 100644 index 0000000000..faec75ffc3 --- /dev/null +++ b/main/src/addins/MonoDevelop.GtkCore2/libstetic/PropertyEditorCell.cs @@ -0,0 +1,302 @@ + +using System; +using System.Collections; +using Gtk; +using Gdk; + +namespace Stetic +{ + public class PropertyEditorCell + { + Pango.Layout layout; + PropertyDescriptor property; + object obj; + Gtk.Widget container; + + static Hashtable editors; + static PropertyEditorCell Default = new PropertyEditorCell (); + static Hashtable cellCache = new Hashtable (); + + static PropertyEditorCell () + { + editors = new Hashtable (); + + editors[typeof (bool)] = typeof (Stetic.Editor.Boolean); + editors[typeof (byte)] = typeof (Stetic.Editor.IntRange); + editors[typeof (sbyte)] = typeof (Stetic.Editor.IntRange); + editors[typeof (short)] = typeof (Stetic.Editor.IntRange); + editors[typeof (ushort)] = typeof (Stetic.Editor.IntRange); + editors[typeof (int)] = typeof (Stetic.Editor.IntRange); + editors[typeof (uint)] = typeof (Stetic.Editor.IntRange); + editors[typeof (long)] = typeof (Stetic.Editor.IntRange); + editors[typeof (ulong)] = typeof (Stetic.Editor.IntRange); + editors[typeof (float)] = typeof (Stetic.Editor.FloatRange); + editors[typeof (double)] = typeof (Stetic.Editor.FloatRange); + editors[typeof (char)] = typeof (Stetic.Editor.Char); + editors[typeof (string)] = typeof (Stetic.Editor.TextEditor); + editors[typeof (DateTime)] = typeof (Stetic.Editor.DateTimeEditorCell); + editors[typeof (TimeSpan)] = typeof (Stetic.Editor.TimeSpanEditorCell); + editors[typeof (string[])] = typeof (Stetic.Editor.StringArray); + editors[typeof (Gdk.Color)] = typeof (Stetic.Editor.Color); + editors[typeof (Stetic.ImageInfo)] = typeof (Stetic.Editor.ImageSelector); + } + + public object Instance { + get { return obj; } + } + + public PropertyDescriptor Property { + get { return property; } + } + + public Gtk.Widget Container { + get { return container; } + } + + public void Initialize (Widget container, PropertyDescriptor property, object obj) + { + this.container = container; + layout = new Pango.Layout (container.PangoContext); + layout.Width = -1; + + Pango.FontDescription des = container.Style.FontDescription.Copy(); + layout.FontDescription = des; + + this.property = property; + this.obj = obj; + Initialize (); + } + + public EditSession StartEditing (Gdk.Rectangle cell_area, StateType state) + { + IPropertyEditor ed = CreateEditor (cell_area, state); + if (ed == null) + return null; + ed.Initialize (property); + if (obj != null) { + ed.AttachObject (obj); + ed.Value = property.GetValue (obj); + } + return new EditSession (container, obj, property, ed); + } + + protected virtual string GetValueText () + { + if (obj == null) return ""; + object val = property.GetValue (obj); + if (val == null) return ""; + else return property.ValueToString (val); + } + + string GetNormalizedText () + { + string s = GetValueText (); + if (s == null) + return ""; + + int i = s.IndexOf ('\n'); + if (i == -1) + return s; + + s = s.TrimStart ('\n',' ','\t'); + i = s.IndexOf ('\n'); + if (i != -1) + return s.Substring (0, i) + "..."; + else + return s; + } + + public object Value { + get { return obj != null ? property.GetValue (obj) : null; } + } + + protected virtual void Initialize () + { + layout.SetText (GetNormalizedText ()); + } + + public virtual void GetSize (int availableWidth, out int width, out int height) + { + layout.GetPixelSize (out width, out height); + } + + public virtual void Render (Drawable window, Gdk.Rectangle bounds, StateType state) + { + int w, h; + layout.GetPixelSize (out w, out h); + int dy = (bounds.Height - h) / 2; + window.DrawLayout (container.Style.TextGC (state), bounds.X, dy + bounds.Y, layout); + } + + protected virtual IPropertyEditor CreateEditor (Gdk.Rectangle cell_area, StateType state) + { + Type editorType = property.EditorType; + + if (editorType == null) { + editorType = GetEditorForType (property.PropertyType); + if (editorType == null) + return null; + } + + IPropertyEditor editor = Activator.CreateInstance (editorType) as IPropertyEditor; + if (editor == null) + throw new Exception ("The property editor '" + editorType + "' must implement the interface IPropertyEditor"); + return editor; + } + + public static Type GetEditorForType (Type propertyType) + { + if (propertyType.IsEnum) { + if (propertyType.IsDefined (typeof (FlagsAttribute), true)) + return typeof (Stetic.Editor.Flags); + else + return typeof (Stetic.Editor.Enumeration); + } else { + return editors [propertyType] as Type; + } + } + + public static PropertyEditorCell GetPropertyCell (PropertyDescriptor property) + { + Type editorType = property.EditorType; + + if (editorType == null) + editorType = GetEditorForType (property.PropertyType); + + if (editorType == null) + return Default; + + if (typeof(IPropertyEditor).IsAssignableFrom (editorType)) { + if (!typeof(Gtk.Widget).IsAssignableFrom (editorType)) + throw new Exception ("The property editor '" + editorType + "' must be a Gtk Widget"); + return Default; + } + + PropertyEditorCell cell = (PropertyEditorCell) cellCache [editorType]; + if (cell != null) + return cell; + + if (!typeof(PropertyEditorCell).IsAssignableFrom (editorType)) + throw new Exception ("The property editor '" + editorType + "' must be a subclass of Stetic.PropertyEditorCell or implement Stetic.IPropertyEditor"); + + cell = (PropertyEditorCell) Activator.CreateInstance (editorType); + cellCache [editorType] = cell; + return cell; + } + } + + + class DefaultPropertyEditor: Gtk.Entry, IPropertyEditor + { + PropertyDescriptor property; + + public void Initialize (PropertyDescriptor property) + { + this.property = property; + } + + public void AttachObject (object obj) + { + } + + public object Value { + get { + return Convert.ChangeType (Text, property.PropertyType); + } + set { + if (value == null) + Text = ""; + else + Text = Convert.ToString (value); + } + } + + protected override void OnChanged () + { + base.OnChanged (); + if (ValueChanged != null) + ValueChanged (this, EventArgs.Empty); + } + + public event EventHandler ValueChanged; + } + + public class EditSession + { + PropertyDescriptor property; + object obj; + Gtk.Widget container; + IPropertyEditor currentEditor; + bool syncing; + object initialVal; + + public EditSession (Gtk.Widget container, object instance, PropertyDescriptor property, IPropertyEditor currentEditor) + { + this.property = property; + this.obj = instance; + this.container = container; + this.currentEditor = currentEditor; + currentEditor.ValueChanged += OnValueChanged; + initialVal = currentEditor.Value; + } + + public object Instance { + get { return obj; } + } + + public PropertyDescriptor Property { + get { return property; } + } + + public Gtk.Widget Container { + get { return container; } + } + + public IPropertyEditor Editor { + get { return currentEditor; } + } + + void OnValueChanged (object s, EventArgs a) + { + if (!syncing) { + syncing = true; + property.SetValue (obj, currentEditor.Value); + Stetic.Wrapper.Widget wrapper = Stetic.Wrapper.Widget.Lookup (obj) as Stetic.Wrapper.Widget; + if (wrapper != null) + wrapper.NotifyChanged (); + syncing = false; + } + } + + public void AttachObject (object ob) + { + if (ob == null) + throw new ArgumentNullException ("ob"); + + syncing = true; + this.obj = ob; + currentEditor.AttachObject (obj); + + // It is the responsibility of the editor to convert value types + object initial = property.GetValue (obj); + currentEditor.Value = initial; + + syncing = false; + } + + public void UpdateEditor () + { + if (!syncing) { + syncing = true; + currentEditor.Value = property.GetValue (obj); + syncing = false; + } + } + + public void Dispose () + { + if (!object.Equals (initialVal, currentEditor.Value)) + OnValueChanged (null, null); + } + } +} diff --git a/main/src/addins/MonoDevelop.GtkCore2/libstetic/RadioGroupManager.cs b/main/src/addins/MonoDevelop.GtkCore2/libstetic/RadioGroupManager.cs new file mode 100644 index 0000000000..73c8fb8f69 --- /dev/null +++ b/main/src/addins/MonoDevelop.GtkCore2/libstetic/RadioGroupManager.cs @@ -0,0 +1,212 @@ +using System; +using System.Collections; +using System.Reflection; +using System.CodeDom; + +// The stetic representation of "radio widget" (Gtk.RadioButton, +// Gtk.RadioToolButton, and Gtk.RadioMenuItem) groups is that the +// groups have names, and each widget's "Group" property stores the +// name of its group. The glade representation is similar, except that +// the group names aren't arbitrary; they have to be the name of the +// first widget in the group. (On disk, the "group leader" has no +// "group" property, and the other widgets have the leader's name as +// their group property.) +// +// The internal gtk representation of groups is that each radio widget +// has a GLib.SList "Group" property. The content of the list is +// essentially opaque. (For Gtk.RadioButton, the list contains all of +// the RadioButtons in the group. But for Gtk.ToolRadioButton it +// contains pointers to internal widgets, not the ToolRadioButtons +// themselves.) The only thing we can do with them then is to read one +// widget's group and then immediately assign it to another widget. We +// can't look into the list, or assume that a widget's Group property +// will keep the same value if any other widget's Group changes. +// +// Each radio widget type wrapper class keeps a static +// RadioGroupManager to handle this string<->GLib.SList translation +// for it. + +namespace Stetic { + + public class RadioGroup { + public string Name; + public ArrayList Widgets; + + public RadioGroup (string name) + { + Name = name; + Widgets = new ArrayList (); + } + } + + public class RadioGroupManager: IRadioGroupManager + { + PropertyInfo groupProperty; + ArrayList groups; + Hashtable widgets; + + public RadioGroupManager (Type widgetType) + { + groupProperty = widgetType.GetProperty ("Group"); + if (groupProperty == null || groupProperty.PropertyType != typeof (GLib.SList)) + throw new ArgumentException ("No 'public GLib.SList Group' property on '" + widgetType.FullName + "'"); + + groups = new ArrayList (); + widgets = new Hashtable (); + } + + public event GroupsChangedDelegate GroupsChanged; + + void EmitGroupsChanged () + { + if (GroupsChanged != null) + GroupsChanged (); + } + + public IEnumerable GroupNames { + get { + string[] names = new string[groups.Count]; + for (int i = 0; i < groups.Count; i++) + names[i] = ((RadioGroup)groups[i]).Name; + return names; + } + } + + public string LastGroup { + get { + if (groups.Count == 0) + Add ("group1"); + RadioGroup group = groups[groups.Count - 1] as RadioGroup; + return group.Name; + } + } + + public RadioGroup FindGroup (string name) + { + for (int i = 0; i < groups.Count; i++) { + RadioGroup group = groups[i] as RadioGroup; + if (group.Name == name) + return group; + } + return null; + } + + void IRadioGroupManager.Add (string name) + { + Add (name); + } + + public RadioGroup Add (string name) + { + RadioGroup group = new RadioGroup (name); + groups.Add (group); + EmitGroupsChanged (); + return group; + } + + public void Rename (string oldName, string newName) + { + RadioGroup group = FindGroup (oldName); + if (group != null) { + group.Name = newName; + EmitGroupsChanged (); + } + } + + void RadioDestroyed (object obj, EventArgs args) + { + Gtk.Widget radio = obj as Gtk.Widget; + this[radio] = null; + } + + public string this[Gtk.Widget radio] { + get { + RadioGroup group = widgets[radio] as RadioGroup; + if (group != null) + return group.Name; + else + return null; + } + set { + GLib.SList group_value; + + RadioGroup oldGroup = widgets[radio] as RadioGroup; + if (oldGroup == null) { + radio.Destroyed += RadioDestroyed; + } else { + if (oldGroup.Name == value) + return; + oldGroup.Widgets.Remove (radio); + if (oldGroup.Widgets.Count == 0) { + groups.Remove (oldGroup); + EmitGroupsChanged (); + } + } + + if (value == null) { + radio.Destroyed -= RadioDestroyed; + groupProperty.SetValue (radio, new GLib.SList (IntPtr.Zero), null); + widgets.Remove (radio); + return; + } + + RadioGroup newGroup = FindGroup (value); + if (newGroup == null) + newGroup = Add (value); + + if (newGroup.Widgets.Count == 0) + group_value = new GLib.SList (IntPtr.Zero); + else + group_value = (GLib.SList)groupProperty.GetValue (newGroup.Widgets[0], null); + + groupProperty.SetValue (radio, group_value, null); + newGroup.Widgets.Add (radio); + widgets[radio] = newGroup; + } + } + + public string GladeGroupName (Gtk.Widget radio) + { + RadioGroup group = widgets[radio] as RadioGroup; + if (group == null || group.Widgets.Count == 0) + return null; + + Gtk.Widget leader = (Gtk.Widget)group.Widgets[0]; + return leader.Name; + } + + public CodeExpression GenerateGroupExpression (GeneratorContext ctx, Gtk.Widget widget) + { + // Returns and expression that represents the group to which the radio belongs. + // This expression can be an empty SList, if this is the first radio of the + // group that has been generated, or an SList taken from previously generated + // radios from the same group. + + RadioGroup group = widgets[widget] as RadioGroup; + CodeExpression var = null; + + foreach (Gtk.Widget radio in group.Widgets) { + if (radio == widget) + continue; + var = ctx.WidgetMap.GetWidgetExp (radio); + if (var != null) + break; + } + + if (var == null) { + return new CodeObjectCreateExpression ( + "GLib.SList".ToGlobalTypeRef (), + new CodePropertyReferenceExpression ( + new CodeTypeReferenceExpression (new CodeTypeReference (typeof(IntPtr), CodeTypeReferenceOptions.GlobalReference)), + "Zero" + ) + ); + } else { + return new CodePropertyReferenceExpression ( + var, + "Group" + ); + } + } + } +} diff --git a/main/src/addins/MonoDevelop.GtkCore2/libstetic/Registry.cs b/main/src/addins/MonoDevelop.GtkCore2/libstetic/Registry.cs new file mode 100644 index 0000000000..3316a524eb --- /dev/null +++ b/main/src/addins/MonoDevelop.GtkCore2/libstetic/Registry.cs @@ -0,0 +1,370 @@ +using System; +using System.Collections; +using System.Reflection; +using System.Xml; +using System.Xml.Xsl; + +namespace Stetic { + public static class Registry { + + static ArrayList libraries = new ArrayList (); + static ArrayList classes = new ArrayList (); + + static XslTransform gladeImport, gladeExport; + static WidgetLibrary coreLib; + static WidgetLibrary coreLib2; + + public static event EventHandler RegistryChanging; + public static event EventHandler RegistryChanged; + + static int changing; + static bool changed; + + public static void Initialize (WidgetLibrary coreLibrary) + { + RegisterWidgetLibrary (coreLibrary); + + coreLib = coreLibrary; + + } + + public static WidgetLibrary CoreWidgetLibrary { + get { return coreLib; } + } + + public static WidgetLibrary CoreWidgetLibrary2 { + get { return coreLib2; } + } + + public static void BeginChangeSet () + { + if (changing == 0) + changed = false; + changing++; + } + + public static void EndChangeSet () + { + if (--changing == 0) { + if (changed) { + foreach (WidgetLibrary lib in libraries) + lib.Flush (); + NotifyChanged (); + } + changed = false; + } + } + + public static void RegisterWidgetLibrary (WidgetLibrary library) + { + NotifyChanging (); + + try { + if (coreLib != null && library.Name == coreLib.Name) { + libraries.Remove (coreLib); + InternalUpdate (); + coreLib = library; + } + libraries.Add (library); + library.Load (); + classes.AddRange (library.AllClasses); + UpdateGladeTransform (); + } catch (Exception ex) { + Console.WriteLine (ex); + throw; + } finally { + NotifyChanged (); + } + } + + public static void UnregisterWidgetLibrary (WidgetLibrary library) + { + if (library == coreLib) + return; + + NotifyChanging (); + + libraries.Remove (library); + library.Dispose (); + InternalUpdate (); + + NotifyChanged (); + } + + + // Returns true if all libraries that need reloading + // could be reloaded + + public static bool ReloadWidgetLibraries () + { + bool needsReload = false; + + // If there is a lib which can't be reloaded, + // there is no need to start the reloading process + + foreach (WidgetLibrary lib in libraries) { + if (lib != coreLib && lib.NeedsReload) { + if (!lib.CanReload) + return false; + needsReload = true; + } + } + + if (!needsReload) + return true; + + try { + NotifyChanging (); + + foreach (WidgetLibrary lib in libraries) + if (lib != coreLib && lib.NeedsReload) + lib.Reload (); + + InternalUpdate (); + } finally { + NotifyChanged (); + } + + return true; + } + + public static bool IsRegistered (WidgetLibrary library) + { + return libraries.Contains (library); + } + + public static WidgetLibrary GetWidgetLibrary (string name) + { + foreach (WidgetLibrary lib in libraries) + if (lib.Name == name) + return lib; + return null; + } + + public static bool IsRegistered (string name) + { + foreach (WidgetLibrary lib in libraries) + if (lib.Name == name) + return true; + return false; + } + + public static WidgetLibrary[] RegisteredWidgetLibraries { + get { return (WidgetLibrary[]) libraries.ToArray (typeof(WidgetLibrary)); } + } + + static void NotifyChanging () + { + if (changing > 0) { + if (changed) + return; + else + changed = true; + } + if (RegistryChanging != null) + RegistryChanging (null, EventArgs.Empty); + } + + static void NotifyChanged () + { + if (changing == 0 && 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 (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 (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 (); + doc.LoadXml ( + "<xsl:stylesheet version='1.0' xmlns:xsl='http://www.w3.org/1999/XSL/Transform'>" + + " <xsl:template match='@*|node()'>" + + " <xsl:copy>" + + " <xsl:apply-templates select='@*|node()' />" + + " </xsl:copy>" + + " </xsl:template>" + + "</xsl:stylesheet>" + ); + return doc; + } + + public static IEnumerable AllClasses { + get { + return classes; + } + } + + public static XslTransform GladeImportXsl { + get { + return gladeImport; + } + } + + public static XslTransform GladeExportXsl { + get { + return gladeExport; + } + } + + public static EnumDescriptor LookupEnum (string typeName) + { + foreach (WidgetLibrary lib in libraries) { + EnumDescriptor desc = lib.LookupEnum (typeName); + if (desc != null) + return desc; + } + return null; + } + + public static ClassDescriptor LookupClassByCName (string cname) + { + foreach (WidgetLibrary lib in libraries) { + ClassDescriptor desc = lib.LookupClassByCName (cname); + if (desc != null) + return desc; + } + return null; + } + + public static ClassDescriptor LookupClassByName (string 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) + { + int sep = name.LastIndexOf ('.'); + string classname = name.Substring (0, sep); + groupname = name.Substring (sep + 1); + ClassDescriptor klass = LookupClassByName (classname); + if (klass == null) { + klass = LookupClassByName (name); + if (klass == null) + throw new ArgumentException ("No class for itemgroup " + name); + classname = name; + groupname = ""; + } + return klass; + } + + public static ItemGroup LookupItemGroup (string name) + { + string groupname; + ClassDescriptor klass = FindGroupClass (name, out groupname); + + foreach (ItemGroup grp in klass.ItemGroups) + if (grp.Name == groupname && grp.DeclaringType == klass) + return grp; + + throw new ArgumentException ("No itemgroup '" + groupname + "' in class " + klass.WrappedTypeName); + } + + public static ItemGroup LookupSignalGroup (string name) + { + string groupname; + ClassDescriptor klass = FindGroupClass (name, out groupname); + + foreach (ItemGroup grp in klass.SignalGroups) + if (grp.Name == groupname && grp.DeclaringType == klass) + return grp; + throw new ArgumentException ("No itemgroup '" + groupname + "' in class " + klass.WrappedTypeName); + } + + public static ItemDescriptor LookupItem (string name) + { + int sep = name.LastIndexOf ('.'); + string classname = name.Substring (0, sep); + string propname = name.Substring (sep + 1); + ClassDescriptor klass = LookupClassByName (classname); + if (klass == null) + throw new ArgumentException ("No class " + classname + " for property " + propname); + ItemDescriptor idesc = klass[propname]; + if (idesc == null) + throw new ArgumentException ("Property '" + propname + "' not found in class '" + classname + "'"); + return idesc; + } + + public static ItemGroup LookupContextMenu (string classname) + { + ClassDescriptor klass = LookupClassByName (classname); + if (klass == null) + throw new ArgumentException ("No class for contextmenu " + classname); + return klass.ContextMenu; + } + + public static object NewInstance (string typeName, IProject 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; + } + + string tname, aname; + int i = typeName.IndexOf (','); + if (i != -1) { + tname = typeName.Substring (0, i).Trim (); + aname = typeName.Substring (i + 1).Trim (); + } + else { + tname = typeName; + aname = null; + } + foreach (Assembly asm in AppDomain.CurrentDomain.GetAssemblies ()) { + if (aname == null || asm.GetName ().Name == aname) { + t = asm.GetType (tname); + if (t != null) + return t; + } + } + + if (throwOnError) + throw new TypeLoadException ("Could not load type '" + typeName + "'"); + + return null; + } + } +} diff --git a/main/src/addins/MonoDevelop.GtkCore2/libstetic/Set.cs b/main/src/addins/MonoDevelop.GtkCore2/libstetic/Set.cs new file mode 100644 index 0000000000..58f0b26b0b --- /dev/null +++ b/main/src/addins/MonoDevelop.GtkCore2/libstetic/Set.cs @@ -0,0 +1,51 @@ +using System; +using System.Collections; + +namespace Stetic { + + public class Set : IEnumerable, IEnumerator { + + Hashtable hash = new Hashtable (); + + public bool this [object obj] { + get { + return hash[obj] != null; + } + set { + if (value) + hash[obj] = obj; + else + hash.Remove (obj); + } + } + + public void Clear () + { + hash.Clear (); + } + + public IEnumerator GetEnumerator () + { + return this; + } + + IDictionaryEnumerator hashEnum; + + public void Reset () + { + hashEnum = hash.GetEnumerator (); + hashEnum.Reset (); + } + + public bool MoveNext () + { + return hashEnum.MoveNext (); + } + + public object Current { + get { + return hashEnum.Key; + } + } + } +} diff --git a/main/src/addins/MonoDevelop.GtkCore2/libstetic/SignalDescriptor.cs b/main/src/addins/MonoDevelop.GtkCore2/libstetic/SignalDescriptor.cs new file mode 100644 index 0000000000..871364d67b --- /dev/null +++ b/main/src/addins/MonoDevelop.GtkCore2/libstetic/SignalDescriptor.cs @@ -0,0 +1,70 @@ +using System; +using System.Reflection; +using System.Xml; + +namespace Stetic +{ + [Serializable] + public abstract class SignalDescriptor: ItemDescriptor + { + 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"); + } + + public override string Name { + get { return name; } + } + + public string Label { + get { return label; } + } + + public string Description { + get { return description; } + } + + public string HandlerTypeName { + get { return handlerTypeName; } + } + + public string HandlerReturnTypeName { + get { return handlerReturnTypeName; } + } + + public ParameterDescriptor[] HandlerParameters { + get { return handlerParameters; } + } + } + + [Serializable] + public class ParameterDescriptor + { + string name, type; + + public ParameterDescriptor (string name, string type) + { + this.name = name; + this.type = type; + } + + public string Name { + get { return name; } + } + + public string TypeName { + get { return type; } + } + } +} diff --git a/main/src/addins/MonoDevelop.GtkCore2/libstetic/TopLevelDialog.cs b/main/src/addins/MonoDevelop.GtkCore2/libstetic/TopLevelDialog.cs new file mode 100644 index 0000000000..04f066e507 --- /dev/null +++ b/main/src/addins/MonoDevelop.GtkCore2/libstetic/TopLevelDialog.cs @@ -0,0 +1,39 @@ +using System; +using System.Collections.Generic; +using System.Text; +using Gtk; + +namespace Stetic +{ + public class TopLevelDialog: TopLevelWindow + { + HButtonBox buttonBox; + VBox vbox; + HSeparator separator; + + public TopLevelDialog ( ) + { + vbox = new VBox (); + separator = new HSeparator (); + buttonBox = new HButtonBox (); + vbox.PackEnd (buttonBox, false, false, 0); + vbox.PackEnd (separator, false, false, 0); + vbox.ShowAll (); + Add (vbox); + } + + public HButtonBox ActionArea { + get { return buttonBox; } + } + + public VBox VBox { + get { return vbox; } + } + + public bool HasSeparator + { + get { return separator.Visible; } + set { separator.Visible = value; } + } + } +} diff --git a/main/src/addins/MonoDevelop.GtkCore2/libstetic/TopLevelWindow.cs b/main/src/addins/MonoDevelop.GtkCore2/libstetic/TopLevelWindow.cs new file mode 100644 index 0000000000..3e3cdc694a --- /dev/null +++ b/main/src/addins/MonoDevelop.GtkCore2/libstetic/TopLevelWindow.cs @@ -0,0 +1,57 @@ +using System; +using System.Collections.Generic; +using System.Text; + +namespace Stetic +{ + public class TopLevelWindow: Gtk.EventBox + { + string title; + Gdk.WindowTypeHint typeHint; + bool modal; + bool resizable = true; + + public event EventHandler PropertyChanged; + + public string Title { + get { return title; } + set { + title = value; + NotifyChange (); + } + } + + public Gdk.WindowTypeHint TypeHint { + get { return typeHint; } + set { + typeHint = value; + NotifyChange (); + } + } + + public bool Modal { + get { return modal; } + set + { + modal = value; + NotifyChange (); + } + } + + public bool Resizable + { + get { return resizable; } + set + { + resizable = value; + NotifyChange (); + } + } + + void NotifyChange ( ) + { + if (PropertyChanged != null) + PropertyChanged (this, EventArgs.Empty); + } + } +} diff --git a/main/src/addins/MonoDevelop.GtkCore2/libstetic/TranslatableAttribute.cs b/main/src/addins/MonoDevelop.GtkCore2/libstetic/TranslatableAttribute.cs new file mode 100644 index 0000000000..2b938420e6 --- /dev/null +++ b/main/src/addins/MonoDevelop.GtkCore2/libstetic/TranslatableAttribute.cs @@ -0,0 +1,8 @@ +using System; + +namespace Stetic { + + [AttributeUsage (AttributeTargets.Property | AttributeTargets.Field)] + public sealed class TranslatableAttribute : Attribute { + } +} diff --git a/main/src/addins/MonoDevelop.GtkCore2/libstetic/TypedClassDescriptor.cs b/main/src/addins/MonoDevelop.GtkCore2/libstetic/TypedClassDescriptor.cs new file mode 100644 index 0000000000..dbf7c6d5af --- /dev/null +++ b/main/src/addins/MonoDevelop.GtkCore2/libstetic/TypedClassDescriptor.cs @@ -0,0 +1,221 @@ +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; + MethodInfo ctorMethodInfoWithClass; + ConstructorInfo cinfo; + ConstructorInfo cinfoNoParams; + bool useGTypeCtor; + Gdk.Pixbuf icon; + bool defaultValuesLoaded; + + const BindingFlags flags = BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.Instance; + + static Gdk.Pixbuf missingIcon; + + public TypedClassDescriptor (Assembly assembly, XmlElement elem) + { + bool inheritedWrapper = false; + + wrapped = Registry.GetType (elem.GetAttribute ("type"), true); + if (wrapped != null) { + ConstructorInfo[] cInfos = wrapped.GetConstructors(); + foreach (ConstructorInfo ci in cInfos) { + if (ci.GetParameters().Length == 0) { + cinfoNoParams = ci; + break; + } + } + } + + if (elem.HasAttribute ("wrapper")) + wrapper = Registry.GetType (elem.GetAttribute ("wrapper"), true); + else { + inheritedWrapper = true; + string baseClass = elem.GetAttribute ("base-type"); + if (baseClass.Length > 0) { + // If a base type is specified, use the wrapper of that base type + TypedClassDescriptor parent = Registry.LookupClassByName (baseClass) as TypedClassDescriptor; + if (parent != null) + wrapper = parent.WrapperType; + } + 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"); + if (iconname.Length > 0) { + try { + // Using the pixbuf resource constructor generates a gdk warning. + Gdk.PixbufLoader loader = new Gdk.PixbufLoader (assembly, iconname); + icon = loader.Pixbuf; + } catch { + Console.WriteLine ("Could not load icon: " + iconname); + icon = GetDefaultIcon (); + } + } else + icon = GetDefaultIcon (); + + BindingFlags flags = BindingFlags.Static | BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.DeclaredOnly; + + // If the wrapper is inherited from a base class, ignore the CreateInstance method + // since it is going to create an instance of the base class. + if (!inheritedWrapper) { + ctorMethodInfoWithClass = wrapper.GetMethod ("CreateInstance", flags, null, new Type[] { typeof(ClassDescriptor)}, null); + if (ctorMethodInfoWithClass == null) { + ctorMethodInfo = wrapper.GetMethod ("CreateInstance", flags, null, Type.EmptyTypes, null); + } + } + + // Look for a constructor even if a CreateInstance method was + // found, since it may return null. + cinfo = wrapped.GetConstructor (Type.EmptyTypes); + 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); + + public override object CreateInstance (IProject proj) + { + object inst; + + + if (ctorMethodInfoWithClass != null) { + inst = ctorMethodInfoWithClass.Invoke (null, new object[] { this }); + if (inst != null) return inst; + } + if (ctorMethodInfo != null) { + inst = ctorMethodInfo.Invoke (null, new object[0]); + if (inst != null) return inst; + } + + if (cinfoNoParams != null) { + inst = cinfoNoParams.Invoke (null, null); + if (inst != null) return inst; + } + + + if (cinfo == null) + throw new InvalidOperationException ("The class '" + wrapped + "' does not have a default constructor."); + + if (!useGTypeCtor) + inst = cinfo.Invoke (new object[0]); + else { + IntPtr raw = g_object_new (gtype.Val, IntPtr.Zero); + inst = cinfo.Invoke (new object[] { raw }); + } + + 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); + } + + Gdk.Pixbuf GetDefaultIcon () + { + if (missingIcon == null) + missingIcon = WidgetUtils.MissingIcon; + return missingIcon; + } + + internal void LoadDefaultValues () + { + // This is a hack because there is no managed way of getting + // the default value of a GObject property. + // This method creates an dummy instance of this class and + // gets the values for their properties. Those values are + // considered the default + + if (defaultValuesLoaded) + return; + defaultValuesLoaded = true; + + object ob = NewInstance (null, false); + + foreach (ItemGroup group in ItemGroups) { + foreach (ItemDescriptor item in group) { + TypedPropertyDescriptor prop = item as TypedPropertyDescriptor; + if (prop == null) + continue; + + if (!prop.HasDefault) { + prop.SetDefault (null); + } else { + object val = prop.GetValue (ob); + prop.SetDefault (val); + } + } + } + ObjectWrapper ww = ObjectWrapper.Lookup (ob); + ww.Dispose (); + } + } +} diff --git a/main/src/addins/MonoDevelop.GtkCore2/libstetic/TypedPropertyDescriptor.cs b/main/src/addins/MonoDevelop.GtkCore2/libstetic/TypedPropertyDescriptor.cs new file mode 100644 index 0000000000..5be86a0ad6 --- /dev/null +++ b/main/src/addins/MonoDevelop.GtkCore2/libstetic/TypedPropertyDescriptor.cs @@ -0,0 +1,321 @@ +using System; +using System.ComponentModel; +using System.Collections; +using System.Reflection; +using System.Xml; + +namespace Stetic +{ + public class TypedPropertyDescriptor : PropertyDescriptor { + + PropertyInfo memberInfo, propertyInfo, runtimePropertyInfo, runtimeMemberInfo; + ParamSpec pspec; + TypedPropertyDescriptor gladeProperty; + bool isWrapperProperty; + TypedClassDescriptor klass; + bool defaultSet; + + const BindingFlags flags = BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.Instance; + + public TypedPropertyDescriptor (XmlElement elem, ItemGroup group, TypedClassDescriptor klass) : base (elem, group, klass) + { + this.klass = 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)); + } + + // Wrapper properties that override widgets properties (using the same name) + // must be considered runtime properties (will be available at run-time). + if (!isWrapperProperty || klass.WrappedType.GetProperty (propertyName) != null) + isRuntimeProperty = true; + + 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 overridden by what's specified in the xml file + description = pspec.Blurb; + minimum = pspec.Minimum; + maximum = pspec.Maximum; + label = propertyName; + if (!elem.HasAttribute ("ignore-default")) + hasDefault = Type.GetTypeCode (PropertyType) != TypeCode.Object || PropertyType.IsEnum; + } else { + label = propertyInfo.Name; + gladeOverride = true; + } + + string typeName = elem.GetAttribute ("editor"); + if (typeName.Length > 0) + editorType = Registry.GetType (typeName, 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 = propertyName; + description = pspec.Blurb; + minimum = pspec.Minimum; + maximum = pspec.Maximum; + hasDefault = Type.GetTypeCode (PropertyType) != TypeCode.Object || PropertyType.IsEnum; + } 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 = null; + + if (wrapperType != null) { + info = wrapperType.GetProperty (propertyName, flags); + if (info != null) + return info; + } + + try { + info = objectType.GetProperty (propertyName, flags); + } + catch (AmbiguousMatchException) { + foreach (PropertyInfo pi in objectType.GetProperties ()) { + if (pi.Name == propertyName) { + info = pi; + break; + } + } + } + + 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 && value != null) + return ParamSpec.IsDefaultValue (value); + else + return false; + } + + public override void ResetValue (object instance) + { + // This is a hack because there is no managed way of getting + // the default value of a GObject property. The call to LoadDefaultValues + // will guess the default values from a dummy instance + if (!defaultSet) { + ObjectWrapper ww = ObjectWrapper.Lookup (instance); + TypedClassDescriptor td = ww.ClassDescriptor as TypedClassDescriptor; + if (td != null) + td.LoadDefaultValues (); + defaultSet = true; + } + base.ResetValue (instance); + } + + internal void SetDefault (object val) + { + defaultValue = val; + defaultSet = true; + } + + // Gets the value of the property on @obj + public override object GetValue (object obj) + { + try { + if (isWrapperProperty) + obj = ObjectWrapper.Lookup (obj); + if (memberInfo != null) + obj = memberInfo.GetValue (obj, null); + return propertyInfo.GetValue (obj, null); + } catch (Exception ex) { + throw new InvalidOperationException ("Could not get value for property " + klass.Name + "." + Name + " from object '" + obj + "'", ex); + } + } + + // 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) + { + ObjectWrapper ww = ObjectWrapper.Lookup (obj); + IDisposable t = ww != null && !ww.Loading? ww.UndoManager.AtomicChange : null; + try { + if (isWrapperProperty) + obj = ww; + if (memberInfo != null) + obj = memberInfo.GetValue (obj, null); + propertyInfo.SetValue (obj, value, null); + } catch (Exception ex) { + throw new InvalidOperationException ("Could not set value for property " + klass.Name + "." + Name + " to object '" + obj + "'", ex); + } finally { + if (t != null) + t.Dispose (); + } + } + + // The property's type at run time + public override Type RuntimePropertyType { + get { + if (runtimePropertyInfo == null) + SetupRuntimeProperties (); + return runtimePropertyInfo.PropertyType; + } + } + + public override void SetRuntimeValue (object obj, object value) + { + if (runtimePropertyInfo == null) + SetupRuntimeProperties (); + if (runtimeMemberInfo != null) + obj = runtimeMemberInfo.GetValue (obj, null); + + if (runtimePropertyInfo.PropertyType.IsInstanceOfType (value)) + runtimePropertyInfo.SetValue (obj, value, null); + } + + public override object GetRuntimeValue (object obj) + { + if (runtimePropertyInfo == null) + SetupRuntimeProperties (); + if (runtimeMemberInfo != null) + obj = runtimeMemberInfo.GetValue (obj, null); + return runtimePropertyInfo.GetValue (obj, null); + } + + void SetupRuntimeProperties () + { + if (isWrapperProperty) { + Type t = klass.WrappedType; + if (memberInfo != null) { + runtimeMemberInfo = t.GetProperty (memberInfo.Name, flags); + t = runtimeMemberInfo.PropertyType; + } + runtimePropertyInfo = t.GetProperty (propertyInfo.Name, flags); + } else { + runtimeMemberInfo = memberInfo; + runtimePropertyInfo = propertyInfo; + } + } + + 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 && pspec.Name != null) + return pspec.Name.Replace ('-', '_'); + else + return null; + } + } + + public override string InternalChildId { + get { return GladeName; } + } + } +} diff --git a/main/src/addins/MonoDevelop.GtkCore2/libstetic/TypedSignalDescriptor.cs b/main/src/addins/MonoDevelop.GtkCore2/libstetic/TypedSignalDescriptor.cs new file mode 100644 index 0000000000..5c87947dee --- /dev/null +++ b/main/src/addins/MonoDevelop.GtkCore2/libstetic/TypedSignalDescriptor.cs @@ -0,0 +1,59 @@ +using System; +using System.Reflection; +using System.Xml; + +namespace Stetic +{ + [Serializable] + public class TypedSignalDescriptor: SignalDescriptor + { + 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 eventInfo = FindEvent (klass.WrapperType, klass.WrappedType, name); + MethodInfo 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); + } + } +} diff --git a/main/src/addins/MonoDevelop.GtkCore2/libstetic/WidgetLibrary.cs b/main/src/addins/MonoDevelop.GtkCore2/libstetic/WidgetLibrary.cs new file mode 100644 index 0000000000..b35c376382 --- /dev/null +++ b/main/src/addins/MonoDevelop.GtkCore2/libstetic/WidgetLibrary.cs @@ -0,0 +1,163 @@ +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 (); + string targetGtkVersion; + + XmlElement[] importElems = new XmlElement [0]; + XmlElement[] exportElems = new XmlElement [0]; + + public event EventHandler Changed; + + public abstract string Name { get; } + + public virtual bool NeedsReload { + get { return false; } + } + + public virtual bool CanReload { + get { return false; } + } + + // Returns true if it is possible to generate code using this widget library. + // Not all widget libraries can generate code. For example, when a widget + // depends on a wrapper class, and the wrapper class can't be loaded in memory, + // then it is not possible to generate code. + public virtual bool CanGenerateCode { + get { return true; } + } + + public virtual string[] GetLibraryDependencies () + { + return new string [0]; + } + + public string TargetGtkVersion { + get { return targetGtkVersion != null && targetGtkVersion.Length > 0 ? targetGtkVersion : "2.4"; } + } + + public bool SupportsGtkVersion (string targetVersion) + { + return WidgetUtils.CompareVersions (TargetGtkVersion, targetVersion) >= 0; + } + + public virtual void Reload () + { + Load (); + } + + public virtual void Load () + { + } + + protected virtual void Load (XmlDocument objects) + { + classes_by_cname.Clear (); + classes_by_csname.Clear (); + enums.Clear (); + + if (objects == null || objects.DocumentElement == null) + return; + + targetGtkVersion = objects.DocumentElement.GetAttribute ("gtk-version"); + if (targetGtkVersion.Length == 0) + targetGtkVersion = "2.4"; + + 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")) + AddClass (LoadClassDescriptor (element)); + + 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]; + } + + protected void AddClass (ClassDescriptor klass) + { + if (klass == null) + return; + klass.SetLibrary (this); + classes_by_cname[klass.CName] = klass; + classes_by_csname[klass.WrappedTypeName] = klass; + } + + public virtual void Dispose () + { + } + + // Flush is called by the registry to free cached data stored in the widget library. + public virtual void Flush () + { + } + + 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; + } + + public virtual System.IO.Stream GetResource (string name) + { + return null; + } + + protected virtual void OnChanged () + { + if (Changed != null) + Changed (this, EventArgs.Empty); + } + } +} diff --git a/main/src/addins/MonoDevelop.GtkCore2/libstetic/WidgetUtils.cs b/main/src/addins/MonoDevelop.GtkCore2/libstetic/WidgetUtils.cs new file mode 100644 index 0000000000..e97b352f49 --- /dev/null +++ b/main/src/addins/MonoDevelop.GtkCore2/libstetic/WidgetUtils.cs @@ -0,0 +1,393 @@ +using System; +using System.IO; +using System.Reflection; +using System.Collections; +using System.Xml; +using Stetic.Wrapper; + +namespace Stetic +{ + public static class WidgetUtils + { + static Gdk.Atom steticAtom; + static int undoIdCount; + static Gdk.Pixbuf missingIcon; + static Gtk.Widget renderer; + + public static Gdk.Atom ApplicationXSteticAtom { + get { + if (steticAtom == null) + steticAtom = Gdk.Atom.Intern ("application/x-stetic", false); + return steticAtom; + } + } + + public static XmlElement 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 (new ObjectWriter (doc, FileFormat.Native)); + doc.AppendChild (elem); + return doc.DocumentElement; + } + + public static Gtk.Widget ImportWidget (IProject project, XmlElement element) + { + ObjectReader reader = new ObjectReader (project, FileFormat.Native); + ObjectWrapper wrapper = Stetic.ObjectWrapper.ReadObject (reader, element, null); + 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 || prop.Name == "Name") // Name is written in the id attribute + 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"); + string tcx = prop.TranslationContext (wrapper.Wrapped); + if (tcx != null && tcx.Length > 0) { + prop_elem.SetAttribute ("context", "yes"); + prop_elem.InnerText = tcx + "|" + prop_elem.InnerText; + } + string tcm = prop.TranslationComment (wrapper.Wrapped); + if (tcm != null && tcm.Length > 0) + prop_elem.SetAttribute ("comments", prop.TranslationComment (wrapper.Wrapped)); + } + + parent_elem.AppendChild (prop_elem); + } + } + } + + public static void GetSignals (ObjectWrapper ob, XmlElement parent_elem) + { + foreach (Signal signal in ob.Signals) { + if (!signal.SignalDescriptor.VisibleFor (ob.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); + //set name before binding to ensure + //that ObjectWrapper.RootWrapperName will be valid + widget.Name = elem.GetAttribute ("id"); + ObjectWrapper.Bind (wrapper.Project, klass, wrapper, widget, true); + } else { + widget.Name = elem.GetAttribute ("id"); + } + + ReadMembers (klass, wrapper, widget, elem); + + if (!(widget is Gtk.Window)) + widget.ShowAll (); + } + + public static void ReadMembers (ClassDescriptor klass, ObjectWrapper wrapper, object wrapped, XmlElement elem) + { + foreach (XmlNode node in elem.ChildNodes) { + XmlElement child = node as XmlElement; + if (child == null) + continue; + + if (child.LocalName == "signal") + ReadSignal (klass, wrapper, child); + else if (child.LocalName == "property") + ReadProperty (klass, wrapper, wrapped, child); + } + } + + public static void ReadSignal (ClassDescriptor klass, ObjectWrapper ob, XmlElement elem) + { + string name = elem.GetAttribute ("name"); + SignalDescriptor signal = klass.SignalGroups.GetItem (name) as SignalDescriptor; + if (signal != null) { + string handler = elem.GetAttribute ("handler"); + bool after = elem.GetAttribute ("after") == "yes"; + ob.Signals.Add (new Signal (signal, handler, after)); + } + } + + public static void ReadProperty (ClassDescriptor klass, ObjectWrapper wrapper, object wrapped, XmlElement prop_node) + { + string name = prop_node.GetAttribute ("name"); + PropertyDescriptor prop = klass [name] as PropertyDescriptor; + if (prop == null || !prop.CanWrite) + return; + + 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; + ReadMembers (klass, wrapper, cc, packing); + } + + internal static XmlElement CreatePacking (XmlDocument doc, Stetic.Wrapper.Container.ContainerChild childwrapper) + { + XmlElement packing_elem = doc.CreateElement ("packing"); + WidgetUtils.GetProps (childwrapper, packing_elem); + return packing_elem; + } + + public static void Copy (Gtk.Widget widget, Gtk.SelectionData seldata, bool copyAsText) + { + XmlElement elem = ExportWidget (widget); + if (elem == null) + return; + + if (copyAsText) + seldata.Text = elem.OuterXml; + else + seldata.Set (ApplicationXSteticAtom, 8, System.Text.Encoding.UTF8.GetBytes (elem.OuterXml)); + } + + public static Stetic.Wrapper.Widget Paste (IProject project, Gtk.SelectionData seldata) + { + if (seldata == null || seldata.Type == null || seldata.Type.Name != ApplicationXSteticAtom.Name) + return null; + + string data = System.Text.Encoding.UTF8.GetString (seldata.Data); + XmlDocument doc = new XmlDocument (); + doc.PreserveWhitespace = true; + try { + doc.LoadXml (data); + } catch { + return null; + } + + Gtk.Widget w = ImportWidget (project, doc.DocumentElement); + return Wrapper.Widget.Lookup (w); + } + + public static IDesignArea GetDesignArea (Gtk.Widget w) + { + while (w != null && !(w is IDesignArea)) + w = w.Parent; + return w as IDesignArea; + } + + internal static void ParseWidgetName (string name, out string baseName, out int idx) + { + // Extract a numerical suffix from the name + // If suffix has more than 4 digits, only the last 4 digits are considered + // a numerical suffix. + + int n; + for (n = name.Length - 1; n >= name.Length-4 && n >= 0 && char.IsDigit (name [n]); n--) + ; + + if (n < name.Length - 1) { + baseName = name.Substring (0, n + 1); + idx = int.Parse (name.Substring (n + 1)); + } else { + baseName = name; + idx = 0; + } + } + + internal static string GetUndoId () + { + return (undoIdCount++).ToString (); + } + + public static Gdk.Pixbuf MissingIcon { + get { + if (missingIcon == null) { + try { + missingIcon = Gtk.IconTheme.Default.LoadIcon ("gtk-missing-image", 16, 0); + } catch {} + if (missingIcon == null) { + try { + missingIcon = Gdk.Pixbuf.LoadFromResource ("missing.png"); + } catch (Exception e) { + Console.WriteLine ("Error while loading pixbuf 'missing.png': " + e); + } + } + } + return missingIcon; + } + } + + public static string AbsoluteToRelativePath (string baseDirectoryPath, string absPath) + { + if (! Path.IsPathRooted (absPath)) + return absPath; + + absPath = Path.GetFullPath (absPath); + baseDirectoryPath = Path.GetFullPath (baseDirectoryPath); + + char[] separators = { Path.DirectorySeparatorChar, Path.VolumeSeparatorChar, Path.AltDirectorySeparatorChar }; + baseDirectoryPath = baseDirectoryPath.TrimEnd (separators); + string[] bPath = baseDirectoryPath.Split (separators); + string[] aPath = absPath.Split (separators); + int indx = 0; + for(; indx < Math.Min(bPath.Length, aPath.Length); ++indx){ + if(!bPath[indx].Equals(aPath[indx])) + break; + } + + if (indx == 0) { + return absPath; + } + + string erg = ""; + + if(indx == bPath.Length) { + erg += "." + Path.DirectorySeparatorChar; + } else { + for (int i = indx; i < bPath.Length; ++i) { + erg += ".." + Path.DirectorySeparatorChar; + } + } + erg += String.Join(Path.DirectorySeparatorChar.ToString(), aPath, indx, aPath.Length-indx); + + return erg; + } + + public static int CompareVersions (string v1, string v2) + { + string[] a1 = v1.Split ('.'); + string[] a2 = v2.Split ('.'); + + for (int n=0; n<a1.Length; n++) { + if (n >= a2.Length) + return -1; + if (a1[n].Length == 0) { + if (a2[n].Length != 0) + return 1; + continue; + } + try { + int n1 = int.Parse (a1[n]); + int n2 = int.Parse (a2[n]); + if (n1 < n2) + return 1; + else if (n1 > n2) + return -1; + } catch { + return 1; + } + } + if (a2.Length > a1.Length) + return 1; + return 0; + } + + public static Gdk.Pixbuf LoadIcon (string name, Gtk.IconSize size) + { + if (renderer == null) + renderer = new Gtk.HBox (); + Gdk.Pixbuf image = renderer.RenderIcon (name, size, null); + if (image != null) + return image; + + int w, h; + Gtk.Icon.SizeLookup (size, out w, out h); + try { + return Gtk.IconTheme.Default.LoadIcon (name, w, 0); + } catch { + // Icon not in theme + return MissingIcon; + } + } + + public static System.CodeDom.CodeTypeReference ToGlobalTypeRef (this Type type) + { + return new System.CodeDom.CodeTypeReference (type, System.CodeDom.CodeTypeReferenceOptions.GlobalReference); + } + + public static System.CodeDom.CodeTypeReference ToGlobalTypeRef (this string type) + { + return new System.CodeDom.CodeTypeReference (type, System.CodeDom.CodeTypeReferenceOptions.GlobalReference); + } + } +} diff --git a/main/src/addins/MonoDevelop.GtkCore2/libstetic/bin/Release/libstetic2.dll.config b/main/src/addins/MonoDevelop.GtkCore2/libstetic/bin/Release/libstetic2.dll.config new file mode 100644 index 0000000000..8c4c6ab9a9 --- /dev/null +++ b/main/src/addins/MonoDevelop.GtkCore2/libstetic/bin/Release/libstetic2.dll.config @@ -0,0 +1,8 @@ +<configuration> + <dllmap dll="libgobject-2.0-0.dll" target="libgobject-2.0.so.0" os="!osx,windows" /> + <dllmap dll="libgobject-2.0-0.dll" target="libgobject-2.0.dylib" os="osx" /> + <dllmap dll="libgtk-win32-2.0-0.dll" target="libgtk-x11-2.0.so.0" os="!osx,windows"/> + <dllmap dll="libgtk-win32-2.0-0.dll" target="libgtk-quartz-2.0.dylib" os="osx"/> + <dllmap dll="libgdk-win32-2.0-0.dll" target="libgdk-x11-2.0.so.0" os="!osx,windows"/> + <dllmap dll="libgdk-win32-2.0-0.dll" target="libgdk-quartz-2.0.dylib" os="osx"/> +</configuration> diff --git a/main/src/addins/MonoDevelop.GtkCore2/libstetic/editor/Accelerator.cs b/main/src/addins/MonoDevelop.GtkCore2/libstetic/editor/Accelerator.cs new file mode 100644 index 0000000000..f6f884848d --- /dev/null +++ b/main/src/addins/MonoDevelop.GtkCore2/libstetic/editor/Accelerator.cs @@ -0,0 +1,196 @@ +using System; +using System.Runtime.InteropServices; +using Mono.Unix; + +namespace Stetic.Editor { + + [PropertyEditor ("Accel", "AccelChanged")] + public class Accelerator : Gtk.HBox, IPropertyEditor { + + uint keyval; + Gdk.ModifierType mask; + bool editing; + + Gtk.Button clearButton; + Gtk.Entry entry; + + public const Gdk.ModifierType AcceleratorModifierMask = ~( + Gdk.ModifierType.Button1Mask | + Gdk.ModifierType.Button2Mask | + Gdk.ModifierType.Button3Mask | + Gdk.ModifierType.Button4Mask | + Gdk.ModifierType.Button5Mask); + + public Accelerator () + { + entry = new Gtk.Entry (); + clearButton = new Gtk.Button (new Gtk.Image (Gtk.Stock.Clear, Gtk.IconSize.Menu)); + PackStart (entry, true, true, 0); + PackStart (clearButton, false, false, 3); + clearButton.Clicked += delegate (object s, EventArgs args) { + Value = null; + }; + entry.IsEditable = false; + entry.ButtonPressEvent += OnButtonPressEvent; + entry.KeyPressEvent += OnKeyPressEvent; + ShowAll (); + } + + public void Initialize (PropertyDescriptor descriptor) + { + if (descriptor.PropertyType != typeof(string)) + throw new ApplicationException ("Accelerator editor does not support editing values of type " + descriptor.PropertyType); + } + + public void AttachObject (object obj) + { + Value = null; + } + + [GLib.ConnectBefore] + void OnButtonPressEvent (object s, Gtk.ButtonPressEventArgs args) + { + if (editing) + Ungrab (args.Event.Time); + else + Grab (args.Event.Window, args.Event.Time); + args.RetVal = true; + } + + GrabDialog grabWindow; + + void Ungrab (uint time) + { + if (!editing) + return; + editing = false; + + if (Value != null) + entry.Text = (string) Value; + else + entry.Text = ""; + + grabWindow.Destroy (); + } + + void Grab (Gdk.Window window, uint time) + { + if (editing) + return; + + grabWindow = new GrabDialog (); + editing = true; + entry.Text = Catalog.GetString ("Press a key..."); + grabWindow.TransientFor = this.Toplevel as Gtk.Window; + grabWindow.Run (); + this.keyval = grabWindow.Keyval; + this.mask = grabWindow.Mask; + Ungrab (time); + EmitAccelChanged (); + } + + [GLib.ConnectBefore] + void OnKeyPressEvent (object s, Gtk.KeyPressEventArgs args) + { + Gdk.EventKey evt = args.Event; + + if (!editing || !Gtk.Accelerator.Valid (evt.KeyValue, evt.State)) + return; + + uint keyval; + int effectiveGroup, level; + Gdk.ModifierType consumedMods, mask; + + // We know this will succeed, since we're already here... + Gdk.Keymap.Default.TranslateKeyboardState (evt.HardwareKeycode, evt.State, evt.Group, out keyval, out effectiveGroup, out level, out consumedMods); + mask = evt.State & AcceleratorModifierMask & ~consumedMods; + + if (evt.Key != Gdk.Key.Escape || mask != 0) { + this.keyval = keyval; + this.mask = mask; + } + + clearButton.Sensitive = true; + + Ungrab (evt.Time); + EmitAccelChanged (); + args.RetVal = true; + } + + public object Value { + get { + if (keyval != 0) + return Gtk.Accelerator.Name (keyval, mask); + else + return null; + } + set { + string s = value as string; + if (s == null) { + keyval = 0; + mask = 0; + clearButton.Sensitive = false; + } else { + Gtk.Accelerator.Parse (s, out keyval, out mask); + clearButton.Sensitive = true; + } + if (Value != null) + entry.Text = (string) Value; + else + entry.Text = ""; + EmitAccelChanged (); + } + } + + public event EventHandler ValueChanged; + + void EmitAccelChanged () + { + if (ValueChanged != null) + ValueChanged (this, EventArgs.Empty); + } + } + + class GrabDialog: Gtk.Dialog + { + public uint Keyval; + public Gdk.ModifierType Mask; + + public GrabDialog () + { + Decorated = false; + this.SkipPagerHint = true; + this.SkipTaskbarHint = true; + this.WindowPosition = Gtk.WindowPosition.CenterOnParent; + Gtk.Frame f = new Gtk.Frame (); + f.Shadow = Gtk.ShadowType.Out; + this.VBox.PackStart (f, true, true, 0); + Gtk.Label lab = new Gtk.Label (Catalog.GetString ("Press the key combination you want to assign to the accelerator...")); + lab.Xpad = 12; + lab.Ypad = 12; + f.Add (lab); + ShowAll (); + } + + protected override bool OnKeyPressEvent (Gdk.EventKey evt) + { + uint keyval; + int effectiveGroup, level; + Gdk.ModifierType consumedMods, mask; + + if (!Gtk.Accelerator.Valid (evt.KeyValue, evt.State)) + return base.OnKeyPressEvent (evt); + + // We know this will succeed, since we're already here... + Gdk.Keymap.Default.TranslateKeyboardState (evt.HardwareKeycode, evt.State, evt.Group, out keyval, out effectiveGroup, out level, out consumedMods); + mask = evt.State & Accelerator.AcceleratorModifierMask & ~consumedMods; + + if (evt.Key != Gdk.Key.Escape || mask != 0) { + Keyval = keyval; + Mask = mask; + this.Respond (0); + } + return false; + } + } +} diff --git a/main/src/addins/MonoDevelop.GtkCore2/libstetic/editor/ActionGroupEditor.cs b/main/src/addins/MonoDevelop.GtkCore2/libstetic/editor/ActionGroupEditor.cs new file mode 100644 index 0000000000..d5de903948 --- /dev/null +++ b/main/src/addins/MonoDevelop.GtkCore2/libstetic/editor/ActionGroupEditor.cs @@ -0,0 +1,577 @@ + +using System; +using System.Collections; +using Stetic.Wrapper; +using Mono.Unix; + +namespace Stetic.Editor +{ + public class ActionGroupEditor: Gtk.EventBox, IMenuItemContainer + { + ActionGroup actionGroup; + Gtk.Table table; + IProject project; + ArrayList items = new ArrayList (); + Gtk.EventBox emptyLabel; + EditableLabel headerLabel; + uint columns = 2; + bool modified; + bool disposed; + ObjectWrapperEventHandler changedEvent; + IDesignArea darea; + + public EventHandler GroupModified; + public EventHandler SelectionChanged; + + public ActionGroupEditor () + { + changedEvent = new ObjectWrapperEventHandler (OnActionChanged); + + Gtk.Fixed fx = new Gtk.Fixed (); + table = new Gtk.Table (0, 0, false); + table.RowSpacing = 8; + table.ColumnSpacing = 8; + table.BorderWidth = 12; + + Gtk.EventBox ebox = new Gtk.EventBox (); + ebox.ModifyBg (Gtk.StateType.Normal, this.Style.Backgrounds [0]); + headerLabel = new EditableLabel (); + headerLabel.MarkupTemplate = "<b>$TEXT</b>"; + headerLabel.Changed += OnGroupNameChanged; + Gtk.VBox vbox = new Gtk.VBox (); + Gtk.Label grpLabel = new Gtk.Label (); + grpLabel.Xalign = 0; + grpLabel.Markup = "<small><i>Action Group</i></small>"; +// vbox.PackStart (grpLabel, false, false, 0); + vbox.PackStart (headerLabel, false, false, 3); + vbox.BorderWidth = 12; + ebox.Add (vbox); + + Gtk.VBox box = new Gtk.VBox (); + box.Spacing = 6; + box.PackStart (ebox, false, false, 0); + box.PackStart (table, false, false, 0); + + fx.Put (box, 0, 0); + Add (fx); + ShowAll (); + } + + public override void Dispose () + { + if (disposed) + return; + disposed = true; + headerLabel.Changed -= OnGroupNameChanged; + if (emptyLabel != null) + emptyLabel.ButtonPressEvent -= OnAddClicked; + + foreach (ActionMenuItem aitem in items) { + aitem.KeyPressEvent -= OnItemKeyPress; + aitem.Node.Dispose (); + aitem.Detach (); + aitem.Destroy (); + } + items.Clear (); + ActionGroup = null; + project = null; + headerLabel = null; + + if (darea != null) { + darea.SelectionChanged -= OnSelectionChanged; + darea = null; + } + + base.Dispose (); + } + + public ActionGroup ActionGroup { + get { return actionGroup; } + set { + if (actionGroup != null) { + actionGroup.ObjectChanged -= OnGroupChanged; + actionGroup.ActionAdded -= OnActionAdded; + actionGroup.ActionRemoved -= OnActionRemoved; + foreach (Wrapper.Action a in actionGroup.Actions) + a.ObjectChanged -= changedEvent; + } + actionGroup = value; + if (actionGroup != null) { + headerLabel.Text = actionGroup.Name; + actionGroup.ObjectChanged += OnGroupChanged; + actionGroup.ActionAdded += OnActionAdded; + actionGroup.ActionRemoved += OnActionRemoved; + foreach (Wrapper.Action a in actionGroup.Actions) + a.ObjectChanged += changedEvent; + } + if (!disposed) + Fill (); + } + } + + public IProject Project { + get { return project; } + set { project = value; } + } + + public bool Modified { + get { return modified; } + set { modified = value; } + } + + public Wrapper.Action SelectedAction { + get { + IDesignArea designArea = GetDesignArea (); + IObjectSelection sel = designArea.GetSelection (); + if (sel != null) + return ObjectWrapper.Lookup (sel.DataObject) as Wrapper.Action; + else + return null; + } + set { + foreach (ActionMenuItem item in items) { + if (item.Node.Action == value) + item.Select (); + } + } + } + + ActionMenuItem SelectedActionMenuItem { + get { + IDesignArea designArea = GetDesignArea (); + IObjectSelection sel = designArea.GetSelection (); + if (sel != null) + return sel.Widget as ActionMenuItem; + else + return null; + } + } + + public void StartEditing () + { + IDesignArea designArea = GetDesignArea (); + designArea.SetSelection (headerLabel, null); + headerLabel.StartEditing (); + } + + void Fill () + { + IDesignArea designArea = GetDesignArea (); + if (designArea == null) + return; + + Wrapper.Action selAction = null; + + foreach (ActionMenuItem item in items) { + if (designArea.IsSelected (item)) + selAction = item.Node.Action; + item.Node.Dispose (); + item.Detach (); + item.Destroy (); + } + items.Clear (); + + if (actionGroup != null) { + Wrapper.Action[] sortedActions = new Wrapper.Action [actionGroup.Actions.Count]; + actionGroup.Actions.CopyTo (sortedActions, 0); + Array.Sort (sortedActions, new ActionComparer ()); + for (int n = 0; n < sortedActions.Length; n++) { + Wrapper.Action action = (Wrapper.Action) sortedActions [n]; + ActionMenuItem item = InsertAction (action, n); + if (selAction == action) + item.Select (); + } + + if (selAction == null) + designArea.SetSelection (null, null); + + headerLabel.Sensitive = true; + PlaceAddLabel (actionGroup.Actions.Count); + } else { + HideAddLabel (); + headerLabel.Text = Catalog.GetString ("No selection"); + headerLabel.Sensitive = false; + } + ShowAll (); + } + + ActionMenuItem InsertAction (Wrapper.Action action, int n) + { + uint row = (uint) n / columns; + uint col = (uint) (n % columns) * 3; + + IDesignArea designArea = GetDesignArea (); + ActionTreeNode node = new ActionTreeNode (Gtk.UIManagerItemType.Menuitem, "", action); + ActionMenuItem aitem = new ActionMenuItem (designArea, project, this, node); + aitem.KeyPressEvent += OnItemKeyPress; + aitem.MinWidth = 150; + aitem.Attach (table, row, col); + + Gtk.Frame fr = new Gtk.Frame (); + fr.Shadow = Gtk.ShadowType.Out; + aitem.Add (fr); + + items.Add (aitem); + return aitem; + } + + void PlaceAddLabel (int n) + { + HideAddLabel (); + + uint r = (uint) n / columns; + uint c = (uint) (n % columns) * 3; + + emptyLabel = new Gtk.EventBox (); + emptyLabel.VisibleWindow = false; + Gtk.Label label = new Gtk.Label (); + label.Xalign = 0; + label.Markup = "<i><span foreground='darkgrey'>" + Catalog.GetString ("Click to create action") + "</span></i>"; + emptyLabel.Add (label); + emptyLabel.ButtonPressEvent += OnAddClicked; + table.Attach (emptyLabel, c, c+3, r, r+1); + } + + void HideAddLabel () + { + if (emptyLabel != null) { + table.Remove (emptyLabel); + emptyLabel.ButtonPressEvent -= OnAddClicked; + } + emptyLabel = null; + } + + void OnGroupChanged (object s, ObjectWrapperEventArgs args) + { + headerLabel.Text = actionGroup.Name; + NotifyModified (); + } + + void OnActionAdded (object s, ActionEventArgs args) + { + args.Action.ObjectChanged += changedEvent; + Fill (); + NotifyModified (); + } + + void OnActionRemoved (object s, ActionEventArgs args) + { + args.Action.ObjectChanged -= changedEvent; + Fill (); + NotifyModified (); + } + + void OnActionChanged (object s, ObjectWrapperEventArgs args) + { + NotifyModified (); + } + + void NotifyModified () + { + modified = true; + if (GroupModified != null) + GroupModified (this, EventArgs.Empty); + } + + void OnAddClicked (object s, Gtk.ButtonPressEventArgs args) + { + Wrapper.Action ac = (Wrapper.Action) ObjectWrapper.Create (project, + new Gtk.Action ("", "", null, null), + ActionGroup); + ActionMenuItem item = InsertAction (ac, actionGroup.Actions.Count); + item.EditingDone += OnEditDone; + item.Select (); + item.StartEditing (); + HideAddLabel (); + ShowAll (); + } + + void OnEditDone (object sender, EventArgs args) + { + ActionMenuItem item = (ActionMenuItem) sender; + item.EditingDone -= OnEditDone; + if (item.Node.Action.GtkAction.Label.Length > 0 || item.Node.Action.GtkAction.StockId != null) { + actionGroup.Actions.Add (item.Node.Action); + } else { + IDesignArea designArea = GetDesignArea (); + designArea.ResetSelection (item); + item.Detach (); + item.Node.Dispose (); + items.Remove (item); + item.Destroy (); + PlaceAddLabel (actionGroup.Actions.Count); + ShowAll (); + } + } + + protected override bool OnButtonPressEvent (Gdk.EventButton ev) + { + IDesignArea designArea = GetDesignArea (); + designArea.SetSelection (null, null); + return true; + } + + void OnItemKeyPress (object s, Gtk.KeyPressEventArgs args) + { + int pos = items.IndexOf (s); + + switch (args.Event.Key) { + case Gdk.Key.Up: + pos -= (int) columns; + break; + case Gdk.Key.Down: + pos += (int) columns; + break; + case Gdk.Key.Right: + pos ++; + break; + case Gdk.Key.Left: + pos --; + break; + } + if (pos >= 0 && pos < items.Count) { + ((ActionMenuItem)items[pos]).Select (); + args.RetVal = true; + } + else if (pos == items.Count) { + OnAddClicked (null, null); + args.RetVal = true; + } + } + + void OnGroupNameChanged (object s, EventArgs args) + { + if (actionGroup != null) + actionGroup.Name = headerLabel.Text; + } + + void OnSelectionChanged (object s, EventArgs args) + { + if (SelectionChanged != null) + SelectionChanged (this, args); + } + + public void Cut () + { + ActionMenuItem menuItem = SelectedActionMenuItem; + if (menuItem != null) + Cut (SelectedActionMenuItem); + } + + public void Copy () + { + ActionMenuItem menuItem = SelectedActionMenuItem; + if (menuItem != null) + Copy (SelectedActionMenuItem); + } + + public void Paste () + { + } + + public void Delete () + { + ActionMenuItem menuItem = SelectedActionMenuItem; + if (menuItem != null) + Delete (SelectedActionMenuItem); + } + + void Cut (ActionMenuItem menuItem) + { + } + + void Copy (ActionMenuItem menuItem) + { + } + + void Paste (ActionMenuItem menuItem) + { + } + + void Delete (ActionMenuItem menuItem) + { + string msg = string.Format (Catalog.GetString ("Are you sure you want to delete the action '{0}'? It will be removed from all menus and toolbars."), menuItem.Node.Action.Name); + Gtk.MessageDialog md = new Gtk.MessageDialog (null, Gtk.DialogFlags.Modal, Gtk.MessageType.Question, Gtk.ButtonsType.YesNo, msg); + md.TransientFor = this.Toplevel as Gtk.Window; + if (md.Run () == (int) Gtk.ResponseType.Yes) { + menuItem.Node.Action.Delete (); + darea.SetSelection (null, null); + } + md.Destroy (); + } + + void IMenuItemContainer.ShowContextMenu (ActionItem aitem) + { + ActionMenuItem menuItem = aitem as ActionMenuItem; + + Gtk.Menu m = new Gtk.Menu (); + Gtk.MenuItem item = new Gtk.ImageMenuItem (Gtk.Stock.Cut, null); + m.Add (item); + item.Activated += delegate (object s, EventArgs a) { + Cut (menuItem); + }; + item.Visible = false; // No copy & paste for now + item = new Gtk.ImageMenuItem (Gtk.Stock.Copy, null); + m.Add (item); + item.Activated += delegate (object s, EventArgs a) { + Copy (menuItem); + }; + item.Visible = false; // No copy & paste for now + item = new Gtk.ImageMenuItem (Gtk.Stock.Paste, null); + m.Add (item); + item.Activated += delegate (object s, EventArgs a) { + Paste (menuItem); + }; + item.Visible = false; // No copy & paste for now + item = new Gtk.ImageMenuItem (Gtk.Stock.Delete, null); + m.Add (item); + item.Activated += delegate (object s, EventArgs a) { + Delete (menuItem); + }; + m.ShowAll (); + m.Popup (); + } + + IDesignArea GetDesignArea () + { + if (darea != null) + return darea; + + darea = WidgetUtils.GetDesignArea (this); + darea.SelectionChanged += OnSelectionChanged; + return darea; + } + + ActionMenu IMenuItemContainer.OpenSubmenu { + get { return null; } + set { } + } + + bool IMenuItemContainer.IsTopMenu { + get { return false; } + } + + Gtk.Widget IMenuItemContainer.Widget { + get { return this; } + } + + class ActionComparer: IComparer + { + public int Compare (object x, object y) + { + return string.Compare (((Wrapper.Action)x).GtkAction.Label, ((Wrapper.Action)y).GtkAction.Label); + } + } + } + + public class EditableLabel: Gtk.EventBox + { + string text; + string markup; + + public EditableLabel (): this ("") + { + } + + public EditableLabel (string txt) + { + VisibleWindow = false; + text = txt; + Add (CreateLabel ()); + } + + public string Text { + get { return text; } + set { + text = value; + if (Child is Gtk.Entry) + ((Gtk.Entry)Child).Text = text; + else + ((Gtk.Label)Child).Markup = Markup; + } + } + + public string MarkupTemplate { + get { return markup; } + set { + markup = value; + if (Child is Gtk.Label) + ((Gtk.Label)Child).Markup = Markup; + } + } + + public string Markup { + get { return markup != null ? markup.Replace ("$TEXT",text) : text; } + } + + protected override bool OnButtonPressEvent (Gdk.EventButton ev) + { + IDesignArea d = WidgetUtils.GetDesignArea (this); + if (d.IsSelected (this)) { + if (Child is Gtk.Label) { + StartEditing (); + return true; + } + } else { + d.SetSelection (this, null); + return true; + } + return false; + } + + void SelectionDisposed (object s, EventArgs args) + { + EndEditing (); + } + + public void StartEditing () + { + if (Child is Gtk.Label) { + IDesignArea d = WidgetUtils.GetDesignArea (this); + IObjectSelection sel = d.GetSelection (this); + if (sel == null) + sel = d.SetSelection (this, null); + + sel.Disposed += SelectionDisposed; + + Remove (Child); + Add (CreateEntry ()); + ShowAll (); + Child.GrabFocus (); + } + } + + public void EndEditing () + { + if (Child is Gtk.Entry) { + Remove (Child); + Add (CreateLabel ()); + ShowAll (); + } + } + + Gtk.Label CreateLabel () + { + Gtk.Label label = new Gtk.Label (); + label.Markup = Markup; + label.Xalign = 0; + return label; + } + + Gtk.Entry CreateEntry () + { + Gtk.Entry e = new Gtk.Entry (text); + e.Changed += delegate (object s, EventArgs a) { + text = e.Text; + if (Changed != null) + Changed (this, a); + }; + e.Activated += delegate (object s, EventArgs a) { + EndEditing (); + }; + return e; + } + + public event EventHandler Changed; + } +} diff --git a/main/src/addins/MonoDevelop.GtkCore2/libstetic/editor/ActionItem.cs b/main/src/addins/MonoDevelop.GtkCore2/libstetic/editor/ActionItem.cs new file mode 100644 index 0000000000..5d2d09cdd8 --- /dev/null +++ b/main/src/addins/MonoDevelop.GtkCore2/libstetic/editor/ActionItem.cs @@ -0,0 +1,209 @@ + +using System; +using Stetic.Wrapper; + +namespace Stetic.Editor +{ + abstract class ActionItem: Gtk.EventBox, IEditableObject + { + protected IMenuItemContainer parentMenu; + protected ActionTreeNode node; + protected Widget wrapper; + protected bool localUpdate; + protected bool editOnRelease; + protected bool editing; + protected uint itemSpacing; + protected int minWidth; + + // To use in the action editor + protected IDesignArea designArea; + protected IProject project; + bool disposed; + + public ActionItem (ActionTreeNode node, IMenuItemContainer parent, uint itemSpacing) + { + DND.SourceSet (this); + this.parentMenu = parent; + this.node = node; + this.VisibleWindow = false; + this.CanFocus = true; + this.Events |= Gdk.EventMask.KeyPressMask; + this.itemSpacing = itemSpacing; + if (node.Action != null) + node.Action.ObjectChanged += OnActionChanged; + } + + public ActionTreeNode Node { + get { return node; } + } + + public uint ItemSpacing { + get { return itemSpacing; } + set { itemSpacing = value; } + } + + public int MinWidth { + get { return minWidth; } + set { minWidth = value; } + } + + public bool IsSelected { + get { + IDesignArea area = GetDesignArea (); + return area.IsSelected (this); + } + } + + protected void UpdateSelectionStatus () + { + IDesignArea area = GetDesignArea (); + IObjectSelection sel = area.GetSelection (); + sel.Disposed -= OnSelectionDisposed; + sel.Drag -= HandleItemDrag; + + area.ResetSelection (this); + + sel = area.SetSelection (this, this); + sel.Drag += HandleItemDrag; + sel.Disposed += OnSelectionDisposed; + } + + public virtual void Select () + { + IDesignArea area = GetDesignArea (); + if (area.IsSelected (this)) + return; + IObjectSelection sel = area.SetSelection (this, node.Action != null ? node.Action.GtkAction : null); + sel.Drag += HandleItemDrag; + sel.Disposed += OnSelectionDisposed; + GrabFocus (); + } + + void OnSelectionDisposed (object ob, EventArgs a) + { + if (!disposed) + EndEditing (Gdk.Key.Return); + } + + protected virtual void EndEditing (Gdk.Key exitKey) + { + } + + public override void Dispose () + { + disposed = true; + base.Dispose (); + } + + + void HandleItemDrag (Gdk.EventMotion evt, int dx, int dy) + { + ProcessDragBegin (null, evt); + } + + protected IDesignArea GetDesignArea () + { + if (wrapper != null) + return wrapper.GetDesignArea (); + else + return designArea; + } + + protected IProject GetProject () + { + if (wrapper != null) + return wrapper.Project; + else + return project; + } + + void OnActionChanged (object ob, ObjectWrapperEventArgs a) + { + if (!localUpdate) + Refresh (); + } + + public abstract void Refresh (); + + protected override bool OnButtonPressEvent (Gdk.EventButton ev) + { + return ProcessButtonPress (ev); + } + + public bool ProcessButtonPress (Gdk.EventButton ev) + { + if (ev.Button == 1) { + IDesignArea area = GetDesignArea (); + if (area == null) + return true; + + // Clicking a selected item starts the edit mode + if (area.IsSelected (this)) { + editOnRelease = true; + return true; + } + } else if (ev.Button == 3) { + parentMenu.ShowContextMenu (this); + } + + Select (); + return true; + } + + protected override void OnDragBegin (Gdk.DragContext ctx) + { + ProcessDragBegin (ctx, null); + } + + public virtual void ProcessDragBegin (Gdk.DragContext ctx, Gdk.EventMotion evt) + { + editOnRelease = false; + ActionPaletteItem item = new ActionPaletteItem (node); + if (ctx != null) + DND.Drag (parentMenu.Widget, ctx, item); + else + DND.Drag (parentMenu.Widget, evt, item); + } + + public bool CanCopy { + get { return !editing; } + } + + public bool CanCut { + get { return false; } + } + + public bool CanPaste { + get { return false; } + } + + public bool CanDelete { + get { return !editing; } + } + + public void Copy () + { + } + + public void Cut () + { + } + + public void Paste () + { + } + + public void Delete () + { + if (node.ParentNode != null) + node.ParentNode.Children.Remove (node); + Destroy (); + } + + void IEditableObject.Delete () + { + if (!editing) + Delete (); + } + } +} diff --git a/main/src/addins/MonoDevelop.GtkCore2/libstetic/editor/ActionMenu.cs b/main/src/addins/MonoDevelop.GtkCore2/libstetic/editor/ActionMenu.cs new file mode 100644 index 0000000000..a34519a194 --- /dev/null +++ b/main/src/addins/MonoDevelop.GtkCore2/libstetic/editor/ActionMenu.cs @@ -0,0 +1,650 @@ + +using System; +using System.Collections; +using Stetic.Wrapper; +using Mono.Unix; + +namespace Stetic.Editor +{ + public class ActionMenu: Gtk.EventBox, IMenuItemContainer + { + ActionTreeNode parentNode; + ActionTreeNodeCollection nodes; + ArrayList menuItems = new ArrayList (); + Gtk.Table table; + ActionMenu openSubmenu; + Widget wrapper; + int dropPosition = -1; + int dropIndex; + Gtk.EventBox emptyLabel; + IMenuItemContainer parentMenu; + + public ActionMenu (IntPtr p): base (p) + {} + + internal ActionMenu (Widget wrapper, IMenuItemContainer parentMenu, ActionTreeNode node) + { + DND.DestSet (this, true); + parentNode = node; + this.parentMenu = parentMenu; + this.wrapper = wrapper; + this.nodes = node.Children; + table = new Gtk.Table (0, 0, false); + table.ColumnSpacing = 5; + table.RowSpacing = 5; + table.BorderWidth = 5; + this.AppPaintable = true; + + Add (table); + + Fill (); + + parentNode.ChildNodeAdded += OnChildAdded; + parentNode.ChildNodeRemoved += OnChildRemoved; + } + + protected override void OnDestroyed () + { + parentNode.ChildNodeAdded -= OnChildAdded; + parentNode.ChildNodeRemoved -= OnChildRemoved; + parentNode = null; + + base.OnDestroyed (); + } + + public void Select (ActionTreeNode node) + { + if (node != null) { + ActionMenuItem item = FindMenuItem (node); + if (item != null) + item.Select (); + } else { + if (menuItems.Count > 0) + ((ActionMenuItem)menuItems [0]).Select (); + else + InsertAction (0); + } + } + + public ActionTreeNode ParentNode { + get { return parentNode; } + } + + bool IMenuItemContainer.IsTopMenu { + get { return false; } + } + + Gtk.Widget IMenuItemContainer.Widget { + get { return this; } + } + + public void TrackWidgetPosition (Gtk.Widget refWidget, bool topMenu) + { + IDesignArea area = wrapper.GetDesignArea (); + Gdk.Rectangle rect = area.GetCoordinates (refWidget); + if (topMenu) + area.MoveWidget (this, rect.X, rect.Bottom); + else + area.MoveWidget (this, rect.Right, rect.Top); + + GLib.Timeout.Add (50, new GLib.TimeoutHandler (RepositionSubmenu)); + } + + public bool RepositionSubmenu () + { + if (openSubmenu == null) + return false; + + ActionMenuItem item = FindMenuItem (openSubmenu.parentNode); + if (item != null) + openSubmenu.TrackWidgetPosition (item, false); + return false; + } + + void Fill () + { + menuItems.Clear (); + + uint n = 0; + ActionMenuItem editItem = null; + + if (nodes.Count > 0) { + foreach (ActionTreeNode node in nodes) { + ActionMenuItem item = new ActionMenuItem (wrapper, this, node); + item.KeyPressEvent += OnItemKeyPress; + item.Attach (table, n++, 0); + menuItems.Add (item); + // If adding an action with an empty name, select and start editing it +// if (node.Action != null && node.Action.Name.Length == 0) +// editItem = item; + } + } + + emptyLabel = new Gtk.EventBox (); + emptyLabel.VisibleWindow = false; + Gtk.Label label = new Gtk.Label (); + label.Xalign = 0; + label.Markup = "<i><span foreground='darkgrey'>" + Catalog.GetString ("Click to create action") + "</span></i>"; + emptyLabel.Add (label); + emptyLabel.ButtonPressEvent += OnAddClicked; + table.Attach (emptyLabel, 1, 2, n, n + 1); + + ShowAll (); + + if (editItem != null) { + // If there is an item with an empty action, it means that it was an item that was + // being edited. Restart the editing now. + GLib.Timeout.Add (200, delegate { + editItem.Select (); + editItem.EditingDone += OnEditingDone; + editItem.StartEditing (); + return false; + }); + } + } + + void Refresh () + { + IDesignArea area = wrapper.GetDesignArea (); + ActionTreeNode selNode = null; + + foreach (Gtk.Widget w in table.Children) { + ActionMenuItem ami = w as ActionMenuItem; + if (area.IsSelected (w) && ami != null) { + selNode = ami.Node; + area.ResetSelection (w); + } + table.Remove (w); + } + + Fill (); + + ActionMenuItem mi = FindMenuItem (selNode); + if (mi != null) + mi.Select (); + + GLib.Timeout.Add (50, new GLib.TimeoutHandler (RepositionSubmenu)); + } + + public ActionMenu OpenSubmenu { + get { return openSubmenu; } + set { + if (openSubmenu != null) { + openSubmenu.OpenSubmenu = null; + IDesignArea area = wrapper.GetDesignArea (); + area.RemoveWidget (openSubmenu); + openSubmenu.Destroy (); + } + openSubmenu = value; + } + } + + internal void ResetSelection () + { + if (OpenSubmenu != null) + OpenSubmenu.ResetSelection (); + IDesignArea area = wrapper.GetDesignArea (); + if (area != null) { + foreach (Gtk.Widget w in table.Children) { + ActionMenuItem ami = w as ActionMenuItem; + if (ami != null) + area.ResetSelection (w); + } + } + } + + ActionTreeNode InsertAction (int pos) + { + using (wrapper.UndoManager.AtomicChange) { + Wrapper.Action ac = (Wrapper.Action) ObjectWrapper.Create (wrapper.Project, + new Gtk.Action ("", "", null, null), + wrapper); + ActionTreeNode newNode = new ActionTreeNode (Gtk.UIManagerItemType.Menuitem, null, ac); + nodes.Insert (pos, newNode); + ActionMenuItem item = FindMenuItem (newNode); + item.EditingDone += OnEditingDone; + item.Select (); + item.StartEditing (); + emptyLabel.Hide (); + + if (wrapper.LocalActionGroups.Count == 0) + wrapper.LocalActionGroups.Add (new ActionGroup ("Default")); + wrapper.LocalActionGroups [0].Actions.Add (ac); + return newNode; + } + } + + void DeleteAction (ActionMenuItem item) + { + int pos = menuItems.IndexOf (item); + item.Delete (); + if (pos >= menuItems.Count) + SelectLastItem (); + else + ((ActionMenuItem)menuItems [pos]).Select (); + } + + void OnEditingDone (object ob, MenuItemEditEventArgs args) + { + ActionMenuItem item = (ActionMenuItem) ob; + item.EditingDone -= OnEditingDone; + if (item.Node.Action.GtkAction.Label.Length == 0 && item.Node.Action.GtkAction.StockId == null) { + IDesignArea area = wrapper.GetDesignArea (); + area.ResetSelection (item); + using (wrapper.UndoManager.AtomicChange) { + nodes.Remove (item.Node); + wrapper.LocalActionGroups [0].Actions.Remove (item.Node.Action); + } + SelectLastItem (); + } + else { + if (args.ExitKey == Gdk.Key.Up || args.ExitKey == Gdk.Key.Down) + ProcessKey (item, args.ExitKey, Gdk.ModifierType.None); + } + } + + void SelectLastItem () + { + if (menuItems.Count > 0) + ((ActionMenuItem)menuItems [menuItems.Count - 1]).Select (); + else if (parentMenu.Widget is ActionMenuBar) { + ActionMenuBar bar = (ActionMenuBar) parentMenu.Widget; + bar.Select (parentNode); + } + else if (parentMenu.Widget is ActionMenu) { + ActionMenu parentAM = (ActionMenu) parentMenu.Widget; + parentAM.Select (parentNode); + } + } + + void OnChildAdded (object ob, ActionTreeNodeArgs args) + { + Refresh (); + } + + void OnChildRemoved (object ob, ActionTreeNodeArgs args) + { + IDesignArea area = wrapper.GetDesignArea (); + IObjectSelection asel = area.GetSelection (); + ActionMenuItem curSel = asel != null ? asel.DataObject as ActionMenuItem : null; + int pos = menuItems.IndexOf (curSel); + + ActionMenuItem mi = FindMenuItem (args.Node); + if (mi != null) { + // Remove the table row that contains the menu item + Gtk.Table.TableChild tc = (Gtk.Table.TableChild) table [mi]; + uint row = tc.TopAttach; + mi.Detach (); + menuItems.Remove (mi); + foreach (Gtk.Widget w in table.Children) { + tc = (Gtk.Table.TableChild) table [w]; + if (tc.TopAttach >= row) + tc.TopAttach--; + if (tc.BottomAttach > row) + tc.BottomAttach--; + } + if (pos != -1 && pos < menuItems.Count) + ((ActionMenuItem)menuItems[pos]).Select (); + else + SelectLastItem (); + GLib.Timeout.Add (50, new GLib.TimeoutHandler (RepositionSubmenu)); + } + } + + protected override bool OnExposeEvent (Gdk.EventExpose ev) + { + int w, h; + this.GdkWindow.GetSize (out w, out h); + Gdk.Rectangle clip = new Gdk.Rectangle (0,0,w,h); + Gtk.Style.PaintBox (this.Style, this.GdkWindow, Gtk.StateType.Normal, Gtk.ShadowType.Out, clip, this, "menu", 0, 0, w, h); + + bool r = base.OnExposeEvent (ev); + + if (dropPosition != -1) { + GdkWindow.DrawRectangle (this.Style.BlackGC, true, 0, dropPosition - 1, w - 2, 3); + } + + return r; + } + + protected override bool OnButtonPressEvent (Gdk.EventButton ev) + { + return true; + } + + void OnAddClicked (object s, Gtk.ButtonPressEventArgs args) + { + InsertAction (menuItems.Count); + args.RetVal = true; + } + + protected override bool OnDragMotion (Gdk.DragContext context, int x, int y, uint time) + { + ActionPaletteItem dragItem = DND.DragWidget as ActionPaletteItem; + if (dragItem == null) + return false; + + if (nodes.Count > 0) { + ActionMenuItem item = LocateWidget (x, y); + if (item != null) { + + // Show the submenu to allow droping to it, but avoid + // droping a submenu inside itself + if (item.HasSubmenu && item.Node != dragItem.Node) + item.ShowSubmenu (wrapper.GetDesignArea(), item); + + // Look for the index where to insert the new item + dropIndex = nodes.IndexOf (item.Node); + int mpos = item.Allocation.Y + item.Allocation.Height / 2; + if (y > mpos) + dropIndex++; + + // Calculate the drop position, used to show the drop bar + if (dropIndex == 0) + dropPosition = item.Allocation.Y; + else if (dropIndex == menuItems.Count) + dropPosition = item.Allocation.Bottom; + else { + item = (ActionMenuItem) menuItems [dropIndex]; + ActionMenuItem prevItem = (ActionMenuItem) menuItems [dropIndex - 1]; + dropPosition = prevItem.Allocation.Bottom + (item.Allocation.Y - prevItem.Allocation.Bottom)/2; + } + } + } else + dropIndex = 0; + + QueueDraw (); + return base.OnDragMotion (context, x, y, time); + } + + protected override void OnDragLeave (Gdk.DragContext context, uint time) + { + dropPosition = -1; + QueueDraw (); + base.OnDragLeave (context, time); + } + + protected override void OnDragDataReceived (Gdk.DragContext context, int x, int y, Gtk.SelectionData data, uint info, uint time) + { + } + + protected override bool OnDragDrop (Gdk.DragContext context, int x, int y, uint time) + { + ActionPaletteItem dropped = DND.Drop (context, null, time) as ActionPaletteItem; + if (dropped == null) + return false; + + if (dropped.Node.Type != Gtk.UIManagerItemType.Menuitem && + dropped.Node.Type != Gtk.UIManagerItemType.Menu && + dropped.Node.Type != Gtk.UIManagerItemType.Toolitem && + dropped.Node.Type != Gtk.UIManagerItemType.Separator) + return false; + + ActionTreeNode newNode = null; + + // Toolitems are copied, not moved + + using (wrapper.UndoManager.AtomicChange) { + if (dropped.Node.ParentNode != null && dropped.Node.Type != Gtk.UIManagerItemType.Toolitem) { + if (dropIndex < nodes.Count) { + // Do nothing if trying to drop the node over the same node + ActionTreeNode dropNode = nodes [dropIndex]; + if (dropNode == dropped.Node) + return false; + + dropped.Node.ParentNode.Children.Remove (dropped.Node); + + // The drop position may have changed after removing the dropped node, + // so get it again. + dropIndex = nodes.IndexOf (dropNode); + nodes.Insert (dropIndex, dropped.Node); + } else { + dropped.Node.ParentNode.Children.Remove (dropped.Node); + nodes.Add (dropped.Node); + dropIndex = nodes.Count - 1; + } + } else { + newNode = new ActionTreeNode (Gtk.UIManagerItemType.Menuitem, null, dropped.Node.Action); + nodes.Insert (dropIndex, newNode); + } + // Select the dropped node + ActionMenuItem mi = (ActionMenuItem) menuItems [dropIndex]; + mi.Select (); + } + + return base.OnDragDrop (context, x, y, time); + } + + [GLib.ConnectBefore] + void OnItemKeyPress (object s, Gtk.KeyPressEventArgs args) + { + ActionMenuItem item = (ActionMenuItem) s; + ProcessKey (item, args.Event.Key, args.Event.State); + args.RetVal = true; + } + + void ProcessKey (ActionMenuItem item, Gdk.Key key, Gdk.ModifierType modifier) + { + int pos = menuItems.IndexOf (item); + + switch (key) { + case Gdk.Key.Up: + if (pos > 0) + ((ActionMenuItem)menuItems[pos - 1]).Select (); + else if (parentMenu.Widget is ActionMenuBar) { + ActionMenuBar bar = (ActionMenuBar) parentMenu.Widget; + bar.Select (parentNode); + } + break; + case Gdk.Key.Down: + if (pos < menuItems.Count - 1) + ((ActionMenuItem)menuItems[pos + 1]).Select (); + else if (pos == menuItems.Count - 1) { + InsertAction (menuItems.Count); + } + break; + case Gdk.Key.Right: + if ((modifier & Gdk.ModifierType.ControlMask) != 0 && item.Node.Type == Gtk.UIManagerItemType.Menuitem) { + // Create a submenu + using (item.Node.Action.UndoManager.AtomicChange) { + item.Node.Type = Gtk.UIManagerItemType.Menu; + } + item.Node.Action.NotifyChanged (); + } + if (item.HasSubmenu) { + item.ShowSubmenu (); + if (openSubmenu != null) + openSubmenu.Select (null); + } else if (parentNode != null) { + ActionMenuBar parentMB = parentMenu.Widget as ActionMenuBar; + if (parentMB != null) { + int i = parentNode.ParentNode.Children.IndexOf (parentNode); + if (i < parentNode.ParentNode.Children.Count - 1) + parentMB.DropMenu (parentNode.ParentNode.Children [i + 1]); + } + } + break; + case Gdk.Key.Left: + if ((modifier & Gdk.ModifierType.ControlMask) != 0 && item.Node.Type == Gtk.UIManagerItemType.Menu) { + // Remove the submenu + OpenSubmenu = null; + using (item.Node.Action.UndoManager.AtomicChange) { + item.Node.Type = Gtk.UIManagerItemType.Menuitem; + item.Node.Children.Clear (); + } + item.Node.Action.NotifyChanged (); + break; + } + if (parentNode != null) { + ActionMenu parentAM = parentMenu.Widget as ActionMenu; + if (parentAM != null) { + parentAM.Select (parentNode); + } + ActionMenuBar parentMB = parentMenu.Widget as ActionMenuBar; + if (parentMB != null) { + int i = parentNode.ParentNode.Children.IndexOf (parentNode); + if (i > 0) + parentMB.DropMenu (parentNode.ParentNode.Children [i - 1]); + } + } + break; + case Gdk.Key.Return: + item.EditingDone += OnEditingDone; + item.StartEditing (); + break; + case Gdk.Key.Insert: + if ((modifier & Gdk.ModifierType.ControlMask) != 0) + InsertActionAt (item, true, true); + else + InsertActionAt (item, false, false); + break; + case Gdk.Key.Delete: + DeleteAction (item); + break; + } + } + + void InsertActionAt (ActionMenuItem item, bool after, bool separator) + { + int pos = menuItems.IndexOf (item); + if (pos == -1) + return; + + if (after) + pos++; + + if (separator) { + ActionTreeNode newNode = new ActionTreeNode (Gtk.UIManagerItemType.Separator, null, null); + nodes.Insert (pos, newNode); + Select (newNode); + } else + InsertAction (pos); + } + + void Paste (ActionMenuItem item) + { + } + + void IMenuItemContainer.ShowContextMenu (ActionItem aitem) + { + ActionMenuItem menuItem = aitem as ActionMenuItem; + Gtk.Menu m = new Gtk.Menu (); + Gtk.MenuItem item = new Gtk.MenuItem (Catalog.GetString ("Insert Before")); + m.Add (item); + item.Activated += delegate (object s, EventArgs a) { + InsertActionAt (menuItem, false, false); + }; + item = new Gtk.MenuItem (Catalog.GetString ("Insert After")); + m.Add (item); + item.Activated += delegate (object s, EventArgs a) { + InsertActionAt (menuItem, true, false); + }; + item = new Gtk.MenuItem (Catalog.GetString ("Insert Separator Before")); + m.Add (item); + item.Activated += delegate (object s, EventArgs a) { + InsertActionAt (menuItem, false, true); + }; + item = new Gtk.MenuItem (Catalog.GetString ("Insert Separator After")); + m.Add (item); + item.Activated += delegate (object s, EventArgs a) { + InsertActionAt (menuItem, true, true); + }; + + m.Add (new Gtk.SeparatorMenuItem ()); + + item = new Gtk.ImageMenuItem (Gtk.Stock.Cut, null); + m.Add (item); + item.Activated += delegate (object s, EventArgs a) { + menuItem.Cut (); + }; + item.Visible = false; // No copy & paste for now + item = new Gtk.ImageMenuItem (Gtk.Stock.Copy, null); + m.Add (item); + item.Activated += delegate (object s, EventArgs a) { + menuItem.Copy (); + }; + item.Visible = false; + item = new Gtk.ImageMenuItem (Gtk.Stock.Paste, null); + m.Add (item); + item.Activated += delegate (object s, EventArgs a) { + Paste (menuItem); + }; + item.Visible = false; + + item = new Gtk.ImageMenuItem (Gtk.Stock.Delete, null); + m.Add (item); + item.Activated += delegate (object s, EventArgs a) { + DeleteAction (menuItem); + }; + m.ShowAll (); + m.Popup (); + } + + internal void SaveStatus (ArrayList status) + { + for (int n=0; n<menuItems.Count; n++) { + ActionMenuItem item = (ActionMenuItem) menuItems [n]; + if (item.IsSelected) { + status.Add (n); + return; + } + if (item.IsSubmenuVisible) { + status.Add (n); + OpenSubmenu.SaveStatus (status); + return; + } + } + } + + internal void RestoreStatus (ArrayList status, int index) + { + int pos = (int) status [index]; + if (pos >= menuItems.Count) + return; + + ActionMenuItem item = (ActionMenuItem)menuItems [pos]; + if (index == status.Count - 1) { + // The last position in the status is the selected item + item.Select (); + if (item.Node.Action != null && item.Node.Action.Name.Length == 0) { + // Then only case when there can have an action when an empty name + // is when the user clicked on the "add action" link. In this case, + // start editing the item again + item.EditingDone += OnEditingDone; + item.StartEditing (); + } + } + else { + item.ShowSubmenu (); + if (OpenSubmenu != null) + OpenSubmenu.RestoreStatus (status, index + 1); + } + } + + ActionMenuItem LocateWidget (int x, int y) + { + foreach (ActionMenuItem mi in menuItems) { + if (mi.Allocation.Contains (x, y)) + return mi; + } + return null; + } + + ActionMenuItem FindMenuItem (ActionTreeNode node) + { + foreach (ActionMenuItem mi in menuItems) { + if (mi.Node == node) + return mi; + } + return null; + } + } + + interface IMenuItemContainer + { + ActionMenu OpenSubmenu { get; set; } + bool IsTopMenu { get; } + Gtk.Widget Widget { get; } + void ShowContextMenu (ActionItem item); + } +} diff --git a/main/src/addins/MonoDevelop.GtkCore2/libstetic/editor/ActionMenuBar.cs b/main/src/addins/MonoDevelop.GtkCore2/libstetic/editor/ActionMenuBar.cs new file mode 100644 index 0000000000..8d834b5583 --- /dev/null +++ b/main/src/addins/MonoDevelop.GtkCore2/libstetic/editor/ActionMenuBar.cs @@ -0,0 +1,555 @@ + +using System; +using System.Xml; +using System.Collections; +using Stetic.Wrapper; +using Mono.Unix; + +namespace Stetic.Editor +{ + class ActionMenuBar: Gtk.MenuBar, IMenuItemContainer + { + ActionMenu openSubmenu; + ActionTree actionTree; + int dropPosition = -1; + int dropIndex; + ArrayList menuItems = new ArrayList (); + bool showPlaceholder; + Gtk.Widget addLabel; + Gtk.Widget spacerItem; + + public ActionMenuBar () + { + DND.DestSet (this, true); + } + + public void FillMenu (ActionTree actionTree) + { + addLabel = null; + + if (this.actionTree != null) { + this.actionTree.ChildNodeAdded -= OnChildAdded; + this.actionTree.ChildNodeRemoved -= OnChildRemoved; + } + + this.actionTree = actionTree; + if (actionTree == null) { + AddSpacerItem (); + return; + } + + actionTree.ChildNodeAdded += OnChildAdded; + actionTree.ChildNodeRemoved += OnChildRemoved; + + HideSpacerItem (); + menuItems.Clear (); + Widget wrapper = Widget.Lookup (this); + + foreach (Gtk.Widget w in Children) { + Remove (w); + w.Destroy (); + } + + foreach (ActionTreeNode node in actionTree.Children) { + ActionMenuItem aitem = new ActionMenuItem (wrapper, this, node); + AddItem (aitem, -1); + menuItems.Add (aitem); + } + + if (showPlaceholder) { + AddCreateItemLabel (); + } else if (actionTree.Children.Count == 0) { + // Give some height to the toolbar + AddSpacerItem (); + } + } + + public object SaveStatus () + { + ArrayList status = new ArrayList (); + + for (int n=0; n<menuItems.Count; n++) { + ActionMenuItem item = (ActionMenuItem) menuItems [n]; + if (item.IsSubmenuVisible) { + status.Add (n); + OpenSubmenu.SaveStatus (status); + break; + } + } + return status; + } + + public void RestoreStatus (object data) + { + ArrayList status = (ArrayList) data; + if (status.Count == 0) + return; + + int pos = (int) status [0]; + if (pos >= menuItems.Count) + return; + + ActionMenuItem item = (ActionMenuItem) menuItems [pos]; + if (status.Count == 1) { + // The last position in the status is the selected item + item.Select (); + if (item.Node.Action != null && item.Node.Action.Name.Length == 0) { + // Then only case when there can have an action when an empty name + // is when the user clicked on the "add action" link. In this case, + // start editing the item again + item.EditingDone += OnEditingDone; + item.StartEditing (); + } + } else { + item.ShowSubmenu (); + if (OpenSubmenu != null) + OpenSubmenu.RestoreStatus (status, 1); + } + } + + void AddCreateItemLabel () + { + HideSpacerItem (); + Gtk.Label emptyLabel = new Gtk.Label (); + emptyLabel.Xalign = 0; + emptyLabel.Markup = "<i><span foreground='darkgrey'>" + Catalog.GetString ("Click to create menu") + "</span></i>"; + Gtk.MenuItem mit = new Gtk.MenuItem (); + mit.Child = emptyLabel; + mit.ButtonPressEvent += OnNewItemPress; + Insert (mit, -1); + mit.ShowAll (); + addLabel = mit; + } + + void AddSpacerItem () + { + if (spacerItem == null) { + Gtk.Label emptyLabel = new Gtk.Label (); + emptyLabel.Xalign = 0; + emptyLabel.Markup = "<i><span foreground='darkgrey'>" + Catalog.GetString ("Empty menu bar") + "</span></i>"; + Gtk.MenuItem mit = new Gtk.MenuItem (); + mit.Child = emptyLabel; + Insert (mit, -1); + spacerItem = mit; + ShowAll (); + } + } + + void HideSpacerItem () + { + if (spacerItem != null) { + Remove (spacerItem); + spacerItem = null; + } + } + + void AddItem (ActionMenuItem aitem, int pos) + { + Gtk.Table t = new Gtk.Table (1, 3, false); + aitem.Attach (t, 0, 0); + aitem.KeyPressEvent += OnItemKeyPress; + t.ShowAll (); + + CustomMenuBarItem it = new CustomMenuBarItem (); + it.ActionMenuItem = aitem; + aitem.Bind (it); + it.Child = t; + it.ShowAll (); + Insert (it, pos); + } + + public bool ShowInsertPlaceholder { + get { return showPlaceholder; } + set { + showPlaceholder = value; + if (value && addLabel == null) { + AddCreateItemLabel (); + } else if (!value && addLabel != null) { + Remove (addLabel); + addLabel = null; + if (menuItems.Count == 0) + AddSpacerItem (); + } + } + } + + public void Unselect () + { + // Unselects any selected item and hides any open submenu menu + Widget wrapper = Widget.Lookup (this); + if (OpenSubmenu != null) + OpenSubmenu.ResetSelection (); + IDesignArea area = wrapper.GetDesignArea (); + if (area != null) { + foreach (Gtk.Widget w in Children) { + CustomMenuBarItem it = w as CustomMenuBarItem; + if (it != null) + area.ResetSelection (it.ActionMenuItem); + } + } + OpenSubmenu = null; + } + + void OnChildAdded (object ob, ActionTreeNodeArgs args) + { + Refresh (); + } + + void OnChildRemoved (object ob, ActionTreeNodeArgs args) + { + OpenSubmenu = null; + + Widget wrapper = Widget.Lookup (this); + IDesignArea area = wrapper.GetDesignArea (); + IObjectSelection asel = area.GetSelection (); + ActionMenuItem curSel = asel != null ? asel.DataObject as ActionMenuItem : null; + int pos = menuItems.IndexOf (curSel); + + foreach (Gtk.Widget w in Children) { + if (w is CustomMenuBarItem && ((CustomMenuBarItem)w).ActionMenuItem.Node == args.Node) { + Remove (w); + menuItems.Remove (((CustomMenuBarItem)w).ActionMenuItem); + if (menuItems.Count == 0 && !showPlaceholder) + AddSpacerItem (); + break; + } + } + if (pos != -1 && pos < menuItems.Count) + ((ActionMenuItem)menuItems[pos]).Select (); + else if (menuItems.Count > 0) + ((ActionMenuItem)menuItems[menuItems.Count-1]).Select (); + } + + void Refresh () + { + Widget wrapper = Widget.Lookup (this); + IDesignArea area = wrapper.GetDesignArea (); + if (area == null) + return; + + ActionTreeNode selNode = null; + + foreach (Gtk.Widget w in Children) { + CustomMenuBarItem it = w as CustomMenuBarItem; + if (it != null && area.IsSelected (it.ActionMenuItem)) { + selNode = it.ActionMenuItem.Node; + area.ResetSelection (it.ActionMenuItem); + } + Remove (w); + } + + FillMenu (actionTree); + + if (selNode != null) { + ActionMenuItem mi = FindMenuItem (selNode); + if (mi != null) + mi.Select (); + } + } + + [GLib.ConnectBeforeAttribute] + void OnNewItemPress (object ob, Gtk.ButtonPressEventArgs args) + { + InsertAction (menuItems.Count); + args.RetVal = true; + } + + void InsertAction (int pos) + { + Widget wrapper = Widget.Lookup (this); + using (wrapper.UndoManager.AtomicChange) { + Wrapper.Action ac = (Wrapper.Action) ObjectWrapper.Create (wrapper.Project, + new Gtk.Action ("", "", null, null), + wrapper); + ActionTreeNode node = new ActionTreeNode (Gtk.UIManagerItemType.Menu, "", ac); + actionTree.Children.Insert (pos, node); + + ActionMenuItem aitem = FindMenuItem (node); + aitem.EditingDone += OnEditingDone; + aitem.Select (); + aitem.StartEditing (); + + if (wrapper.LocalActionGroups.Count == 0) + wrapper.LocalActionGroups.Add (new ActionGroup ("Default")); + wrapper.LocalActionGroups[0].Actions.Add (ac); + } + } + + void OnEditingDone (object ob, EventArgs args) + { + ActionMenuItem item = (ActionMenuItem) ob; + item.EditingDone -= OnEditingDone; + Widget wrapper = Widget.Lookup (this); + + if (item.Node.Action.GtkAction.Label.Length == 0 && item.Node.Action.GtkAction.StockId == null) { + IDesignArea area = wrapper.GetDesignArea (); + area.ResetSelection (item); + using (wrapper.UndoManager.AtomicChange) { + actionTree.Children.Remove (item.Node); + wrapper.LocalActionGroups [0].Actions.Remove (item.Node.Action); + } + } + } + + public void Select (ActionTreeNode node) + { + ActionMenuItem item = FindMenuItem (node); + if (item != null) + item.Select (); + } + + public void DropMenu (ActionTreeNode node) + { + ActionMenuItem item = FindMenuItem (node); + if (item != null) { + if (item.HasSubmenu) { + item.ShowSubmenu (); + if (openSubmenu != null) + openSubmenu.Select (null); + } + else + item.Select (); + } + } + + public ActionMenu OpenSubmenu { + get { return openSubmenu; } + set { + if (openSubmenu != null) { + openSubmenu.OpenSubmenu = null; + Widget wrapper = Widget.Lookup (this); + IDesignArea area = wrapper.GetDesignArea (); + if (area != null) + area.RemoveWidget (openSubmenu); + openSubmenu.Destroy (); + } + openSubmenu = value; + } + } + + bool IMenuItemContainer.IsTopMenu { + get { return true; } + } + + Gtk.Widget IMenuItemContainer.Widget { + get { return this; } + } + + protected override bool OnDragMotion (Gdk.DragContext context, int x, int y, uint time) + { + ActionPaletteItem dragItem = DND.DragWidget as ActionPaletteItem; + if (dragItem == null) + return false; + + if (actionTree.Children.Count > 0) { + ActionMenuItem item = LocateWidget (x, y); + if (item != null) { + Widget wrapper = Widget.Lookup (this); + + // Show the submenu to allow droping to it, but avoid + // droping a submenu inside itself + if (item.HasSubmenu && item.Node != dragItem.Node) + item.ShowSubmenu (wrapper.GetDesignArea(), item); + + // Look for the index where to insert the new item + dropIndex = actionTree.Children.IndexOf (item.Node); + int mpos = item.Allocation.X + item.Allocation.Width / 2; + if (x > mpos) + dropIndex++; + + // Calculate the drop position, used to show the drop bar + if (dropIndex == 0) + dropPosition = item.Allocation.X; + else if (dropIndex == menuItems.Count) + dropPosition = item.Allocation.Right; + else { + item = (ActionMenuItem) menuItems [dropIndex]; + ActionMenuItem prevItem = (ActionMenuItem) menuItems [dropIndex - 1]; + dropPosition = prevItem.Allocation.Right + (item.Allocation.X - prevItem.Allocation.Right)/2; + } + } + } else + dropIndex = 0; + + QueueDraw (); + return base.OnDragMotion (context, x, y, time); + } + + protected override void OnDragLeave (Gdk.DragContext context, uint time) + { + dropPosition = -1; + QueueDraw (); + base.OnDragLeave (context, time); + } + + protected override bool OnDragDrop (Gdk.DragContext context, int x, int y, uint time) + { + ActionPaletteItem dropped = DND.Drop (context, null, time) as ActionPaletteItem; + if (dropped == null) + return false; + + if (dropped.Node.Type != Gtk.UIManagerItemType.Menuitem && + dropped.Node.Type != Gtk.UIManagerItemType.Menu && + dropped.Node.Type != Gtk.UIManagerItemType.Toolitem && + dropped.Node.Type != Gtk.UIManagerItemType.Separator) + return false; + + ActionTreeNode newNode = dropped.Node; + if (dropped.Node.Type == Gtk.UIManagerItemType.Toolitem) { + newNode = newNode.Clone (); + newNode.Type = Gtk.UIManagerItemType.Menuitem; + } + + Widget wrapper = Widget.Lookup (this); + using (wrapper.UndoManager.AtomicChange) { + if (dropIndex < actionTree.Children.Count) { + // Do nothing if trying to drop the node over the same node + ActionTreeNode dropNode = actionTree.Children [dropIndex]; + if (dropNode == dropped.Node) + return false; + + if (newNode.ParentNode != null) + newNode.ParentNode.Children.Remove (newNode); + + // The drop position may have changed after removing the dropped node, + // so get it again. + dropIndex = actionTree.Children.IndexOf (dropNode); + actionTree.Children.Insert (dropIndex, newNode); + } else { + if (newNode.ParentNode != null) + newNode.ParentNode.Children.Remove (newNode); + actionTree.Children.Add (newNode); + dropIndex = actionTree.Children.Count - 1; + } + + // Select the dropped node + ActionMenuItem mi = (ActionMenuItem) menuItems [dropIndex]; + mi.Select (); + } + + return base.OnDragDrop (context, x, y, time); + } + protected override bool OnExposeEvent (Gdk.EventExpose ev) + { + bool r = base.OnExposeEvent (ev); + int w, h; + this.GdkWindow.GetSize (out w, out h); + if (dropPosition != -1) + GdkWindow.DrawRectangle (this.Style.BlackGC, true, dropPosition, 0, 3, h); + return r; + } + + void OnItemKeyPress (object s, Gtk.KeyPressEventArgs args) + { + int pos = menuItems.IndexOf (s); + ActionMenuItem item = (ActionMenuItem) s; + + switch (args.Event.Key) { + case Gdk.Key.Left: + if (pos > 0) + ((ActionMenuItem)menuItems[pos - 1]).Select (); + break; + case Gdk.Key.Right: + if (pos < menuItems.Count - 1) + ((ActionMenuItem)menuItems[pos + 1]).Select (); + else if (pos == menuItems.Count - 1) + InsertAction (menuItems.Count); + break; + case Gdk.Key.Down: + if (item.HasSubmenu) { + item.ShowSubmenu (); + if (openSubmenu != null) + openSubmenu.Select (null); + } + break; + case Gdk.Key.Up: + OpenSubmenu = null; + break; + } + args.RetVal = true; + } + + void InsertActionAt (ActionMenuItem item, bool after, bool separator) + { + int pos = menuItems.IndexOf (item); + if (pos == -1) + return; + + if (after) + pos++; + + if (separator) { + ActionTreeNode newNode = new ActionTreeNode (Gtk.UIManagerItemType.Separator, null, null); + actionTree.Children.Insert (pos, newNode); + } else + InsertAction (pos); + } + + void Paste (ActionMenuItem item) + { + } + + public void ShowContextMenu (ActionItem aitem) + { + ActionMenuItem menuItem = (ActionMenuItem) aitem; + + Gtk.Menu m = new Gtk.Menu (); + Gtk.MenuItem item = new Gtk.MenuItem (Catalog.GetString ("Insert Before")); + m.Add (item); + item.Activated += delegate (object s, EventArgs a) { + InsertActionAt (menuItem, false, false); + }; + item = new Gtk.MenuItem (Catalog.GetString ("Insert After")); + m.Add (item); + item.Activated += delegate (object s, EventArgs a) { + InsertActionAt (menuItem, true, false); + }; + + m.Add (new Gtk.SeparatorMenuItem ()); + + item = new Gtk.ImageMenuItem (Gtk.Stock.Cut, null); + m.Add (item); + item.Activated += delegate (object s, EventArgs a) { + menuItem.Cut (); + }; + item.Visible = false; // No copy & paste for now + item = new Gtk.ImageMenuItem (Gtk.Stock.Copy, null); + m.Add (item); + item.Activated += delegate (object s, EventArgs a) { + menuItem.Copy (); + }; + item.Visible = false; // No copy & paste for now + item = new Gtk.ImageMenuItem (Gtk.Stock.Paste, null); + m.Add (item); + item.Activated += delegate (object s, EventArgs a) { + Paste (menuItem); + }; + item.Visible = false; // No copy & paste for now + item = new Gtk.ImageMenuItem (Gtk.Stock.Delete, null); + m.Add (item); + item.Activated += delegate (object s, EventArgs a) { + menuItem.Delete (); + }; + m.ShowAll (); + m.Popup (); + } + + ActionMenuItem LocateWidget (int x, int y) + { + foreach (ActionMenuItem mi in menuItems) { + if (mi.Allocation.Contains (x, y)) + return mi; + } + return null; + } + + ActionMenuItem FindMenuItem (ActionTreeNode node) + { + foreach (ActionMenuItem mi in menuItems) { + if (mi.Node == node) + return mi; + } + return null; + } + } +} diff --git a/main/src/addins/MonoDevelop.GtkCore2/libstetic/editor/ActionMenuItem.cs b/main/src/addins/MonoDevelop.GtkCore2/libstetic/editor/ActionMenuItem.cs new file mode 100644 index 0000000000..9ac08166b0 --- /dev/null +++ b/main/src/addins/MonoDevelop.GtkCore2/libstetic/editor/ActionMenuItem.cs @@ -0,0 +1,588 @@ + +using System; +using Stetic.Wrapper; +using Mono.Unix; + +namespace Stetic.Editor +{ + class ActionMenuItem: ActionItem + { + Gtk.Widget icon; + Gtk.Widget label; + Gtk.Widget accel; + bool motionDrag; + CustomMenuBarItem menuBarItem; + + static Gdk.Pixbuf addMenuImage; + static Gdk.Pixbuf removeMenuImage; + + public event MenuItemEditEventHandler EditingDone; + + static ActionMenuItem () + { + try { + addMenuImage = Gdk.Pixbuf.LoadFromResource ("add-menu.png"); + removeMenuImage = Gdk.Pixbuf.LoadFromResource ("remove-menu.png"); + } catch (Exception e) { + Console.WriteLine ("Error while loading pixbuf: " + e); + } + } + + internal ActionMenuItem (Widget wrapper, IMenuItemContainer parent, ActionTreeNode node) + : this (wrapper, parent, node, 0) + { + } + + internal ActionMenuItem (IDesignArea designArea, IProject project, IMenuItemContainer parent, ActionTreeNode node) + : this (null, parent, node, 6) + { + this.project = project; + this.designArea = designArea; + } + + internal ActionMenuItem (Widget wrapper, IMenuItemContainer parent, ActionTreeNode node, uint itemSpacing): base (node, parent, itemSpacing) + { + this.wrapper = wrapper; + CreateControls (); + } + + bool disposed; + + public override void Dispose () + { + if (disposed) + return; + disposed = true; + if (menuBarItem != null) { + menuBarItem.ButtonPressEvent -= OnMenuItemPress; + menuBarItem.ButtonReleaseEvent -= OnMemuItemRelease; + menuBarItem.MotionNotifyEvent -= OnMotionNotify; + } + if (node.Action != null) + node.Action.ObjectChanged -= OnActionChanged; + base.Dispose (); + } + + public bool HasSubmenu { + get { return node.Type == Gtk.UIManagerItemType.Menu; } + } + + public void StartEditing () + { + if (!editing) { + editing = true; + + Refresh (); + if (node.Type == Gtk.UIManagerItemType.Menu) + HideSubmenu (); + + UpdateSelectionStatus (); + } + } + + + protected override void EndEditing (Gdk.Key exitKey) + { + if (editing) { + Gtk.Entry entry = label as Gtk.Entry; + if (entry != null && exitKey != Gdk.Key.Escape) { + localUpdate = true; + if (entry.Text.Trim().Length > 0 || node.Action.GtkAction.StockId != null) { + using (node.Action.UndoManager.AtomicChange) { + node.Action.Label = entry.Text; + node.Action.NotifyChanged (); + } + } + localUpdate = false; + } + + editing = false; + Refresh (); + while (Gtk.Application.EventsPending ()) + Gtk.Application.RunIteration (); + if (node.Type == Gtk.UIManagerItemType.Menu) { + if (wrapper != null) { + IDesignArea area = wrapper.GetDesignArea (); + if (area != null) + ShowSubmenu (area, this); + } + } + GrabFocus (); + UpdateSelectionStatus (); + + if (EditingDone != null) { + MenuItemEditEventArgs args = new MenuItemEditEventArgs (); + args.ExitKey = exitKey; + EditingDone (this, args); + } + } + } + + public override void Select () + { + base.Select (); + + if (!IsSubmenuVisible) { + parentMenu.OpenSubmenu = null; + if (HasSubmenu) + ShowSubmenu (GetDesignArea (), this); + } + GrabFocus (); + } + + public void Attach (Gtk.Table table, uint row, uint col) + { + table.Attach (this, col, col + 3, row, row + 1); + Show (); + AttachChildren (table, row, col); + } + + void AttachChildren (Gtk.Table table, uint row, uint col) + { + if (icon != null) { + table.Attach (icon, col, col + 1, row, row + 1); + Gtk.Table.TableChild tc = (Gtk.Table.TableChild) table [icon]; + if (!editing) + tc.YPadding = itemSpacing; + } + if (label != null) { + table.Attach (label, col + 1, col + 2, row, row + 1); + Gtk.Table.TableChild tc = (Gtk.Table.TableChild) table [label]; + if (!editing) + tc.YPadding = itemSpacing; + label.GrabFocus (); + } + if (accel != null) + table.Attach (accel, col + 2, col + 3, row, row + 1); + + if (minWidth > 0 && label != null) { + if (label.SizeRequest().Width < minWidth) + label.WidthRequest = minWidth; + } + + bool sens = editing || node.Action == null || node.Action.GtkAction.Sensitive; + if (icon != null) + icon.Sensitive = sens; + if (label != null) + label.Sensitive = sens; + if (accel != null) + accel.Sensitive = sens; + } + + void CreateControls () + { + if (node.Type == Gtk.UIManagerItemType.Separator) { + Gtk.Widget sep; + if (parentMenu.IsTopMenu) { + sep = new Gtk.VSeparator (); + sep.WidthRequest = 6; + } else { + sep = new Gtk.HSeparator (); + sep.HeightRequest = 6; + } + Add (sep); + ShowAll (); + return; + } else { + if (Child != null && Child is Gtk.Separator) + Remove (Child); + } + + if (node.Action == null) + return; + + bool isGlobal = wrapper != null && wrapper.Project.ActionGroups.IndexOf (node.Action.ActionGroup) != -1; + + Gtk.Action gaction = node.Action.GtkAction; + bool barItem = parentMenu.IsTopMenu; + + string text = gaction.Label; + string stock = gaction.StockId; + + if (barItem) { + icon = null; + } else if (node.Action.Type == Stetic.Wrapper.Action.ActionType.Radio) { + icon = new CheckActionIcon (true, node.Action.Active); + } else if (node.Action.Type == Stetic.Wrapper.Action.ActionType.Toggle) { + icon = new CheckActionIcon (node.Action.DrawAsRadio, node.Action.Active); + } + + if (stock != null) { + Gtk.StockItem item = Gtk.Stock.Lookup (stock); + if (text == null || text.Length == 0) + text = item.Label; + + if (item.Keyval != 0 && !editing && !barItem) { + Gtk.Label lac = new Gtk.Label (); + string accelName = Gtk.Accelerator.Name (item.Keyval, item.Modifier).ToUpper (); + accelName = accelName.Replace ("<CONTROL>", "Ctrl+"); + accelName = accelName.Replace ("<SHIFT>", "Shift+"); + accelName = accelName.Replace ("<ALT>", "Alt+"); + lac.Text = accelName; + accel = lac; + } + + if (icon == null && !barItem) + icon = node.Action.CreateIcon (Gtk.IconSize.Menu); + } + + if (editing && !isGlobal) { + if (!barItem) { + Gtk.HBox bbox = new Gtk.HBox (); + if (icon != null) { + bbox.PackStart (icon, false, false, 0); + } + bbox.PackStart (new Gtk.Arrow (Gtk.ArrowType.Down, Gtk.ShadowType.In), false, false, 0); + Gtk.Button b = new Gtk.Button (bbox); + b.TooltipText = Catalog.GetString ("Select action type"); + b.Relief = Gtk.ReliefStyle.None; + b.ButtonPressEvent += OnSelectIcon; + icon = b; + } else + icon = null; + + Gtk.Entry entry = new Gtk.Entry (); + entry.Text = text; + entry.Activated += OnLabelActivated; + entry.KeyPressEvent += OnEntryKeyPress; + entry.HasFrame = false; + this.label = entry; + entry.TooltipText = Catalog.GetString ("Action label"); + } else { + Gtk.Label label = new Gtk.Label (text); + label.Xalign = 0; + this.label = label; + } + + if (editing && wrapper != null) { + // Add a button for creating / deleting a submenu + Gdk.Pixbuf img; + string tip; + if (node.Type != Gtk.UIManagerItemType.Menu) { + img = addMenuImage; + tip = Catalog.GetString ("Add submenu (Ctrl+Right)"); + } else { + img = removeMenuImage; + tip = Catalog.GetString ("Remove submenu (Ctrl+Left)"); + } + + Gtk.Button sb = new Gtk.Button (new Gtk.Image (img)); + sb.TooltipText = tip; + sb.Relief = Gtk.ReliefStyle.None; + sb.Clicked += OnCreateDeleteSubmenu; + + // Make sure the button is alligned to the right of the column + Gtk.HBox bbox = new Gtk.HBox (); + bbox.PackEnd (sb, false, false, 0); + accel = bbox; + } + + + if (node.Type == Gtk.UIManagerItemType.Menu && !editing && !barItem) { + Gtk.Arrow arrow = new Gtk.Arrow (Gtk.ArrowType.Right, Gtk.ShadowType.None); + arrow.Xalign = 1; + this.accel = arrow; + } + + if (itemSpacing > 0 && icon != null) { + // Add some padding to the left of the icon + Gtk.Alignment a = new Gtk.Alignment (0, 0.5f, 0, 0); + a.LeftPadding = itemSpacing; + a.Add (icon); + icon = a; + } + } + + public void Detach () + { + if (disposed) + return; + + Gtk.Table table = (Gtk.Table)Parent; + if (table == null) + return; + if (icon != null) + table.Remove (icon); + if (label != null) + table.Remove (label); + if (accel != null) + table.Remove (accel); + table.Remove (this); + } + + void OnCreateDeleteSubmenu (object ob, EventArgs args) + { + using (node.Action.UndoManager.AtomicChange) { + if (node.Type == Gtk.UIManagerItemType.Menu) { + node.Type = Gtk.UIManagerItemType.Menuitem; + node.Children.Clear (); + } else { + node.Type = Gtk.UIManagerItemType.Menu; + } + + EndEditing (Gdk.Key.Return); + node.Action.NotifyChanged (); + } + } + + void OnLabelActivated (object ob, EventArgs args) + { + EndEditing (Gdk.Key.Return); + } + + [GLib.ConnectBefore] + void OnEntryKeyPress (object ob, Gtk.KeyPressEventArgs args) + { + switch (args.Event.Key) { + case Gdk.Key.Down: + case Gdk.Key.Escape: + case Gdk.Key.Up: + EndEditing (args.Event.Key); + args.RetVal = true; + break; + } + args.RetVal = false; + } + + [GLib.ConnectBeforeAttribute] + void OnSelectIcon (object sender, Gtk.ButtonPressEventArgs e) + { + Gtk.Menu menu = new Gtk.Menu (); + + Gtk.CheckMenuItem item = new Gtk.CheckMenuItem (Catalog.GetString ("Action")); + item.DrawAsRadio = true; + item.Active = (node.Action.Type == Stetic.Wrapper.Action.ActionType.Action); + item.Activated += OnSetActionType; + menu.Insert (item, -1); + + item = new Gtk.CheckMenuItem (Catalog.GetString ("Radio Action")); + item.DrawAsRadio = true; + item.Active = (node.Action.Type == Stetic.Wrapper.Action.ActionType.Radio); + item.Activated += OnSetRadioType; + menu.Insert (item, -1); + + item = new Gtk.CheckMenuItem (Catalog.GetString ("Toggle Action")); + item.DrawAsRadio = true; + item.Active = (node.Action.Type == Stetic.Wrapper.Action.ActionType.Toggle); + item.Activated += OnSetToggleType; + menu.Insert (item, -1); + + menu.Insert (new Gtk.SeparatorMenuItem (), -1); + + Gtk.MenuItem itIcons = new Gtk.MenuItem (Catalog.GetString ("Select Icon")); + menu.Insert (itIcons, -1); + IconSelectorMenu menuIcons = new IconSelectorMenu (GetProject ()); + menuIcons.IconSelected += OnStockSelected; + itIcons.Submenu = menuIcons; + + Gtk.MenuItem it = new Gtk.MenuItem (Catalog.GetString ("Clear Icon")); + it.Sensitive = (node.Action.GtkAction.StockId != null); + it.Activated += OnClearIcon; + menu.Insert (it, -1); + + menu.ShowAll (); + menu.Popup (null, null, new Gtk.MenuPositionFunc (OnDropMenuPosition), 3, Gtk.Global.CurrentEventTime); + e.RetVal = false; + } + + void OnDropMenuPosition (Gtk.Menu menu, out int x, out int y, out bool pushIn) + { + this.ParentWindow.GetOrigin (out x, out y); + x += this.Allocation.X; + y += this.Allocation.Y + this.Allocation.Height; + pushIn = true; + } + + void OnStockSelected (object s, IconEventArgs args) + { + using (node.Action.UndoManager.AtomicChange) { + node.Action.StockId = args.IconId; + node.Action.NotifyChanged (); + } + } + + void OnSetToggleType (object ob, EventArgs args) + { + using (node.Action.UndoManager.AtomicChange) { + node.Action.Type = Stetic.Wrapper.Action.ActionType.Toggle; + node.Action.NotifyChanged (); + } + } + + void OnSetRadioType (object ob, EventArgs args) + { + using (node.Action.UndoManager.AtomicChange) { + node.Action.Type = Stetic.Wrapper.Action.ActionType.Radio; + node.Action.NotifyChanged (); + } + } + + void OnSetActionType (object ob, EventArgs args) + { + using (node.Action.UndoManager.AtomicChange) { + node.Action.Type = Stetic.Wrapper.Action.ActionType.Action; + node.Action.NotifyChanged (); + } + } + + void OnClearIcon (object on, EventArgs args) + { + using (node.Action.UndoManager.AtomicChange) { + node.Action.StockId = null; + node.Action.NotifyChanged (); + } + } + + public override void Refresh () + { + Gtk.Table table = (Gtk.Table)Parent; + if (table == null) + return; + + if (icon != null && icon.Parent != null) + table.Remove (icon); + if (label != null && label.Parent != null) + table.Remove (label); + if (accel != null && accel.Parent != null) + table.Remove (accel); + + icon = label = accel = null; + CreateControls (); + Gtk.Table.TableChild tc = (Gtk.Table.TableChild)table[this]; + AttachChildren (table, tc.TopAttach, tc.LeftAttach); + + table.ShowAll (); + } + + internal void Bind (CustomMenuBarItem item) + { + // When embedding the action menu in a MenuBar, + // the parent menu item intercepts the mouse events, + // so those events must be manually bound here + menuBarItem = item; + item.ButtonPressEvent += OnMenuItemPress; + item.ButtonReleaseEvent += OnMemuItemRelease; + item.MotionNotifyEvent += OnMotionNotify; + } + + [GLib.ConnectBeforeAttribute] + void OnMenuItemPress (object ob, Gtk.ButtonPressEventArgs args) + { + Gtk.Widget mit = (Gtk.Widget) ob; + if (wrapper != null && wrapper.Project.Selection != mit.Parent) { + wrapper.Select (); + args.RetVal = true; + return; + } + motionDrag = true; + args.RetVal = ProcessButtonPress (args.Event); + } + + [GLib.ConnectBeforeAttribute] + void OnMemuItemRelease (object ob, Gtk.ButtonReleaseEventArgs args) + { + args.RetVal = ProcessButtonRelease (args.Event); + motionDrag = false; + } + + void OnMotionNotify (object ob, Gtk.MotionNotifyEventArgs args) + { + if (motionDrag) { + // Looks like drag begin can be intercepted, so the motion notify + // has to be used. + ProcessDragBegin (null, args.Event); + motionDrag = false; + } + } + + protected override bool OnButtonReleaseEvent (Gdk.EventButton ev) + { + return ProcessButtonRelease (ev); + } + + public bool ProcessButtonRelease (Gdk.EventButton ev) + { + // Clicking a selected item starts the edit mode + if (editOnRelease) + StartEditing (); + + editOnRelease = false; + return true; + } + + public override void ProcessDragBegin (Gdk.DragContext ctx, Gdk.EventMotion evt) + { + if (HasSubmenu) + HideSubmenu (); + base.ProcessDragBegin (ctx, evt); + } + + void OnActionChanged (object ob, ObjectWrapperEventArgs a) + { + if (!localUpdate) + Refresh (); + } + + public bool IsSubmenuVisible { + get { + ActionMenu menu = parentMenu.OpenSubmenu; + return (menu != null && menu.ParentNode == node); + } + } + + public void ShowSubmenu () + { + ShowSubmenu (wrapper.GetDesignArea (), this); + } + + public void ShowSubmenu (IDesignArea area, Gtk.Widget refWidget) + { + HideSubmenu (); + Gdk.Rectangle rect = area.GetCoordinates (refWidget); + ActionMenu menu = new ActionMenu (wrapper, parentMenu, node); + menu.ShowAll (); + area.AddWidget (menu, rect.Right, rect.Top); + menu.TrackWidgetPosition (refWidget, parentMenu.IsTopMenu); + + parentMenu.OpenSubmenu = menu; + } + + void HideSubmenu () + { + parentMenu.OpenSubmenu = null; + } + } + + class CheckActionIcon: Gtk.EventBox + { + readonly bool isRadio; + readonly bool active; + + public CheckActionIcon (bool isRadio, bool active) + { + this.isRadio = isRadio; + this.active = active; + WidthRequest = HeightRequest = 16; + } + + protected override bool OnExposeEvent (Gdk.EventExpose ev) + { + Gdk.Rectangle rect = Allocation; + rect.X = rect.Y = 0; + + Gtk.ShadowType sh = active ? Gtk.ShadowType.In : Gtk.ShadowType.Out; + if (isRadio) + Gtk.Style.PaintOption (this.Style, this.GdkWindow, this.State, sh, rect, this, "", rect.X, rect.Y, rect.Width, rect.Height); + else + Gtk.Style.PaintCheck (this.Style, this.GdkWindow, this.State, sh, rect, this, "", rect.X, rect.Y, rect.Width, rect.Height); + return true; + } + } + + delegate void MenuItemEditEventHandler (object s, MenuItemEditEventArgs args); + + class MenuItemEditEventArgs: EventArgs + { + public Gdk.Key ExitKey; + } +} diff --git a/main/src/addins/MonoDevelop.GtkCore2/libstetic/editor/ActionToolItem.cs b/main/src/addins/MonoDevelop.GtkCore2/libstetic/editor/ActionToolItem.cs new file mode 100644 index 0000000000..5b27ab4c1c --- /dev/null +++ b/main/src/addins/MonoDevelop.GtkCore2/libstetic/editor/ActionToolItem.cs @@ -0,0 +1,371 @@ + +using System; +using Stetic.Wrapper; +using Mono.Unix; + +namespace Stetic.Editor +{ + class ActionToolItem: ActionItem + { + ActionToolbar parentToolbar; + + bool motionDrag; + bool showingText; + Gtk.Widget dropButton; + + public event EventHandler EditingDone; + + internal ActionToolItem (Widget wrapper, ActionToolbar parent, ActionTreeNode node) + : this (wrapper, parent, node, 0) + { + } + + internal ActionToolItem (Widget wrapper, ActionToolbar parent, ActionTreeNode node, uint itemSpacing): base (node, parent, itemSpacing) + { + this.parentToolbar = parent; + this.wrapper = wrapper; + CreateControls (); + } + + public void StartEditing (bool doClick) + { + if (!editing && node.Action != null) { + // Don't allow efiting global actions + if (wrapper != null && wrapper.Project.ActionGroups.IndexOf (node.Action.ActionGroup) != -1) + return; + editing = true; + Refresh (); + + if (doClick && dropButton != null) { + // Make sure the dropButton is properly shown + while (Gtk.Application.EventsPending ()) + Gtk.Application.RunIteration (); + OnSelectIcon (null, null); + } + } + } + + protected override void EndEditing (Gdk.Key exitKey) + { + if (editing) { + editing = false; + Refresh (); + while (Gtk.Application.EventsPending ()) + Gtk.Application.RunIteration (); + GrabFocus (); + if (EditingDone != null) + EditingDone (this, EventArgs.Empty); + } + } + + void CreateControls () + { + Gtk.Widget icon = null; + Gtk.Widget label = null; + dropButton = null; + + if (Child != null) { + Gtk.Widget w = Child; + Remove (w); + w.Destroy (); + } + + if (node.Type == Gtk.UIManagerItemType.Separator) { + Gtk.Widget sep; + if (parentToolbar.Orientation == Gtk.Orientation.Horizontal) { + sep = new Gtk.VSeparator (); + } else { + sep = new Gtk.HSeparator (); + } + Gtk.HBox box = new Gtk.HBox (); + box.BorderWidth = 6; + box.PackStart (sep, true, true, 0); + Add (box); + return; + } + + if (node.Action == null) + return; + + Gtk.Action gaction = node.Action.GtkAction; + + bool showText = parentToolbar.ToolbarStyle == Gtk.ToolbarStyle.Text; + bool showIcon = parentToolbar.ToolbarStyle == Gtk.ToolbarStyle.Icons; + if (parentToolbar.ToolbarStyle == Gtk.ToolbarStyle.Both) { + showText = showIcon = true; + } + else if (parentToolbar.ToolbarStyle == Gtk.ToolbarStyle.BothHoriz) { + showText = parentToolbar.Orientation == Gtk.Orientation.Vertical || gaction.IsImportant; + showIcon = true; + } + + string text = node.Action.ToolLabel; + showingText = showText; + + if (showIcon) + { + if (gaction.StockId != null) { + icon = node.Action.CreateIcon (parentToolbar.IconSize); + } else if (!gaction.IsImportant) { + icon = CreateFakeItem (); + } + } + + if (editing) { + Gtk.HBox bbox = new Gtk.HBox (); + bbox.Spacing = 3; + if (icon != null) { + bbox.PackStart (icon, false, false, 0); + } + bbox.PackStart (new Gtk.Arrow (Gtk.ArrowType.Down, Gtk.ShadowType.In), false, false, 0); + Gtk.Button b = new Gtk.Button (bbox); + b.TooltipText = Catalog.GetString ("Select action type"); + b.Relief = Gtk.ReliefStyle.None; + b.ButtonPressEvent += OnSelectIcon; + dropButton = b; + icon = b; + + if (showText) { + Gtk.Entry entry = new Gtk.Entry (); + entry.Text = text; + entry.Changed += OnLabelChanged; + entry.Activated += OnLabelActivated; + entry.HasFrame = false; + label = entry; + entry.TooltipText = Catalog.GetString ("Action label"); + } + } else if (showText && text != null && text.Length > 0) { + label = new Gtk.Label (text); + label.Sensitive = editing || node.Action == null || node.Action.GtkAction.Sensitive; + } + + if (icon != null && label != null) { + if (parentToolbar.ToolbarStyle == Gtk.ToolbarStyle.BothHoriz) { + Gtk.HBox box = new Gtk.HBox (); + box.PackStart (icon, false, false, 0); + box.PackStart (label, true, true, 0); + icon = box; + } else if (parentToolbar.ToolbarStyle == Gtk.ToolbarStyle.Both) { + Gtk.VBox box = new Gtk.VBox (); + Gtk.Alignment al = new Gtk.Alignment (0.5f, 0f, 0f, 0f); + al.Add (icon); + box.PackStart (al, false, false, 0); + box.PackStart (label, true, true, 0); + icon = box; + } + } else if (label != null) { + icon = label; + } + + if (icon == null) { + icon = CreateFakeItem (); + } + + icon.Sensitive = editing || node.Action == null || node.Action.GtkAction.Sensitive; + + if (!editing) { + Gtk.Button but = new Gtk.Button (icon); + but.Relief = Gtk.ReliefStyle.None; + but.ButtonPressEvent += OnToolItemPress; + but.ButtonReleaseEvent += OnMemuItemRelease; + but.MotionNotifyEvent += OnMotionNotify; + but.Events |= Gdk.EventMask.PointerMotionMask; + icon = but; + } + + Add (icon); + + ShowAll (); + } + + Gtk.Widget CreateFakeItem () + { + Gtk.Frame frm = new Gtk.Frame (); + frm.ShadowType = Gtk.ShadowType.Out; + int w, h; + Gtk.Icon.SizeLookup (parentToolbar.IconSize, out w, out h); + frm.WidthRequest = w; + frm.HeightRequest = h; + return frm; + } + + void OnLabelChanged (object ob, EventArgs args) + { + localUpdate = true; + + Gtk.Entry entry = ob as Gtk.Entry; + if (entry.Text.Length > 0 || node.Action.GtkAction.StockId != null) { + using (node.Action.UndoManager.AtomicChange) { + node.Action.Label = entry.Text; + node.Action.NotifyChanged (); + } + } + localUpdate = false; + } + + void OnLabelActivated (object ob, EventArgs args) + { + EndEditing (Gdk.Key.Return); + } + + [GLib.ConnectBeforeAttribute] + void OnSelectIcon (object s, Gtk.ButtonPressEventArgs args) + { + Gtk.Menu menu = new Gtk.Menu (); + + Gtk.CheckMenuItem item = new Gtk.CheckMenuItem (Catalog.GetString ("Action")); + item.DrawAsRadio = true; + item.Active = (node.Action.Type == Stetic.Wrapper.Action.ActionType.Action); + item.Activated += OnSetActionType; + menu.Insert (item, -1); + + item = new Gtk.CheckMenuItem (Catalog.GetString ("Radio Action")); + item.DrawAsRadio = true; + item.Active = (node.Action.Type == Stetic.Wrapper.Action.ActionType.Radio); + item.Activated += OnSetRadioType; + menu.Insert (item, -1); + + item = new Gtk.CheckMenuItem (Catalog.GetString ("Toggle Action")); + item.DrawAsRadio = true; + item.Active = (node.Action.Type == Stetic.Wrapper.Action.ActionType.Toggle); + item.Activated += OnSetToggleType; + menu.Insert (item, -1); + + menu.Insert (new Gtk.SeparatorMenuItem (), -1); + + Gtk.MenuItem itIcons = new Gtk.MenuItem (Catalog.GetString ("Select Icon")); + menu.Insert (itIcons, -1); + IconSelectorMenu menuIcons = new IconSelectorMenu (GetProject ()); + menuIcons.IconSelected += OnStockSelected; + itIcons.Submenu = menuIcons; + + Gtk.MenuItem it = new Gtk.MenuItem (Catalog.GetString ("Clear Icon")); + it.Sensitive = (node.Action.GtkAction.StockId != null); + it.Activated += OnClearIcon; + menu.Insert (it, -1); + + menu.ShowAll (); + + uint but = args != null ? args.Event.Button : 1; + menu.Popup (null, null, new Gtk.MenuPositionFunc (OnDropMenuPosition), but, Gtk.Global.CurrentEventTime); + + // Make sure we get the focus after closing the menu, so we can keep browsing buttons + // using the keyboard. + menu.Hidden += delegate (object sender, EventArgs a) { + GrabFocus (); + }; + + if (args != null) + args.RetVal = false; + } + + void OnDropMenuPosition (Gtk.Menu menu, out int x, out int y, out bool pushIn) + { + dropButton.ParentWindow.GetOrigin (out x, out y); + x += dropButton.Allocation.X; + y += dropButton.Allocation.Y + dropButton.Allocation.Height; + pushIn = true; + } + + void OnSetToggleType (object ob, EventArgs args) + { + using (node.Action.UndoManager.AtomicChange) { + node.Action.Type = Stetic.Wrapper.Action.ActionType.Toggle; + node.Action.NotifyChanged (); + } + } + + void OnSetRadioType (object ob, EventArgs args) + { + using (node.Action.UndoManager.AtomicChange) { + node.Action.Type = Stetic.Wrapper.Action.ActionType.Radio; + node.Action.NotifyChanged (); + } + } + + void OnSetActionType (object ob, EventArgs args) + { + using (node.Action.UndoManager.AtomicChange) { + node.Action.Type = Stetic.Wrapper.Action.ActionType.Action; + node.Action.NotifyChanged (); + } + } + + void OnStockSelected (object s, IconEventArgs args) + { + using (node.Action.UndoManager.AtomicChange) { + node.Action.StockId = args.IconId; + node.Action.NotifyChanged (); + } + } + + void OnClearIcon (object on, EventArgs args) + { + using (node.Action.UndoManager.AtomicChange) { + node.Action.StockId = null; + node.Action.NotifyChanged (); + } + } + + public override void Refresh () + { + CreateControls (); + } + + [GLib.ConnectBeforeAttribute] + void OnToolItemPress (object ob, Gtk.ButtonPressEventArgs args) + { + if (wrapper != null && wrapper.Project.Selection != wrapper.Wrapped) { + wrapper.Select (); + args.RetVal = true; + return; + } + if (args.Event.Button == 1) + motionDrag = true; + args.RetVal = ProcessButtonPress (args.Event); + } + + [GLib.ConnectBeforeAttribute] + void OnMemuItemRelease (object ob, Gtk.ButtonReleaseEventArgs args) + { + args.RetVal = ProcessButtonRelease (args.Event); + motionDrag = false; + } + + [GLib.ConnectBeforeAttribute] + void OnMotionNotify (object ob, Gtk.MotionNotifyEventArgs args) + { + if (motionDrag) { + // Looks like drag begin can be intercepted, so the motion notify + // has to be used. + ProcessDragBegin (null, args.Event); + motionDrag = false; + } + } + + protected override bool OnButtonReleaseEvent (Gdk.EventButton ev) + { + return ProcessButtonRelease (ev); + } + + public bool ProcessButtonRelease (Gdk.EventButton ev) + { + // Clicking a selected item starts the edit mode + if (editOnRelease) { + StartEditing (!showingText); + } + + editOnRelease = false; + return true; + } + + protected override bool OnKeyPressEvent (Gdk.EventKey e) + { + if (e.Key == Gdk.Key.Return) + EndEditing (Gdk.Key.Return); + else if (e.Key == Gdk.Key.Escape) + EndEditing (Gdk.Key.Escape); + return base.OnKeyPressEvent (e); + } + } +} diff --git a/main/src/addins/MonoDevelop.GtkCore2/libstetic/editor/ActionToolbar.cs b/main/src/addins/MonoDevelop.GtkCore2/libstetic/editor/ActionToolbar.cs new file mode 100644 index 0000000000..3166f669a3 --- /dev/null +++ b/main/src/addins/MonoDevelop.GtkCore2/libstetic/editor/ActionToolbar.cs @@ -0,0 +1,542 @@ + +using System; +using System.Xml; +using System.Collections; +using Stetic.Wrapper; +using Mono.Unix; + +namespace Stetic.Editor +{ + class ActionToolbar: Gtk.Toolbar, IMenuItemContainer + { + ActionTree actionTree; + int dropPosition = -1; + int dropIndex; + ArrayList toolItems = new ArrayList (); + bool showPlaceholder = true; + Gtk.Widget addLabel; + Gtk.Widget spacerItem; + + public ActionToolbar () + { + DND.DestSet (this, true); + this.ShowArrow = false; + } + + public void FillMenu (ActionTree actionTree) + { + addLabel = null; + + if (this.actionTree != null) { + this.actionTree.ChildNodeAdded -= OnChildAdded; + this.actionTree.ChildNodeRemoved -= OnChildRemoved; + } + + this.actionTree = actionTree; + if (actionTree == null) { + AddSpacerItem (); + return; + } + + actionTree.ChildNodeAdded += OnChildAdded; + actionTree.ChildNodeRemoved += OnChildRemoved; + + HideSpacerItem (); + toolItems.Clear (); + Widget wrapper = Stetic.Wrapper.Widget.Lookup (this); + + foreach (Gtk.Widget w in Children) { + Remove (w); + w.Destroy (); + } + + foreach (ActionTreeNode node in actionTree.Children) { + ActionToolItem aitem = new ActionToolItem (wrapper, this, node); + AddItem (aitem, -1); + toolItems.Add (aitem); + } + + if (actionTree.Children.Count == 0) { + // If there are no buttons in the toolbar, give it some height so it is selectable. + AddSpacerItem (); + } + + if (showPlaceholder) { + AddCreateItemLabel (); + } + } + + void AddCreateItemLabel () + { + HideSpacerItem (); + Gtk.EventBox ebox = new Gtk.EventBox (); + ebox.VisibleWindow = false; + Gtk.Label emptyLabel = new Gtk.Label (); + emptyLabel.Xalign = 0; + if (this.Orientation == Gtk.Orientation.Vertical) + emptyLabel.Markup = "<i><span foreground='darkgrey'>" + Catalog.GetString ("New\nbutton") + "</span></i>"; + else + emptyLabel.Markup = "<i><span foreground='darkgrey'>" + Catalog.GetString ("New button") + "</span></i>"; + ebox.BorderWidth = 3; + ebox.Add (emptyLabel); + Gtk.ToolItem mit = new Gtk.ToolItem (); + mit.Child = ebox; + ebox.ButtonPressEvent += OnNewItemPress; + Insert (mit, -1); + mit.ShowAll (); + addLabel = mit; + } + + void AddSpacerItem () + { + if (spacerItem == null) { + Gtk.ToolItem tb = new Gtk.ToolItem (); + Gtk.Label emptyLabel = new Gtk.Label (); + emptyLabel.Xalign = 0; + emptyLabel.Xpad = 3; + emptyLabel.Ypad = 3; + if (this.Orientation == Gtk.Orientation.Vertical) + emptyLabel.Markup = "<i><span foreground='darkgrey'>" + Catalog.GetString ("Empty\ntoolbar") + "</span></i>"; + else + emptyLabel.Markup = "<i><span foreground='darkgrey'>" + Catalog.GetString ("Empty toolbar") + "</span></i>"; + tb.Child = emptyLabel; + Insert (tb, -1); + ShowAll (); + spacerItem = tb; + } + } + + void HideSpacerItem () + { + if (spacerItem != null) { + Remove (spacerItem); + spacerItem = null; + } + } + + void AddItem (ActionToolItem aitem, int pos) + { + aitem.KeyPressEvent += OnItemKeyPress; + + CustomToolbarItem it = new CustomToolbarItem (); + it.ActionToolItem = aitem; + it.Child = aitem; + it.ShowAll (); + Insert (it, pos); + } + + public bool ShowInsertPlaceholder { + get { return showPlaceholder; } + set { + showPlaceholder = value; + if (value && addLabel == null) { + AddCreateItemLabel (); + } else if (!value && addLabel != null) { + Remove (addLabel); + addLabel.Destroy (); + addLabel = null; + if (actionTree.Children.Count == 0) + AddSpacerItem (); + } + } + } + + public Stetic.Editor.ActionMenu OpenSubmenu { + get { return null; } + set { } + } + + public bool IsTopMenu { + get { return true; } + } + + public Gtk.Widget Widget { + get { return this; } + } + + public void Unselect () + { + // Unselects any selected item + Widget wrapper = Stetic.Wrapper.Widget.Lookup (this); + IDesignArea area = wrapper.GetDesignArea (); + if (area != null) { + foreach (Gtk.Widget w in Children) { + CustomToolbarItem it = w as CustomToolbarItem; + if (it != null) + area.ResetSelection (it.ActionToolItem); + } + } + } + + void OnChildAdded (object ob, ActionTreeNodeArgs args) + { + Refresh (); + } + + void OnChildRemoved (object ob, ActionTreeNodeArgs args) + { + Widget wrapper = Stetic.Wrapper.Widget.Lookup (this); + IDesignArea area = wrapper.GetDesignArea (); + IObjectSelection asel = area.GetSelection (); + ActionToolItem curSel = asel != null ? asel.DataObject as ActionToolItem : null; + int pos = toolItems.IndexOf (curSel); + + foreach (Gtk.Widget w in Children) { + if (w is CustomToolbarItem && ((CustomToolbarItem)w).ActionToolItem.Node == args.Node) { + Remove (w); + toolItems.Remove (((CustomToolbarItem)w).ActionToolItem); + w.Destroy (); + if (!showPlaceholder && toolItems.Count == 0) + AddSpacerItem (); + break; + } + } + + if (pos != -1 && pos < toolItems.Count) + ((ActionToolItem)toolItems[pos]).Select (); + else if (toolItems.Count > 0) + ((ActionToolItem)toolItems[toolItems.Count-1]).Select (); + } + + void Refresh () + { + Widget wrapper = Stetic.Wrapper.Widget.Lookup (this); + IDesignArea area = wrapper.GetDesignArea (); + if (area == null) + return; + + ActionTreeNode selNode = null; + + foreach (Gtk.Widget w in Children) { + CustomToolbarItem it = w as CustomToolbarItem; + if (it != null && area.IsSelected (it.ActionToolItem)) { + selNode = it.ActionToolItem.Node; + area.ResetSelection (it.ActionToolItem); + } + Remove (w); + w.Destroy (); + } + + FillMenu (actionTree); + + if (selNode != null) { + ActionToolItem mi = FindMenuItem (selNode); + if (mi != null) + mi.Select (); + } + } + + [GLib.ConnectBeforeAttribute] + void OnNewItemPress (object ob, Gtk.ButtonPressEventArgs args) + { + InsertAction (toolItems.Count); + args.RetVal = true; + } + + void InsertAction (int pos) + { + Widget wrapper = Stetic.Wrapper.Widget.Lookup (this); + using (wrapper.UndoManager.AtomicChange) { + Wrapper.Action ac = (Wrapper.Action) ObjectWrapper.Create (wrapper.Project, + new Gtk.Action ("", "", null, null), + wrapper); + ActionTreeNode node = new ActionTreeNode (Gtk.UIManagerItemType.Toolitem, "", ac); + actionTree.Children.Insert (pos, node); + + ActionToolItem aitem = FindMenuItem (node); + aitem.EditingDone += OnEditingDone; + aitem.Select (); + aitem.StartEditing (false); + //ShowInsertPlaceholder = false; + + if (wrapper.LocalActionGroups.Count == 0) + wrapper.LocalActionGroups.Add (new ActionGroup ("Default")); + wrapper.LocalActionGroups[0].Actions.Add (ac); + } + } + + void OnEditingDone (object ob, EventArgs args) + { + Widget wrapper = Stetic.Wrapper.Widget.Lookup (this); + if (wrapper == null) + return; + + IDesignArea area = wrapper.GetDesignArea (); + if (area == null) // The toolbar may be disposed before ending editing + return; + + ActionToolItem item = (ActionToolItem) ob; + item.EditingDone -= OnEditingDone; + + if (item.Node.Action.GtkAction.Label.Length == 0 && item.Node.Action.GtkAction.StockId == null) { + area.ResetSelection (item); + using (wrapper.UndoManager.AtomicChange) { + actionTree.Children.Remove (item.Node); + wrapper.LocalActionGroups [0].Actions.Remove (item.Node.Action); + } + } + } + + public void Select (ActionTreeNode node) + { + ActionToolItem item = FindMenuItem (node); + if (item != null) + item.Select (); + } + + protected override bool OnDragMotion (Gdk.DragContext context, int x, int y, uint time) + { + ActionPaletteItem dragItem = DND.DragWidget as ActionPaletteItem; + if (dragItem == null) + return false; + + x += Allocation.X; + y += Allocation.Y; + + if (actionTree.Children.Count > 0) { + ActionToolItem item = LocateWidget (x, y); + if (item != null) { + // Look for the index where to insert the new item + dropIndex = actionTree.Children.IndexOf (item.Node); + int spos = (Orientation == Gtk.Orientation.Horizontal) ? x : y; + int mpos = GetButtonPos (item) + GetButtonSize (item) / 2; + if (spos > mpos) + dropIndex++; + + // Calculate the drop position, used to show the drop bar + if (dropIndex == 0) + dropPosition = GetButtonPos (item); + else if (dropIndex == toolItems.Count) + dropPosition = GetButtonEndPos (item); + else { + item = (ActionToolItem) toolItems [dropIndex]; + ActionToolItem prevItem = (ActionToolItem) toolItems [dropIndex - 1]; + dropPosition = GetButtonEndPos (prevItem) + (GetButtonPos (item) - GetButtonEndPos (prevItem))/2; + } + } + } else + dropIndex = 0; + + QueueDraw (); + return base.OnDragMotion (context, x, y, time); + } + + int GetButtonPos (Gtk.Widget w) + { + return (Orientation == Gtk.Orientation.Horizontal) ? w.Allocation.X : w.Allocation.Y; + } + + int GetButtonEndPos (Gtk.Widget w) + { + return (Orientation == Gtk.Orientation.Horizontal) ? w.Allocation.Right : w.Allocation.Bottom; + } + + int GetButtonSize (Gtk.Widget w) + { + return (Orientation == Gtk.Orientation.Horizontal) ? w.Allocation.Width : w.Allocation.Height; + } + + protected override void OnDragLeave (Gdk.DragContext context, uint time) + { + dropPosition = -1; + QueueDraw (); + base.OnDragLeave (context, time); + } + + protected override bool OnDragDrop (Gdk.DragContext context, int x, int y, uint time) + { + ActionPaletteItem dropped = DND.Drop (context, null, time) as ActionPaletteItem; + if (dropped == null) + return false; + + if (dropped.Node.Type != Gtk.UIManagerItemType.Menuitem && + dropped.Node.Type != Gtk.UIManagerItemType.Toolitem && + dropped.Node.Type != Gtk.UIManagerItemType.Separator) + return false; + + ActionTreeNode newNode = dropped.Node; + if (dropped.Node.Type == Gtk.UIManagerItemType.Menuitem) { + newNode = newNode.Clone (); + newNode.Type = Gtk.UIManagerItemType.Toolitem; + } + + Widget wrapper = Stetic.Wrapper.Widget.Lookup (this); + using (wrapper.UndoManager.AtomicChange) { + if (dropIndex < actionTree.Children.Count) { + // Do nothing if trying to drop the node over the same node + ActionTreeNode dropNode = actionTree.Children [dropIndex]; + if (dropNode == newNode) + return false; + + if (newNode.ParentNode != null) + newNode.ParentNode.Children.Remove (newNode); + + // The drop position may have changed after removing the dropped node, + // so get it again. + dropIndex = actionTree.Children.IndexOf (dropNode); + actionTree.Children.Insert (dropIndex, newNode); + } else { + if (newNode.ParentNode != null) + newNode.ParentNode.Children.Remove (newNode); + actionTree.Children.Add (newNode); + dropIndex = actionTree.Children.Count - 1; + } + } + // Select the dropped node + ActionToolItem mi = (ActionToolItem) toolItems [dropIndex]; + mi.Select (); + + return base.OnDragDrop (context, x, y, time); + } + protected override bool OnExposeEvent (Gdk.EventExpose ev) + { + bool r = base.OnExposeEvent (ev); + if (dropPosition != -1) { + if (this.Orientation == Gtk.Orientation.Horizontal) + GdkWindow.DrawRectangle (this.Style.BlackGC, true, dropPosition, Allocation.Y, 3, Allocation.Height); + else + GdkWindow.DrawRectangle (this.Style.BlackGC, true, Allocation.X, dropPosition, Allocation.Width, 3); + } + return r; + } + + void OnItemKeyPress (object s, Gtk.KeyPressEventArgs args) + { + int pos = toolItems.IndexOf (s); + args.RetVal = false; + + switch (args.Event.Key) { + case Gdk.Key.Left: + args.RetVal = true; + if (pos > 0) + ((ActionToolItem)toolItems[pos - 1]).Select (); + break; + case Gdk.Key.Right: + args.RetVal = true; + if (pos < toolItems.Count - 1) + ((ActionToolItem)toolItems[pos + 1]).Select (); + else if (pos == toolItems.Count - 1) + InsertAction (toolItems.Count); + break; + } + } + + void InsertActionAt (ActionToolItem item, bool after, bool separator) + { + int pos = toolItems.IndexOf (item); + if (pos == -1) + return; + + if (after) + pos++; + + if (separator) { + ActionTreeNode newNode = new ActionTreeNode (Gtk.UIManagerItemType.Separator, null, null); + actionTree.Children.Insert (pos, newNode); + } else + InsertAction (pos); + } + + void Paste (ActionToolItem item) + { + } + + public void ShowContextMenu (ActionItem aitem) + { + ActionToolItem menuItem = aitem as ActionToolItem; + + Gtk.Menu m = new Gtk.Menu (); + Gtk.MenuItem item = new Gtk.MenuItem (Catalog.GetString ("Insert Before")); + m.Add (item); + item.Activated += delegate (object s, EventArgs a) { + InsertActionAt (menuItem, false, false); + }; + item = new Gtk.MenuItem (Catalog.GetString ("Insert After")); + m.Add (item); + item.Activated += delegate (object s, EventArgs a) { + InsertActionAt (menuItem, true, false); + }; + item = new Gtk.MenuItem (Catalog.GetString ("Insert Separator Before")); + m.Add (item); + item.Activated += delegate (object s, EventArgs a) { + InsertActionAt (menuItem, false, true); + }; + item = new Gtk.MenuItem (Catalog.GetString ("Insert Separator After")); + m.Add (item); + item.Activated += delegate (object s, EventArgs a) { + InsertActionAt (menuItem, true, true); + }; + + m.Add (new Gtk.SeparatorMenuItem ()); + + item = new Gtk.ImageMenuItem (Gtk.Stock.Cut, null); + m.Add (item); + item.Activated += delegate (object s, EventArgs a) { + menuItem.Cut (); + }; + item = new Gtk.ImageMenuItem (Gtk.Stock.Copy, null); + m.Add (item); + item.Activated += delegate (object s, EventArgs a) { + menuItem.Copy (); + }; + item = new Gtk.ImageMenuItem (Gtk.Stock.Paste, null); + m.Add (item); + item.Activated += delegate (object s, EventArgs a) { + Paste (menuItem); + }; + item = new Gtk.ImageMenuItem (Gtk.Stock.Delete, null); + m.Add (item); + item.Activated += delegate (object s, EventArgs a) { + menuItem.Delete (); + }; + m.ShowAll (); + m.Popup (); + } + + public object SaveStatus () + { + for (int n=0; n<toolItems.Count; n++) + if (((ActionToolItem)toolItems[n]).IsSelected) + return n; + return null; + } + + public void RestoreStatus (object stat) + { + if (stat == null) + return; + int n = (int) stat; + if (n < toolItems.Count) + ((ActionToolItem)toolItems[n]).Select (); + } + + ActionToolItem LocateWidget (int x, int y) + { + foreach (ActionToolItem mi in toolItems) { + if (mi.Allocation.Contains (x, y)) + return mi; + } + return null; + } + + ActionToolItem FindMenuItem (ActionTreeNode node) + { + foreach (ActionToolItem mi in toolItems) { + if (mi.Node == node) + return mi; + } + return null; + } + } + + class CustomToolbarItem: Gtk.ToolItem + { + public override void Dispose () + { + ActionToolItem.Destroy (); + base.Dispose (); + } + + public ActionToolItem ActionToolItem; + } +} diff --git a/main/src/addins/MonoDevelop.GtkCore2/libstetic/editor/Boolean.cs b/main/src/addins/MonoDevelop.GtkCore2/libstetic/editor/Boolean.cs new file mode 100644 index 0000000000..26d4a12c55 --- /dev/null +++ b/main/src/addins/MonoDevelop.GtkCore2/libstetic/editor/Boolean.cs @@ -0,0 +1,67 @@ +using System; + +namespace Stetic.Editor { + + public class Boolean : PropertyEditorCell + { + static int indicatorSize; + static int indicatorSpacing; + + static Boolean () + { + Gtk.CheckButton cb = new Gtk.CheckButton (); + indicatorSize = (int) cb.StyleGetProperty ("indicator-size"); + indicatorSpacing = (int) cb.StyleGetProperty ("indicator-spacing"); + } + + public override void GetSize (int availableWidth, out int width, out int height) + { + width = 20; + height = 20; + } + + public override void Render (Gdk.Drawable window, Gdk.Rectangle bounds, Gtk.StateType state) + { + Gtk.ShadowType sh = (bool) Value ? Gtk.ShadowType.In : Gtk.ShadowType.Out; + int s = indicatorSize - 1; + if (s > bounds.Height) + s = bounds.Height; + if (s > bounds.Width) + s = bounds.Width; + Gtk.Style.PaintCheck (Container.Style, window, state, sh, bounds, Container, "checkbutton", bounds.X + indicatorSpacing - 1, bounds.Y + (bounds.Height - s)/2, s, s); + } + + protected override IPropertyEditor CreateEditor (Gdk.Rectangle cell_area, Gtk.StateType state) + { + return new BooleanEditor (); + } + } + + [PropertyEditor ("Active", "Toggled")] + public class BooleanEditor : Gtk.CheckButton, IPropertyEditor + { + public void Initialize (PropertyDescriptor descriptor) + { + if (descriptor.PropertyType != typeof(bool)) + throw new ApplicationException ("Boolean editor does not support editing values of type " + descriptor.PropertyType); + } + + public void AttachObject (object obj) + { + } + + public object Value { + get { return Active; } + set { Active = (bool) value; } + } + + protected override void OnToggled () + { + base.OnToggled (); + if (ValueChanged != null) + ValueChanged (this, EventArgs.Empty); + } + + public event EventHandler ValueChanged; + } +} diff --git a/main/src/addins/MonoDevelop.GtkCore2/libstetic/editor/CellRendererComboBox.cs b/main/src/addins/MonoDevelop.GtkCore2/libstetic/editor/CellRendererComboBox.cs new file mode 100644 index 0000000000..186f446729 --- /dev/null +++ b/main/src/addins/MonoDevelop.GtkCore2/libstetic/editor/CellRendererComboBox.cs @@ -0,0 +1,111 @@ +// +// CellRendererComboBox.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.Editor +{ + public class CellRendererComboBox: CellRendererText + { + string[] values; + string path; + int rowHeight; + + public CellRendererComboBox () + { + Mode |= Gtk.CellRendererMode.Editable; + Entry dummyEntry = new Gtk.Entry (); + rowHeight = dummyEntry.SizeRequest ().Height; + } + + public string[] Values { + get { return values; } + set { values = value; } + } + + public override void GetSize (Widget widget, ref Rectangle cell_area, out int x_offset, out int y_offset, out int width, out int height) + { + base.GetSize (widget, ref cell_area, out x_offset, out y_offset, out width, out height); + if (height < rowHeight) + height = rowHeight; + } + + public override CellEditable StartEditing (Gdk.Event ev, Widget widget, string path, Gdk.Rectangle background_area, Gdk.Rectangle cell_area, CellRendererState flags) + { + this.path = path; + + Gtk.ComboBox combo = Gtk.ComboBox.NewText (); + foreach (string s in values) + combo.AppendText (s); + + combo.Active = Array.IndexOf (values, Text); + combo.Changed += new EventHandler (SelectionChanged); + return new TreeViewCellContainer (combo); + } + + void SelectionChanged (object s, EventArgs a) + { + Gtk.ComboBox combo = (Gtk.ComboBox) s; + if (Changed != null) + Changed (this, new ComboSelectionChangedArgs (path, combo.Active, (combo.Active != -1 ? values [combo.Active] : null))); + } + + // Fired when the selection changes + public event ComboSelectionChangedHandler Changed; + } + + public delegate void ComboSelectionChangedHandler (object sender, ComboSelectionChangedArgs args); + + public class ComboSelectionChangedArgs: EventArgs + { + string path; + int active; + string activeText; + + internal ComboSelectionChangedArgs (string path, int active, string activeText) + { + this.path = path; + this.active = active; + this.activeText = activeText; + } + + public string Path { + get { return path; } + } + + public int Active { + get { return active; } + } + + public string ActiveText { + get { return activeText; } + } + } +} diff --git a/main/src/addins/MonoDevelop.GtkCore2/libstetic/editor/ChangeLog b/main/src/addins/MonoDevelop.GtkCore2/libstetic/editor/ChangeLog new file mode 100644 index 0000000000..35c0dbd643 --- /dev/null +++ b/main/src/addins/MonoDevelop.GtkCore2/libstetic/editor/ChangeLog @@ -0,0 +1,16 @@ +2010-08-07 Krzysztof Marecki <marecki.krzysztof@gmail.com> + + * SelectIconDialog.cs: Remove setting Project.Modified property + * EditIconFactoryDialog.cs: Remove setting Project.Modified property + +2010-08-03 Krzysztof Marecki <marecki.krzysztof@gmail.com> + + * ActionMenu.cs: Pass root wrapper as an argument for ObjectWrapper.Create + * ActionToolbar.cs: + * ActionMenuBar.cs: + * ActionGroupEditor.cs: + +2010-06-07 Krzysztof Marecki <marecki.krzysztof@gmail.com> + + * SelectImageDialog.cs: + diff --git a/main/src/addins/MonoDevelop.GtkCore2/libstetic/editor/Char.cs b/main/src/addins/MonoDevelop.GtkCore2/libstetic/editor/Char.cs new file mode 100644 index 0000000000..e27b1b7662 --- /dev/null +++ b/main/src/addins/MonoDevelop.GtkCore2/libstetic/editor/Char.cs @@ -0,0 +1,45 @@ +using System; + +namespace Stetic.Editor { + + public class Char : Gtk.Entry, IPropertyEditor { + + public Char () + { + MaxLength = 1; + } + + public void Initialize (PropertyDescriptor descriptor) + { + if (descriptor.PropertyType != typeof(char)) + throw new ApplicationException ("Char editor does not support editing values of type " + descriptor.PropertyType); + } + + public void AttachObject (object obj) + { + } + + char last; + + public object Value { + get { + if (Text.Length == 0) + return last; + else + return Text[0]; + } + set { + Text = value.ToString (); + last = (char) value; + } + } + + protected override void OnChanged () + { + if (ValueChanged != null) + ValueChanged (this, EventArgs.Empty); + } + + public event EventHandler ValueChanged; + } +} diff --git a/main/src/addins/MonoDevelop.GtkCore2/libstetic/editor/Color.cs b/main/src/addins/MonoDevelop.GtkCore2/libstetic/editor/Color.cs new file mode 100644 index 0000000000..b771521aad --- /dev/null +++ b/main/src/addins/MonoDevelop.GtkCore2/libstetic/editor/Color.cs @@ -0,0 +1,54 @@ +using System; + +namespace Stetic.Editor { + + public class Color: PropertyEditorCell + { + public override void GetSize (int availableWidth, out int width, out int height) + { + width = 16; + height = 16; + } + + public override void Render (Gdk.Drawable window, Gdk.Rectangle bounds, Gtk.StateType state) + { + Gdk.GC gc = new Gdk.GC (window); + gc.RgbFgColor = (Gdk.Color) Value; + window.DrawRectangle (gc, true, bounds.X, bounds.Y, bounds.Width - 1, bounds.Height - 1); + window.DrawRectangle (Container.Style.BlackGC, false, bounds.X, bounds.Y, bounds.Width - 1, bounds.Height - 1); + } + + protected override IPropertyEditor CreateEditor (Gdk.Rectangle cell_area, Gtk.StateType state) + { + return new ColorEditor (); + } + } + + [PropertyEditor ("Color", "ColorSet")] + public class ColorEditor : Gtk.ColorButton, IPropertyEditor + { + public void Initialize (PropertyDescriptor descriptor) + { + if (descriptor.PropertyType != typeof(Gdk.Color)) + throw new ApplicationException ("Color editor does not support editing values of type " + descriptor.PropertyType); + } + + public void AttachObject (object obj) + { + } + + public object Value { + get { return Color; } + set { Color = (Gdk.Color) value; } + } + + protected override void OnColorSet () + { + base.OnColorSet (); + if (ValueChanged != null) + ValueChanged (this, EventArgs.Empty); + } + + public event EventHandler ValueChanged; + } +} diff --git a/main/src/addins/MonoDevelop.GtkCore2/libstetic/editor/DateTimeEditor.cs b/main/src/addins/MonoDevelop.GtkCore2/libstetic/editor/DateTimeEditor.cs new file mode 100644 index 0000000000..f338b8c54e --- /dev/null +++ b/main/src/addins/MonoDevelop.GtkCore2/libstetic/editor/DateTimeEditor.cs @@ -0,0 +1,72 @@ + +using System; +using Gtk; +using Gdk; +using System.Text; + +namespace Stetic.Editor +{ + public class DateTimeEditorCell: PropertyEditorCell + { + protected override string GetValueText () + { + return ((DateTime)Value).ToLongDateString (); + } + + protected override IPropertyEditor CreateEditor (Gdk.Rectangle cell_area, Gtk.StateType state) + { + return new DateTimeEditor (); + } + } + + public class DateTimeEditor: Gtk.HBox, IPropertyEditor + { + Gtk.Entry entry; + DateTime time; + + public DateTimeEditor() + { + entry = new Gtk.Entry (); + entry.Changed += OnChanged; + PackStart (entry, true, true, 0); + ShowAll (); + } + + public void Initialize (PropertyDescriptor descriptor) + { + } + + public void AttachObject (object ob) + { + } + + public object Value { + get { return time; } + set { + time = (DateTime) value; + entry.Changed -= OnChanged; + entry.Text = time.ToString ("G"); + entry.Changed += OnChanged; + } + } + + void OnChanged (object o, EventArgs a) + { + string s = entry.Text; + + foreach (string form in formats) { + try { + time = DateTime.ParseExact (s, form, null); + if (ValueChanged != null) + ValueChanged (this, a); + break; + } catch { + } + } + } + + public event EventHandler ValueChanged; + + static string[] formats = {"u", "G", "g", "d", "T", "t"}; + } +} diff --git a/main/src/addins/MonoDevelop.GtkCore2/libstetic/editor/EditIconDialog.cs b/main/src/addins/MonoDevelop.GtkCore2/libstetic/editor/EditIconDialog.cs new file mode 100644 index 0000000000..d5ea4d8678 --- /dev/null +++ b/main/src/addins/MonoDevelop.GtkCore2/libstetic/editor/EditIconDialog.cs @@ -0,0 +1,284 @@ + +using System; +using System.Collections; +using Mono.Unix; + +namespace Stetic.Editor +{ + public class EditIconDialog: IDisposable + { + [Glade.Widget] Gtk.Entry nameEntry; + [Glade.Widget] Gtk.TreeView sourceList; + [Glade.Widget] Gtk.RadioButton radioSingle; + [Glade.Widget] Gtk.RadioButton radioMultiple; + [Glade.Widget] Gtk.Label imageLabel; + [Glade.Widget] Gtk.Image imageImage; + [Glade.Widget] Gtk.Button okButton; + [Glade.Widget] Gtk.HBox hboxSingle; + [Glade.Widget] Gtk.HBox hboxMultiple; + [Glade.Widget ("EditIconDialog")] Gtk.Dialog dialog; + + Gtk.ListStore sourceListStore; + + ProjectIconSet iconSet; + IProject project; + + ImageInfo singleIcon; + + string[] sizes = { Catalog.GetString ("All Sizes"), "Menu", "SmallToolbar", "LargeToolbar", "Button", "Dnd", "Dialog" }; + string[] states = { Catalog.GetString ("All States"), "Normal", "Active", "Prelight", "Selected", "Insensitive" }; + string[] directions = { Catalog.GetString ("All Directions"), "Ltr", "Rtl" }; + + public EditIconDialog (IProject project, ProjectIconSet iconSet) + { + Glade.XML xml = new Glade.XML (null, "stetic.glade", "EditIconDialog", null); + xml.Autoconnect (this); + dialog.Response += OnResponse; + + this.project = project; + this.iconSet = iconSet; + + nameEntry.Text = iconSet.Name; + + if (iconSet.Sources.Count == 0) { + radioSingle.Active = true; + imageLabel.Text = ""; + } + else if (iconSet.Sources.Count == 1 && iconSet.Sources[0].AllWildcarded) { + radioSingle.Active = true; + singleIcon = iconSet.Sources[0].Image; + if (singleIcon != null) { + imageLabel.Text = singleIcon.Label; + imageImage.Pixbuf = singleIcon.GetThumbnail (project, 16); + } else + imageLabel.Text = ""; + } else { + radioMultiple.Active = true; + } + + hboxSingle.Sensitive = radioSingle.Active; + hboxMultiple.Sensitive = !radioSingle.Active; + + // Build the tree + + sourceListStore = new Gtk.ListStore (typeof(Gdk.Pixbuf), typeof(string), typeof(string), typeof(string), typeof(string), typeof(object)); + sourceList.Model = sourceListStore; + + Gtk.TreeViewColumn col = new Gtk.TreeViewColumn (); + + Gtk.CellRendererPixbuf pr = new Gtk.CellRendererPixbuf (); + col.Title = Catalog.GetString ("Image"); + col.PackStart (pr, false); + col.AddAttribute (pr, "pixbuf", 0); + + Gtk.CellRendererText crt = new Gtk.CellRendererText (); + col.PackStart (crt, true); + col.AddAttribute (crt, "text", 1); + sourceList.AppendColumn (col); + + col = new Gtk.TreeViewColumn (); + col.Expand = true; + col.Title = Catalog.GetString ("Size"); + CellRendererComboBox crtb = new CellRendererComboBox (); + crtb.Changed += new ComboSelectionChangedHandler (OnSizeComboChanged); + crtb.Values = sizes; + col.PackStart (crtb, true); + col.AddAttribute (crtb, "text", 2); + sourceList.AppendColumn (col); + + col = new Gtk.TreeViewColumn (); + col.Expand = true; + col.Title = Catalog.GetString ("State"); + crtb = new CellRendererComboBox (); + crtb.Changed += new ComboSelectionChangedHandler (OnStateComboChanged); + crtb.Values = states; + col.PackStart (crtb, true); + col.AddAttribute (crtb, "text", 3); + sourceList.AppendColumn (col); + + col = new Gtk.TreeViewColumn (); + col.Expand = true; + col.Title = Catalog.GetString ("Direction"); + crtb = new CellRendererComboBox (); + crtb.Changed += new ComboSelectionChangedHandler (OnDirComboChanged); + crtb.Values = directions; + col.PackStart (crtb, true); + col.AddAttribute (crtb, "text", 4); + sourceList.AppendColumn (col); + + foreach (ProjectIconSource source in iconSet.Sources) + AddSource (source); + + UpdateButtons (); + } + + public Gtk.Window TransientFor { + set { dialog.TransientFor = value; } + } + + public int Run () + { + return dialog.Run (); + } + + public void Dispose () + { + dialog.Destroy (); + } + + void AddSource (ProjectIconSource source) + { + string size = source.SizeWildcarded ? sizes[0] : source.Size.ToString (); + string state = source.StateWildcarded ? states[0] : source.State.ToString (); + string dir = source.DirectionWildcarded ? directions[0] : source.Direction.ToString (); + sourceListStore.AppendValues (source.Image.GetThumbnail (project, 16), source.Image.Label, size, state, dir, source.Image); + } + + ProjectIconSource GetSource (Gtk.TreeIter iter) + { + ProjectIconSource src = new ProjectIconSource (); + src.Image = (ImageInfo) sourceListStore.GetValue (iter, 5); + string s = (string) sourceListStore.GetValue (iter, 2); + if (s == sizes[0]) + src.SizeWildcarded = true; + else { + src.SizeWildcarded = false; + src.Size = (Gtk.IconSize) Enum.Parse (typeof(Gtk.IconSize), s); + } + + s = (string) sourceListStore.GetValue (iter, 3); + if (s == states[0]) + src.StateWildcarded = true; + else { + src.StateWildcarded = false; + src.State = (Gtk.StateType) Enum.Parse (typeof(Gtk.StateType), s); + } + + s = (string) sourceListStore.GetValue (iter, 4); + if (s == directions[0]) + src.DirectionWildcarded = true; + else { + src.DirectionWildcarded = false; + src.Direction = (Gtk.TextDirection) Enum.Parse (typeof(Gtk.TextDirection), s); + } + + return src; + } + + void Save () + { + iconSet.Name = nameEntry.Text; + iconSet.Sources.Clear (); + + if (radioSingle.Active) { + ProjectIconSource src = new ProjectIconSource (); + src.AllWildcarded = true; + src.Image = singleIcon; + iconSet.Sources.Add (src); + } else { + Gtk.TreeIter iter; + if (sourceListStore.GetIterFirst (out iter)) { + do { + iconSet.Sources.Add (GetSource (iter)); + } + while (sourceListStore.IterNext (ref iter)); + } + } + } + + void OnResponse (object o, Gtk.ResponseArgs args) + { + if (args.ResponseId == Gtk.ResponseType.Ok) + Save (); + } + + protected void OnSelectImage (object s, EventArgs args) + { + using (SelectImageDialog dlg = new SelectImageDialog (dialog, project)) { + if (dlg.Run () == (int) Gtk.ResponseType.Ok) { + singleIcon = dlg.Icon; + imageLabel.Text = singleIcon.Label; + imageImage.Pixbuf = singleIcon.GetThumbnail (project, 16); + UpdateButtons (); + } + } + } + + protected void OnAddSource (object s, EventArgs args) + { + using (SelectImageDialog dlg = new SelectImageDialog (dialog, project)) { + if (dlg.Run () == (int) Gtk.ResponseType.Ok) { + ProjectIconSource src = new ProjectIconSource (); + src.Image = dlg.Icon; + src.AllWildcarded = true; + AddSource (src); + UpdateButtons (); + } + } + } + + protected void OnRemoveSource (object s, EventArgs args) + { + Gtk.TreeIter iter; + Gtk.TreeModel model; + if (sourceList.Selection.GetSelected (out model, out iter)) { + sourceListStore.Remove (ref iter); + UpdateButtons (); + } + } + + protected void OnSingleClicked (object s, EventArgs args) + { + hboxSingle.Sensitive = true; + hboxMultiple.Sensitive = false; + UpdateButtons (); + } + + protected void OnMultipleClicked (object s, EventArgs args) + { + hboxSingle.Sensitive = false; + hboxMultiple.Sensitive = true; + UpdateButtons (); + } + + protected void OnNameChanged (object s, EventArgs args) + { + UpdateButtons (); + } + + void OnSizeComboChanged (object s, ComboSelectionChangedArgs args) + { + UpdateComboValue (args.Path, 2, args.ActiveText); + } + + void OnStateComboChanged (object s, ComboSelectionChangedArgs args) + { + UpdateComboValue (args.Path, 3, args.ActiveText); + } + + void OnDirComboChanged (object s, ComboSelectionChangedArgs args) + { + UpdateComboValue (args.Path, 4, args.ActiveText); + } + + void UpdateComboValue (string path, int col, string activeText) + { + Gtk.TreeIter iter; + if (sourceListStore.GetIter (out iter, new Gtk.TreePath (path))) { + sourceListStore.SetValue (iter, col, activeText); + } + } + + void UpdateButtons () + { + if (nameEntry.Text.Length == 0) { + okButton.Sensitive = false; + } else if (radioSingle.Active) { + okButton.Sensitive = singleIcon != null; + } else { + Gtk.TreeIter iter; + okButton.Sensitive = sourceListStore != null && sourceListStore.GetIterFirst (out iter); + } + } + } +} diff --git a/main/src/addins/MonoDevelop.GtkCore2/libstetic/editor/EditIconFactoryDialog.cs b/main/src/addins/MonoDevelop.GtkCore2/libstetic/editor/EditIconFactoryDialog.cs new file mode 100644 index 0000000000..ee4f5c29ec --- /dev/null +++ b/main/src/addins/MonoDevelop.GtkCore2/libstetic/editor/EditIconFactoryDialog.cs @@ -0,0 +1,95 @@ + +using System; +using System.Collections; +using System.IO; +using Gtk; +using Mono.Unix; + +namespace Stetic.Editor +{ + public class EditIconFactoryDialog: IDisposable + { + [Glade.Widget] Gtk.ScrolledWindow iconListScrolledwindow; + [Glade.Widget ("EditIconFactoryDialog")] Gtk.Dialog dialog; + + ProjectIconList customIconList; + + Gtk.Window parent; + Stetic.IProject project; + ProjectIconFactory iconFactory; + + public EditIconFactoryDialog (Gtk.Window parent, Stetic.IProject project, ProjectIconFactory iconFactory) + { + this.iconFactory = iconFactory; + this.parent = parent; + this.project = project; + + Glade.XML xml = new Glade.XML (null, "stetic.glade", "EditIconFactoryDialog", null); + xml.Autoconnect (this); + + customIconList = new ProjectIconList (project, iconFactory); + iconListScrolledwindow.AddWithViewport (customIconList); + } + + public int Run () + { + dialog.ShowAll (); + dialog.TransientFor = parent; + return dialog.Run (); + } + + public void Dispose () + { + dialog.Destroy (); + } + + protected void OnAddIcon (object ob, EventArgs args) + { + ProjectIconSet icon = new ProjectIconSet (); + using (EditIconDialog dlg = new EditIconDialog (project, icon)) { + if (parent != null) + dlg.TransientFor = parent.Toplevel as Gtk.Window; + if (dlg.Run () == (int) Gtk.ResponseType.Ok) { + iconFactory.Icons.Add (icon); + customIconList.Refresh (); + customIconList.Selection = icon.Name; +// project.Modified = true; + } + } + } + + protected void OnRemoveIcon (object ob, EventArgs args) + { + string name = customIconList.Selection; + ProjectIconSet icon = iconFactory.GetIcon (name); + if (icon != null) { + Gtk.MessageDialog md = new Gtk.MessageDialog (dialog, Gtk.DialogFlags.Modal, Gtk.MessageType.Question, Gtk.ButtonsType.YesNo, string.Format (Catalog.GetString ("Are you sure you want to delete the icon '{0}'"), icon.Name)); + if (parent != null) + md.TransientFor = parent.Toplevel as Gtk.Window; + if (md.Run () == (int) Gtk.ResponseType.Yes) { + iconFactory.Icons.Remove (icon); + customIconList.Refresh (); +// project.Modified = true; + } + md.Destroy (); + } + } + + protected void OnEditIcon (object ob, EventArgs args) + { + string name = customIconList.Selection; + ProjectIconSet icon = iconFactory.GetIcon (name); + if (icon != null) { + using (EditIconDialog dlg = new EditIconDialog (project, icon)) { + if (parent != null) + dlg.TransientFor = parent.Toplevel as Gtk.Window; + if (dlg.Run () == (int) Gtk.ResponseType.Ok) { + customIconList.Refresh (); + customIconList.Selection = icon.Name; +// project.Modified = true; + } + } + } + } + } +} diff --git a/main/src/addins/MonoDevelop.GtkCore2/libstetic/editor/Enumeration.cs b/main/src/addins/MonoDevelop.GtkCore2/libstetic/editor/Enumeration.cs new file mode 100644 index 0000000000..fd2237d02a --- /dev/null +++ b/main/src/addins/MonoDevelop.GtkCore2/libstetic/editor/Enumeration.cs @@ -0,0 +1,87 @@ +using System; +using System.Collections; + +namespace Stetic.Editor { + + public class Enumeration: PropertyEditorCell + { + protected override string GetValueText () + { + if (Value == null) + return ""; + + EnumDescriptor enm = Registry.LookupEnum (Property.PropertyType.FullName); + EnumValue ev = enm [(Enum)Value]; + if (ev != null) + return ev.Label; + else + return ""; + } + + protected override IPropertyEditor CreateEditor (Gdk.Rectangle cell_area, Gtk.StateType state) + { + return new EnumerationEditor (); + } + } + + public class EnumerationEditor : Gtk.HBox, IPropertyEditor { + + Gtk.EventBox ebox; + Gtk.ComboBoxEntry combo; + EnumDescriptor enm; + + public EnumerationEditor () : base (false, 0) + { + } + + public void Initialize (PropertyDescriptor prop) + { + if (!prop.PropertyType.IsEnum) + throw new ApplicationException ("Enumeration editor does not support editing values of type " + prop.PropertyType); + + ebox = new Gtk.EventBox (); + ebox.Show (); + PackStart (ebox, true, true, 0); + + combo = Gtk.ComboBoxEntry.NewText (); + combo.Changed += combo_Changed; + combo.Entry.IsEditable = false; + combo.Entry.HasFrame = false; + combo.Entry.HeightRequest = combo.SizeRequest ().Height; // The combo does not set the entry to the correct size when it does not have a frame + combo.Show (); + ebox.Add (combo); + + enm = Registry.LookupEnum (prop.PropertyType.FullName); + foreach (Enum value in enm.Values) + combo.AppendText (enm[value].Label); + } + + public void AttachObject (object obj) + { + } + + public object Value { + get { + return enm.Values[combo.Active]; + } + set { + int i = Array.IndexOf (enm.Values, (Enum)value); + if (i != -1) + combo.Active = i; + } + } + + public event EventHandler ValueChanged; + + void combo_Changed (object o, EventArgs args) + { + if (ValueChanged != null) + ValueChanged (this, EventArgs.Empty); + EnumValue value = enm[(Enum)Value]; + if (value != null) + ebox.TooltipText = value.Description; + else + ebox.TooltipText = string.Empty; + } + } +} diff --git a/main/src/addins/MonoDevelop.GtkCore2/libstetic/editor/Flags.cs b/main/src/addins/MonoDevelop.GtkCore2/libstetic/editor/Flags.cs new file mode 100644 index 0000000000..031d7a1319 --- /dev/null +++ b/main/src/addins/MonoDevelop.GtkCore2/libstetic/editor/Flags.cs @@ -0,0 +1,174 @@ +using Gtk; +using System; +using System.Collections; + +namespace Stetic.Editor { + + public class Flags: PropertyEditorCell + { + protected override string GetValueText () + { + if (Value == null) + return ""; + + uint value = (uint)(int)Value; + EnumDescriptor enm = Registry.LookupEnum (Property.PropertyType.FullName); + string txt = ""; + foreach (Enum val in enm.Values) { + EnumValue eval = enm[val]; + if (eval.Label == "") + continue; + + if ((value & (uint) Convert.ToInt32 (eval.Value)) != 0) { + if (txt.Length > 0) txt += ", "; + txt += eval.Label; + } + } + return txt; + } + + protected override IPropertyEditor CreateEditor (Gdk.Rectangle cell_area, Gtk.StateType state) + { + return new FlagsEditor (); + } + } + + public class FlagsEditor : Gtk.HBox, IPropertyEditor { + + EnumDescriptor enm; + Hashtable flags; + Gtk.Entry flagsLabel; + string property; + + public FlagsEditor () + { + } + + public void Initialize (PropertyDescriptor prop) + { + if (!prop.PropertyType.IsEnum) + throw new ApplicationException ("Flags editor does not support editing values of type " + prop.PropertyType); + + property = prop.Label; + Spacing = 3; + + // For small enums, the editor is a list of checkboxes inside a frame + // For large enums (>5), use a selector dialog. + + enm = Registry.LookupEnum (prop.PropertyType.FullName); + + if (enm.Values.Length < 6) + { + Gtk.VBox vbox = new Gtk.VBox (true, 3); + + flags = new Hashtable (); + + foreach (Enum value in enm.Values) { + EnumValue eval = enm[value]; + if (eval.Label == "") + continue; + + Gtk.CheckButton check = new Gtk.CheckButton (eval.Label); + check.TooltipText = eval.Description; + uint uintVal = (uint) Convert.ToInt32 (eval.Value); + flags[check] = uintVal; + flags[uintVal] = check; + + check.Toggled += FlagToggled; + vbox.PackStart (check, false, false, 0); + } + + Gtk.Frame frame = new Gtk.Frame (); + frame.Add (vbox); + frame.ShowAll (); + PackStart (frame, true, true, 0); + } + else + { + flagsLabel = new Gtk.Entry (); + flagsLabel.IsEditable = false; + flagsLabel.HasFrame = false; + flagsLabel.ShowAll (); + PackStart (flagsLabel, true, true, 0); + + Gtk.Button but = new Gtk.Button ("..."); + but.Clicked += OnSelectFlags; + but.ShowAll (); + PackStart (but, false, false, 0); + } + } + + public void AttachObject (object ob) + { + } + + public object Value { + get { + return Enum.ToObject (enm.EnumType, UIntValue); + } + set { + uint newVal = (uint)(int)value; + if (flagsLabel != null) { + string txt = ""; + foreach (Enum val in enm.Values) { + EnumValue eval = enm[val]; + if (eval.Label == "") + continue; + + if ((newVal & (uint) Convert.ToInt32 (eval.Value)) != 0) { + if (txt.Length > 0) txt += ", "; + txt += eval.Label; + } + } + flagsLabel.Text = txt; + UIntValue = newVal; + } + else { + for (uint i = 1; i <= uintValue || i <= newVal; i = i << 1) { + if ((uintValue & i) != (newVal & i)) { + Gtk.CheckButton check = (Gtk.CheckButton)flags[i]; + if (check != null) + check.Active = !check.Active; + } + } + } + } + } + + public event EventHandler ValueChanged; + + uint uintValue; + uint UIntValue { + get { + return uintValue; + } + set { + if (uintValue != value) { + uintValue = value; + if (ValueChanged != null) + ValueChanged (this, EventArgs.Empty); + } + } + } + + void FlagToggled (object o, EventArgs args) + { + Gtk.CheckButton check = (Gtk.CheckButton)o; + uint val = (uint)flags[o]; + + if (check.Active) + UIntValue |= val; + else + UIntValue &= ~val; + } + + void OnSelectFlags (object o, EventArgs args) + { + using (FlagsSelectorDialog dialog = new FlagsSelectorDialog (null, enm, UIntValue, property)) { + if (dialog.Run () == (int) ResponseType.Ok) { + Value = Enum.ToObject (enm.EnumType, dialog.Value); + } + } + } + } +} diff --git a/main/src/addins/MonoDevelop.GtkCore2/libstetic/editor/FlagsSelectorDialog.cs b/main/src/addins/MonoDevelop.GtkCore2/libstetic/editor/FlagsSelectorDialog.cs new file mode 100644 index 0000000000..f2d8ca75e7 --- /dev/null +++ b/main/src/addins/MonoDevelop.GtkCore2/libstetic/editor/FlagsSelectorDialog.cs @@ -0,0 +1,79 @@ + +using System; + +namespace Stetic.Editor +{ + public class FlagsSelectorDialog: IDisposable + { + [Glade.Widget] Gtk.TreeView treeView; + [Glade.Widget ("FlagsSelectorDialog")] Gtk.Dialog dialog; + Gtk.ListStore store; + Gtk.Window parent; + uint flags; + + public FlagsSelectorDialog (Gtk.Window parent, EnumDescriptor enumDesc, uint flags, string title) + { + this.flags = flags; + this.parent = parent; + + Glade.XML xml = new Glade.XML (null, "stetic.glade", "FlagsSelectorDialog", null); + xml.Autoconnect (this); + + store = new Gtk.ListStore (typeof(bool), typeof(string), typeof(uint)); + treeView.Model = store; + + Gtk.TreeViewColumn col = new Gtk.TreeViewColumn (); + + Gtk.CellRendererToggle tog = new Gtk.CellRendererToggle (); + tog.Toggled += new Gtk.ToggledHandler (OnToggled); + col.PackStart (tog, false); + col.AddAttribute (tog, "active", 0); + + Gtk.CellRendererText crt = new Gtk.CellRendererText (); + col.PackStart (crt, true); + col.AddAttribute (crt, "text", 1); + + treeView.AppendColumn (col); + + foreach (Enum value in enumDesc.Values) { + EnumValue eval = enumDesc[value]; + if (eval.Label == "") + continue; + uint val = (uint) Convert.ToInt32 (eval.Value); + store.AppendValues (((flags & val) != 0), eval.Label, val); + } + } + + public int Run () + { + dialog.ShowAll (); + dialog.TransientFor = parent; + return dialog.Run (); + } + + public void Dispose () + { + dialog.Destroy (); + } + + void OnToggled (object s, Gtk.ToggledArgs args) + { + Gtk.TreeIter iter; + if (!store.GetIterFromString (out iter, args.Path)) + return; + + bool oldValue = (bool) store.GetValue (iter, 0); + uint flag = (uint) store.GetValue (iter, 2); + store.SetValue (iter, 0, !oldValue); + + if (oldValue) + flags &= ~flag; + else + flags |= flag; + } + + public uint Value { + get { return flags; } + } + } +} diff --git a/main/src/addins/MonoDevelop.GtkCore2/libstetic/editor/FloatRange.cs b/main/src/addins/MonoDevelop.GtkCore2/libstetic/editor/FloatRange.cs new file mode 100644 index 0000000000..2b8894dbf3 --- /dev/null +++ b/main/src/addins/MonoDevelop.GtkCore2/libstetic/editor/FloatRange.cs @@ -0,0 +1,47 @@ +using System; + +namespace Stetic.Editor { + + public class FloatRange : Gtk.SpinButton, IPropertyEditor + { + Type propType; + + public FloatRange (): base (0, 0, 0.01) + { + } + + public void Initialize (PropertyDescriptor prop) + { + propType = prop.PropertyType; + + double min, max; + + if (propType == typeof(double)) { + min = Double.MinValue; + max = Double.MaxValue; + } else if (propType == typeof(float)) { + min = float.MinValue; + max = float.MaxValue; + } else + throw new ApplicationException ("FloatRange editor does not support editing values of type " + propType); + + if (prop.Minimum != null) + min = (double) Convert.ChangeType (prop.Minimum, typeof(double)); + if (prop.Maximum != null) + max = (double) Convert.ChangeType (prop.Maximum, typeof(double)); + + SetRange (min, max); + + Digits = 2; + } + + public void AttachObject (object ob) + { + } + + object IPropertyEditor.Value { + get { return Convert.ChangeType (base.Value, propType); } + set { base.Value = (double) Convert.ChangeType (value, typeof(double)); } + } + } +} diff --git a/main/src/addins/MonoDevelop.GtkCore2/libstetic/editor/GroupPicker.cs b/main/src/addins/MonoDevelop.GtkCore2/libstetic/editor/GroupPicker.cs new file mode 100644 index 0000000000..fd9d4b24cc --- /dev/null +++ b/main/src/addins/MonoDevelop.GtkCore2/libstetic/editor/GroupPicker.cs @@ -0,0 +1,175 @@ +using Gtk; +using Gdk; +using GLib; +using System; +using System.Collections; +using System.Reflection; +using Mono.Unix; + +namespace Stetic.Editor { + + [PropertyEditor ("Group", "Changed")] + class GroupPicker : Gtk.HBox, IPropertyEditor { + + Gtk.ComboBox combo; + IRadioGroupManager manager; + ArrayList values; + string group; + + const BindingFlags flags = BindingFlags.Static | BindingFlags.Public | BindingFlags.NonPublic; + + public GroupPicker () : base (false, 0) + { + } + + public void Initialize (PropertyDescriptor prop) + { + } + + public void AttachObject (object ob) + { + ob = ObjectWrapper.Lookup (ob); + + IRadioGroupManagerProvider provider = ob as IRadioGroupManagerProvider; + + if (provider == null) + throw new ArgumentException ("The class " + ob.GetType() + " does not implement IRadioGroupManagerProvider"); + + manager = provider.GetGroupManager (); + manager.GroupsChanged += GroupsChanged; + GroupsChanged (); + } + + public override void Dispose () + { + manager.GroupsChanged -= GroupsChanged; + base.Dispose (); + } + + void GroupsChanged () + { + if (combo != null) { + combo.Changed -= combo_Changed; + Remove (combo); + } + + combo = Gtk.ComboBox.NewText (); + combo.Changed += combo_Changed; +#if GTK_SHARP_2_6 + combo.RowSeparatorFunc = RowSeparatorFunc; +#endif + combo.Show (); + PackStart (combo, true, true, 0); + + values = new ArrayList (); + int i = 0; + foreach (string name in manager.GroupNames) { + values.Add (name); + combo.AppendText (name); + if (name == group) + combo.Active = i; + i++; + } + +#if GTK_SHARP_2_6 + combo.AppendText (""); +#endif + + combo.AppendText (Catalog.GetString ("Rename Group...")); + combo.AppendText (Catalog.GetString ("New Group...")); + } + +#if GTK_SHARP_2_6 + bool RowSeparatorFunc (Gtk.TreeModel model, Gtk.TreeIter iter) + { + GLib.Value val = new GLib.Value (); + model.GetValue (iter, 0, ref val); + bool sep = ((string)val) == ""; + val.Dispose (); + return sep; + } +#endif + + public object Value { + get { + return group; + } + set { + int index = values.IndexOf ((string) value); + if (index != -1) { + combo.Active = index; + group = values[index] as string; + } + } + } + + public event EventHandler ValueChanged; + + void combo_Changed (object o, EventArgs args) + { + if (combo.Active >= values.Count) { + doDialog (); + return; + } + + group = values[combo.Active] as string; + if (ValueChanged != null) + ValueChanged (this, EventArgs.Empty); + } + + void doDialog () + { +#if GTK_SHARP_2_6 + bool rename = combo.Active == values.Count + 1; +#else + bool rename = combo.Active == values.Count; +#endif + Gtk.Dialog dialog = new Gtk.Dialog ( + rename ? Catalog.GetString ("Rename Group") : Catalog.GetString ("New Group"), + combo.Toplevel as Gtk.Window, + Gtk.DialogFlags.Modal | Gtk.DialogFlags.NoSeparator, + Gtk.Stock.Cancel, Gtk.ResponseType.Cancel, + Gtk.Stock.Ok, Gtk.ResponseType.Ok); + dialog.DefaultResponse = Gtk.ResponseType.Ok; + dialog.HasSeparator = false; + dialog.BorderWidth = 12; + dialog.VBox.Spacing = 18; + dialog.VBox.BorderWidth = 0; + + Gtk.HBox hbox = new Gtk.HBox (false, 12); + Gtk.Label label = new Gtk.Label (rename ? Catalog.GetString ("_New name:") : Catalog.GetString ("_Name:")); + Gtk.Entry entry = new Gtk.Entry (); + label.MnemonicWidget = entry; + hbox.PackStart (label, false, false, 0); + entry.ActivatesDefault = true; + if (rename) + entry.Text = group; + hbox.PackStart (entry, true, true, 0); + dialog.VBox.PackStart (hbox, false, false, 0); + + dialog.ShowAll (); + // Have to set this *after* ShowAll + dialog.ActionArea.BorderWidth = 0; + dialog.TransientFor = this.Toplevel as Gtk.Window; + Gtk.ResponseType response = (Gtk.ResponseType)dialog.Run (); + if (response == Gtk.ResponseType.Cancel || entry.Text.Length == 0) { + dialog.Destroy (); + Value = group; // reset combo.Active + return; + } + + string oldname = group; + group = entry.Text; + dialog.Destroy (); + + // FIXME: check that the new name doesn't already exist + + // This will trigger a GroupsChanged, which will eventually + // update combo.Active + if (rename) + manager.Rename (oldname, group); + else + manager.Add (group); + } + } +} diff --git a/main/src/addins/MonoDevelop.GtkCore2/libstetic/editor/IconList.cs b/main/src/addins/MonoDevelop.GtkCore2/libstetic/editor/IconList.cs new file mode 100644 index 0000000000..0803726b23 --- /dev/null +++ b/main/src/addins/MonoDevelop.GtkCore2/libstetic/editor/IconList.cs @@ -0,0 +1,205 @@ + +using System; +using System.Collections; +using Gtk; + +namespace Stetic.Editor +{ + // This is the internal class the represents the actual two-column + // icon list. This can't just be handled as an HBox inside the main + // window, because we need to override SetScrollAdjustments. + class IconList : Gtk.HBox + { + ThemedIconColumn left, right; + ArrayList IconNames = new ArrayList (); + + public event EventHandler Activated; + + protected IconList () + { + left = new ThemedIconColumn (); + PackStart (left); + right = new ThemedIconColumn (); + PackStart (right); + + left.Selection.Changed += LeftSelectionChanged; + right.Selection.Changed += RightSelectionChanged; + left.RowActivated += RowActivated; + right.RowActivated += RowActivated; + left.KeyPressEvent += ColumnKeyPressEvent; + right.KeyPressEvent += ColumnKeyPressEvent; + } + + protected void AddIcon (string name, Gdk.Pixbuf pixbuf, string label) + { + int i = IconNames.Count; + IconNames.Add (name); + + if (i % 2 == 0) + left.Append (pixbuf, name); + else + right.Append (pixbuf, name); + } + + protected void Clear () + { + IconNames.Clear (); + left.Clear (); + right.Clear (); + } + + void RowActivated (object obj, RowActivatedArgs args) + { + if (Activated != null) + Activated (this, EventArgs.Empty); + } + + public int SelectionIndex { + get { + Gtk.TreePath[] selection; + selection = left.Selection.GetSelectedRows (); + if (selection.Length > 0) + return selection[0].Indices[0] * 2; + selection = right.Selection.GetSelectedRows (); + if (selection.Length > 0) + return selection[0].Indices[0] * 2 + 1; + return -1; + } + set { + if (value != -1) { + if (value % 2 == 0) + left.SelectRow (value / 2); + else + right.SelectRow (value / 2); + } else { + left.Selection.UnselectAll (); + right.Selection.UnselectAll (); + } + } + } + + public string Selection { + get { + int i = SelectionIndex; + if (i != -1) + return (string) IconNames [i]; + else + return null; + } + set { + if (value != null) + SelectionIndex = IconNames.IndexOf (value); + else + SelectionIndex = -1; + } + } + + public event EventHandler SelectionChanged; + + public void Find (string text) + { + int selection = SelectionIndex; + for (int i = (selection + 1) % IconNames.Count; i != selection; i = (i + 1) % IconNames.Count) { + if (((string)IconNames[i]).IndexOf (text) != -1) { + SelectionIndex = i; + return; + } + } + SelectionIndex = -1; + } + + void LeftSelectionChanged (object obj, EventArgs args) + { + if (left.Selection.GetSelectedRows().Length != 0) + right.Selection.UnselectAll (); + if (SelectionChanged != null) + SelectionChanged (this, EventArgs.Empty); + } + + void RightSelectionChanged (object obj, EventArgs args) + { + if (right.Selection.GetSelectedRows().Length != 0) + left.Selection.UnselectAll (); + if (SelectionChanged != null) + SelectionChanged (this, EventArgs.Empty); + } + + [GLib.ConnectBefore] + void ColumnKeyPressEvent (object obj, KeyPressEventArgs args) + { + if (args.Event.Key == Gdk.Key.Right) { + if (obj == (object)left) { + SelectionIndex++; + right.GrabFocus (); + } + args.RetVal = true; + } else if (args.Event.Key == Gdk.Key.Left) { + if (obj == (object)right) { + SelectionIndex--; + left.GrabFocus (); + } + args.RetVal = true; + } + } + + protected override void OnSetScrollAdjustments (Gtk.Adjustment hadj, Gtk.Adjustment vadj) + { + left.SetScrollAdjustments (null, vadj); + right.SetScrollAdjustments (null, vadj); + } + } + + // Another internal class. This is a single column of the ThemedIconList + class ThemedIconColumn : Gtk.TreeView + { + public ThemedIconColumn () + { + Model = store = new Gtk.ListStore (typeof (Gdk.Pixbuf), + typeof (string)); + HeadersVisible = false; + EnableSearch = false; + + TreeViewColumn col; + CellRenderer renderer; + + col = new TreeViewColumn (); + renderer = new CellRendererPixbuf (); + col.PackStart (renderer, false); + col.AddAttribute (renderer, "pixbuf", 0); + renderer = new CellRendererText (); + col.PackStart (renderer, false); + col.AddAttribute (renderer, "text", 1); + AppendColumn (col); + } + + Gtk.ListStore store; + + public void Append (Gdk.Pixbuf pixbuf, string name) + { + if (name.Length > 30) + name = name.Substring (0, 30) + "..."; + store.AppendValues (pixbuf, name); + } + + public void SelectRow (int row) + { + Gtk.TreeIter iter; + if (store.IterNthChild (out iter, row)) { + Gtk.TreePath path = store.GetPath (iter); + + SetCursor (path, null, false); + + // We want the initial selection to be centered + if (!IsRealized) + ScrollToCell (path, null, true, 0.5f, 0.0f); + } + } + + public void Clear () + { + store.Clear (); + } + } +} + + diff --git a/main/src/addins/MonoDevelop.GtkCore2/libstetic/editor/IconSelectorItem.cs b/main/src/addins/MonoDevelop.GtkCore2/libstetic/editor/IconSelectorItem.cs new file mode 100644 index 0000000000..9c5980ce04 --- /dev/null +++ b/main/src/addins/MonoDevelop.GtkCore2/libstetic/editor/IconSelectorItem.cs @@ -0,0 +1,285 @@ + +using System; +using System.Reflection; +using System.Collections; + +namespace Stetic.Editor +{ + public class IconSelectorItem: Gtk.EventBox + { + ArrayList icons = new ArrayList (); + ArrayList labels = new ArrayList (); + ArrayList names = new ArrayList (); + int columns = 12; + int iconSize = 16; + int spacing = 3; + int selIndex = -1; + int sectionGap = 10; + int lastSel = -1; + int xmax; + int ymax; + string title; + Gtk.Window tipWindow; + bool inited; + + public IconSelectorItem (IntPtr ptr): base (ptr) + { + } + + public IconSelectorItem (string title) + { + this.title = title; + + int w, h; + Gtk.Icon.SizeLookup (Gtk.IconSize.Menu, out w, out h); + iconSize = w; + + this.Events |= Gdk.EventMask.PointerMotionMask; + } + + protected override void OnSizeRequested (ref Gtk.Requisition req) + { + if (!inited) { + CreateIcons (); + inited = true; + } + + base.OnSizeRequested (ref req); + CalcSize (); + + Gtk.Requisition nr = new Gtk.Requisition (); + nr.Width = xmax; + nr.Height = ymax; + req = nr; + } + + protected virtual void CreateIcons () + { + } + + public int SelectedIndex { + get { return selIndex; } + } + + public string SelectedIcon { + get { + if (selIndex != -1) + return (string) names [selIndex]; + else + return null; + } + } + + protected void AddIcon (string name, Gdk.Pixbuf pix, string label) + { + icons.Add (pix); + labels.Add (label); + names.Add (name); + } + + protected void AddSeparator (string separator) + { + icons.Add (null); + labels.Add (null); + names.Add (separator); + } + + protected override bool OnMotionNotifyEvent (Gdk.EventMotion ev) + { + ProcessMotionEvent ((int) ev.X, (int) ev.Y); + return true; + } + + internal void ProcessMotionEvent (int x, int y) + { + int ix, iy; + GetIconIndex (x, y, out selIndex, out ix, out iy); + if (selIndex != -1) { + string name = labels [selIndex] as string; + if (name == null || name.Length == 0) + name = names [selIndex] as string; + if (selIndex != lastSel) { + HideTip (); + ShowTip (ix, iy + iconSize + spacing*2, name); + } + } else + HideTip (); + + lastSel = selIndex; + + QueueDraw (); + } + + void ShowTip (int x, int y, string text) + { + if (GdkWindow == null) + return; + if (tipWindow == null) { + tipWindow = new TipWindow (); + Gtk.Label lab = new Gtk.Label (text); + lab.Xalign = 0; + lab.Xpad = 3; + lab.Ypad = 3; + tipWindow.Add (lab); + } + ((Gtk.Label)tipWindow.Child).Text = text; + int w = tipWindow.Child.SizeRequest().Width; + int ox, oy; + GdkWindow.GetOrigin (out ox, out oy); + tipWindow.Move (ox + x - (w/2) + (iconSize/2), oy + y); + tipWindow.ShowAll (); + } + + void HideTip () + { + if (tipWindow != null) { + tipWindow.Destroy (); + tipWindow = null; + } + } + + public override void Dispose () + { + HideTip (); + base.Dispose (); + } + + protected override bool OnLeaveNotifyEvent (Gdk.EventCrossing ev) + { + HideTip (); + return base.OnLeaveNotifyEvent (ev); + } + + internal void ProcessLeaveNotifyEvent (Gdk.EventCrossing ev) + { + HideTip (); + } + + protected override bool OnExposeEvent (Gdk.EventExpose ev) + { + Draw (); + return true; + } + + void Draw () + { + int a,b; + Expose (true, -1, -1, out a, out b); + } + + void CalcSize () + { + int a,b; + Expose (false, -1, -1, out a, out b); + } + + void GetIconIndex (int x, int y, out int index, out int ix, out int iy) + { + index = Expose (false, x, y, out ix, out iy); + } + + int Expose (bool draw, int testx, int testy, out int ix, out int iy) + { + int x = spacing; + int y = spacing; + int sx = spacing; + int maxx = columns * (iconSize + spacing) + spacing; + bool calcSize = (testx == -1); + + Pango.Layout layout = new Pango.Layout (this.PangoContext); + Pango.FontDescription des = this.Style.FontDescription.Copy(); + des.Size = 10 * (int) Pango.Scale.PangoScale; + layout.FontDescription = des; + layout.SetMarkup (title); + layout.Width = -1; + int w, h; + int tborder = 1; + layout.GetPixelSize (out w, out h); + if (draw) { + GdkWindow.DrawRectangle (this.Style.DarkGC (Gtk.StateType.Normal), true, x, y, Allocation.Width + tborder*2, h + tborder*2); + GdkWindow.DrawLayout (this.Style.ForegroundGC (Gtk.StateType.Normal), x + tborder + 2, y + tborder, layout); + } + + if (calcSize) + xmax = 0; + + y += h + spacing*2 + tborder*2; + + for (int n=0; n<icons.Count; n++) { + string cmd = names [n] as string; + Gdk.Pixbuf pix = icons [n] as Gdk.Pixbuf; + + if (cmd == "-") { + if (x > sx) { + y += iconSize + spacing; + } + x = sx; + y -= spacing; + if (draw) { + Gdk.Rectangle rect = new Gdk.Rectangle (0, y+(sectionGap/2), Allocation.Width - x, 1); + Gtk.Style.PaintHline (this.Style, this.GdkWindow, Gtk.StateType.Normal, rect, this, "", rect.X, rect.Right, rect.Y); + } + y += sectionGap; + continue; + } + + if (cmd == "|") { + if (x == sx) + continue; + x += spacing; + if (draw) { + Gdk.Rectangle rect = new Gdk.Rectangle (x, y, 1, iconSize); + Gtk.Style.PaintVline (this.Style, this.GdkWindow, Gtk.StateType.Normal, rect, this, "", rect.Y, rect.Bottom, rect.X); + } + x += spacing*2; + continue; + } + + if (testx != -1 && testx >= (x - spacing/2) && testx < (x + iconSize + spacing) && testy >= (y - spacing/2) && testy < (y + iconSize + spacing)) { + ix = x; + iy = y; + return n; + } + + if (draw) { + Gtk.StateType state = (n == selIndex) ? Gtk.StateType.Selected : Gtk.StateType.Normal; + if (n == selIndex) + GdkWindow.DrawRectangle (this.Style.BackgroundGC (state), true, x-spacing, y-spacing, iconSize + spacing*2, iconSize + spacing*2); + GdkWindow.DrawPixbuf (this.Style.ForegroundGC (state), pix, 0, 0, x, y, pix.Width, pix.Height, Gdk.RgbDither.None, 0, 0); + } + + x += (iconSize + spacing); + if (calcSize && x > xmax) + xmax = x; + + if (x >= maxx) { + x = sx; + y += iconSize + spacing; + } + } + if (calcSize) { + if (x > sx) + y += iconSize + spacing; + ymax = y; + } + + ix = iy = 0; + return -1; + } + } + + class TipWindow: Gtk.Window + { + public TipWindow (): base (Gtk.WindowType.Popup) + { + } + + protected override bool OnExposeEvent (Gdk.EventExpose ev) + { + base.OnExposeEvent (ev); + Gtk.Requisition req = SizeRequest (); + Gtk.Style.PaintFlatBox (this.Style, this.GdkWindow, Gtk.StateType.Normal, Gtk.ShadowType.Out, Gdk.Rectangle.Zero, this, "tooltip", 0, 0, req.Width, req.Height); + return true; + } + } +} diff --git a/main/src/addins/MonoDevelop.GtkCore2/libstetic/editor/IconSelectorMenu.cs b/main/src/addins/MonoDevelop.GtkCore2/libstetic/editor/IconSelectorMenu.cs new file mode 100644 index 0000000000..ab6af38d28 --- /dev/null +++ b/main/src/addins/MonoDevelop.GtkCore2/libstetic/editor/IconSelectorMenu.cs @@ -0,0 +1,56 @@ + +using System; +using System.Reflection; +using System.Collections; +using Mono.Unix; + +namespace Stetic.Editor +{ + public class IconSelectorMenu: Gtk.Menu + { + IProject project; + + public event IconEventHandler IconSelected; + + public IconSelectorMenu (IProject project) + { + this.project = project; + + // Stock icon selector + IconSelectorMenuItem selStock = new IconSelectorMenuItem (new StockIconSelectorItem ()); + selStock.IconSelected += OnStockSelected; + Insert (selStock, -1); + + // Project icon selector + if (project != null && project.IconFactory.Icons.Count > 0) { + IconSelectorMenuItem selProject = new IconSelectorMenuItem (new ProjectIconSelectorItem (project)); + selProject.IconSelected += OnStockSelected; + Insert (selProject, -1); + } + + Insert (new Gtk.SeparatorMenuItem (), -1); + + Gtk.MenuItem it = new Gtk.MenuItem (Catalog.GetString ("More...")); + it.Activated += OnSetStockActionType; + Insert (it, -1); + } + + void OnStockSelected (object s, IconEventArgs args) + { + if (IconSelected != null) + IconSelected (this, args); + } + + void OnSetStockActionType (object ob, EventArgs args) + { + Stetic.Editor.SelectIconDialog dialog = new Stetic.Editor.SelectIconDialog (this.Toplevel as Gtk.Window, project); + using (dialog) + { + if (dialog.Run () != (int) Gtk.ResponseType.Ok) + return; + if (IconSelected != null) + IconSelected (this, new IconEventArgs (dialog.Icon)); + } + } + } +} diff --git a/main/src/addins/MonoDevelop.GtkCore2/libstetic/editor/IconSelectorMenuItem.cs b/main/src/addins/MonoDevelop.GtkCore2/libstetic/editor/IconSelectorMenuItem.cs new file mode 100644 index 0000000000..5ac94883eb --- /dev/null +++ b/main/src/addins/MonoDevelop.GtkCore2/libstetic/editor/IconSelectorMenuItem.cs @@ -0,0 +1,59 @@ + +using System; + +namespace Stetic.Editor +{ + public class IconSelectorMenuItem: Gtk.MenuItem + { + IconSelectorItem selector; + + public event IconEventHandler IconSelected; + + public IconSelectorMenuItem (IconSelectorItem item) + { + selector = item; + Add (selector); + } + + protected override bool OnButtonPressEvent (Gdk.EventButton ev) + { + if (IconSelected != null) + IconSelected (this, new IconEventArgs (selector.SelectedIcon)); + selector.Destroy (); + return base.OnButtonPressEvent (ev); + } + + protected override bool OnEnterNotifyEvent (Gdk.EventCrossing ev) + { + return true; + } + + protected override bool OnLeaveNotifyEvent (Gdk.EventCrossing ev) + { + selector.ProcessLeaveNotifyEvent (ev); + return true; + } + + protected override bool OnMotionNotifyEvent (Gdk.EventMotion ev) + { + selector.ProcessMotionEvent ((int)ev.X - selector.Allocation.X + Allocation.X, (int)ev.Y - selector.Allocation.Y + Allocation.Y); + return true; + } + } + + public delegate void IconEventHandler (object s, IconEventArgs args); + + public class IconEventArgs: EventArgs + { + string iconId; + + public IconEventArgs (string iconId) + { + this.iconId = iconId; + } + + public string IconId { + get { return iconId; } + } + } +} diff --git a/main/src/addins/MonoDevelop.GtkCore2/libstetic/editor/Identifier.cs b/main/src/addins/MonoDevelop.GtkCore2/libstetic/editor/Identifier.cs new file mode 100644 index 0000000000..6b7c42101e --- /dev/null +++ b/main/src/addins/MonoDevelop.GtkCore2/libstetic/editor/Identifier.cs @@ -0,0 +1,78 @@ + +using System; +using System.Text; +using Gtk; +using Gdk; + +namespace Stetic.Editor +{ + public class Identifier: Gtk.Entry, IPropertyEditor + { + string id; + int min = -1; + int max = -1; + + public Identifier() + { + ShowAll (); + HasFrame = false; + } + + public void Initialize (PropertyDescriptor descriptor) + { + if (descriptor.PropertyType != typeof(string)) + throw new InvalidOperationException ("TextEditor only can edit string properties"); + + try { + if (descriptor.Minimum != null) + min = Convert.ToInt32 (descriptor.Minimum); + } catch {} + + try { + if (descriptor.Maximum != null) + max = Convert.ToInt32 (descriptor.Maximum); + } catch {} + } + + public void AttachObject (object obj) + { + } + + protected override bool OnFocusOutEvent (Gdk.EventFocus e) + { + DoChanged (); + return base.OnFocusOutEvent (e); + } + + void DoChanged () + { + StringBuilder sb = new StringBuilder (); + foreach (char c in Text) { + if (char.IsLetterOrDigit (c) || c == '_') + sb.Append (c); + } + + string s = sb.ToString (); + if (min != -1 && s.Length < min) + return; + if (max != -1 && s.Length > max) + return; + + if (s == Text) { + id = Text; + if (ValueChanged != null) + ValueChanged (this, EventArgs.Empty); + } else { + Text = s; + } + } + + public object Value { + get { return id; } + set { id = Text = (value != null ? (string) value : ""); } + } + + // To be fired when the edited value changes. + public event EventHandler ValueChanged; + } +} diff --git a/main/src/addins/MonoDevelop.GtkCore2/libstetic/editor/Image.cs b/main/src/addins/MonoDevelop.GtkCore2/libstetic/editor/Image.cs new file mode 100644 index 0000000000..0dbd5ed7e0 --- /dev/null +++ b/main/src/addins/MonoDevelop.GtkCore2/libstetic/editor/Image.cs @@ -0,0 +1,265 @@ +using System; +using System.Collections; +using System.Reflection; +using Mono.Unix; + +namespace Stetic.Editor { + + [PropertyEditor ("Value", "Changed")] + public class Image : Gtk.HBox, IPropertyEditor { + Gtk.Image image; + Gtk.ComboBoxEntry combo; + Gtk.Entry entry; + Gtk.Button button; + Gtk.ListStore store; + + const int IconColumn = 0; + const int LabelColumn = 1; + + static string[] stockIds, stockLabels; + static int imgWidth, imgHeight; + + static Image () + { + ArrayList tmpIds = new ArrayList (); + + // We can't use Gtk.Stock.ListIds, because that returns different + // values depending on what version of libgtk you have installed... + foreach (PropertyInfo info in typeof (Gtk.Stock).GetProperties (BindingFlags.Public | BindingFlags.Static)) { + if (info.CanRead && info.PropertyType == typeof (string)) + tmpIds.Add (info.GetValue (null, null)); + } + foreach (PropertyInfo info in GnomeStock.Properties) { + if (info.CanRead && info.PropertyType == typeof (string)) + tmpIds.Add (info.GetValue (null, null)); + } + + ArrayList items = new ArrayList (), nonItems = new ArrayList (); + foreach (string id in tmpIds) { + Gtk.StockItem item = Gtk.Stock.Lookup (id); + if (item.StockId == null) + nonItems.Add (id); + else { + item.Label = item.Label.Replace ("_", ""); + items.Add (item); + } + } + items.Sort (new StockItemSorter ()); + nonItems.Sort (); + + stockIds = new string[items.Count + nonItems.Count]; + stockLabels = new string[items.Count + nonItems.Count]; + for (int i = 0; i < items.Count; i++) { + stockIds[i] = ((Gtk.StockItem)items[i]).StockId; + stockLabels[i] = ((Gtk.StockItem)items[i]).Label; + } + for (int i = 0; i < nonItems.Count; i++) { + stockIds[i + items.Count] = nonItems[i] as string; + stockLabels[i + items.Count] = nonItems[i] as string; + } + + Gtk.Icon.SizeLookup (Gtk.IconSize.Button, out imgWidth, out imgHeight); + } + + class StockItemSorter : IComparer { + public int Compare (object itemx, object itemy) + { + Gtk.StockItem x = (Gtk.StockItem)itemx; + Gtk.StockItem y = (Gtk.StockItem)itemy; + + return string.Compare (x.Label, y.Label); + } + } + + public Image () : this (true, true) {} + + public Image (bool allowStock, bool allowFile) : base (false, 6) + { + image = new Gtk.Image (GnomeStock.Blank, Gtk.IconSize.Button); + PackStart (image, false, false, 0); + + if (allowStock) { + store = new Gtk.ListStore (typeof (string), typeof (string)); + store.AppendValues (GnomeStock.Blank, Catalog.GetString ("(None)")); + for (int i = 0; i < stockIds.Length; i++) + store.AppendValues (stockIds[i], stockLabels[i]); + + combo = new Gtk.ComboBoxEntry (store, LabelColumn); + Gtk.CellRendererPixbuf iconRenderer = new Gtk.CellRendererPixbuf (); + iconRenderer.StockSize = (uint)Gtk.IconSize.Menu; + combo.PackStart (iconRenderer, false); + combo.Reorder (iconRenderer, 0); + combo.AddAttribute (iconRenderer, "stock-id", IconColumn); + combo.Changed += combo_Changed; + + // Pack the combo non-expandily into a VBox so it doesn't + // get stretched to the file button's height + Gtk.VBox vbox = new Gtk.VBox (false, 0); + vbox.PackStart (combo, true, false, 0); + PackStart (vbox, true, true, 0); + + entry = (Gtk.Entry)combo.Child; + entry.Changed += entry_Changed; + + useStock = true; + } + + if (allowFile) { + if (!allowStock) { + entry = new Gtk.Entry (); + PackStart (entry, true, true, 0); + entry.Changed += entry_Changed; + } + + button = new Gtk.Button (); + Gtk.Image icon = new Gtk.Image (Gtk.Stock.Open, Gtk.IconSize.Button); + button.Add (icon); + PackStart (button, false, false, 0); + button.Clicked += button_Clicked; + } + ShowAll (); + } + + public void Initialize (PropertyDescriptor prop) + { + if (prop.PropertyType != typeof(string)) + throw new ApplicationException ("Image editor does not support editing values of type " + prop.PropertyType); + } + + public void AttachObject (object ob) + { + } + + public event EventHandler ValueChanged; + + bool syncing; + + void combo_Changed (object obj, EventArgs args) + { + if (syncing) + return; + + useStock = true; + syncing = true; + if (combo.Active > 0) + StockId = stockIds[combo.Active - 1]; + else + StockId = null; + if (ValueChanged != null) + ValueChanged (this, EventArgs.Empty); + syncing = false; + } + + void entry_Changed (object obj, EventArgs args) + { + if (syncing) + return; + + useStock = true; + syncing = true; + StockId = entry.Text; + if (ValueChanged != null) + ValueChanged (this, EventArgs.Empty); + syncing = false; + } + + void button_Clicked (object obj, EventArgs args) + { + Gtk.FileChooserDialog dialog = + new Gtk.FileChooserDialog (Catalog.GetString ("Image"), null, Gtk.FileChooserAction.Open, + Gtk.Stock.Cancel, Gtk.ResponseType.Cancel, + Gtk.Stock.Open, Gtk.ResponseType.Ok); + dialog.TransientFor = this.Toplevel as Gtk.Window; + int response = dialog.Run (); + string file = dialog.Filename; + dialog.Destroy (); + + if (response == (int)Gtk.ResponseType.Ok) { + syncing = true; + useStock = false; + entry.Text = file; + File = file; + if (ValueChanged != null) + ValueChanged (this, EventArgs.Empty); + syncing = false; + } + } + + bool useStock; + + string stockId; + public string StockId { + get { + return stockId; + } + set { + useStock = true; + stockId = value; + file = null; + + image.SetFromStock (stockId, Gtk.IconSize.Button); + + if (!syncing) { + int id = Array.IndexOf (stockIds, value); + if (id != -1) { + syncing = true; + combo.Active = id + 1; + syncing = false; + } + } + } + } + + string file; + public string File { + get { + return file; + } + set { + useStock = false; + stockId = null; + file = value; + + if (value == null) + value = ""; + + try { + image.Pixbuf = new Gdk.Pixbuf (value, imgWidth, imgHeight); + } catch { + image.SetFromStock (GnomeStock.Blank, Gtk.IconSize.Button); + } + + if (!syncing) { + syncing = true; + entry.Text = value; + syncing = false; + } + } + } + + public virtual object Value { + get { + if (useStock) { + if (StockId != null) + return "stock:" + StockId; + else + return null; + } else { + if (File != null) + return "file:" + File; + else + return null; + } + } + set { + string val = value as string; + if (val == null) + File = null; + else if (val.StartsWith ("stock:")) + StockId = val.Substring (6); + else if (val.StartsWith ("file:")) + File = val.Substring (5); + } + } + } +} diff --git a/main/src/addins/MonoDevelop.GtkCore2/libstetic/editor/ImageFile.cs b/main/src/addins/MonoDevelop.GtkCore2/libstetic/editor/ImageFile.cs new file mode 100644 index 0000000000..4d9ad3211a --- /dev/null +++ b/main/src/addins/MonoDevelop.GtkCore2/libstetic/editor/ImageFile.cs @@ -0,0 +1,10 @@ +using System; + +namespace Stetic.Editor { + + [PropertyEditor ("File", "Changed")] + public class ImageFile : Image { + + public ImageFile () : base (false, true) { } + } +} diff --git a/main/src/addins/MonoDevelop.GtkCore2/libstetic/editor/ImageSelector.cs b/main/src/addins/MonoDevelop.GtkCore2/libstetic/editor/ImageSelector.cs new file mode 100644 index 0000000000..d983c521ec --- /dev/null +++ b/main/src/addins/MonoDevelop.GtkCore2/libstetic/editor/ImageSelector.cs @@ -0,0 +1,177 @@ + +using System; + +namespace Stetic.Editor +{ + public class BaseImageCell: PropertyEditorCell + { + const int imgSize = 24; + const int imgPad = 2; + const int spacing = 5; + Gdk.Pixbuf image; + + protected Gdk.Pixbuf Image { + get { return image; } + set { image = value; } + } + + protected int ImageSize { + get { return 16; }//imgSize - imgPad*2; } + } + + public override void GetSize (int availableWidth, out int width, out int height) + { + base.GetSize (availableWidth, out width, out height); + width += imgSize + spacing; + height = Math.Max (imgSize, height); + } + + public override void Render (Gdk.Drawable window, Gdk.Rectangle bounds, Gtk.StateType state) + { + int iy = bounds.Y + (bounds.Height - imgSize) / 2; + + if (image != null) { + int dy = (imgSize - image.Height) / 2; + int dx = (imgSize - image.Width) / 2; + window.DrawPixbuf (Container.Style.BackgroundGC (state), image, 0, 0, bounds.X + dx, iy + dy, -1, -1, Gdk.RgbDither.None, 0, 0); + } + + window.DrawRectangle (Container.Style.DarkGC (state), false, bounds.X, iy, imgSize - 1, imgSize - 1); + + bounds.X += imgSize + spacing; + base.Render (window, bounds, state); + } + } + + public class ImageSelector: BaseImageCell + { + IProject project; + ImageInfo imageInfo; + + protected override void Initialize () + { + base.Initialize (); + + if (Property.PropertyType != typeof(ImageInfo)) + throw new ApplicationException ("ImageSelector editor does not support editing values of type " + Property.PropertyType); + + if (Instance == null) + return; + + Stetic.ObjectWrapper w = Stetic.ObjectWrapper.Lookup (Instance); + project = w.Project; + imageInfo = (ImageInfo)Value; + if (imageInfo != null) + Image = imageInfo.GetThumbnail (project, ImageSize); + else + Image = null; + } + + protected override string GetValueText () + { + if (imageInfo == null) + return ""; + return imageInfo.Label; + } + + protected override IPropertyEditor CreateEditor (Gdk.Rectangle cell_area, Gtk.StateType state) + { + return new ImageSelectorEditor (); + } + } + + public class ImageSelectorEditor: Gtk.HBox, IPropertyEditor + { + Gtk.Image image; + Gtk.Label entry; + Gtk.Button button; + Gtk.Button clearButton; + ImageInfo icon; + IProject project; + Gtk.Frame imageFrame; + + public ImageSelectorEditor() + { + Spacing = 3; + imageFrame = new Gtk.Frame (); + imageFrame.Shadow = Gtk.ShadowType.In; + imageFrame.BorderWidth = 2; + PackStart (imageFrame, false, false, 0); + + image = new Gtk.Image (GnomeStock.Blank, Gtk.IconSize.Button); + imageFrame.Add (image); + + Gtk.Frame frame = new Gtk.Frame (); + entry = new Gtk.Label (); + entry.Xalign = 0; + frame.Shadow = Gtk.ShadowType.In; + frame.BorderWidth = 2; + frame.Add (entry); + PackStart (frame, true, true, 0); + + clearButton = new Gtk.Button (new Gtk.Image (Gtk.Stock.Clear, Gtk.IconSize.Menu)); + clearButton.Clicked += OnClearImage; + PackStart (clearButton, false, false, 0); + + button = new Gtk.Button ("..."); + PackStart (button, false, false, 0); + button.Clicked += button_Clicked; + ShowAll (); + } + + void button_Clicked (object obj, EventArgs args) + { + Gtk.Window parent = (Gtk.Window)GetAncestor (Gtk.Window.GType); + using (SelectImageDialog dlg = new SelectImageDialog (parent, project)) { + dlg.Icon = (ImageInfo) Value; + if (dlg.Run () == (int) Gtk.ResponseType.Ok) + Value = dlg.Icon; + } + } + + void OnClearImage (object obj, EventArgs args) + { + Value = null; + } + + // Called once to initialize the editor. + public void Initialize (PropertyDescriptor prop) + { + if (prop.PropertyType != typeof(ImageInfo)) + throw new ApplicationException ("ImageSelector editor does not support editing values of type " + prop.PropertyType); + } + + // Called when the object to be edited changes. + public void AttachObject (object obj) + { + Stetic.ObjectWrapper w = Stetic.ObjectWrapper.Lookup (obj); + project = w.Project; + } + + // Gets/Sets the value of the editor. If the editor supports + // several value types, it is the responsibility of the editor + // to return values with the expected type. + public object Value { + get { return icon; } + set { + icon = (ImageInfo) value; + if (icon != null) { + entry.Text = icon.Label; + image.Pixbuf = icon.GetThumbnail (project, 16); + imageFrame.Show (); + clearButton.Show (); + } else { + imageFrame.Hide (); + clearButton.Hide (); + entry.Text = ""; + } + + if (ValueChanged != null) + ValueChanged (this, EventArgs.Empty); + } + } + + // To be fired when the edited value changes. + public event EventHandler ValueChanged; + } +} diff --git a/main/src/addins/MonoDevelop.GtkCore2/libstetic/editor/IntRange.cs b/main/src/addins/MonoDevelop.GtkCore2/libstetic/editor/IntRange.cs new file mode 100644 index 0000000000..415becc0dc --- /dev/null +++ b/main/src/addins/MonoDevelop.GtkCore2/libstetic/editor/IntRange.cs @@ -0,0 +1,120 @@ +using System; + +namespace Stetic.Editor { + + public class IntRange : PropertyEditorCell + { + bool optInteger; + + bool HasValue { + get { + if (!optInteger) return true; + int val = (int) Convert.ChangeType (Value, typeof(int)); + return (val != -1); + } + } + + protected override void Initialize () + { + base.Initialize (); + + if (Property.Minimum != null && Property.PropertyType == typeof(int)) { + int min = (int) Convert.ChangeType (Property.Minimum, typeof(int)); + optInteger = (min == -1); + } else + optInteger = false; + } + + public override void GetSize (int availableWidth, out int width, out int height) + { + if (HasValue) + base.GetSize (availableWidth, out width, out height); + else + width = height = 0; + } + + public override void Render (Gdk.Drawable window, Gdk.Rectangle bounds, Gtk.StateType state) + { + if (HasValue) + base.Render (window, bounds, state); + } + + protected override IPropertyEditor CreateEditor (Gdk.Rectangle cell_area, Gtk.StateType state) + { + if (optInteger) + return new OptIntRange (0, null); + else + return new IntRangeEditor (); + } + } + + public class IntRangeEditor : Gtk.SpinButton, IPropertyEditor { + + Type propType; + + public IntRangeEditor () : base (0, 0, 1.0) + { + this.HasFrame = false; + } + + public void Initialize (PropertyDescriptor prop) + { + propType = prop.PropertyType; + + double min, max; + + switch (Type.GetTypeCode (propType)) { + case TypeCode.Int16: + min = (double) Int16.MinValue; + max = (double) Int16.MaxValue; + break; + case TypeCode.UInt16: + min = (double) UInt16.MinValue; + max = (double) UInt16.MaxValue; + break; + case TypeCode.Int32: + min = (double) Int32.MinValue; + max = (double) Int32.MaxValue; + break; + case TypeCode.UInt32: + min = (double) UInt32.MinValue; + max = (double) UInt32.MaxValue; + break; + case TypeCode.Int64: + min = (double) Int64.MinValue; + max = (double) Int64.MaxValue; + break; + case TypeCode.UInt64: + min = (double) UInt64.MinValue; + max = (double) UInt64.MaxValue; + break; + case TypeCode.Byte: + min = (double) Byte.MinValue; + max = (double) Byte.MaxValue; + break; + case TypeCode.SByte: + min = (double) SByte.MinValue; + max = (double) SByte.MaxValue; + break; + default: + throw new ApplicationException ("IntRange editor does not support editing values of type " + prop.PropertyType); + } + + if (prop.Minimum != null) + min = (double) Convert.ChangeType (prop.Minimum, typeof(double)); + if (prop.Maximum != null) + max = (double) Convert.ChangeType (prop.Maximum, typeof(double)); + + SetRange (min, max); + } + + public void AttachObject (object ob) + { + } + + object IPropertyEditor.Value { + get { return Convert.ChangeType (base.Value, propType); } + set { base.Value = (double) Convert.ChangeType (value, typeof(double)); } + } + } +} diff --git a/main/src/addins/MonoDevelop.GtkCore2/libstetic/editor/NonContainerWarningDialog.cs b/main/src/addins/MonoDevelop.GtkCore2/libstetic/editor/NonContainerWarningDialog.cs new file mode 100644 index 0000000000..3b212baa52 --- /dev/null +++ b/main/src/addins/MonoDevelop.GtkCore2/libstetic/editor/NonContainerWarningDialog.cs @@ -0,0 +1,51 @@ + +using System; +using Mono.Unix; + +namespace Stetic.Editor +{ + public delegate void ShowUrlDelegate (string url); + + public class NonContainerWarningDialog: IDisposable + { + [Glade.Widget] Gtk.CheckButton showCheck; + [Glade.Widget] Gtk.Button linkButton; + [Glade.Widget] Gtk.Button okbutton; + [Glade.Widget ("AddNonContainerDialog")] Gtk.Dialog dialog; + + public static ShowUrlDelegate ShowUrl; + + public NonContainerWarningDialog() + { + Glade.XML xml = new Glade.XML (null, "stetic.glade", "AddNonContainerDialog", null); + xml.Autoconnect (this); + + ((Gtk.Label)linkButton.Child).Markup = "<u><span foreground='blue'>" + Catalog.GetString ("GTK# Widget Layout and Packing") + "</span></u>"; + + linkButton.Clicked += delegate { + if (ShowUrl != null) + ShowUrl ("http://www.mono-project.com/GtkSharp:_Widget_Layout_and_Packing"); + }; + okbutton.HasFocus = true; + } + + public bool ShowAgain { + get { return !showCheck.Active; } + set { showCheck.Active = !value; } + } + + public Gtk.Window TransientFor { + set { dialog.TransientFor = value; } + } + + public int Run () + { + return dialog.Run (); + } + + public void Dispose () + { + dialog.Destroy (); + } + } +} diff --git a/main/src/addins/MonoDevelop.GtkCore2/libstetic/editor/OptIntRange.cs b/main/src/addins/MonoDevelop.GtkCore2/libstetic/editor/OptIntRange.cs new file mode 100644 index 0000000000..784c41f33b --- /dev/null +++ b/main/src/addins/MonoDevelop.GtkCore2/libstetic/editor/OptIntRange.cs @@ -0,0 +1,90 @@ +using System; + +namespace Stetic.Editor { + + public class OptIntRange : Gtk.HBox, IPropertyEditor { + + Gtk.CheckButton check; + Gtk.SpinButton spin; + object omin, omax; + + public OptIntRange () : base (false, 6) + { + } + + public OptIntRange (object omin, object omax) : base (false, 6) + { + this.omin = omin; + this.omax = omax; + } + + public void Initialize (PropertyDescriptor prop) + { + if (prop.PropertyType != typeof(int)) + throw new ApplicationException ("OptIntRange editor does not support editing values of type " + prop.PropertyType); + + double min = (double) Int32.MinValue; + double max = (double) Int32.MaxValue; + + if (omin == null) + omin = prop.Minimum; + if (omax == null) + omax = prop.Maximum; + + if (omin != null) + min = (double) Convert.ChangeType (omin, typeof(double)); + if (omax != null) + max = (double) Convert.ChangeType (omax, typeof(double)); + + check = new Gtk.CheckButton (); + check.Show (); + check.Toggled += check_Toggled; + PackStart (check, false, false, 0); + + spin = new Gtk.SpinButton (min, max, 1.0); + spin.Show (); + spin.HasFrame = false; + spin.ValueChanged += spin_ValueChanged; + PackStart (spin, true, true, 0); + } + + public void AttachObject (object ob) + { + } + + void check_Toggled (object o, EventArgs args) + { + spin.Sensitive = check.Active; + if (ValueChanged != null) + ValueChanged (this, EventArgs.Empty); + } + + void spin_ValueChanged (object o, EventArgs args) + { + if (ValueChanged != null) + ValueChanged (this, EventArgs.Empty); + } + + public object Value { + get { + if (check.Active) + return (int)spin.Value; + else + return -1; + } + set { + int val = (int) value; + if (val == -1) { + check.Active = false; + spin.Sensitive = false; + } else { + check.Active = true; + spin.Sensitive = true; + spin.Value = (double)val; + } + } + } + + public event EventHandler ValueChanged; + } +} diff --git a/main/src/addins/MonoDevelop.GtkCore2/libstetic/editor/ProjectIconList.cs b/main/src/addins/MonoDevelop.GtkCore2/libstetic/editor/ProjectIconList.cs new file mode 100644 index 0000000000..ff6a2fcce9 --- /dev/null +++ b/main/src/addins/MonoDevelop.GtkCore2/libstetic/editor/ProjectIconList.cs @@ -0,0 +1,29 @@ + +using System; +using System.Collections; +using Gtk; + +namespace Stetic.Editor +{ + class ProjectIconList : IconList + { + IProject project; + ProjectIconFactory icons; + + public ProjectIconList (IProject project, ProjectIconFactory icons) + { + this.project = project; + this.icons = icons; + Refresh (); + } + + public void Refresh () + { + Clear (); + foreach (ProjectIconSet icon in icons.Icons) + AddIcon (icon.Name, icon.Sources [0].Image.GetThumbnail (project, 16), icon.Name); + } + } +} + + diff --git a/main/src/addins/MonoDevelop.GtkCore2/libstetic/editor/ProjectIconSelectorItem.cs b/main/src/addins/MonoDevelop.GtkCore2/libstetic/editor/ProjectIconSelectorItem.cs new file mode 100644 index 0000000000..fe5683918c --- /dev/null +++ b/main/src/addins/MonoDevelop.GtkCore2/libstetic/editor/ProjectIconSelectorItem.cs @@ -0,0 +1,21 @@ + +using System; + +namespace Stetic.Editor +{ + public class ProjectIconSelectorItem: IconSelectorItem + { + IProject project; + + public ProjectIconSelectorItem (IProject project): base ("Project Icons") + { + this.project = project; + } + + protected override void CreateIcons () + { + foreach (ProjectIconSet icon in project.IconFactory.Icons) + AddIcon (icon.Name, icon.Sources [0].Image.GetScaledImage (project, Gtk.IconSize.Menu), icon.Name); + } + } +} diff --git a/main/src/addins/MonoDevelop.GtkCore2/libstetic/editor/ResponseId.cs b/main/src/addins/MonoDevelop.GtkCore2/libstetic/editor/ResponseId.cs new file mode 100644 index 0000000000..bc7ef54bab --- /dev/null +++ b/main/src/addins/MonoDevelop.GtkCore2/libstetic/editor/ResponseId.cs @@ -0,0 +1,100 @@ +using System; +using System.Collections; +using System.Reflection; + +namespace Stetic.Editor +{ + public class ResponseId: PropertyEditorCell + { + protected override string GetValueText () + { + if (Value == null) + return ""; + + int val = (int) Value; + EnumDescriptor enm = Registry.LookupEnum ("Gtk.ResponseType"); + foreach (Enum value in enm.Values) { + if (Convert.ToInt32 (enm[value].Value) == val) { + return enm[value].Label; + } + } + return val.ToString (); + } + + protected override IPropertyEditor CreateEditor (Gdk.Rectangle cell_area, Gtk.StateType state) + { + return new ResponseIdEditor (); + } + } + + public class ResponseIdEditor : Gtk.HBox, IPropertyEditor { + + Gtk.ComboBoxEntry combo; + Gtk.Entry entry; + EnumDescriptor enm; + ArrayList values; + + public ResponseIdEditor () + { + combo = Gtk.ComboBoxEntry.NewText (); + combo.Changed += combo_Changed; + combo.Show (); + PackStart (combo, true, true, 0); + + entry = combo.Child as Gtk.Entry; + entry.Changed += entry_Changed; + + enm = Registry.LookupEnum ("Gtk.ResponseType"); + values = new ArrayList (); + foreach (Enum value in enm.Values) { + if (enm[value].Label != "") { + combo.AppendText (enm[value].Label); + values.Add (Convert.ToInt32 (enm[value].Value)); + } + } + } + + public void Initialize (PropertyDescriptor prop) + { + if (prop.PropertyType != typeof(int)) + throw new ApplicationException ("ResponseId editor does not support editing values of type " + prop.PropertyType); + } + + public void AttachObject (object ob) + { + } + + public object Value { + get { + if (combo.Active != -1) + return (int)values[combo.Active]; + else { + try { + return Int32.Parse (entry.Text); + } catch { + return 0; + } + } + } + set { + combo.Active = values.IndexOf ((int)value); + if (combo.Active == -1) + entry.Text = value.ToString (); + } + } + + public event EventHandler ValueChanged; + + void combo_Changed (object o, EventArgs args) + { + if (ValueChanged != null) + ValueChanged (this, EventArgs.Empty); + } + + void entry_Changed (object o, EventArgs args) + { + if (combo.Active == -1 && ValueChanged != null) + ValueChanged (this, EventArgs.Empty); + } + } +} diff --git a/main/src/addins/MonoDevelop.GtkCore2/libstetic/editor/SelectIconDialog.cs b/main/src/addins/MonoDevelop.GtkCore2/libstetic/editor/SelectIconDialog.cs new file mode 100644 index 0000000000..1d9c3b220d --- /dev/null +++ b/main/src/addins/MonoDevelop.GtkCore2/libstetic/editor/SelectIconDialog.cs @@ -0,0 +1,179 @@ + +using System; +using System.Collections; +using System.IO; +using Gtk; +using Mono.Unix; + +namespace Stetic.Editor +{ + public class SelectIconDialog: IDisposable + { + [Glade.Widget] Gtk.Entry stockIconEntry; + [Glade.Widget] Gtk.Notebook notebook; + [Glade.Widget] Gtk.ScrolledWindow iconScrolledwindow; + [Glade.Widget] Gtk.ScrolledWindow customIconScrolledwindow; + [Glade.Widget] Gtk.Image previewIcon; + [Glade.Widget] Gtk.Button okButton; + [Glade.Widget] Gtk.Widget labelWarningIcon; + [Glade.Widget ("SelectIconDialog")] Gtk.Dialog dialog; + + StockIconList iconList; + ProjectIconList customIconList; + + Gtk.Window parent; + Stetic.IProject project; + + public SelectIconDialog (Gtk.Window parent, Stetic.IProject project) + { + this.parent = parent; + this.project = project; + + Glade.XML xml = new Glade.XML (null, "stetic.glade", "SelectIconDialog", null); + xml.Autoconnect (this); + + // Stock icon list + + iconList = new StockIconList (); + iconList.SelectionChanged += new EventHandler (OnIconSelectionChanged); + iconScrolledwindow.AddWithViewport (iconList); + + // Custom icon list + + customIconList = new ProjectIconList (project, project.IconFactory); + customIconList.SelectionChanged += new EventHandler (OnCustomIconSelectionChanged); + customIconScrolledwindow.AddWithViewport (customIconList); + dialog.ShowAll (); + + UpdateIconSelection (); + UpdateButtons (); + } + + public int Run () + { + dialog.Show (); + dialog.TransientFor = parent; + return dialog.Run (); + } + + public void Dispose () + { + dialog.Destroy (); + } + + public string Icon { + get { + if (notebook.Page == 0) { + if (stockIconEntry.Text.Length == 0) + return null; + return stockIconEntry.Text; + } else { + return customIconList.Selection; + } + } + set { + if (value == null) + return; + + if (project.IconFactory.GetIcon (value) != null) { + notebook.Page = 1; + customIconList.Selection = value; + } else { + stockIconEntry.Text = value; + iconList.Selection = value; + notebook.Page = 0; + } + } + } + + void UpdateButtons () + { + okButton.Sensitive = Icon != null; + } + + protected void OnCurrentPageChanged (object s, Gtk.SwitchPageArgs args) + { + UpdateButtons (); + } + + void OnIconSelectionChanged (object s, EventArgs args) + { + if (iconList.Selection != null) { + stockIconEntry.Text = iconList.Selection; + } + } + + void OnCustomIconSelectionChanged (object s, EventArgs args) + { + UpdateButtons (); + } + + void UpdateIconSelection () + { + labelWarningIcon.Visible = stockIconEntry.Text.Length > 0 && (!stockIconEntry.Text.StartsWith ("gtk-")); + + Gdk.Pixbuf icon = null; + if (stockIconEntry.Text.Length > 0) { + icon = WidgetUtils.LoadIcon (stockIconEntry.Text, Gtk.IconSize.Menu); + } + if (icon == null) + icon = WidgetUtils.MissingIcon; + previewIcon.Pixbuf = icon; + } + + protected void OnIconNameChanged (object ob, EventArgs args) + { + UpdateIconSelection (); + UpdateButtons (); + } + + protected void OnAddIcon (object ob, EventArgs args) + { + ProjectIconSet icon = new ProjectIconSet (); + using (EditIconDialog dlg = new EditIconDialog (project, icon)) { + if (parent != null) + dlg.TransientFor = parent.Toplevel as Gtk.Window; + if (dlg.Run () == (int) Gtk.ResponseType.Ok) { + project.IconFactory.Icons.Add (icon); + customIconList.Refresh (); + customIconList.Selection = icon.Name; +// project.Modified = true; + } + } + } + + protected void OnRemoveIcon (object ob, EventArgs args) + { + string name = customIconList.Selection; + ProjectIconSet icon = project.IconFactory.GetIcon (name); + if (icon != null) { + Gtk.MessageDialog md = new Gtk.MessageDialog (dialog, Gtk.DialogFlags.Modal, Gtk.MessageType.Question, Gtk.ButtonsType.YesNo, string.Format (Catalog.GetString ("Are you sure you want to delete the icon '{0}'"), icon.Name)); + if (parent != null) + md.TransientFor = parent.Toplevel as Gtk.Window; + if (md.Run () == (int) Gtk.ResponseType.Yes) { + project.IconFactory.Icons.Remove (icon); + customIconList.Refresh (); +// project.Modified = true; + } + md.Destroy (); + } + } + + protected void OnEditIcon (object ob, EventArgs args) + { + string name = customIconList.Selection; + ProjectIconSet icon = project.IconFactory.GetIcon (name); + if (icon != null) { + using (EditIconDialog dlg = new EditIconDialog (project, icon)) { + if (parent != null) + dlg.TransientFor = parent.Toplevel as Gtk.Window; + if (dlg.Run () == (int) Gtk.ResponseType.Ok) { + customIconList.Refresh (); + customIconList.Selection = icon.Name; +// project.Modified = true; + } + } + } + } + } +} diff --git a/main/src/addins/MonoDevelop.GtkCore2/libstetic/editor/SelectImageDialog.cs b/main/src/addins/MonoDevelop.GtkCore2/libstetic/editor/SelectImageDialog.cs new file mode 100644 index 0000000000..1ab23740aa --- /dev/null +++ b/main/src/addins/MonoDevelop.GtkCore2/libstetic/editor/SelectImageDialog.cs @@ -0,0 +1,314 @@ + +using System; +using System.Collections; +using System.IO; +using Gtk; + +namespace Stetic.Editor +{ + public class SelectImageDialog: IDisposable + { + [Glade.Widget] Gtk.TreeView resourceList; + [Glade.Widget] Gtk.FileChooserWidget fileChooser; + [Glade.Widget] Gtk.Entry iconNameEntry; + [Glade.Widget] Gtk.Notebook notebook; + [Glade.Widget] Gtk.ScrolledWindow iconScrolledwindow; + [Glade.Widget] Gtk.Image previewIcon; + [Glade.Widget] Gtk.Image previewResource; + [Glade.Widget] Gtk.ComboBox iconSizeCombo; + [Glade.Widget] Gtk.Entry resourceNameEntry; + [Glade.Widget] Gtk.Button okButton; + [Glade.Widget] Gtk.Button buttonAdd; + [Glade.Widget] Gtk.Button buttonRemove; + [Glade.Widget ("SelectImageDialog")] Gtk.Dialog dialog; + + ThemedIconList iconList; + + Gtk.ListStore resourceListStore; + Gtk.Window parent; + + int thumbnailSize = 30; + Hashtable resources = new Hashtable (); // Stores resourceName -> thumbnail pixbuf + Gdk.Pixbuf missingThumbnail; + IResourceProvider resourceProvider; + string importedImageFile; + Stetic.IProject project; + + public SelectImageDialog (Gtk.Window parent, Stetic.IProject project) + { + this.parent = parent; + this.project = project; + Glade.XML xml = new Glade.XML (null, "stetic.glade", "SelectImageDialog", null); + xml.Autoconnect (this); + + // Stock icon list + + iconList = new ThemedIconList (); + iconList.SelectionChanged += new EventHandler (OnIconSelectionChanged); + iconScrolledwindow.AddWithViewport (iconList); + + // Icon Sizes + + foreach (IconSize s in Enum.GetValues (typeof(Gtk.IconSize))) { + if (s != IconSize.Invalid) + iconSizeCombo.AppendText (s.ToString ()); + } + iconSizeCombo.Active = 0; + + // Resource list + + resourceListStore = new Gtk.ListStore (typeof(Gdk.Pixbuf), typeof(string), typeof(string)); + resourceList.Model = resourceListStore; + + Gtk.TreeViewColumn col = new Gtk.TreeViewColumn (); + + Gtk.CellRendererPixbuf pr = new Gtk.CellRendererPixbuf (); + pr.Xpad = 3; + col.PackStart (pr, false); + col.AddAttribute (pr, "pixbuf", 0); + + Gtk.CellRendererText crt = new Gtk.CellRendererText (); + col.PackStart (crt, true); + col.AddAttribute (crt, "markup", 1); + + resourceList.AppendColumn (col); + resourceProvider = project.ResourceProvider; + if (resourceProvider == null) { + buttonAdd.Sensitive = false; + buttonRemove.Sensitive = false; + } + FillResources (); + resourceList.Selection.Changed += OnResourceSelectionChanged; + + if (project.FolderName != null) + fileChooser.SetCurrentFolder (project.ImagesRootPath); + + fileChooser.SelectionChanged += delegate (object s, EventArgs a) { + UpdateButtons (); + }; + + fileChooser.FileActivated += delegate (object s, EventArgs a) { + if (Icon != null) { + if (Validate ()) + dialog.Respond (Gtk.ResponseType.Ok); + } + }; + + okButton.Clicked += OnOkClicked; + + UpdateButtons (); + } + + public int Run () + { + dialog.ShowAll (); + dialog.TransientFor = parent; + return dialog.Run (); + } + + public void Dispose () + { + dialog.Destroy (); + } + + public ImageInfo Icon { + get { + if (notebook.Page == 0) { + if (iconNameEntry.Text.Length == 0) + return null; + return ImageInfo.FromTheme (iconNameEntry.Text, SelectedIconSize); + } else if (notebook.Page == 1) { + if (resourceNameEntry.Text.Length == 0) + return null; + return ImageInfo.FromResource (resourceNameEntry.Text); + } else { + if (importedImageFile != null) + return ImageInfo.FromFile (importedImageFile); + if (fileChooser.Filename == null || fileChooser.Filename.Length == 0 || !File.Exists (fileChooser.Filename)) + return null; + return ImageInfo.FromFile (fileChooser.Filename); + } + } + set { + if (value == null) + return; + if (value.Source == ImageSource.Theme) { + iconNameEntry.Text = value.Name; + SelectedIconSize = value.ThemeIconSize; + notebook.Page = 0; + } else if (value.Source == ImageSource.Resource) { + notebook.Page = 1; + resourceNameEntry.Text = value.Name; + } else { + fileChooser.SetFilename (value.Name); + notebook.Page = 2; + } + } + } + + Gtk.IconSize SelectedIconSize { + get { return (IconSize) iconSizeCombo.Active + 1; } + set { iconSizeCombo.Active = ((int) value) - 1; } + } + + void UpdateButtons () + { + okButton.Sensitive = Icon != null; + } + + protected void OnCurrentPageChanged (object s, Gtk.SwitchPageArgs args) + { + UpdateButtons (); + } + + void OnIconSelectionChanged (object s, EventArgs args) + { + if (iconList.Selection != null) { + iconNameEntry.Text = iconList.Selection; + } + } + + void UpdateIconSelection () + { + Gdk.Pixbuf icon = null; + if (iconNameEntry.Text.Length > 0) { + icon = WidgetUtils.LoadIcon (iconNameEntry.Text, SelectedIconSize); + } + if (icon == null) + icon = WidgetUtils.MissingIcon; + previewIcon.Pixbuf = icon; + } + + protected void OnIconSizeChanged (object ob, EventArgs args) + { + UpdateIconSelection (); + } + + protected void OnIconNameChanged (object ob, EventArgs args) + { + UpdateIconSelection (); + UpdateButtons (); + } + + void FillResources () + { + resourceListStore.Clear (); + resources.Clear (); + if (resourceProvider != null) { + foreach (ResourceInfo res in resourceProvider.GetResources ()) { + if (res.MimeType.StartsWith ("image/")) { + AppendResource (resourceProvider.GetResourceStream (res.Name), res.Name); + } + } + } + } + + void AppendResource (Stream stream, string name) + { + try { + Gdk.Pixbuf pix = new Gdk.Pixbuf (stream); + stream.Close (); + string txt = name + "\n<span foreground='darkgrey' size='x-small'>" + pix.Width + " x " + pix.Height + "</span>"; + pix = GetThumbnail (pix); + resourceListStore.AppendValues (pix, txt, name); + resources [name] = pix; + } catch { + // Doesn't look like a valid image. Just ignore it. + } + } + + Gdk.Pixbuf GetThumbnail (Gdk.Pixbuf pix) + { + if (pix.Width > pix.Height) { + if (pix.Width > thumbnailSize) { + float prop = (float) pix.Height / (float) pix.Width; + return pix.ScaleSimple (thumbnailSize, (int)(thumbnailSize * prop), Gdk.InterpType.Bilinear); + } + } else { + if (pix.Height > thumbnailSize) { + float prop = (float) pix.Width / (float) pix.Height; + return pix.ScaleSimple ((int)(thumbnailSize * prop), thumbnailSize, Gdk.InterpType.Bilinear); + } + } + return pix; + } + + void OnResourceSelectionChanged (object obj, EventArgs args) + { + Gtk.TreeIter iter; + Gtk.TreeModel model; + if (!resourceList.Selection.GetSelected (out model, out iter)) { + resourceNameEntry.Text = ""; + } else { + resourceNameEntry.Text = (string) resourceListStore.GetValue (iter, 2); + } + } + + protected void OnResourceNameChanged (object ob, EventArgs args) + { + Gdk.Pixbuf pix = (Gdk.Pixbuf) resources [resourceNameEntry.Text]; + if (pix != null) + previewResource.Pixbuf = pix; + else { + if (missingThumbnail == null) + missingThumbnail = WidgetUtils.MissingIcon; + previewResource.Pixbuf = missingThumbnail; + } + UpdateButtons (); + } + + protected void OnAddResource (object ob, EventArgs args) + { + FileChooserDialog dialog = + new FileChooserDialog ("Open File", null, FileChooserAction.Open, + Gtk.Stock.Cancel, Gtk.ResponseType.Cancel, + Gtk.Stock.Open, Gtk.ResponseType.Ok); + if (parent != null) + dialog.TransientFor = parent.Toplevel as Gtk.Window; + int response = dialog.Run (); + if (response == (int)Gtk.ResponseType.Ok) { + ResourceInfo rinfo = resourceProvider.AddResource (dialog.Filename); + AppendResource (resourceProvider.GetResourceStream (rinfo.Name), rinfo.Name); + resourceNameEntry.Text = rinfo.Name; + } + dialog.Destroy (); + } + + protected void OnRemoveResource (object ob, EventArgs args) + { + Gtk.TreeIter iter; + Gtk.TreeModel model; + if (resourceList.Selection.GetSelected (out model, out iter)) { + string res = (string) resourceListStore.GetValue (iter, 2); + Gtk.MessageDialog msg = new Gtk.MessageDialog (dialog, DialogFlags.Modal, MessageType.Question, ButtonsType.YesNo, "Are you sure you want to delete the resource '{0}'?", res); + if (parent != null) + msg.TransientFor = parent.Toplevel as Gtk.Window; + if (msg.Run () == (int) ResponseType.Yes) { + resourceProvider.RemoveResource (res); + resourceListStore.Remove (ref iter); + } + msg.Destroy (); + } + } + + bool Validate () + { + if (notebook.Page == 2) { + if (fileChooser.Filename == null || fileChooser.Filename.Length == 0 || !File.Exists (fileChooser.Filename)) + return true; + + importedImageFile = project.ImportFile (fileChooser.Filename); + if (importedImageFile != null) + importedImageFile = WidgetUtils.AbsoluteToRelativePath (project.ImagesRootPath, importedImageFile); + return importedImageFile != null; + } + return true; + } + + void OnOkClicked (object s, EventArgs args) + { + if (Validate ()) + dialog.Respond (Gtk.ResponseType.Ok); + } + } +} diff --git a/main/src/addins/MonoDevelop.GtkCore2/libstetic/editor/StockIconList.cs b/main/src/addins/MonoDevelop.GtkCore2/libstetic/editor/StockIconList.cs new file mode 100644 index 0000000000..b8c5676990 --- /dev/null +++ b/main/src/addins/MonoDevelop.GtkCore2/libstetic/editor/StockIconList.cs @@ -0,0 +1,27 @@ + +using System; +using System.Reflection; +using System.Collections; +using Gtk; + +namespace Stetic.Editor +{ + class StockIconList : IconList + { + public StockIconList () + { + foreach (PropertyInfo info in typeof (Gtk.Stock).GetProperties (BindingFlags.Public | BindingFlags.Static)) { + if (info.CanRead && info.PropertyType == typeof (string)) { + string name = (string) info.GetValue (null, null); + AddIcon (name, WidgetUtils.LoadIcon (name, Gtk.IconSize.Menu), name); + } + } + foreach (PropertyInfo info in GnomeStock.Properties) { + if (info.CanRead && info.PropertyType == typeof (string)) { + string name = (string) info.GetValue (null, null); + AddIcon (name, WidgetUtils.LoadIcon (name, Gtk.IconSize.Menu), name); + } + } + } + } +} diff --git a/main/src/addins/MonoDevelop.GtkCore2/libstetic/editor/StockIconSelectorItem.cs b/main/src/addins/MonoDevelop.GtkCore2/libstetic/editor/StockIconSelectorItem.cs new file mode 100644 index 0000000000..bf18e604f4 --- /dev/null +++ b/main/src/addins/MonoDevelop.GtkCore2/libstetic/editor/StockIconSelectorItem.cs @@ -0,0 +1,134 @@ + +using System; +using Mono.Unix; + +namespace Stetic.Editor +{ + public class StockIconSelectorItem: IconSelectorItem + { + public StockIconSelectorItem (IntPtr ptr): base (ptr) + { + } + + public StockIconSelectorItem (): base (Catalog.GetString ("Stock Icons")) + { + } + + protected override void CreateIcons () + { + foreach (string s in StockIconHelper.StockIcons) { + if (s != "-" && s != "|") { + Gdk.Pixbuf pix = WidgetUtils.LoadIcon (s, Gtk.IconSize.Menu); + if (pix != null) AddIcon (s, pix, s); + } + else + AddSeparator (s); + } + } + } + + class StockIconHelper + { + public static string[] StockIcons = { + // Commands + "gtk-new", + "gtk-open", + "gtk-save", + "gtk-save-as", + "gtk-revert-to-saved", + "gtk-quit", + "gtk-print", + "gtk-print-preview", + "gtk-properties", + "|", + "gtk-cut", + "gtk-copy", + "gtk-paste", + "gtk-delete", + "gtk-undelete", + "gtk-undo", + "gtk-redo", + "gtk-preferences", + "|", + "gtk-execute", + "gtk-stop", + "gtk-refresh", + "gtk-find", + "gtk-find-and-replace", + "|", + "gtk-spell-check", + "gtk-convert", + "gtk-help", + "|", + "gtk-add", + "gtk-remove", + "gtk-clear", + "-", + + // Formatting + "gtk-bold", + "gtk-italic", + "gtk-underline", + "gtk-strikethrough", + "gtk-select-color", + "gtk-select-font", + "|", + "gtk-indent", + "gtk-unindent", + "gtk-justify-center", + "gtk-justify-fill", + "gtk-justify-left", + "gtk-justify-right", + "|", + "gtk-sort-ascending", + "gtk-sort-descending", + "|", + "gtk-zoom-100", + "gtk-zoom-fit", + "gtk-zoom-in", + "gtk-zoom-out", + "-", + + + // Dialog + "gtk-yes", + "gtk-no", + "gtk-cancel", + "gtk-ok", + "gtk-apply", + "gtk-close", + "|", + "gtk-dialog-error", + "gtk-dialog-info", + "gtk-dialog-question", + "gtk-dialog-warning", + "-", + + // Navigation + "gtk-goto-bottom", + "gtk-goto-first", + "gtk-goto-last", + "gtk-goto-top", + "|", + "gtk-go-back", + "gtk-go-down", + "gtk-go-forward", + "gtk-go-up", + "|", + "gtk-home", + "gtk-jump-to", + "-", + + // Misc + "gtk-cdrom", + "gtk-floppy", + "gtk-harddisk", + "gtk-network", + "gtk-color-picker", + "gtk-dnd", + "gtk-dnd-multiple", + "gtk-missing-image", + "gtk-index" + }; + } +} diff --git a/main/src/addins/MonoDevelop.GtkCore2/libstetic/editor/StockItem.cs b/main/src/addins/MonoDevelop.GtkCore2/libstetic/editor/StockItem.cs new file mode 100644 index 0000000000..5d9ed308da --- /dev/null +++ b/main/src/addins/MonoDevelop.GtkCore2/libstetic/editor/StockItem.cs @@ -0,0 +1,200 @@ +using System; +using System.Collections.Generic; +using System.Reflection; + +namespace Stetic.Editor { + + internal static class GnomeStock { + + static string blank; + static List<PropertyInfo> props = new List<PropertyInfo> (); + + static GnomeStock () + { + try { + Assembly assm = Assembly.Load ("gnome-sharp, Version=2.8.0.0, Culture=neutral, PublicKeyToken=35e10195dab3c99f"); + if (assm == null) + return; + + Type type = assm.GetType ("Gnome.Stock"); + if (type == null) + return; + + foreach (PropertyInfo info in type.GetProperties (BindingFlags.Static | BindingFlags.Public)) { + if (info.Name == "Blank") + blank = (string) info.GetValue (null, null); + props.Add (info); + } + } catch { + } + } + + public static string Blank { + get { return blank == null ? Gtk.Stock.New : blank; } + } + + public static List<PropertyInfo> Properties { + get { return props; } + } + } + + public class StockItem: BaseImageCell + { + string label; + + protected override void Initialize () + { + base.Initialize (); + string name = (string)Value; + if (name != null) { + Stetic.ObjectWrapper w = Stetic.ObjectWrapper.Lookup (Instance); + Stetic.IProject project = w.Project; + Gdk.Pixbuf px = project.IconFactory.RenderIcon (project, name, ImageSize); + if (px != null) { + Image = px; + label = name; + return; + } + + Gtk.StockItem item = Gtk.Stock.Lookup (name); + label = item.Label != null && item.Label.Length > 0 ? item.Label : name; + label = label.Replace ("_", ""); + + Gtk.IconSet iset = Gtk.IconFactory.LookupDefault (name); + if (iset == null) + Image = WidgetUtils.MissingIcon; + else + Image = iset.RenderIcon (new Gtk.Style (), Gtk.TextDirection.Ltr, Gtk.StateType.Normal, Gtk.IconSize.Menu, null, ""); + } else { + Image = null; + label = ""; + } + } + + protected override string GetValueText () + { + return label; + } + + protected override IPropertyEditor CreateEditor (Gdk.Rectangle cell_area, Gtk.StateType state) + { + return new StockItemEditor (); + } + } + +/* [PropertyEditor ("StockId", "Changed")] + public class StockItemEditor : Image { + + public StockItemEditor () : base (true, false) { } + + public override object Value { + get { return StockId; } + set { StockId = (string) value; } + } + } + */ + + public class StockItemEditor: Gtk.HBox, IPropertyEditor + { + Gtk.Image image; + Gtk.Entry entry; + Gtk.Button button; + string icon; + IProject project; + Gtk.Frame imageFrame; + + public StockItemEditor() + { + Spacing = 3; + imageFrame = new Gtk.Frame (); + imageFrame.Shadow = Gtk.ShadowType.In; + imageFrame.BorderWidth = 2; + PackStart (imageFrame, false, false, 0); + + image = new Gtk.Image (GnomeStock.Blank, Gtk.IconSize.Button); + imageFrame.Add (image); + + entry = new Gtk.Entry (); + entry.Changed += OnTextChanged; + entry.HasFrame = false; + PackStart (entry, true, true, 0); + + button = new Gtk.Button (); + button.Add (new Gtk.Arrow (Gtk.ArrowType.Down, Gtk.ShadowType.Out)); + PackStart (button, false, false, 0); + button.Clicked += button_Clicked; + ShowAll (); + } + + void button_Clicked (object obj, EventArgs args) + { + IconSelectorMenu menu = new IconSelectorMenu (project); + menu.IconSelected += OnStockSelected; + menu.ShowAll (); + menu.Popup (null, null, new Gtk.MenuPositionFunc (OnDropMenuPosition), 3, Gtk.Global.CurrentEventTime); + } + + void OnDropMenuPosition (Gtk.Menu menu, out int x, out int y, out bool pushIn) + { + button.ParentWindow.GetOrigin (out x, out y); + x += button.Allocation.X; + y += button.Allocation.Y + button.Allocation.Height; + pushIn = true; + } + + void OnStockSelected (object s, IconEventArgs args) + { + Value = args.IconId; + } + + void OnTextChanged (object s, EventArgs a) + { + if (entry.Text.Length == 0) + Value = null; + else + Value = entry.Text; + } + + // Called once to initialize the editor. + public void Initialize (PropertyDescriptor prop) + { + if (prop.PropertyType != typeof(string)) + throw new ApplicationException ("StockItem editor does not support editing values of type " + prop.PropertyType); + } + + // Called when the object to be edited changes. + public void AttachObject (object obj) + { + Stetic.ObjectWrapper w = Stetic.ObjectWrapper.Lookup (obj); + project = w.Project; + } + + // Gets/Sets the value of the editor. If the editor supports + // several value types, it is the responsibility of the editor + // to return values with the expected type. + public object Value { + get { return icon; } + set { + icon = (string) value; + if (icon != null && icon.Length > 0) { + entry.Text = icon; + Gdk.Pixbuf px = project.IconFactory.RenderIcon (project, icon, Gtk.IconSize.Menu); + if (px == null) + px = WidgetUtils.LoadIcon (icon, Gtk.IconSize.Menu); + image.Pixbuf = px; + imageFrame.Show (); + } else { + imageFrame.Hide (); + entry.Text = ""; + } + + if (ValueChanged != null) + ValueChanged (this, EventArgs.Empty); + } + } + + // To be fired when the edited value changes. + public event EventHandler ValueChanged; + } + +} diff --git a/main/src/addins/MonoDevelop.GtkCore2/libstetic/editor/String.cs b/main/src/addins/MonoDevelop.GtkCore2/libstetic/editor/String.cs new file mode 100644 index 0000000000..dafbb3922a --- /dev/null +++ b/main/src/addins/MonoDevelop.GtkCore2/libstetic/editor/String.cs @@ -0,0 +1,44 @@ +using System; + +namespace Stetic.Editor { + + [PropertyEditor ("Text", "Changed")] + public class String : Translatable { + + Gtk.Entry entry; + + public override void Initialize (PropertyDescriptor prop) + { + base.Initialize (prop); + + entry = new Gtk.Entry (); + entry.HasFrame = false; + entry.Show (); + entry.Changed += EntryChanged; + Add (entry); + } + + protected override void CheckType (PropertyDescriptor prop) + { + if (prop.PropertyType != typeof(string)) + throw new ApplicationException ("String editor does not support editing values of type " + prop.PropertyType); + } + + public override object Value { + get { + return entry.Text; + } + set { + if (value == null) + entry.Text = ""; + else + entry.Text = (string) value; + } + } + + void EntryChanged (object obj, EventArgs args) + { + OnValueChanged (); + } + } +} diff --git a/main/src/addins/MonoDevelop.GtkCore2/libstetic/editor/StringArray.cs b/main/src/addins/MonoDevelop.GtkCore2/libstetic/editor/StringArray.cs new file mode 100644 index 0000000000..ca8d5bd064 --- /dev/null +++ b/main/src/addins/MonoDevelop.GtkCore2/libstetic/editor/StringArray.cs @@ -0,0 +1,99 @@ + +using System; +using Gtk; +using Gdk; +using System.Text; + +namespace Stetic.Editor +{ + public class StringArray: PropertyEditorCell + { + protected override string GetValueText () + { + string[] val = (string[]) Value; + return val == null ? string.Empty : "(Collection)"; + } + + protected override IPropertyEditor CreateEditor (Gdk.Rectangle cell_area, Gtk.StateType state) + { + return new StringArrayEditor (); + } + } + + public class StringArrayEditor: Gtk.HBox, IPropertyEditor + { + Gtk.Entry label; + Gtk.Button button; + PropertyDescriptor prop; + object obj; + string[] strings; + + public StringArrayEditor() + { + label = new Gtk.Entry (); + label.IsEditable = false; + PackStart (label, true, true, 0); + button = new Button ("..."); + PackStart (button, false, false, 3); + button.Clicked += ButtonClicked; + ShowAll (); + } + + void ButtonClicked (object s, EventArgs a) + { + using (TextEditorDialog dlg = new TextEditorDialog ()) { + dlg.Text = strings != null ? string.Join ("\n", strings) : ""; + dlg.SetTranslatable (prop.Translatable); + dlg.TransientFor = this.Toplevel as Gtk.Window; + if (prop.Translatable) { + dlg.Translated = prop.IsTranslated (obj); + dlg.ContextHint = prop.TranslationContext (obj); + dlg.Comment = prop.TranslationComment (obj); + } + if (dlg.Run () == (int) ResponseType.Ok) { + if (prop.Translatable) { + prop.SetTranslated (obj, dlg.Translated); + if (dlg.Translated) { + prop.SetTranslationComment (obj, dlg.Comment); + prop.SetTranslationContext (obj, dlg.ContextHint); + } + } + if (dlg.Text.Length == 0) + strings = null; + else + strings = dlg.Text.Split ('\n'); + UpdateLabel (); + if (ValueChanged != null) + ValueChanged (this, EventArgs.Empty); + } + } + } + + public void Initialize (PropertyDescriptor descriptor) + { + if (descriptor.PropertyType != typeof(string[])) + throw new InvalidOperationException ("StringArrayEditor can only edit string[] properties"); + prop = descriptor; + } + + public void AttachObject (object obj) + { + this.obj = obj; + } + + public object Value { + get { return strings; } + set { + strings = (string[]) value; + UpdateLabel (); + } + } + + void UpdateLabel () + { + label.Text = strings != null ? "(Collection)" : System.String.Empty; + } + + public event EventHandler ValueChanged; + } +} diff --git a/main/src/addins/MonoDevelop.GtkCore2/libstetic/editor/Text.cs b/main/src/addins/MonoDevelop.GtkCore2/libstetic/editor/Text.cs new file mode 100644 index 0000000000..667ccb2537 --- /dev/null +++ b/main/src/addins/MonoDevelop.GtkCore2/libstetic/editor/Text.cs @@ -0,0 +1,14 @@ +using System; + +namespace Stetic.Editor +{ + public class Text : TextEditor + { + public Text () + { + // Don't allow editing the text in the editor + // since there is no room for multiline edit in the grid. + entry.Sensitive = false; + } + } +} diff --git a/main/src/addins/MonoDevelop.GtkCore2/libstetic/editor/TextBox.cs b/main/src/addins/MonoDevelop.GtkCore2/libstetic/editor/TextBox.cs new file mode 100644 index 0000000000..6dd84a878c --- /dev/null +++ b/main/src/addins/MonoDevelop.GtkCore2/libstetic/editor/TextBox.cs @@ -0,0 +1,51 @@ +using System; + +namespace Stetic.Editor { + + public class TextBox : Gtk.ScrolledWindow { + + Gtk.TextView textview; + + public TextBox (int nlines) + { + ShadowType = Gtk.ShadowType.In; + SetPolicy (Gtk.PolicyType.Never, Gtk.PolicyType.Automatic); + + textview = new Gtk.TextView (); + textview.WrapMode = Gtk.WrapMode.Word; + textview.Show (); + Add (textview); + + Pango.Context ctx = textview.PangoContext; + Pango.FontMetrics metrics = ctx.GetMetrics (textview.Style.FontDescription, + ctx.Language); + int lineHeight = (metrics.Ascent + metrics.Descent) / (int)Pango.Scale.PangoScale; + SetSizeRequest (-1, lineHeight * nlines); + + textview.Buffer.Changed += Buffer_Changed; + } + + public Gtk.TextView TextView { + get { + return textview; + } + } + + public string Text { + get { + return textview.Buffer.Text; + } + set { + textview.Buffer.Text = value; + } + } + + void Buffer_Changed (object obj, EventArgs args) + { + if (Changed != null) + Changed (this, EventArgs.Empty); + } + + public event EventHandler Changed; + } +} diff --git a/main/src/addins/MonoDevelop.GtkCore2/libstetic/editor/TextEditor.cs b/main/src/addins/MonoDevelop.GtkCore2/libstetic/editor/TextEditor.cs new file mode 100644 index 0000000000..d2c135a2a6 --- /dev/null +++ b/main/src/addins/MonoDevelop.GtkCore2/libstetic/editor/TextEditor.cs @@ -0,0 +1,83 @@ + +using System; +using Gtk; +using Gdk; + +namespace Stetic.Editor +{ + public class TextEditor: Gtk.HBox, IPropertyEditor + { + protected Gtk.Entry entry; + protected Gtk.Button button; + PropertyDescriptor prop; + object obj; + + public TextEditor() + { + Spacing = 3; + entry = new Entry (); + entry.HasFrame = false; + PackStart (entry, true, true, 0); + button = new Button ("..."); + button.Relief = ReliefStyle.Half; + PackStart (button, false, false, 0); + button.Clicked += ButtonClicked; + entry.Activated += TextChanged; + ShowAll (); + } + + void ButtonClicked (object s, EventArgs a) + { + using (TextEditorDialog dlg = new TextEditorDialog ()) { + dlg.Text = entry.Text; + dlg.SetTranslatable (prop.Translatable); + dlg.TransientFor = this.Toplevel as Gtk.Window; + if (prop.Translatable) { + dlg.Translated = prop.IsTranslated (obj); + dlg.ContextHint = prop.TranslationContext (obj); + dlg.Comment = prop.TranslationComment (obj); + } + if (dlg.Run () == (int) ResponseType.Ok) { + if (prop.Translatable) { + prop.SetTranslated (obj, dlg.Translated); + if (dlg.Translated) { + prop.SetTranslationComment (obj, dlg.Comment); + prop.SetTranslationContext (obj, dlg.ContextHint); + } + } + entry.Text = dlg.Text; + TextChanged (null, null); + } + } + } + + void TextChanged (object s, EventArgs a) + { + if (ValueChanged != null) + ValueChanged (this, a); + } + + public void Initialize (PropertyDescriptor descriptor) + { + if (descriptor.PropertyType != typeof(string)) + throw new InvalidOperationException ("TextEditor only can edit string properties"); + prop = descriptor; + } + + public void AttachObject (object obj) + { + this.obj = obj; + } + + // Gets/Sets the value of the editor. If the editor supports + // several value types, it is the responsibility of the editor + // to return values with the expected type. + public object Value { + get { return entry.Text; } + set { entry.Text = value != null ? (string) value : ""; } + } + + // To be fired when the edited value changes. + public event EventHandler ValueChanged; + } +} diff --git a/main/src/addins/MonoDevelop.GtkCore2/libstetic/editor/TextEditorDialog.cs b/main/src/addins/MonoDevelop.GtkCore2/libstetic/editor/TextEditorDialog.cs new file mode 100644 index 0000000000..b7df291eab --- /dev/null +++ b/main/src/addins/MonoDevelop.GtkCore2/libstetic/editor/TextEditorDialog.cs @@ -0,0 +1,70 @@ + +using System; + +namespace Stetic.Editor +{ + public class TextEditorDialog: IDisposable + { + [Glade.Widget] Gtk.TextView textview; + [Glade.Widget] Gtk.CheckButton checkTranslatable; + [Glade.Widget] Gtk.Entry entryContext; + [Glade.Widget] Gtk.Entry entryComment; + [Glade.Widget] Gtk.Table translationTable; + [Glade.Widget ("TextEditorDialog")] Gtk.Dialog dialog; + + public TextEditorDialog () + { + Glade.XML xml = new Glade.XML (null, "stetic.glade", "TextEditorDialog", null); + xml.Autoconnect (this); + entryContext.Sensitive = entryComment.Sensitive = false; + } + + public string Text { + get { return textview.Buffer.Text; } + set { textview.Buffer.Text = value; } + } + + public string ContextHint { + get { return entryContext.Text; } + set { entryContext.Text = value != null ? value : ""; } + } + + public string Comment { + get { return entryComment.Text; } + set { entryComment.Text = value != null ? value : ""; } + } + + public bool Translated { + get { return checkTranslatable.Active; } + set { checkTranslatable.Active = value; } + } + + public Gtk.Window TransientFor { + set { dialog.TransientFor = value; } + } + + public void SetTranslatable (bool translatable) + { + if (!translatable) { + translationTable.Visible = false; + checkTranslatable.Visible = false; + } + } + + protected void OnTranslatableToggled (object s, EventArgs a) + { + entryContext.Sensitive = checkTranslatable.Active; + entryComment.Sensitive = checkTranslatable.Active; + } + + public int Run () + { + return dialog.Run (); + } + + public void Dispose () + { + dialog.Destroy (); + } + } +} diff --git a/main/src/addins/MonoDevelop.GtkCore2/libstetic/editor/ThemedIcon.cs b/main/src/addins/MonoDevelop.GtkCore2/libstetic/editor/ThemedIcon.cs new file mode 100644 index 0000000000..3da369f94c --- /dev/null +++ b/main/src/addins/MonoDevelop.GtkCore2/libstetic/editor/ThemedIcon.cs @@ -0,0 +1,162 @@ +using Gtk; +using System; + +namespace Stetic.Editor { + + [PropertyEditor ("Value", "Changed")] + public class ThemedIcon : Gtk.HBox, IPropertyEditor { + Gtk.Image image; + Gtk.Entry entry; + Gtk.Button button; + + public ThemedIcon () : base (false, 6) + { + image = new Gtk.Image (GnomeStock.Blank, Gtk.IconSize.Button); + PackStart (image, false, false, 0); + + entry = new Gtk.Entry (); + PackStart (entry, true, true, 0); + entry.Changed += entry_Changed; + + button = new Gtk.Button ("..."); + PackStart (button, false, false, 0); + button.Clicked += button_Clicked; + } + + public void Initialize (PropertyDescriptor prop) + { + if (prop.PropertyType != typeof(string)) + throw new ApplicationException ("ThemedIcon editor does not support editing values of type " + prop.PropertyType); + } + + public void AttachObject (object ob) + { + } + + public event EventHandler ValueChanged; + + bool syncing; + + void entry_Changed (object obj, EventArgs args) + { + if (!syncing) + Value = entry.Text; + } + + void button_Clicked (object obj, EventArgs args) + { + Gtk.Window parent = (Gtk.Window)GetAncestor (Gtk.Window.GType); + Value = ThemedIconBrowser.Browse (parent, (string) Value); + } + + string icon; + public object Value { + get { + return icon; + } + set { + string val = (string) value; + if (icon == val) + return; + + icon = val; + Gdk.Pixbuf pix = WidgetUtils.LoadIcon (icon, Gtk.IconSize.Menu); + if (pix != null) { + image.Pixbuf = pix; + } else { + image.Stock = GnomeStock.Blank; + } + + syncing = true; + entry.Text = icon; + syncing = false; + + if (ValueChanged != null) + ValueChanged (this, EventArgs.Empty); + } + } + } + + public class ThemedIconBrowser : Gtk.Dialog { + + public ThemedIconBrowser (Gtk.Window parent) : + base ("Select a Themed Icon", parent, Gtk.DialogFlags.Modal, + Gtk.Stock.Cancel, Gtk.ResponseType.Cancel, + Gtk.Stock.Ok, Gtk.ResponseType.Ok) + { + HasSeparator = false; + BorderWidth = 12; + VBox.Spacing = 18; + VBox.BorderWidth = 0; + + DefaultResponse = Gtk.ResponseType.Ok; + + Gtk.HBox hbox = new Gtk.HBox (false, 12); + VBox.PackStart (hbox, false, false, 0); + + entry = new Gtk.Entry (); + entry.Activated += DoFind; + hbox.PackStart (entry); + + Gtk.Button button = new Gtk.Button (Gtk.Stock.Find); + button.Clicked += DoFind; + hbox.PackStart (button, false, false, 0); + + ScrolledWindow scwin = new Gtk.ScrolledWindow (); + scwin.SizeRequested += ScrolledWindowSizeRequested; + VBox.PackStart (scwin, true, true, 0); + scwin.SetPolicy (Gtk.PolicyType.Never, Gtk.PolicyType.Automatic); + scwin.ShadowType = Gtk.ShadowType.In; + + list = new ThemedIconList (); + scwin.Add (list); + list.SelectionChanged += ListSelectionChanged; + list.Activated += ListActivated; + SetResponseSensitive (Gtk.ResponseType.Ok, false); + + VBox.ShowAll (); + } + + public static string Browse (Gtk.Window parent, string selection) + { + ThemedIconBrowser browser = new ThemedIconBrowser (parent); + browser.list.Selection = selection; + int response = browser.Run (); + if (response == (int)Gtk.ResponseType.Ok) + selection = browser.list.Selection; + browser.Destroy (); + return selection; + } + + Gtk.Entry entry; + ThemedIconList list; + + void ScrolledWindowSizeRequested (object obj, SizeRequestedArgs args) + { + Gtk.Requisition req = list.SizeRequest (); + if (req.Width <= 0) + return; + + Gtk.ScrolledWindow scwin = ((Gtk.ScrolledWindow)obj); + scwin.SizeRequested -= ScrolledWindowSizeRequested; + scwin.SetSizeRequest (req.Width, req.Width * 2 / 3); + ActionArea.BorderWidth = 0; // has to happen post-realize + } + + void ListSelectionChanged (object obj, EventArgs args) + { + SetResponseSensitive (Gtk.ResponseType.Ok, list.Selection != null); + } + + void ListActivated (object obj, EventArgs args) + { + Respond (Gtk.ResponseType.Ok); + } + + void DoFind (object obj, EventArgs args) + { + list.Find (entry.Text); + } + + } +} diff --git a/main/src/addins/MonoDevelop.GtkCore2/libstetic/editor/ThemedIconList.cs b/main/src/addins/MonoDevelop.GtkCore2/libstetic/editor/ThemedIconList.cs new file mode 100644 index 0000000000..d3b16aadb9 --- /dev/null +++ b/main/src/addins/MonoDevelop.GtkCore2/libstetic/editor/ThemedIconList.cs @@ -0,0 +1,1018 @@ + +using System; +using System.Collections; +using Gtk; + +namespace Stetic.Editor +{ + class ThemedIconList : IconList + { + public ThemedIconList () + { + Gtk.IconTheme theme = Gtk.IconTheme.Default; + foreach (string icon in ThemeIconNames) + AddIcon (icon, GetPixbuf (theme, icon), icon); + } + + Gdk.Pixbuf GetPixbuf (Gtk.IconTheme theme, string name) + { + try { + return theme.LoadIcon (name, 16, 0); + } catch { + return RenderIcon (name, Gtk.IconSize.Menu, null); + } + } + + public static string[] ThemeIconNames = new string[] { + // Gtk 2.6 stock icons + "gtk-about", + "gtk-add", + "gtk-apply", + "gtk-bold", + "gtk-cancel", + "gtk-cdrom", + "gtk-clear", + "gtk-close", + "gtk-color-picker", + "gtk-connect", + "gtk-convert", + "gtk-copy", + "gtk-cut", + "gtk-delete", + "gtk-dialog-authentication", + "gtk-dialog-error", + "gtk-dialog-info", + "gtk-dialog-question", + "gtk-dialog-warning", + "gtk-directory", + "gtk-disconnect", + "gtk-dnd", + "gtk-dnd-multiple", + "gtk-edit", + "gtk-execute", + "gtk-file", + "gtk-find", + "gtk-find-and-replace", + "gtk-floppy", + "gtk-go-back", + "gtk-go-down", + "gtk-go-forward", + "gtk-go-up", + "gtk-goto-bottom", + "gtk-goto-first", + "gtk-goto-last", + "gtk-goto-top", + "gtk-harddisk", + "gtk-help", + "gtk-home", + "gtk-indent", + "gtk-index", + "gtk-italic", + "gtk-jump-to", + "gtk-justify-center", + "gtk-justify-fill", + "gtk-justify-left", + "gtk-justify-right", + "gtk-media-forward", + "gtk-media-next", + "gtk-media-pause", + "gtk-media-play", + "gtk-media-previous", + "gtk-media-record", + "gtk-media-rewind", + "gtk-media-stop", + "gtk-missing-image", + "gtk-network", + "gtk-new", + "gtk-no", + "gtk-ok", + "gtk-open", + "gtk-paste", + "gtk-preferences", + "gtk-print", + "gtk-print-preview", + "gtk-properties", + "gtk-quit", + "gtk-redo", + "gtk-refresh", + "gtk-remove", + "gtk-revert-to-saved", + "gtk-save", + "gtk-save-as", + "gtk-select-color", + "gtk-select-font", + "gtk-sort-ascending", + "gtk-sort-descending", + "gtk-spell-check", + "gtk-stop", + "gtk-strikethrough", + "gtk-undelete", + "gtk-underline", + "gtk-undo", + "gtk-unindent", + "gtk-yes", + "gtk-zoom-100", + "gtk-zoom-fit", + "gtk-zoom-in", + "gtk-zoom-out", + + // Themable stock icons + "stock_about", + "stock_active", + "stock_add-bookmark", + "stock_add-decimal-place", + "stock_addressbook", + "stock_advanced-filter", + "stock_alarm", + "stock_alignment", + "stock_alignment-bottom", + "stock_alignment-centered", + "stock_alignment-centered-vertically", + "stock_alignment-left", + "stock_alignment-right", + "stock_alignment-top", + "stock_allow-effects", + "stock_anchor", + "stock_animation", + "stock_appointment-reminder", + "stock_appointment-reminder-excl", + "stock_arrowstyle", + "stock_attach", + "stock_auto-contour", + "stock_autocompletion", + "stock_autofilter", + "stock_autoformat", + "stock_autopilot", + "stock_autopilot-24", + "stock_autospellcheck", + "stock_autotext", + "stock_bell", + "stock_bluetooth", + "stock_book_blue", + "stock_book_green", + "stock_book_open", + "stock_book_red", + "stock_book_yellow", + "stock_bookmark", + "stock_bottom", + "stock_briefcase", + "stock_brightness", + "stock_bring-backward", + "stock_bring-forward", + "stock_bucketfill", + "stock_calc-accept", + "stock_calc-cancel", + "stock_calendar", + "stock_calendar-and-tasks", + "stock_calendar-view-day", + "stock_calendar-view-list", + "stock_calendar-view-month", + "stock_calendar-view-week", + "stock_calendar-view-work-week", + "stock_calendar-view-year", + "stock_cell-align-bottom", + "stock_cell-align-center", + "stock_cell-align-top", + "stock_cell-phone", + "stock_certificate", + "stock_channel", + "stock_channel-blue", + "stock_channel-green", + "stock_channel-red", + "stock_chart", + "stock_chart-autoformat", + "stock_chart-data-in-columns", + "stock_chart-data-in-rows", + "stock_chart-edit-type", + "stock_chart-reorganize", + "stock_chart-scale-text", + "stock_chart-toggle-axes", + "stock_chart-toggle-axes-title", + "stock_chart-toggle-hgrid", + "stock_chart-toggle-legend", + "stock_chart-toggle-title", + "stock_chart-toggle-vgrid", + "stock_check-filled", + "stock_choose-themes", + "stock_close", + "stock_color", + "stock_compile", + "stock_connect", + "stock_connect-to-url", + "stock_contact", + "stock_contact-list", + "stock_contrast", + "stock_copy", + "stock_create-with-attributes", + "stock_creditcard", + "stock_crop", + "stock_cut", + "stock_data-delete-link", + "stock_data-delete-query", + "stock_data-delete-record", + "stock_data-delete-sql-query", + "stock_data-delete-table", + "stock_data-edit-link", + "stock_data-edit-query", + "stock_data-edit-sql-query", + "stock_data-edit-table", + "stock_data-explorer", + "stock_data-first", + "stock_data-last", + "stock_data-link", + "stock_data-linked-table", + "stock_data-links", + "stock_data-new-link", + "stock_data-new-query", + "stock_data-new-record", + "stock_data-new-sql-query", + "stock_data-new-table", + "stock_data-next", + "stock_data-previous", + "stock_data-queries", + "stock_data-query", + "stock_data-query-rename", + "stock_data-save", + "stock_data-sources", + "stock_data-sources-delete", + "stock_data-sources-hand", + "stock_data-sources-modified", + "stock_data-sources-new", + "stock_data-table", + "stock_data-tables", + "stock_data-undo", + "stock_datapilot", + "stock_decrease-font", + "stock_default-folder", + "stock_delete", + "stock_delete-autofilter", + "stock_delete-bookmark", + "stock_delete-column", + "stock_delete-decimal-place", + "stock_delete-row", + "stock_dialog-error", + "stock_dialog-info", + "stock_dialog-question", + "stock_dialog-warning", + "stock_directcursor", + "stock_directory-server", + "stock_disconnect", + "stock_display-grid", + "stock_display-guides", + "stock_distort", + "stock_down", + "stock_down-with-subpoints", + "stock_drag-mode", + "stock_draw-arc", + "stock_draw-callouts", + "stock_draw-circle", + "stock_draw-circle-arc", + "stock_draw-circle-pie", + "stock_draw-circle-pie-unfilled", + "stock_draw-circle-segment", + "stock_draw-circle-segment-unfilled", + "stock_draw-circle-unfilled", + "stock_draw-cone", + "stock_draw-connector", + "stock_draw-connector-ends-with-arrow", + "stock_draw-connector-ends-with-circle", + "stock_draw-connector-starts-with-arrow", + "stock_draw-connector-starts-with-circle", + "stock_draw-connector-with-arrows", + "stock_draw-connector-with-circles", + "stock_draw-cube", + "stock_draw-curve", + "stock_draw-curve-filled", + "stock_draw-curved-connector", + "stock_draw-curved-connector-ends-with-arrow", + "stock_draw-curved-connector-ends-with-circle", + "stock_draw-curved-connector-starts-with-arrow", + "stock_draw-curved-connector-starts-with-circle", + "stock_draw-curved-connector-with-arrows", + "stock_draw-curved-connector-with-circles", + "stock_draw-cylinder", + "stock_draw-dimension-line", + "stock_draw-ellipse", + "stock_draw-ellipse-pie", + "stock_draw-ellipse-pie-unfilled", + "stock_draw-ellipse-segment", + "stock_draw-ellipse-segment-unfilled", + "stock_draw-ellipse-unfilled", + "stock_draw-freeform-line", + "stock_draw-freeform-line-filled", + "stock_draw-half-sphere", + "stock_draw-line", + "stock_draw-line-45", + "stock_draw-line-connector", + "stock_draw-line-connector-ends-with-arrow", + "stock_draw-line-connector-ends-with-circle", + "stock_draw-line-connector-starts-with-arrow", + "stock_draw-line-connector-starts-with-circle", + "stock_draw-line-connector-with-arrows", + "stock_draw-line-connector-with-circles", + "stock_draw-line-ends-with-arrow", + "stock_draw-line-starts-with-arrow", + "stock_draw-line-with-arrow-circle", + "stock_draw-line-with-arrow-square", + "stock_draw-line-with-arrows", + "stock_draw-line-with-circle-arrow", + "stock_draw-line-with-square-arrow", + "stock_draw-polygon", + "stock_draw-polygon-45", + "stock_draw-polygon-45-filled", + "stock_draw-polygon-filled", + "stock_draw-pyramid", + "stock_draw-rectangle", + "stock_draw-rectangle-unfilled", + "stock_draw-rounded-rectangle", + "stock_draw-rounded-rectangle-unfilled", + "stock_draw-rounded-square", + "stock_draw-rounded-square-unfilled", + "stock_draw-selection", + "stock_draw-shell", + "stock_draw-sphere", + "stock_draw-square", + "stock_draw-square-unfilled", + "stock_draw-straight-connector", + "stock_draw-straight-connector-ends-with-arrow", + "stock_draw-straight-connector-ends-with-circle", + "stock_draw-straight-connector-starts-with-arrow", + "stock_draw-straight-connector-starts-with-circle", + "stock_draw-straight-connector-with-arrows", + "stock_draw-straight-connector-with-circles", + "stock_draw-text", + "stock_draw-text-animation", + "stock_draw-text-frame", + "stock_draw-torus", + "stock_draw-vertical-callouts", + "stock_draw-vertical-text", + "stock_draw-vertical-text-frame", + "stock_edit", + "stock_edit-bookmark", + "stock_edit-contour", + "stock_edit-headers-and-footers", + "stock_edit-points", + "stock_effects", + "stock_effects-more-options", + "stock_effects-object", + "stock_effects-object-colorize", + "stock_effects-object-hide", + "stock_effects-play-in-full", + "stock_effects-preview", + "stock_effects-sound", + "stock_effects-text", + "stock_enter-group", + "stock_equals", + "stock_error-next", + "stock_error-next-16", + "stock_error-previous", + "stock_error-previous-16", + "stock_euro", + "stock_example", + "stock_exchange-columns", + "stock_exchange-connector", + "stock_exchange-rows", + "stock_exit", + "stock_exit-group", + "stock_export", + "stock_extended-help", + "stock_file-properties", + "stock_file-with-objects", + "stock_filter-data-by-criteria", + "stock_filter-navigator", + "stock_filters", + "stock_filters-aging", + "stock_filters-charcoal", + "stock_filters-invert", + "stock_filters-pixelize", + "stock_filters-pop-art", + "stock_filters-posterize", + "stock_filters-relief", + "stock_filters-remove-noise", + "stock_filters-sharpen", + "stock_filters-smooth", + "stock_filters-solarize", + "stock_first", + "stock_first-page", + "stock_flip", + "stock_flip-horizontally", + "stock_flip-vertically", + "stock_folder", + "stock_folder-copy", + "stock_folder-move", + "stock_folder-properties", + "stock_font", + "stock_font-formatting-toggle", + "stock_font-size", + "stock_fontwork", + "stock_fontwork-2dshadow", + "stock_fontwork-3dshadow", + "stock_fontwork-adaptation-off", + "stock_fontwork-adaptation-rotate", + "stock_fontwork-adaptation-slant-h", + "stock_fontwork-adaptation-slant-v", + "stock_fontwork-adaptation-straight", + "stock_fontwork-align-fill", + "stock_fontwork-noshadow", + "stock_fontwork-preview-spline", + "stock_fontwork-reverse-text-flow", + "stock_fontwork-shadow-angle", + "stock_fontwork-shadow-length", + "stock_fontwork-shadow-x-offset", + "stock_fontwork-shadow-y-offset", + "stock_fontwork-spline-distance", + "stock_fontwork-spline-indent", + "stock_fontwork-text-border", + "stock_form-activation-order", + "stock_form-add-field", + "stock_form-automatic-control-focus", + "stock_form-autopilots", + "stock_form-button", + "stock_form-checkbox", + "stock_form-combobox", + "stock_form-control-properties", + "stock_form-currency-field", + "stock_form-date-field", + "stock_form-design-mode", + "stock_form-file-selection", + "stock_form-formatted-field", + "stock_form-frame", + "stock_form-image-button", + "stock_form-image-control", + "stock_form-label", + "stock_form-letter-dialog", + "stock_form-line-horizontal", + "stock_form-line-vertical", + "stock_form-listbox", + "stock_form-navigator", + "stock_form-numerical-field", + "stock_form-open-in-design-mode", + "stock_form-pattern-field", + "stock_form-progressbar", + "stock_form-properties", + "stock_form-radio", + "stock_form-table-control", + "stock_form-text-box", + "stock_form-time-field", + "stock_format-character", + "stock_format-default", + "stock_format-numbering-bullets", + "stock_format-object", + "stock_format-page", + "stock_format-paragraph", + "stock_format-percent", + "stock_format-scientific", + "stock_formula-cursor", + "stock_frame", + "stock_fullscreen", + "stock_function-autopilot", + "stock_gamma", + "stock_glue", + "stock_gluepoint-down", + "stock_gluepoint-horizontal-center", + "stock_gluepoint-horizontal-left", + "stock_gluepoint-horizontal-right", + "stock_gluepoint-left", + "stock_gluepoint-relative", + "stock_gluepoint-right", + "stock_gluepoint-up", + "stock_gluepoint-vertical-bottom", + "stock_gluepoint-vertical-center", + "stock_gluepoint-vertical-top", + "stock_goal-seek", + "stock_gradient", + "stock_graphic-styles", + "stock_graphics-align-bottom", + "stock_graphics-align-center", + "stock_graphics-align-centered", + "stock_graphics-align-left", + "stock_graphics-align-right", + "stock_graphics-align-top", + "stock_group", + "stock_group-cells", + "stock_groupwise-connector", + "stock_guides", + "stock_hand-signed", + "stock_handles-big", + "stock_handles-simple", + "stock_headphones", + "stock_help", + "stock_help-add-bookmark", + "stock_help-agent", + "stock_help-book", + "stock_help-book-open", + "stock_help-chat", + "stock_help-document", + "stock_help-pane-off", + "stock_help-pane-on", + "stock_home", + "stock_hyperlink", + "stock_hyperlink-internet-search", + "stock_hyperlink-target", + "stock_hyperlink-toolbar", + "stock_id", + "stock_imagemap-editor", + "stock_inbox", + "stock_increase-font", + "stock_init", + "stock_insert-applet", + "stock_insert-caption", + "stock_insert-cells", + "stock_insert-cells-down", + "stock_insert-cells-right", + "stock_insert-chart", + "stock_insert-columns", + "stock_insert-cross-reference", + "stock_insert-fields", + "stock_insert-fields-author", + "stock_insert-fields-subject", + "stock_insert-fields-title", + "stock_insert-file", + "stock_insert-floating-frame", + "stock_insert-footer", + "stock_insert-form", + "stock_insert-gluepoint", + "stock_insert-header", + "stock_insert-math-object", + "stock_insert-names-define", + "stock_insert-note", + "stock_insert-ole-object", + "stock_insert-plugin", + "stock_insert-rows", + "stock_insert-rule", + "stock_insert-single-column-text-frame", + "stock_insert-slide", + "stock_insert-sound-plugin", + "stock_insert-table", + "stock_insert-text-frame", + "stock_insert-url", + "stock_insert-video-plugin", + "stock_insert_endnote", + "stock_insert_footnote", + "stock_insert_graphic", + "stock_insert_image", + "stock_insert_index_marker", + "stock_insert_section", + "stock_insert_special_character", + "stock_interaction", + "stock_internet", + "stock_keyring", + "stock_landline-phone", + "stock_last", + "stock_last-page", + "stock_left", + "stock_left-with-subpoints", + "stock_line-spacing-1", + "stock_line-spacing-1.5", + "stock_line-spacing-2", + "stock_line_in", + "stock_linepen", + "stock_link", + "stock_list-insert-unnumbered", + "stock_list_bullet", + "stock_list_enum", + "stock_list_enum-off", + "stock_list_enum-restart", + "stock_live-mode", + "stock_lock", + "stock_lock-broken", + "stock_lock-ok", + "stock_lock-open", + "stock_macro-check-brackets", + "stock_macro-controls", + "stock_macro-insert", + "stock_macro-insert-breakpoint", + "stock_macro-jump-back", + "stock_macro-objects", + "stock_macro-organizer", + "stock_macro-stop-after-command", + "stock_macro-stop-after-procedure", + "stock_macro-stop-watching", + "stock_macro-watch-variable", + "stock_mail", + "stock_mail-accounts", + "stock_mail-compose", + "stock_mail-copy", + "stock_mail-druid", + "stock_mail-druid-account", + "stock_mail-filters-apply", + "stock_mail-flag-for-followup", + "stock_mail-flag-for-followup-done", + "stock_mail-forward", + "stock_mail-handling", + "stock_mail-hide-deleted", + "stock_mail-hide-read", + "stock_mail-hide-selected", + "stock_mail-import", + "stock_mail-merge", + "stock_mail-move", + "stock_mail-open", + "stock_mail-open-multiple", + "stock_mail-priority-high", + "stock_mail-receive", + "stock_mail-replied", + "stock_mail-reply", + "stock_mail-reply-to-all", + "stock_mail-send", + "stock_mail-send-receive", + "stock_mail-unread", + "stock_mail-unread-multiple", + "stock_mark", + "stock_media-fwd", + "stock_media-next", + "stock_media-pause", + "stock_media-play", + "stock_media-prev", + "stock_media-rec", + "stock_media-rew", + "stock_media-shuffle", + "stock_media-stop", + "stock_message-display", + "stock_mic", + "stock_midi", + "stock_modify-layout", + "stock_music-library", + "stock_my-documents", + "stock_navigate-next", + "stock_navigate-prev", + "stock_navigator", + "stock_navigator-all-or-sel-toggle", + "stock_navigator-database-ranges", + "stock_navigator-drag-mode", + "stock_navigator-edit-entry", + "stock_navigator-foonote-body-toggle", + "stock_navigator-footer-body-toggle", + "stock_navigator-header-body-toggle", + "stock_navigator-headings", + "stock_navigator-indexes", + "stock_navigator-insert-as-copy", + "stock_navigator-insert-as-link", + "stock_navigator-insert-index", + "stock_navigator-insert-linked", + "stock_navigator-levels", + "stock_navigator-list-box-toggle", + "stock_navigator-master-toggle", + "stock_navigator-next-object", + "stock_navigator-open-toolbar", + "stock_navigator-previous-object", + "stock_navigator-range-names", + "stock_navigator-references", + "stock_navigator-reminder", + "stock_navigator-scenarios", + "stock_navigator-sections", + "stock_navigator-shift-down", + "stock_navigator-shift-left", + "stock_navigator-shift-right", + "stock_navigator-shift-up", + "stock_navigator-table-formula", + "stock_navigator-text", + "stock_navigator-update-entry", + "stock_navigator-wrong-table-formula", + "stock_network-printer", + "stock_new", + "stock_new", + "stock_new-24h-appointment", + "stock_new-appointment", + "stock_new-bcard", + "stock_new-dir", + "stock_new-drawing", + "stock_new-formula", + "stock_new-html", + "stock_new-labels", + "stock_new-master-document", + "stock_new-meeting", + "stock_new-presentation", + "stock_new-spreadsheet", + "stock_new-tab", + "stock_new-template", + "stock_new-text", + "stock_new-window", + "stock_news", + "stock_next", + "stock_next-page", + "stock_node-add", + "stock_node-close-path", + "stock_node-convert", + "stock_node-corner", + "stock_node-corner-to-smooth", + "stock_node-curve-split", + "stock_node-delete", + "stock_node-mark-for-deletion", + "stock_node-move", + "stock_node-smooth-to-symmetrical", + "stock_nonprinting-chars", + "stock_not", + "stock_not-spam", + "stock_notebook", + "stock_notes", + "stock_object-behind", + "stock_object-infront", + "stock_online-layout", + "stock_open", + "stock_open-read-only", + "stock_openoffice", + "stock_opensave", + "stock_outbox", + "stock_page-number", + "stock_page-total-number", + "stock_paragraph-spacing-decrease", + "stock_paragraph-spacing-increase", + "stock_paste", + "stock_people", + "stock_person", + "stock_pin", + "stock_placeholder-graphic", + "stock_placeholder-line-contour", + "stock_placeholder-picture", + "stock_placeholder-text", + "stock_playlist", + "stock_position-size", + "stock_post-message", + "stock_presentation-box", + "stock_presentation-styles", + "stock_preview-four-pages", + "stock_preview-two-pages", + "stock_previous", + "stock_previous-page", + "stock_print", + "stock_print-driver", + "stock_print-duplex", + "stock_print-duplex-no-tumble", + "stock_print-duplex-tumble", + "stock_print-layout", + "stock_print-non-duplex", + "stock_print-options", + "stock_print-preview", + "stock_print-preview-print", + "stock_print-resolution", + "stock_print-setup", + "stock_printers", + "stock_properties", + "stock_proxy", + "stock_quickmask", + "stock_record-macro", + "stock_record-number", + "stock_redo", + "stock_refresh", + "stock_reload", + "stock_repeat", + "stock_reverse-order", + "stock_right", + "stock_right-with-subpoints", + "stock_rotate", + "stock_rotate-3d", + "stock_rotation-mode", + "stock_run-macro", + "stock_samples", + "stock_save", + "stock_save-as", + "stock_save-pdf", + "stock_save-template", + "stock_save_as", + "stock_score-high", + "stock_score-higher", + "stock_score-highest", + "stock_score-low", + "stock_score-lower", + "stock_score-lowest", + "stock_score-normal", + "stock_scores", + "stock_script", + "stock_script", + "stock_scripts", + "stock_search", + "stock_search-and-replace", + "stock_select-all", + "stock_select-cell", + "stock_select-column", + "stock_select-row", + "stock_select-table", + "stock_send-fax", + "stock_sent-mail", + "stock_shadow", + "stock_show-all", + "stock_show-draw-functions", + "stock_show-form-dialog", + "stock_show-hidden-controls", + "stock_shuffle", + "stock_signature", + "stock_signature-bad", + "stock_signature-ok", + "stock_slide-design", + "stock_slide-duplicate", + "stock_slide-expand", + "stock_slide-reherse-timings", + "stock_slide-show", + "stock_slide-showhide", + "stock_smart-playlist", + "stock_smiley-1", + "stock_smiley-2", + "stock_smiley-3", + "stock_smiley-4", + "stock_smiley-5", + "stock_smiley-6", + "stock_smiley-7", + "stock_smiley-8", + "stock_smiley-9", + "stock_smiley-10", + "stock_smiley-11", + "stock_smiley-12", + "stock_smiley-13", + "stock_smiley-14", + "stock_smiley-15", + "stock_smiley-16", + "stock_smiley-17", + "stock_smiley-18", + "stock_smiley-19", + "stock_smiley-20", + "stock_smiley-21", + "stock_smiley-22", + "stock_smiley-23", + "stock_smiley-24", + "stock_smiley-25", + "stock_smiley-26", + "stock_snap-grid", + "stock_snap-guides", + "stock_snap-margins", + "stock_snap-object", + "stock_snap-object-points", + "stock_sort-ascending", + "stock_sort-column-ascending", + "stock_sort-criteria", + "stock_sort-descending", + "stock_sort-row-ascending", + "stock_sort-table-column-ascending", + "stock_sort-table-row-ascending", + "stock_sound", + "stock_spam", + "stock_spellcheck", + "stock_standard-filter", + "stock_stop", + "stock_styles", + "stock_styles-character-styles", + "stock_styles-fill-format-mode", + "stock_styles-frame-styles", + "stock_styles-new-style-from-selection", + "stock_styles-numbering-styles", + "stock_styles-page-styles", + "stock_styles-paragraph-styles", + "stock_styles-update-style", + "stock_subscript", + "stock_sum", + "stock_summary", + "stock_superscript", + "stock_symbol-selection", + "stock_table-align-bottom", + "stock_table-align-center", + "stock_table-align-top", + "stock_table-borders", + "stock_table-combine", + "stock_table-fit-height", + "stock_table-fit-width", + "stock_table-fixed", + "stock_table-fixed-proportional", + "stock_table-line-color", + "stock_table-line-style", + "stock_table-optimize", + "stock_table-same-height", + "stock_table-same-width", + "stock_table-split", + "stock_table-variable", + "stock_table_borders", + "stock_table_fill", + "stock_task", + "stock_task-assigned", + "stock_task-assigned-to", + "stock_task-recurring", + "stock_test-mode", + "stock_text-direction-ltr", + "stock_text-direction-ttb", + "stock_text-double-click-to-edit", + "stock_text-monospaced", + "stock_text-outline", + "stock_text-quickedit", + "stock_text-select-text-only", + "stock_text-shadow", + "stock_text-spacing", + "stock_text-strikethrough", + "stock_text_bold", + "stock_text_center", + "stock_text_color_background", + "stock_text_color_foreground", + "stock_text_color_hilight", + "stock_text_indent", + "stock_text_italic", + "stock_text_justify", + "stock_text_left", + "stock_text_right", + "stock_text_underlined", + "stock_text_underlined-double", + "stock_text_unindent", + "stock_thesaurus", + "stock_3d-3d-attributes-only", + "stock_3d-all-attributes", + "stock_3d-color-picker", + "stock_3d-colors", + "stock_3d-custom-color", + "stock_3d-effects", + "stock_3d-favourites", + "stock_3d-geometry", + "stock_3d-light", + "stock_3d-light-off", + "stock_3d-light-on", + "stock_3d-material", + "stock_3d-normals-double-sided", + "stock_3d-normals-double-sided-closed-body", + "stock_3d-normals-flat", + "stock_3d-normals-flip-illumination", + "stock_3d-normals-object-specific", + "stock_3d-normals-spherical", + "stock_3d-perspective", + "stock_3d-shading", + "stock_3d-texture", + "stock_3d-texture-and-shading", + "stock_3d-texture-object-specific", + "stock_3d-texture-only", + "stock_3d-texture-parallel", + "stock_3d-texture-spherical", + "stock_3dsound", + "stock_timer", + "stock_timer_stopped", + "stock_timezone", + "stock_to-3d", + "stock_to-3d-rotation-object", + "stock_to-background", + "stock_to-bottom", + "stock_to-curve", + "stock_to-foreground", + "stock_to-polygon", + "stock_to-top", + "stock_todo", + "stock_toggle-graphics", + "stock_toggle-info", + "stock_toggle-preview", + "stock_toilet-paper", + "stock_tools-hyphenation", + "stock_tools-macro", + "stock_top", + "stock_transform-circle-perspective", + "stock_transform-circle-slant", + "stock_transparency", + "stock_trash_full", + "stock_undelete", + "stock_undo", + "stock_undo-history", + "stock_ungroup", + "stock_ungroup-cells", + "stock_unknown", + "stock_unlink", + "stock_up", + "stock_up-one-dir", + "stock_up-with-subpoints", + "stock_update-data", + "stock_update-fields", + "stock_video-conferencing", + "stock_view-details", + "stock_view-field-shadings", + "stock_view-fields", + "stock_view-function-selection", + "stock_view-html-source", + "stock_volume", + "stock_wallpaper-center", + "stock_wallpaper-fill", + "stock_wallpaper-scale", + "stock_wallpaper-tile", + "stock_weather-cloudy", + "stock_weather-few-clouds", + "stock_weather-fog", + "stock_weather-night-clear", + "stock_weather-night-few-clouds", + "stock_weather-showers", + "stock_weather-snow", + "stock_weather-storm", + "stock_weather-sunny", + "stock_web-calendar", + "stock_web-support", + "stock_wrap-around", + "stock_wrap-behind", + "stock_wrap-contour", + "stock_wrap-interrupt", + "stock_wrap-left", + "stock_wrap-optimal", + "stock_wrap-right", + "stock_zoom", + "stock_zoom-1", + "stock_zoom-in", + "stock_zoom-next", + "stock_zoom-object", + "stock_zoom-optimal", + "stock_zoom-out", + "stock_zoom-page", + "stock_zoom-page-width", + "stock_zoom-previous", + "stock_zoom-shift", + }; + } +} + + diff --git a/main/src/addins/MonoDevelop.GtkCore2/libstetic/editor/TimeSpanEditor.cs b/main/src/addins/MonoDevelop.GtkCore2/libstetic/editor/TimeSpanEditor.cs new file mode 100644 index 0000000000..fb40194da3 --- /dev/null +++ b/main/src/addins/MonoDevelop.GtkCore2/libstetic/editor/TimeSpanEditor.cs @@ -0,0 +1,67 @@ + +using System; +using Gtk; +using Gdk; +using System.Text; + +namespace Stetic.Editor +{ + public class TimeSpanEditorCell: PropertyEditorCell + { + protected override string GetValueText () + { + return ((TimeSpan)Value).ToString (); + } + + protected override IPropertyEditor CreateEditor (Gdk.Rectangle cell_area, Gtk.StateType state) + { + return new TimeSpanEditor (); + } + } + + public class TimeSpanEditor: Gtk.HBox, IPropertyEditor + { + Gtk.Entry entry; + TimeSpan time; + + public TimeSpanEditor() + { + entry = new Gtk.Entry (); + entry.Changed += OnChanged; + PackStart (entry, true, true, 0); + ShowAll (); + } + + public void Initialize (PropertyDescriptor descriptor) + { + } + + public void AttachObject (object ob) + { + } + + public object Value { + get { return time; } + set { + time = (TimeSpan) value; + entry.Changed -= OnChanged; + entry.Text = time.ToString (); + entry.Changed += OnChanged; + } + } + + void OnChanged (object o, EventArgs a) + { + string s = entry.Text; + + try { + time = TimeSpan.Parse (s); + if (ValueChanged != null) + ValueChanged (this, a); + } catch { + } + } + + public event EventHandler ValueChanged; + } +} diff --git a/main/src/addins/MonoDevelop.GtkCore2/libstetic/editor/Translatable.cs b/main/src/addins/MonoDevelop.GtkCore2/libstetic/editor/Translatable.cs new file mode 100644 index 0000000000..c04192620f --- /dev/null +++ b/main/src/addins/MonoDevelop.GtkCore2/libstetic/editor/Translatable.cs @@ -0,0 +1,233 @@ +using System; + +namespace Stetic.Editor { + + public abstract class Translatable : Gtk.VBox, IPropertyEditor { + + PropertyDescriptor prop; + object obj; + + Gtk.Box mainHBox, contextBox, commentBox; + Gtk.Button button; + Gdk.Pixbuf globe, globe_not; + Gtk.Image image; + Gtk.Menu menu; + Gtk.CheckMenuItem markItem; + Gtk.MenuItem addContextItem, remContextItem, addCommentItem, remCommentItem; + Gtk.Entry contextEntry; + TextBox commentText; + bool initializing; + + public virtual void Initialize (PropertyDescriptor prop) + { + CheckType (prop); + + this.prop = prop; + + mainHBox = new Gtk.HBox (false, 6); + PackStart (mainHBox, false, false, 0); + + if (!prop.Translatable) + return; + + button = new Gtk.Button (); + try { + globe = Gdk.Pixbuf.LoadFromResource ("globe.png"); + globe_not = Gdk.Pixbuf.LoadFromResource ("globe-not.png"); + } catch (Exception e) { + Console.WriteLine ("Error while loading pixbuf: " + e); + } + image = new Gtk.Image (globe); + button.Add (image); + button.ButtonPressEvent += ButtonPressed; + mainHBox.PackEnd (button, false, false, 0); + mainHBox.ShowAll (); + + menu = new Gtk.Menu (); + + markItem = new Gtk.CheckMenuItem ("Mark for Translation"); + markItem.Toggled += ToggleMark; + markItem.Show (); + menu.Add (markItem); + + addContextItem = new Gtk.MenuItem ("Add Translation Context Hint"); + addContextItem.Activated += AddContext; + menu.Add (addContextItem); + remContextItem = new Gtk.MenuItem ("Remove Translation Context Hint"); + remContextItem.Activated += RemoveContext; + menu.Add (remContextItem); + + addCommentItem = new Gtk.MenuItem ("Add Comment for Translators"); + addCommentItem.Activated += AddComment; + menu.Add (addCommentItem); + remCommentItem = new Gtk.MenuItem ("Remove Comment for Translators"); + remCommentItem.Activated += RemoveComment; + menu.Add (remCommentItem); + + contextBox = new Gtk.HBox (false, 6); + Gtk.Label contextLabel = new Gtk.Label ("Translation context"); + contextLabel.Xalign = 0.0f; + contextBox.PackStart (contextLabel, false, false, 0); + contextEntry = new Gtk.Entry (); + contextEntry.WidthChars = 8; + contextBox.PackStart (contextEntry, true, true, 0); + contextBox.ShowAll (); + contextEntry.Changed += ContextChanged; + + commentBox = new Gtk.VBox (false, 3); + Gtk.Label commentLabel = new Gtk.Label ("Comment for Translators:"); + commentLabel.Xalign = 0.0f; + commentBox.PackStart (commentLabel, false, false, 0); + commentText = new TextBox (3); + commentBox.PackStart (commentText, false, false, 0); + commentBox.ShowAll (); + commentText.Changed += CommentChanged; + } + + protected virtual void CheckType (PropertyDescriptor prop) + { + } + + public virtual void AttachObject (object ob) + { + this.obj = ob; + + if (!prop.Translatable) + return; + + initializing = true; + + if (contextBox.Parent != null) + Remove (contextBox); + if (commentBox.Parent != null) + Remove (commentBox); + + markItem.Active = prop.IsTranslated (obj); + image.Pixbuf = markItem.Active ? globe : globe_not; + + if (prop.IsTranslated (obj)) { + if (prop.TranslationContext (obj) != null) { + remContextItem.Show (); + PackStart (contextBox, false, false, 0); + contextEntry.Text = prop.TranslationContext (obj); + } else + addContextItem.Show (); + } else { + addContextItem.Show (); + addContextItem.Sensitive = false; + } + + if (prop.IsTranslated (obj)) { + if (prop.TranslationComment (obj) != null) { + remCommentItem.Show (); + PackEnd (commentBox, false, false, 0); + commentText.Text = prop.TranslationComment (obj); + } else + addCommentItem.Show (); + } else { + addCommentItem.Show (); + addCommentItem.Sensitive = false; + } + + initializing = false; + } + + + public abstract object Value { get; set; } + + public event EventHandler ValueChanged; + + protected virtual void OnValueChanged () + { + if (ValueChanged != null) + ValueChanged (this, EventArgs.Empty); + } + + protected override void OnAdded (Gtk.Widget child) + { + mainHBox.PackStart (child, true, true, 0); + } + + void MenuPosition (Gtk.Menu menu, out int x, out int y, out bool push_in) + { + button.GdkWindow.GetOrigin (out x, out y); + Gdk.Rectangle alloc = button.Allocation; + x += alloc.X; + y += alloc.Y + alloc.Height; + push_in = true; + } + + [GLib.ConnectBefore] + void ButtonPressed (object o, Gtk.ButtonPressEventArgs args) + { + menu.Popup (null, null, MenuPosition, 1, args.Event.Time); + args.RetVal = true; + } + + void ToggleMark (object o, EventArgs args) + { + if (initializing) return; + if (!markItem.Active) { + // Make sure we're showing the "Add" menu items + // rather than the "Remove" ones + if (prop.TranslationContext (obj) != null) + RemoveContext (remContextItem, EventArgs.Empty); + if (prop.TranslationComment (obj) != null) + RemoveComment (remCommentItem, EventArgs.Empty); + } + + prop.SetTranslated (obj, markItem.Active); + image.Pixbuf = markItem.Active ? globe : globe_not; + addContextItem.Sensitive = markItem.Active; + addCommentItem.Sensitive = markItem.Active; + } + + void AddContext (object o, EventArgs args) + { + prop.SetTranslationContext (obj, contextEntry.Text); + PackStart (contextBox, false, false, 0); + + addContextItem.Hide (); + remContextItem.Show (); + } + + void RemoveContext (object o, EventArgs args) + { + prop.SetTranslationContext (obj, null); + Remove (contextBox); + + remContextItem.Hide (); + addContextItem.Show (); + } + + void ContextChanged (object o, EventArgs args) + { + if (initializing) return; + prop.SetTranslationContext (obj, contextEntry.Text); + } + + void AddComment (object o, EventArgs args) + { + prop.SetTranslationComment (obj, commentText.Text); + PackEnd (commentBox, false, false, 0); + + addCommentItem.Hide (); + remCommentItem.Show (); + } + + void RemoveComment (object o, EventArgs args) + { + prop.SetTranslationComment (obj, null); + Remove (commentBox); + + remCommentItem.Hide (); + addCommentItem.Show (); + } + + void CommentChanged (object o, EventArgs args) + { + if (initializing) return; + prop.SetTranslationComment (obj, commentText.Text); + } + } +} diff --git a/main/src/addins/MonoDevelop.GtkCore2/libstetic/editor/TreeViewCellContainer.cs b/main/src/addins/MonoDevelop.GtkCore2/libstetic/editor/TreeViewCellContainer.cs new file mode 100644 index 0000000000..c027a02986 --- /dev/null +++ b/main/src/addins/MonoDevelop.GtkCore2/libstetic/editor/TreeViewCellContainer.cs @@ -0,0 +1,82 @@ +// +// TreeViewCellContainer.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.Editor +{ + class TreeViewCellContainer: Entry + { + EventBox box; + + public TreeViewCellContainer (Gtk.Widget child) + { + box = new EventBox (); + box.ButtonPressEvent += new ButtonPressEventHandler (OnClickBox); + box.ModifyBg (StateType.Normal, Style.White); + box.Add (child); + child.Show (); + Show (); + } + + [GLib.ConnectBefore] + void OnClickBox (object s, ButtonPressEventArgs args) + { + // Avoid forwarding the button press event to the + // tree, since it would hide the cell editor. + args.RetVal = true; + } + + protected override void OnParentSet (Gtk.Widget parent) + { + base.OnParentSet (parent); + + if (Parent != null) { + if (ParentWindow != null) + box.ParentWindow = ParentWindow; + box.Parent = Parent; + box.Show (); + } + else + box.Unparent (); + } + + protected override void OnShown () + { + // Do nothing. + } + + protected override void OnSizeAllocated (Gdk.Rectangle allocation) + { + base.OnSizeAllocated (allocation); + box.SizeRequest (); + box.Allocation = allocation; + } + } +} diff --git a/main/src/addins/MonoDevelop.GtkCore2/libstetic/editor/WidgetSelector.cs b/main/src/addins/MonoDevelop.GtkCore2/libstetic/editor/WidgetSelector.cs new file mode 100644 index 0000000000..68991a32e6 --- /dev/null +++ b/main/src/addins/MonoDevelop.GtkCore2/libstetic/editor/WidgetSelector.cs @@ -0,0 +1,98 @@ + +using System; +using System.Collections; +using Gtk; +using Gdk; + +namespace Stetic.Editor +{ + public class WidgetSelector: ComboBox, IPropertyEditor + { + Gtk.Widget obj; + ListStore store; + Hashtable widgets = new Hashtable (); + + public void Initialize (PropertyDescriptor descriptor) + { + store = new ListStore (typeof(Pixbuf), typeof(string)); + Model = store; + store.SetSortColumnId (1, SortType.Ascending); + CellRendererPixbuf crp = new CellRendererPixbuf (); + CellRendererText crt = new CellRendererText (); + PackStart (crp, false); + PackStart (crt, true); + SetAttributes (crp, "pixbuf", 0); + SetAttributes (crt, "text", 1); + } + + public void AttachObject (object obj) + { + this.obj = obj as Gtk.Widget; + FillWidgets (); + } + + void FillWidgets () + { + store.Clear (); + widgets.Clear (); + + Stetic.Wrapper.Widget widget = Stetic.Wrapper.Widget.Lookup (obj); + if (widget == null) + return; + + while (!widget.IsTopLevel) + widget = widget.ParentWrapper; + + store.AppendValues (null, "(None)"); + FillWidgets (widget, 0); + } + + void FillWidgets (Stetic.Wrapper.Widget widget, int level) + { + if (!widget.Unselectable) { + TreeIter iter = store.AppendValues (widget.ClassDescriptor.Icon, widget.Wrapped.Name); + widgets [widget.Wrapped.Name] = iter; + } + Gtk.Container cont = widget.Wrapped as Gtk.Container; + if (cont != null && widget.ClassDescriptor.AllowChildren) { + foreach (Gtk.Widget child in cont.AllChildren) { + Stetic.Wrapper.Widget cwidget = Stetic.Wrapper.Widget.Lookup (child); + if (cwidget != null) + FillWidgets (cwidget, level+1); + } + } + } + + + public object Value { + get { + if (Active <= 0) + return null; + else { + TreeIter iter; + if (!GetActiveIter (out iter)) + return null; + return (string) store.GetValue (iter, 1); + } + } + set { + if (value == null) + Active = 0; + else if (widgets.Contains ((string) value)) { + TreeIter iter = (TreeIter) widgets [value]; + SetActiveIter (iter); + } + } + } + + protected override void OnChanged () + { + base.OnChanged (); + if (ValueChanged != null) + ValueChanged (this, EventArgs.Empty); + } + + // To be fired when the edited value changes. + public event EventHandler ValueChanged; + } +} diff --git a/main/src/addins/MonoDevelop.GtkCore2/libstetic/libstetic.csproj b/main/src/addins/MonoDevelop.GtkCore2/libstetic/libstetic.csproj new file mode 100644 index 0000000000..96142a024c --- /dev/null +++ b/main/src/addins/MonoDevelop.GtkCore2/libstetic/libstetic.csproj @@ -0,0 +1,471 @@ +<?xml version="1.0" encoding="utf-8"?> +<Project DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003" ToolsVersion="3.5"> + <PropertyGroup> + <Configuration Condition=" '$(Configuration)' == '' ">Debug</Configuration> + <Platform Condition=" '$(Platform)' == '' ">AnyCPU</Platform> + <ProductVersion>9.0.21022</ProductVersion> + <SchemaVersion>2.0</SchemaVersion> + <ProjectGuid>{90CBA7FD-CB46-4711-97BB-2420DC01F016}</ProjectGuid> + <OutputType>Library</OutputType> + <AssemblyName>libstetic2</AssemblyName> + <TargetFrameworkVersion>v3.5</TargetFrameworkVersion> + <RootNamespace>Stetic</RootNamespace> + </PropertyGroup> + <PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|AnyCPU' "> + <DebugSymbols>true</DebugSymbols> + <DebugType>full</DebugType> + <Optimize>false</Optimize> + <OutputPath>..\..\..\..\build\AddIns\MonoDevelop.GtkCore2</OutputPath> + <DefineConstants>DEBUG</DefineConstants> + <ErrorReport>prompt</ErrorReport> + <WarningLevel>4</WarningLevel> + <Execution> + <Execution clr-version="Net_2_0" /> + </Execution> + </PropertyGroup> + <PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|AnyCPU' "> + <DebugType>none</DebugType> + <Optimize>false</Optimize> + <OutputPath>bin\Release</OutputPath> + <ErrorReport>prompt</ErrorReport> + <WarningLevel>4</WarningLevel> + <Execution> + <Execution clr-version="Net_2_0" /> + </Execution> + </PropertyGroup> + <ItemGroup> + <Reference Include="Mono.Posix" /> + <Reference Include="System" /> + <Reference Include="System.Xml" /> + <Reference Include="glib-sharp, Version=2.12.0.0, Culture=neutral, PublicKeyToken=35e10195dab3c99f"> + <SpecificVersion>False</SpecificVersion> + </Reference> + <Reference Include="pango-sharp, Version=2.12.0.0, Culture=neutral, PublicKeyToken=35e10195dab3c99f"> + <SpecificVersion>False</SpecificVersion> + </Reference> + <Reference Include="atk-sharp, Version=2.12.0.0, Culture=neutral, PublicKeyToken=35e10195dab3c99f"> + <SpecificVersion>False</SpecificVersion> + </Reference> + <Reference Include="gdk-sharp, Version=2.12.0.0, Culture=neutral, PublicKeyToken=35e10195dab3c99f"> + <SpecificVersion>False</SpecificVersion> + </Reference> + <Reference Include="gtk-sharp, Version=2.12.0.0, Culture=neutral, PublicKeyToken=35e10195dab3c99f"> + <SpecificVersion>False</SpecificVersion> + </Reference> + <Reference Include="glade-sharp, Version=2.12.0.0, Culture=neutral, PublicKeyToken=35e10195dab3c99f"> + <SpecificVersion>False</SpecificVersion> + </Reference> + <Reference Include="Mono.Cairo" /> + <Reference Include="System.Core" /> + </ItemGroup> + <ItemGroup> + <Compile Include="ClassDescriptor.cs" /> + <Compile Include="Clipboard.cs" /> + <Compile Include="CommandDescriptor.cs" /> + <Compile Include="CustomWidget.cs" /> + <Compile Include="DND.cs" /> + <Compile Include="editor\Accelerator.cs" /> + <Compile Include="editor\ActionGroupEditor.cs" /> + <Compile Include="editor\ActionItem.cs" /> + <Compile Include="editor\ActionMenu.cs" /> + <Compile Include="editor\ActionMenuBar.cs" /> + <Compile Include="editor\ActionMenuItem.cs" /> + <Compile Include="editor\ActionToolbar.cs" /> + <Compile Include="editor\ActionToolItem.cs" /> + <Compile Include="editor\Boolean.cs" /> + <Compile Include="editor\CellRendererComboBox.cs" /> + <Compile Include="editor\Char.cs" /> + <Compile Include="editor\Color.cs" /> + <Compile Include="editor\DateTimeEditor.cs" /> + <Compile Include="editor\EditIconDialog.cs" /> + <Compile Include="editor\EditIconFactoryDialog.cs" /> + <Compile Include="editor\Enumeration.cs" /> + <Compile Include="editor\Flags.cs" /> + <Compile Include="editor\FlagsSelectorDialog.cs" /> + <Compile Include="editor\FloatRange.cs" /> + <Compile Include="editor\GroupPicker.cs" /> + <Compile Include="editor\IconList.cs" /> + <Compile Include="editor\IconSelectorItem.cs" /> + <Compile Include="editor\IconSelectorMenu.cs" /> + <Compile Include="editor\IconSelectorMenuItem.cs" /> + <Compile Include="editor\Identifier.cs" /> + <Compile Include="editor\Image.cs" /> + <Compile Include="editor\ImageFile.cs" /> + <Compile Include="editor\ImageSelector.cs" /> + <Compile Include="editor\IntRange.cs" /> + <Compile Include="editor\NonContainerWarningDialog.cs" /> + <Compile Include="editor\OptIntRange.cs" /> + <Compile Include="editor\ProjectIconList.cs" /> + <Compile Include="editor\ProjectIconSelectorItem.cs" /> + <Compile Include="editor\ResponseId.cs" /> + <Compile Include="editor\SelectIconDialog.cs" /> + <Compile Include="editor\SelectImageDialog.cs" /> + <Compile Include="editor\StockIconList.cs" /> + <Compile Include="editor\StockIconSelectorItem.cs" /> + <Compile Include="editor\StockItem.cs" /> + <Compile Include="editor\String.cs" /> + <Compile Include="editor\StringArray.cs" /> + <Compile Include="editor\Text.cs" /> + <Compile Include="editor\TextBox.cs" /> + <Compile Include="editor\TextEditor.cs" /> + <Compile Include="editor\TextEditorDialog.cs" /> + <Compile Include="editor\ThemedIcon.cs" /> + <Compile Include="editor\ThemedIconList.cs" /> + <Compile Include="editor\TimeSpanEditor.cs" /> + <Compile Include="editor\Translatable.cs" /> + <Compile Include="editor\TreeViewCellContainer.cs" /> + <Compile Include="editor\WidgetSelector.cs" /> + <Compile Include="EnumDescriptor.cs" /> + <Compile Include="ErrorWidget.cs" /> + <Compile Include="GeneratorContext.cs" /> + <Compile Include="GladeException.cs" /> + <Compile Include="GladeUtils.cs" /> + <Compile Include="IDesignArea.cs" /> + <Compile Include="IEditableObject.cs" /> + <Compile Include="ImageInfo.cs" /> + <Compile Include="IProject.cs" /> + <Compile Include="IPropertyEditor.cs" /> + <Compile Include="IRadioGroupManager.cs" /> + <Compile Include="IResourceProvider.cs" /> + <Compile Include="ItemDescriptor.cs" /> + <Compile Include="ItemGroup.cs" /> + <Compile Include="ItemGroupCollection.cs" /> + <Compile Include="NoGuiDispatchAttribute.cs" /> + <Compile Include="ObjectReader.cs" /> + <Compile Include="ObjectWrapper.cs" /> + <Compile Include="ObjectWrapperEventHandler.cs" /> + <Compile Include="ObjectWriter.cs" /> + <Compile Include="ParamSpec.cs" /> + <Compile Include="Placeholder.cs" /> + <Compile Include="ProjectIconFactory.cs" /> + <Compile Include="PropertyDescriptor.cs" /> + <Compile Include="PropertyEditorAttribute.cs" /> + <Compile Include="PropertyEditorCell.cs" /> + <Compile Include="RadioGroupManager.cs" /> + <Compile Include="Registry.cs" /> + <Compile Include="Set.cs" /> + <Compile Include="SignalDescriptor.cs" /> + <Compile Include="TranslatableAttribute.cs" /> + <Compile Include="TypedClassDescriptor.cs" /> + <Compile Include="TypedPropertyDescriptor.cs" /> + <Compile Include="TypedSignalDescriptor.cs" /> + <Compile Include="undo\ActionDiffAdaptor.cs" /> + <Compile Include="undo\DiffGenerator.cs" /> + <Compile Include="undo\IDiffAdaptor.cs" /> + <Compile Include="undo\UndoManager.cs" /> + <Compile Include="undo\XmlDiffAdaptor.cs" /> + <Compile Include="WidgetLibrary.cs" /> + <Compile Include="WidgetUtils.cs" /> + <Compile Include="wrapper\Action.cs" /> + <Compile Include="wrapper\ActionGroup.cs" /> + <Compile Include="wrapper\ActionToolbarWrapper.cs" /> + <Compile Include="wrapper\ActionTree.cs" /> + <Compile Include="wrapper\Bin.cs" /> + <Compile Include="wrapper\Box.cs" /> + <Compile Include="wrapper\Button.cs" /> + <Compile Include="wrapper\ButtonBox.cs" /> + <Compile Include="wrapper\CheckButton.cs" /> + <Compile Include="wrapper\ColorButton.cs" /> + <Compile Include="wrapper\ComboBox.cs" /> + <Compile Include="wrapper\ComboBoxEntry.cs" /> + <Compile Include="wrapper\Container.cs" /> + <Compile Include="wrapper\Custom.cs" /> + <Compile Include="wrapper\Dialog.cs" /> + <Compile Include="wrapper\Entry.cs" /> + <Compile Include="wrapper\Expander.cs" /> + <Compile Include="wrapper\Fixed.cs" /> + <Compile Include="wrapper\FontButton.cs" /> + <Compile Include="wrapper\FontSelectionDialog.cs" /> + <Compile Include="wrapper\Frame.cs" /> + <Compile Include="wrapper\HScale.cs" /> + <Compile Include="wrapper\HScrollbar.cs" /> + <Compile Include="wrapper\IconView.cs" /> + <Compile Include="wrapper\Image.cs" /> + <Compile Include="wrapper\ImageMenuItem.cs" /> + <Compile Include="wrapper\Label.cs" /> + <Compile Include="wrapper\MenuBar.cs" /> + <Compile Include="wrapper\MenuItem.cs" /> + <Compile Include="wrapper\MessageDialog.cs" /> + <Compile Include="wrapper\Misc.cs" /> + <Compile Include="wrapper\Notebook.cs" /> + <Compile Include="wrapper\Object.cs" /> + <Compile Include="wrapper\OptionMenu.cs" /> + <Compile Include="wrapper\Paned.cs" /> + <Compile Include="wrapper\RadioActionGroupManager.cs" /> + <Compile Include="wrapper\RadioButton.cs" /> + <Compile Include="wrapper\RadioMenuItem.cs" /> + <Compile Include="wrapper\RadioToolButton.cs" /> + <Compile Include="wrapper\Range.cs" /> + <Compile Include="wrapper\Scale.cs" /> + <Compile Include="wrapper\ScrolledWindow.cs" /> + <Compile Include="wrapper\Signal.cs" /> + <Compile Include="wrapper\SignalChangedEventHandler.cs" /> + <Compile Include="wrapper\SignalCollection.cs" /> + <Compile Include="wrapper\SignalEventHandler.cs" /> + <Compile Include="wrapper\SpinButton.cs" /> + <Compile Include="wrapper\Table.cs" /> + <Compile Include="wrapper\TextView.cs" /> + <Compile Include="wrapper\ToggleToolButton.cs" /> + <Compile Include="wrapper\Toolbar.cs" /> + <Compile Include="wrapper\ToolButton.cs" /> + <Compile Include="wrapper\TreeView.cs" /> + <Compile Include="wrapper\Viewport.cs" /> + <Compile Include="wrapper\VScale.cs" /> + <Compile Include="wrapper\VScrollbar.cs" /> + <Compile Include="wrapper\Widget.cs" /> + <Compile Include="wrapper\WidgetEventHandler.cs" /> + <Compile Include="wrapper\WidgetNameChangedHandler.cs" /> + <Compile Include="wrapper\Window.cs" /> + <Compile Include="TopLevelDialog.cs" /> + <Compile Include="TopLevelWindow.cs" /> + </ItemGroup> + <ItemGroup> + <EmbeddedResource Include="stetic.glade"> + <LogicalName>stetic.glade</LogicalName> + </EmbeddedResource> + <EmbeddedResource Include="wrapper\objects.xml"> + <LogicalName>objects.xml</LogicalName> + </EmbeddedResource> + <EmbeddedResource Include="wrapper\pixmaps\accellabel.png"> + <LogicalName>accellabel.png</LogicalName> + </EmbeddedResource> + <EmbeddedResource Include="wrapper\pixmaps\actiongroup.png"> + <LogicalName>actiongroup.png</LogicalName> + </EmbeddedResource> + <EmbeddedResource Include="wrapper\pixmaps\add-check-label.png"> + <LogicalName>add-check-label.png</LogicalName> + </EmbeddedResource> + <EmbeddedResource Include="wrapper\pixmaps\add-menu.png"> + <LogicalName>add-menu.png</LogicalName> + </EmbeddedResource> + <EmbeddedResource Include="wrapper\pixmaps\alignment.png"> + <LogicalName>alignment.png</LogicalName> + </EmbeddedResource> + <EmbeddedResource Include="wrapper\pixmaps\arrow.png"> + <LogicalName>arrow.png</LogicalName> + </EmbeddedResource> + <EmbeddedResource Include="wrapper\pixmaps\box-expand.png"> + <LogicalName>box-expand.png</LogicalName> + </EmbeddedResource> + <EmbeddedResource Include="wrapper\pixmaps\box-fill.png"> + <LogicalName>box-fill.png</LogicalName> + </EmbeddedResource> + <EmbeddedResource Include="wrapper\pixmaps\button.png"> + <LogicalName>button.png</LogicalName> + </EmbeddedResource> + <EmbeddedResource Include="wrapper\pixmaps\calendar.png"> + <LogicalName>calendar.png</LogicalName> + </EmbeddedResource> + <EmbeddedResource Include="wrapper\pixmaps\cell-expand-h.png"> + <LogicalName>cell-expand-h.png</LogicalName> + </EmbeddedResource> + <EmbeddedResource Include="wrapper\pixmaps\cell-expand-v.png"> + <LogicalName>cell-expand-v.png</LogicalName> + </EmbeddedResource> + <EmbeddedResource Include="wrapper\pixmaps\cell-fill-h.png"> + <LogicalName>cell-fill-h.png</LogicalName> + </EmbeddedResource> + <EmbeddedResource Include="wrapper\pixmaps\cell-fill-v.png"> + <LogicalName>cell-fill-v.png</LogicalName> + </EmbeddedResource> + <EmbeddedResource Include="wrapper\pixmaps\checkbutton.png"> + <LogicalName>checkbutton.png</LogicalName> + </EmbeddedResource> + <EmbeddedResource Include="wrapper\pixmaps\colorbutton.png"> + <LogicalName>colorbutton.png</LogicalName> + </EmbeddedResource> + <EmbeddedResource Include="wrapper\pixmaps\colorselection.png"> + <LogicalName>colorselection.png</LogicalName> + </EmbeddedResource> + <EmbeddedResource Include="wrapper\pixmaps\colorselectiondialog.png"> + <LogicalName>colorselectiondialog.png</LogicalName> + </EmbeddedResource> + <EmbeddedResource Include="wrapper\pixmaps\combo.png"> + <LogicalName>combo.png</LogicalName> + </EmbeddedResource> + <EmbeddedResource Include="wrapper\pixmaps\comboentry.png"> + <LogicalName>comboentry.png</LogicalName> + </EmbeddedResource> + <EmbeddedResource Include="wrapper\pixmaps\custom.png"> + <LogicalName>custom.png</LogicalName> + </EmbeddedResource> + <EmbeddedResource Include="wrapper\pixmaps\dec-border.png"> + <LogicalName>dec-border.png</LogicalName> + </EmbeddedResource> + <EmbeddedResource Include="wrapper\pixmaps\dialog.png"> + <LogicalName>dialog.png</LogicalName> + </EmbeddedResource> + <EmbeddedResource Include="wrapper\pixmaps\drawingarea.png"> + <LogicalName>drawingarea.png</LogicalName> + </EmbeddedResource> + <EmbeddedResource Include="wrapper\pixmaps\entry.png"> + <LogicalName>entry.png</LogicalName> + </EmbeddedResource> + <EmbeddedResource Include="wrapper\pixmaps\eventbox.png"> + <LogicalName>eventbox.png</LogicalName> + </EmbeddedResource> + <EmbeddedResource Include="wrapper\pixmaps\expander.png"> + <LogicalName>expander.png</LogicalName> + </EmbeddedResource> + <EmbeddedResource Include="wrapper\pixmaps\fileselection.png"> + <LogicalName>fileselection.png</LogicalName> + </EmbeddedResource> + <EmbeddedResource Include="wrapper\pixmaps\fixed.png"> + <LogicalName>fixed.png</LogicalName> + </EmbeddedResource> + <EmbeddedResource Include="wrapper\pixmaps\fontbutton.png"> + <LogicalName>fontbutton.png</LogicalName> + </EmbeddedResource> + <EmbeddedResource Include="wrapper\pixmaps\fontselection.png"> + <LogicalName>fontselection.png</LogicalName> + </EmbeddedResource> + <EmbeddedResource Include="wrapper\pixmaps\fontselectiondialog.png"> + <LogicalName>fontselectiondialog.png</LogicalName> + </EmbeddedResource> + <EmbeddedResource Include="wrapper\pixmaps\frame.png"> + <LogicalName>frame.png</LogicalName> + </EmbeddedResource> + <EmbeddedResource Include="wrapper\pixmaps\globe.png"> + <LogicalName>globe.png</LogicalName> + </EmbeddedResource> + <EmbeddedResource Include="wrapper\pixmaps\globe-not.png"> + <LogicalName>globe-not.png</LogicalName> + </EmbeddedResource> + <EmbeddedResource Include="wrapper\pixmaps\handlebox.png"> + <LogicalName>handlebox.png</LogicalName> + </EmbeddedResource> + <EmbeddedResource Include="wrapper\pixmaps\hbox.png"> + <LogicalName>hbox.png</LogicalName> + </EmbeddedResource> + <EmbeddedResource Include="wrapper\pixmaps\hbuttonbox.png"> + <LogicalName>hbuttonbox.png</LogicalName> + </EmbeddedResource> + <EmbeddedResource Include="wrapper\pixmaps\hpaned.png"> + <LogicalName>hpaned.png</LogicalName> + </EmbeddedResource> + <EmbeddedResource Include="wrapper\pixmaps\hscale.png"> + <LogicalName>hscale.png</LogicalName> + </EmbeddedResource> + <EmbeddedResource Include="wrapper\pixmaps\hscrollbar.png"> + <LogicalName>hscrollbar.png</LogicalName> + </EmbeddedResource> + <EmbeddedResource Include="wrapper\pixmaps\hseparator.png"> + <LogicalName>hseparator.png</LogicalName> + </EmbeddedResource> + <EmbeddedResource Include="wrapper\pixmaps\iconview.png"> + <LogicalName>iconview.png</LogicalName> + </EmbeddedResource> + <EmbeddedResource Include="wrapper\pixmaps\image.png"> + <LogicalName>image.png</LogicalName> + </EmbeddedResource> + <EmbeddedResource Include="wrapper\pixmaps\inc-border.png"> + <LogicalName>inc-border.png</LogicalName> + </EmbeddedResource> + <EmbeddedResource Include="wrapper\pixmaps\label.png"> + <LogicalName>label.png</LogicalName> + </EmbeddedResource> + <EmbeddedResource Include="wrapper\pixmaps\menu.png"> + <LogicalName>menu.png</LogicalName> + </EmbeddedResource> + <EmbeddedResource Include="wrapper\pixmaps\menubar.png"> + <LogicalName>menubar.png</LogicalName> + </EmbeddedResource> + <EmbeddedResource Include="wrapper\pixmaps\messagedialog.png"> + <LogicalName>messagedialog.png</LogicalName> + </EmbeddedResource> + <EmbeddedResource Include="wrapper\pixmaps\missing.png"> + <LogicalName>missing.png</LogicalName> + </EmbeddedResource> + <EmbeddedResource Include="wrapper\pixmaps\notebook.png"> + <LogicalName>notebook.png</LogicalName> + </EmbeddedResource> + <EmbeddedResource Include="wrapper\pixmaps\optionmenu.png"> + <LogicalName>optionmenu.png</LogicalName> + </EmbeddedResource> + <EmbeddedResource Include="wrapper\pixmaps\progressbar.png"> + <LogicalName>progressbar.png</LogicalName> + </EmbeddedResource> + <EmbeddedResource Include="wrapper\pixmaps\radiobutton.png"> + <LogicalName>radiobutton.png</LogicalName> + </EmbeddedResource> + <EmbeddedResource Include="wrapper\pixmaps\remove-check-label.png"> + <LogicalName>remove-check-label.png</LogicalName> + </EmbeddedResource> + <EmbeddedResource Include="wrapper\pixmaps\remove-menu.png"> + <LogicalName>remove-menu.png</LogicalName> + </EmbeddedResource> + <EmbeddedResource Include="wrapper\pixmaps\scrolledwindow.png"> + <LogicalName>scrolledwindow.png</LogicalName> + </EmbeddedResource> + <EmbeddedResource Include="wrapper\pixmaps\spinbutton.png"> + <LogicalName>spinbutton.png</LogicalName> + </EmbeddedResource> + <EmbeddedResource Include="wrapper\pixmaps\statusbar.png"> + <LogicalName>statusbar.png</LogicalName> + </EmbeddedResource> + <EmbeddedResource Include="wrapper\pixmaps\table.png"> + <LogicalName>table.png</LogicalName> + </EmbeddedResource> + <EmbeddedResource Include="wrapper\pixmaps\textview.png"> + <LogicalName>textview.png</LogicalName> + </EmbeddedResource> + <EmbeddedResource Include="wrapper\pixmaps\togglebutton.png"> + <LogicalName>togglebutton.png</LogicalName> + </EmbeddedResource> + <EmbeddedResource Include="wrapper\pixmaps\toolbar.png"> + <LogicalName>toolbar.png</LogicalName> + </EmbeddedResource> + <EmbeddedResource Include="wrapper\pixmaps\treeview.png"> + <LogicalName>treeview.png</LogicalName> + </EmbeddedResource> + <EmbeddedResource Include="wrapper\pixmaps\vbox.png"> + <LogicalName>vbox.png</LogicalName> + </EmbeddedResource> + <EmbeddedResource Include="wrapper\pixmaps\vbuttonbox.png"> + <LogicalName>vbuttonbox.png</LogicalName> + </EmbeddedResource> + <EmbeddedResource Include="wrapper\pixmaps\viewport.png"> + <LogicalName>viewport.png</LogicalName> + </EmbeddedResource> + <EmbeddedResource Include="wrapper\pixmaps\vpaned.png"> + <LogicalName>vpaned.png</LogicalName> + </EmbeddedResource> + <EmbeddedResource Include="wrapper\pixmaps\vscale.png"> + <LogicalName>vscale.png</LogicalName> + </EmbeddedResource> + <EmbeddedResource Include="wrapper\pixmaps\vscrollbar.png"> + <LogicalName>vscrollbar.png</LogicalName> + </EmbeddedResource> + <EmbeddedResource Include="wrapper\pixmaps\vseparator.png"> + <LogicalName>vseparator.png</LogicalName> + </EmbeddedResource> + <EmbeddedResource Include="wrapper\pixmaps\widget.png"> + <LogicalName>widget.png</LogicalName> + </EmbeddedResource> + <EmbeddedResource Include="wrapper\pixmaps\window.png"> + <LogicalName>window.png</LogicalName> + </EmbeddedResource> + </ItemGroup> + <ItemGroup> + <None Include="libstetic.dll.config"> + <CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory> + </None> + </ItemGroup> + <Import Project="$(MSBuildBinPath)\Microsoft.CSharp.targets" /> + <ProjectExtensions> + <MonoDevelop> + <Properties> + <MonoDevelop.Autotools.MakefileInfo IntegrationEnabled="true" RelativeMakefileName="Makefile.am" BuildTargetName="" CleanTargetName="" SyncReferences="true" IsAutotoolsProject="true" RelativeConfigureInPath="../../../.."> + <BuildFilesVar Sync="true" Name="FILES" /> + <DeployFilesVar /> + <ResourcesVar Sync="true" Name="RES" /> + <OthersVar /> + <GacRefVar Sync="true" Name="REFS" Prefix="-r:" /> + <AsmRefVar Sync="true" Name="REFS" Prefix="-r:" /> + <ProjectRefVar Sync="true" Name="REFS" Prefix="-r:" /> + </MonoDevelop.Autotools.MakefileInfo> + </Properties> + </MonoDevelop> + <VisualStudio /> + </ProjectExtensions> +</Project> diff --git a/main/src/addins/MonoDevelop.GtkCore2/libstetic/libstetic.dll.config b/main/src/addins/MonoDevelop.GtkCore2/libstetic/libstetic.dll.config new file mode 100644 index 0000000000..8c4c6ab9a9 --- /dev/null +++ b/main/src/addins/MonoDevelop.GtkCore2/libstetic/libstetic.dll.config @@ -0,0 +1,8 @@ +<configuration> + <dllmap dll="libgobject-2.0-0.dll" target="libgobject-2.0.so.0" os="!osx,windows" /> + <dllmap dll="libgobject-2.0-0.dll" target="libgobject-2.0.dylib" os="osx" /> + <dllmap dll="libgtk-win32-2.0-0.dll" target="libgtk-x11-2.0.so.0" os="!osx,windows"/> + <dllmap dll="libgtk-win32-2.0-0.dll" target="libgtk-quartz-2.0.dylib" os="osx"/> + <dllmap dll="libgdk-win32-2.0-0.dll" target="libgdk-x11-2.0.so.0" os="!osx,windows"/> + <dllmap dll="libgdk-win32-2.0-0.dll" target="libgdk-quartz-2.0.dylib" os="osx"/> +</configuration> diff --git a/main/src/addins/MonoDevelop.GtkCore2/libstetic/libstetic2.csproj b/main/src/addins/MonoDevelop.GtkCore2/libstetic/libstetic2.csproj new file mode 100644 index 0000000000..195aeed1d7 --- /dev/null +++ b/main/src/addins/MonoDevelop.GtkCore2/libstetic/libstetic2.csproj @@ -0,0 +1,471 @@ +<?xml version="1.0" encoding="utf-8"?> +<Project DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003" ToolsVersion="3.5"> + <PropertyGroup> + <Configuration Condition=" '$(Configuration)' == '' ">Debug</Configuration> + <Platform Condition=" '$(Platform)' == '' ">AnyCPU</Platform> + <ProductVersion>9.0.21022</ProductVersion> + <SchemaVersion>2.0</SchemaVersion> + <ProjectGuid>{90CBA7FD-CB46-4711-97BB-2420DC01F016}</ProjectGuid> + <OutputType>Library</OutputType> + <AssemblyName>libstetic2</AssemblyName> + <TargetFrameworkVersion>v3.5</TargetFrameworkVersion> + <RootNamespace>Stetic</RootNamespace> + </PropertyGroup> + <PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|AnyCPU' "> + <DebugSymbols>true</DebugSymbols> + <DebugType>full</DebugType> + <Optimize>false</Optimize> + <OutputPath>..\..\..\..\build\AddIns\MonoDevelop.GtkCore2</OutputPath> + <DefineConstants>DEBUG</DefineConstants> + <ErrorReport>prompt</ErrorReport> + <WarningLevel>4</WarningLevel> + <Execution> + <Execution clr-version="Net_2_0" /> + </Execution> + </PropertyGroup> + <PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|AnyCPU' "> + <DebugType>none</DebugType> + <Optimize>false</Optimize> + <OutputPath>bin\Release</OutputPath> + <ErrorReport>prompt</ErrorReport> + <WarningLevel>4</WarningLevel> + <Execution> + <Execution clr-version="Net_2_0" /> + </Execution> + </PropertyGroup> + <ItemGroup> + <Reference Include="Mono.Posix" /> + <Reference Include="System" /> + <Reference Include="System.Xml" /> + <Reference Include="glib-sharp, Version=2.12.0.0, Culture=neutral, PublicKeyToken=35e10195dab3c99f"> + <SpecificVersion>False</SpecificVersion> + </Reference> + <Reference Include="pango-sharp, Version=2.12.0.0, Culture=neutral, PublicKeyToken=35e10195dab3c99f"> + <SpecificVersion>False</SpecificVersion> + </Reference> + <Reference Include="atk-sharp, Version=2.12.0.0, Culture=neutral, PublicKeyToken=35e10195dab3c99f"> + <SpecificVersion>False</SpecificVersion> + </Reference> + <Reference Include="gdk-sharp, Version=2.12.0.0, Culture=neutral, PublicKeyToken=35e10195dab3c99f"> + <SpecificVersion>False</SpecificVersion> + </Reference> + <Reference Include="gtk-sharp, Version=2.12.0.0, Culture=neutral, PublicKeyToken=35e10195dab3c99f"> + <SpecificVersion>False</SpecificVersion> + </Reference> + <Reference Include="glade-sharp, Version=2.12.0.0, Culture=neutral, PublicKeyToken=35e10195dab3c99f"> + <SpecificVersion>False</SpecificVersion> + </Reference> + <Reference Include="Mono.Cairo" /> + <Reference Include="System.Core" /> + </ItemGroup> + <ItemGroup> + <Compile Include="ClassDescriptor.cs" /> + <Compile Include="Clipboard.cs" /> + <Compile Include="CommandDescriptor.cs" /> + <Compile Include="CustomWidget.cs" /> + <Compile Include="DND.cs" /> + <Compile Include="editor\Accelerator.cs" /> + <Compile Include="editor\ActionGroupEditor.cs" /> + <Compile Include="editor\ActionItem.cs" /> + <Compile Include="editor\ActionMenu.cs" /> + <Compile Include="editor\ActionMenuBar.cs" /> + <Compile Include="editor\ActionMenuItem.cs" /> + <Compile Include="editor\ActionToolbar.cs" /> + <Compile Include="editor\ActionToolItem.cs" /> + <Compile Include="editor\Boolean.cs" /> + <Compile Include="editor\CellRendererComboBox.cs" /> + <Compile Include="editor\Char.cs" /> + <Compile Include="editor\Color.cs" /> + <Compile Include="editor\DateTimeEditor.cs" /> + <Compile Include="editor\EditIconDialog.cs" /> + <Compile Include="editor\EditIconFactoryDialog.cs" /> + <Compile Include="editor\Enumeration.cs" /> + <Compile Include="editor\Flags.cs" /> + <Compile Include="editor\FlagsSelectorDialog.cs" /> + <Compile Include="editor\FloatRange.cs" /> + <Compile Include="editor\GroupPicker.cs" /> + <Compile Include="editor\IconList.cs" /> + <Compile Include="editor\IconSelectorItem.cs" /> + <Compile Include="editor\IconSelectorMenu.cs" /> + <Compile Include="editor\IconSelectorMenuItem.cs" /> + <Compile Include="editor\Identifier.cs" /> + <Compile Include="editor\Image.cs" /> + <Compile Include="editor\ImageFile.cs" /> + <Compile Include="editor\ImageSelector.cs" /> + <Compile Include="editor\IntRange.cs" /> + <Compile Include="editor\NonContainerWarningDialog.cs" /> + <Compile Include="editor\OptIntRange.cs" /> + <Compile Include="editor\ProjectIconList.cs" /> + <Compile Include="editor\ProjectIconSelectorItem.cs" /> + <Compile Include="editor\ResponseId.cs" /> + <Compile Include="editor\SelectIconDialog.cs" /> + <Compile Include="editor\SelectImageDialog.cs" /> + <Compile Include="editor\StockIconList.cs" /> + <Compile Include="editor\StockIconSelectorItem.cs" /> + <Compile Include="editor\StockItem.cs" /> + <Compile Include="editor\String.cs" /> + <Compile Include="editor\StringArray.cs" /> + <Compile Include="editor\Text.cs" /> + <Compile Include="editor\TextBox.cs" /> + <Compile Include="editor\TextEditor.cs" /> + <Compile Include="editor\TextEditorDialog.cs" /> + <Compile Include="editor\ThemedIcon.cs" /> + <Compile Include="editor\ThemedIconList.cs" /> + <Compile Include="editor\TimeSpanEditor.cs" /> + <Compile Include="editor\Translatable.cs" /> + <Compile Include="editor\TreeViewCellContainer.cs" /> + <Compile Include="editor\WidgetSelector.cs" /> + <Compile Include="EnumDescriptor.cs" /> + <Compile Include="ErrorWidget.cs" /> + <Compile Include="GeneratorContext.cs" /> + <Compile Include="GladeException.cs" /> + <Compile Include="GladeUtils.cs" /> + <Compile Include="IDesignArea.cs" /> + <Compile Include="IEditableObject.cs" /> + <Compile Include="ImageInfo.cs" /> + <Compile Include="IProject.cs" /> + <Compile Include="IPropertyEditor.cs" /> + <Compile Include="IRadioGroupManager.cs" /> + <Compile Include="IResourceProvider.cs" /> + <Compile Include="ItemDescriptor.cs" /> + <Compile Include="ItemGroup.cs" /> + <Compile Include="ItemGroupCollection.cs" /> + <Compile Include="NoGuiDispatchAttribute.cs" /> + <Compile Include="ObjectReader.cs" /> + <Compile Include="ObjectWrapper.cs" /> + <Compile Include="ObjectWrapperEventHandler.cs" /> + <Compile Include="ObjectWriter.cs" /> + <Compile Include="ParamSpec.cs" /> + <Compile Include="Placeholder.cs" /> + <Compile Include="ProjectIconFactory.cs" /> + <Compile Include="PropertyDescriptor.cs" /> + <Compile Include="PropertyEditorAttribute.cs" /> + <Compile Include="PropertyEditorCell.cs" /> + <Compile Include="RadioGroupManager.cs" /> + <Compile Include="Registry.cs" /> + <Compile Include="Set.cs" /> + <Compile Include="SignalDescriptor.cs" /> + <Compile Include="TranslatableAttribute.cs" /> + <Compile Include="TypedClassDescriptor.cs" /> + <Compile Include="TypedPropertyDescriptor.cs" /> + <Compile Include="TypedSignalDescriptor.cs" /> + <Compile Include="undo\ActionDiffAdaptor.cs" /> + <Compile Include="undo\DiffGenerator.cs" /> + <Compile Include="undo\IDiffAdaptor.cs" /> + <Compile Include="undo\UndoManager.cs" /> + <Compile Include="undo\XmlDiffAdaptor.cs" /> + <Compile Include="WidgetLibrary.cs" /> + <Compile Include="WidgetUtils.cs" /> + <Compile Include="wrapper\Action.cs" /> + <Compile Include="wrapper\ActionGroup.cs" /> + <Compile Include="wrapper\ActionToolbarWrapper.cs" /> + <Compile Include="wrapper\ActionTree.cs" /> + <Compile Include="wrapper\Bin.cs" /> + <Compile Include="wrapper\Box.cs" /> + <Compile Include="wrapper\Button.cs" /> + <Compile Include="wrapper\ButtonBox.cs" /> + <Compile Include="wrapper\CheckButton.cs" /> + <Compile Include="wrapper\ColorButton.cs" /> + <Compile Include="wrapper\ComboBox.cs" /> + <Compile Include="wrapper\ComboBoxEntry.cs" /> + <Compile Include="wrapper\Container.cs" /> + <Compile Include="wrapper\Custom.cs" /> + <Compile Include="wrapper\Dialog.cs" /> + <Compile Include="wrapper\Entry.cs" /> + <Compile Include="wrapper\Expander.cs" /> + <Compile Include="wrapper\Fixed.cs" /> + <Compile Include="wrapper\FontButton.cs" /> + <Compile Include="wrapper\FontSelectionDialog.cs" /> + <Compile Include="wrapper\Frame.cs" /> + <Compile Include="wrapper\HScale.cs" /> + <Compile Include="wrapper\HScrollbar.cs" /> + <Compile Include="wrapper\IconView.cs" /> + <Compile Include="wrapper\Image.cs" /> + <Compile Include="wrapper\ImageMenuItem.cs" /> + <Compile Include="wrapper\Label.cs" /> + <Compile Include="wrapper\MenuBar.cs" /> + <Compile Include="wrapper\MenuItem.cs" /> + <Compile Include="wrapper\MessageDialog.cs" /> + <Compile Include="wrapper\Misc.cs" /> + <Compile Include="wrapper\Notebook.cs" /> + <Compile Include="wrapper\Object.cs" /> + <Compile Include="wrapper\OptionMenu.cs" /> + <Compile Include="wrapper\Paned.cs" /> + <Compile Include="wrapper\RadioActionGroupManager.cs" /> + <Compile Include="wrapper\RadioButton.cs" /> + <Compile Include="wrapper\RadioMenuItem.cs" /> + <Compile Include="wrapper\RadioToolButton.cs" /> + <Compile Include="wrapper\Range.cs" /> + <Compile Include="wrapper\Scale.cs" /> + <Compile Include="wrapper\ScrolledWindow.cs" /> + <Compile Include="wrapper\Signal.cs" /> + <Compile Include="wrapper\SignalChangedEventHandler.cs" /> + <Compile Include="wrapper\SignalCollection.cs" /> + <Compile Include="wrapper\SignalEventHandler.cs" /> + <Compile Include="wrapper\SpinButton.cs" /> + <Compile Include="wrapper\Table.cs" /> + <Compile Include="wrapper\TextView.cs" /> + <Compile Include="wrapper\ToggleToolButton.cs" /> + <Compile Include="wrapper\Toolbar.cs" /> + <Compile Include="wrapper\ToolButton.cs" /> + <Compile Include="wrapper\TreeView.cs" /> + <Compile Include="wrapper\Viewport.cs" /> + <Compile Include="wrapper\VScale.cs" /> + <Compile Include="wrapper\VScrollbar.cs" /> + <Compile Include="wrapper\Widget.cs" /> + <Compile Include="wrapper\WidgetEventHandler.cs" /> + <Compile Include="wrapper\WidgetNameChangedHandler.cs" /> + <Compile Include="wrapper\Window.cs" /> + <Compile Include="TopLevelDialog.cs" /> + <Compile Include="TopLevelWindow.cs" /> + </ItemGroup> + <ItemGroup> + <EmbeddedResource Include="stetic.glade"> + <LogicalName>stetic.glade</LogicalName> + </EmbeddedResource> + <EmbeddedResource Include="wrapper\objects.xml"> + <LogicalName>objects.xml</LogicalName> + </EmbeddedResource> + <EmbeddedResource Include="wrapper\pixmaps\accellabel.png"> + <LogicalName>accellabel.png</LogicalName> + </EmbeddedResource> + <EmbeddedResource Include="wrapper\pixmaps\actiongroup.png"> + <LogicalName>actiongroup.png</LogicalName> + </EmbeddedResource> + <EmbeddedResource Include="wrapper\pixmaps\add-check-label.png"> + <LogicalName>add-check-label.png</LogicalName> + </EmbeddedResource> + <EmbeddedResource Include="wrapper\pixmaps\add-menu.png"> + <LogicalName>add-menu.png</LogicalName> + </EmbeddedResource> + <EmbeddedResource Include="wrapper\pixmaps\alignment.png"> + <LogicalName>alignment.png</LogicalName> + </EmbeddedResource> + <EmbeddedResource Include="wrapper\pixmaps\arrow.png"> + <LogicalName>arrow.png</LogicalName> + </EmbeddedResource> + <EmbeddedResource Include="wrapper\pixmaps\box-expand.png"> + <LogicalName>box-expand.png</LogicalName> + </EmbeddedResource> + <EmbeddedResource Include="wrapper\pixmaps\box-fill.png"> + <LogicalName>box-fill.png</LogicalName> + </EmbeddedResource> + <EmbeddedResource Include="wrapper\pixmaps\button.png"> + <LogicalName>button.png</LogicalName> + </EmbeddedResource> + <EmbeddedResource Include="wrapper\pixmaps\calendar.png"> + <LogicalName>calendar.png</LogicalName> + </EmbeddedResource> + <EmbeddedResource Include="wrapper\pixmaps\cell-expand-h.png"> + <LogicalName>cell-expand-h.png</LogicalName> + </EmbeddedResource> + <EmbeddedResource Include="wrapper\pixmaps\cell-expand-v.png"> + <LogicalName>cell-expand-v.png</LogicalName> + </EmbeddedResource> + <EmbeddedResource Include="wrapper\pixmaps\cell-fill-h.png"> + <LogicalName>cell-fill-h.png</LogicalName> + </EmbeddedResource> + <EmbeddedResource Include="wrapper\pixmaps\cell-fill-v.png"> + <LogicalName>cell-fill-v.png</LogicalName> + </EmbeddedResource> + <EmbeddedResource Include="wrapper\pixmaps\checkbutton.png"> + <LogicalName>checkbutton.png</LogicalName> + </EmbeddedResource> + <EmbeddedResource Include="wrapper\pixmaps\colorbutton.png"> + <LogicalName>colorbutton.png</LogicalName> + </EmbeddedResource> + <EmbeddedResource Include="wrapper\pixmaps\colorselection.png"> + <LogicalName>colorselection.png</LogicalName> + </EmbeddedResource> + <EmbeddedResource Include="wrapper\pixmaps\colorselectiondialog.png"> + <LogicalName>colorselectiondialog.png</LogicalName> + </EmbeddedResource> + <EmbeddedResource Include="wrapper\pixmaps\combo.png"> + <LogicalName>combo.png</LogicalName> + </EmbeddedResource> + <EmbeddedResource Include="wrapper\pixmaps\comboentry.png"> + <LogicalName>comboentry.png</LogicalName> + </EmbeddedResource> + <EmbeddedResource Include="wrapper\pixmaps\custom.png"> + <LogicalName>custom.png</LogicalName> + </EmbeddedResource> + <EmbeddedResource Include="wrapper\pixmaps\dec-border.png"> + <LogicalName>dec-border.png</LogicalName> + </EmbeddedResource> + <EmbeddedResource Include="wrapper\pixmaps\dialog.png"> + <LogicalName>dialog.png</LogicalName> + </EmbeddedResource> + <EmbeddedResource Include="wrapper\pixmaps\drawingarea.png"> + <LogicalName>drawingarea.png</LogicalName> + </EmbeddedResource> + <EmbeddedResource Include="wrapper\pixmaps\entry.png"> + <LogicalName>entry.png</LogicalName> + </EmbeddedResource> + <EmbeddedResource Include="wrapper\pixmaps\eventbox.png"> + <LogicalName>eventbox.png</LogicalName> + </EmbeddedResource> + <EmbeddedResource Include="wrapper\pixmaps\expander.png"> + <LogicalName>expander.png</LogicalName> + </EmbeddedResource> + <EmbeddedResource Include="wrapper\pixmaps\fileselection.png"> + <LogicalName>fileselection.png</LogicalName> + </EmbeddedResource> + <EmbeddedResource Include="wrapper\pixmaps\fixed.png"> + <LogicalName>fixed.png</LogicalName> + </EmbeddedResource> + <EmbeddedResource Include="wrapper\pixmaps\fontbutton.png"> + <LogicalName>fontbutton.png</LogicalName> + </EmbeddedResource> + <EmbeddedResource Include="wrapper\pixmaps\fontselection.png"> + <LogicalName>fontselection.png</LogicalName> + </EmbeddedResource> + <EmbeddedResource Include="wrapper\pixmaps\fontselectiondialog.png"> + <LogicalName>fontselectiondialog.png</LogicalName> + </EmbeddedResource> + <EmbeddedResource Include="wrapper\pixmaps\frame.png"> + <LogicalName>frame.png</LogicalName> + </EmbeddedResource> + <EmbeddedResource Include="wrapper\pixmaps\globe.png"> + <LogicalName>globe.png</LogicalName> + </EmbeddedResource> + <EmbeddedResource Include="wrapper\pixmaps\globe-not.png"> + <LogicalName>globe-not.png</LogicalName> + </EmbeddedResource> + <EmbeddedResource Include="wrapper\pixmaps\handlebox.png"> + <LogicalName>handlebox.png</LogicalName> + </EmbeddedResource> + <EmbeddedResource Include="wrapper\pixmaps\hbox.png"> + <LogicalName>hbox.png</LogicalName> + </EmbeddedResource> + <EmbeddedResource Include="wrapper\pixmaps\hbuttonbox.png"> + <LogicalName>hbuttonbox.png</LogicalName> + </EmbeddedResource> + <EmbeddedResource Include="wrapper\pixmaps\hpaned.png"> + <LogicalName>hpaned.png</LogicalName> + </EmbeddedResource> + <EmbeddedResource Include="wrapper\pixmaps\hscale.png"> + <LogicalName>hscale.png</LogicalName> + </EmbeddedResource> + <EmbeddedResource Include="wrapper\pixmaps\hscrollbar.png"> + <LogicalName>hscrollbar.png</LogicalName> + </EmbeddedResource> + <EmbeddedResource Include="wrapper\pixmaps\hseparator.png"> + <LogicalName>hseparator.png</LogicalName> + </EmbeddedResource> + <EmbeddedResource Include="wrapper\pixmaps\iconview.png"> + <LogicalName>iconview.png</LogicalName> + </EmbeddedResource> + <EmbeddedResource Include="wrapper\pixmaps\image.png"> + <LogicalName>image.png</LogicalName> + </EmbeddedResource> + <EmbeddedResource Include="wrapper\pixmaps\inc-border.png"> + <LogicalName>inc-border.png</LogicalName> + </EmbeddedResource> + <EmbeddedResource Include="wrapper\pixmaps\label.png"> + <LogicalName>label.png</LogicalName> + </EmbeddedResource> + <EmbeddedResource Include="wrapper\pixmaps\menu.png"> + <LogicalName>menu.png</LogicalName> + </EmbeddedResource> + <EmbeddedResource Include="wrapper\pixmaps\menubar.png"> + <LogicalName>menubar.png</LogicalName> + </EmbeddedResource> + <EmbeddedResource Include="wrapper\pixmaps\messagedialog.png"> + <LogicalName>messagedialog.png</LogicalName> + </EmbeddedResource> + <EmbeddedResource Include="wrapper\pixmaps\missing.png"> + <LogicalName>missing.png</LogicalName> + </EmbeddedResource> + <EmbeddedResource Include="wrapper\pixmaps\notebook.png"> + <LogicalName>notebook.png</LogicalName> + </EmbeddedResource> + <EmbeddedResource Include="wrapper\pixmaps\optionmenu.png"> + <LogicalName>optionmenu.png</LogicalName> + </EmbeddedResource> + <EmbeddedResource Include="wrapper\pixmaps\progressbar.png"> + <LogicalName>progressbar.png</LogicalName> + </EmbeddedResource> + <EmbeddedResource Include="wrapper\pixmaps\radiobutton.png"> + <LogicalName>radiobutton.png</LogicalName> + </EmbeddedResource> + <EmbeddedResource Include="wrapper\pixmaps\remove-check-label.png"> + <LogicalName>remove-check-label.png</LogicalName> + </EmbeddedResource> + <EmbeddedResource Include="wrapper\pixmaps\remove-menu.png"> + <LogicalName>remove-menu.png</LogicalName> + </EmbeddedResource> + <EmbeddedResource Include="wrapper\pixmaps\scrolledwindow.png"> + <LogicalName>scrolledwindow.png</LogicalName> + </EmbeddedResource> + <EmbeddedResource Include="wrapper\pixmaps\spinbutton.png"> + <LogicalName>spinbutton.png</LogicalName> + </EmbeddedResource> + <EmbeddedResource Include="wrapper\pixmaps\statusbar.png"> + <LogicalName>statusbar.png</LogicalName> + </EmbeddedResource> + <EmbeddedResource Include="wrapper\pixmaps\table.png"> + <LogicalName>table.png</LogicalName> + </EmbeddedResource> + <EmbeddedResource Include="wrapper\pixmaps\textview.png"> + <LogicalName>textview.png</LogicalName> + </EmbeddedResource> + <EmbeddedResource Include="wrapper\pixmaps\togglebutton.png"> + <LogicalName>togglebutton.png</LogicalName> + </EmbeddedResource> + <EmbeddedResource Include="wrapper\pixmaps\toolbar.png"> + <LogicalName>toolbar.png</LogicalName> + </EmbeddedResource> + <EmbeddedResource Include="wrapper\pixmaps\treeview.png"> + <LogicalName>treeview.png</LogicalName> + </EmbeddedResource> + <EmbeddedResource Include="wrapper\pixmaps\vbox.png"> + <LogicalName>vbox.png</LogicalName> + </EmbeddedResource> + <EmbeddedResource Include="wrapper\pixmaps\vbuttonbox.png"> + <LogicalName>vbuttonbox.png</LogicalName> + </EmbeddedResource> + <EmbeddedResource Include="wrapper\pixmaps\viewport.png"> + <LogicalName>viewport.png</LogicalName> + </EmbeddedResource> + <EmbeddedResource Include="wrapper\pixmaps\vpaned.png"> + <LogicalName>vpaned.png</LogicalName> + </EmbeddedResource> + <EmbeddedResource Include="wrapper\pixmaps\vscale.png"> + <LogicalName>vscale.png</LogicalName> + </EmbeddedResource> + <EmbeddedResource Include="wrapper\pixmaps\vscrollbar.png"> + <LogicalName>vscrollbar.png</LogicalName> + </EmbeddedResource> + <EmbeddedResource Include="wrapper\pixmaps\vseparator.png"> + <LogicalName>vseparator.png</LogicalName> + </EmbeddedResource> + <EmbeddedResource Include="wrapper\pixmaps\widget.png"> + <LogicalName>widget.png</LogicalName> + </EmbeddedResource> + <EmbeddedResource Include="wrapper\pixmaps\window.png"> + <LogicalName>window.png</LogicalName> + </EmbeddedResource> + </ItemGroup> + <ItemGroup> + <None Include="libstetic2.dll.config"> + <CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory> + </None> + </ItemGroup> + <Import Project="$(MSBuildBinPath)\Microsoft.CSharp.targets" /> + <ProjectExtensions> + <MonoDevelop> + <Properties> + <MonoDevelop.Autotools.MakefileInfo IntegrationEnabled="true" RelativeMakefileName="Makefile.am" BuildTargetName="" CleanTargetName="" SyncReferences="true" IsAutotoolsProject="true" RelativeConfigureInPath="../../../.."> + <BuildFilesVar Sync="true" Name="FILES" /> + <DeployFilesVar /> + <ResourcesVar Sync="true" Name="RES" /> + <OthersVar /> + <GacRefVar Sync="true" Name="REFS" Prefix="-r:" /> + <AsmRefVar Sync="true" Name="REFS" Prefix="-r:" /> + <ProjectRefVar Sync="true" Name="REFS" Prefix="-r:" /> + </MonoDevelop.Autotools.MakefileInfo> + </Properties> + </MonoDevelop> + <VisualStudio /> + </ProjectExtensions> +</Project> diff --git a/main/src/addins/MonoDevelop.GtkCore2/libstetic/libstetic2.dll.config b/main/src/addins/MonoDevelop.GtkCore2/libstetic/libstetic2.dll.config new file mode 100644 index 0000000000..8c4c6ab9a9 --- /dev/null +++ b/main/src/addins/MonoDevelop.GtkCore2/libstetic/libstetic2.dll.config @@ -0,0 +1,8 @@ +<configuration> + <dllmap dll="libgobject-2.0-0.dll" target="libgobject-2.0.so.0" os="!osx,windows" /> + <dllmap dll="libgobject-2.0-0.dll" target="libgobject-2.0.dylib" os="osx" /> + <dllmap dll="libgtk-win32-2.0-0.dll" target="libgtk-x11-2.0.so.0" os="!osx,windows"/> + <dllmap dll="libgtk-win32-2.0-0.dll" target="libgtk-quartz-2.0.dylib" os="osx"/> + <dllmap dll="libgdk-win32-2.0-0.dll" target="libgdk-x11-2.0.so.0" os="!osx,windows"/> + <dllmap dll="libgdk-win32-2.0-0.dll" target="libgdk-quartz-2.0.dylib" os="osx"/> +</configuration> diff --git a/main/src/addins/MonoDevelop.GtkCore2/libstetic/stetic.glade b/main/src/addins/MonoDevelop.GtkCore2/libstetic/stetic.glade new file mode 100644 index 0000000000..9f58816ce1 --- /dev/null +++ b/main/src/addins/MonoDevelop.GtkCore2/libstetic/stetic.glade @@ -0,0 +1,2107 @@ +<?xml version="1.0" standalone="no"?> <!--*- mode: xml -*--> +<!DOCTYPE glade-interface SYSTEM "http://glade.gnome.org/glade-2.0.dtd"> + +<glade-interface> + +<widget class="GtkDialog" id="SelectImageDialog"> + <property name="visible">True</property> + <property name="title" translatable="yes">Select Image</property> + <property name="type">GTK_WINDOW_TOPLEVEL</property> + <property name="window_position">GTK_WIN_POS_NONE</property> + <property name="modal">False</property> + <property name="default_width">650</property> + <property name="default_height">450</property> + <property name="resizable">True</property> + <property name="destroy_with_parent">False</property> + <property name="decorated">True</property> + <property name="skip_taskbar_hint">False</property> + <property name="skip_pager_hint">False</property> + <property name="type_hint">GDK_WINDOW_TYPE_HINT_DIALOG</property> + <property name="gravity">GDK_GRAVITY_NORTH_WEST</property> + <property name="focus_on_map">True</property> + <property name="urgency_hint">False</property> + <property name="has_separator">True</property> + + <child internal-child="vbox"> + <widget class="GtkVBox" id="dialog-vbox1"> + <property name="visible">True</property> + <property name="homogeneous">False</property> + <property name="spacing">0</property> + + <child internal-child="action_area"> + <widget class="GtkHButtonBox" id="dialog-action_area1"> + <property name="visible">True</property> + <property name="layout_style">GTK_BUTTONBOX_END</property> + + <child> + <widget class="GtkButton" id="cancelbutton1"> + <property name="visible">True</property> + <property name="can_default">True</property> + <property name="can_focus">True</property> + <property name="label">gtk-cancel</property> + <property name="use_stock">True</property> + <property name="relief">GTK_RELIEF_NORMAL</property> + <property name="focus_on_click">True</property> + <property name="response_id">-6</property> + </widget> + </child> + + <child> + <widget class="GtkButton" id="okButton"> + <property name="visible">True</property> + <property name="can_default">True</property> + <property name="can_focus">True</property> + <property name="label">gtk-ok</property> + <property name="use_stock">True</property> + <property name="relief">GTK_RELIEF_NORMAL</property> + <property name="focus_on_click">True</property> + <property name="response_id">0</property> + </widget> + </child> + </widget> + <packing> + <property name="padding">0</property> + <property name="expand">False</property> + <property name="fill">True</property> + <property name="pack_type">GTK_PACK_END</property> + </packing> + </child> + + <child> + <widget class="GtkNotebook" id="notebook"> + <property name="border_width">6</property> + <property name="visible">True</property> + <property name="can_focus">True</property> + <property name="show_tabs">True</property> + <property name="show_border">True</property> + <property name="tab_pos">GTK_POS_TOP</property> + <property name="scrollable">False</property> + <property name="enable_popup">False</property> + <signal name="switch_page" handler="OnCurrentPageChanged" last_modification_time="Thu, 18 May 2006 12:07:20 GMT"/> + + <child> + <widget class="GtkVBox" id="vbox1"> + <property name="border_width">6</property> + <property name="visible">True</property> + <property name="homogeneous">False</property> + <property name="spacing">6</property> + + <child> + <widget class="GtkScrolledWindow" id="iconScrolledwindow"> + <property name="visible">True</property> + <property name="can_focus">True</property> + <property name="hscrollbar_policy">GTK_POLICY_NEVER</property> + <property name="vscrollbar_policy">GTK_POLICY_AUTOMATIC</property> + <property name="shadow_type">GTK_SHADOW_IN</property> + <property name="window_placement">GTK_CORNER_TOP_LEFT</property> + + <child> + <placeholder/> + </child> + </widget> + <packing> + <property name="padding">0</property> + <property name="expand">True</property> + <property name="fill">True</property> + </packing> + </child> + + <child> + <widget class="GtkHBox" id="hbox1"> + <property name="visible">True</property> + <property name="homogeneous">False</property> + <property name="spacing">6</property> + + <child> + <widget class="GtkImage" id="previewIcon"> + <property name="visible">True</property> + <property name="icon_size">4</property> + <property name="icon_name">gtk-missing-image</property> + <property name="xalign">0.5</property> + <property name="yalign">0.5</property> + <property name="xpad">3</property> + <property name="ypad">3</property> + </widget> + <packing> + <property name="padding">0</property> + <property name="expand">False</property> + <property name="fill">False</property> + </packing> + </child> + + <child> + <widget class="GtkVBox" id="vbox3"> + <property name="visible">True</property> + <property name="homogeneous">False</property> + <property name="spacing">0</property> + + <child> + <widget class="GtkHBox" id="hbox3"> + <property name="visible">True</property> + <property name="homogeneous">False</property> + <property name="spacing">6</property> + + <child> + <widget class="GtkLabel" id="label5"> + <property name="visible">True</property> + <property name="label" translatable="yes">_Icon Name:</property> + <property name="use_underline">True</property> + <property name="use_markup">False</property> + <property name="justify">GTK_JUSTIFY_LEFT</property> + <property name="wrap">False</property> + <property name="selectable">False</property> + <property name="xalign">0.5</property> + <property name="yalign">0.5</property> + <property name="xpad">0</property> + <property name="ypad">0</property> + <property name="mnemonic_widget">iconNameEntry</property> + <property name="ellipsize">PANGO_ELLIPSIZE_NONE</property> + <property name="width_chars">-1</property> + <property name="single_line_mode">False</property> + <property name="angle">0</property> + </widget> + <packing> + <property name="padding">0</property> + <property name="expand">False</property> + <property name="fill">False</property> + </packing> + </child> + + <child> + <widget class="GtkEntry" id="iconNameEntry"> + <property name="visible">True</property> + <property name="can_focus">True</property> + <property name="editable">True</property> + <property name="visibility">True</property> + <property name="max_length">0</property> + <property name="text" translatable="yes"></property> + <property name="has_frame">True</property> + <property name="invisible_char">*</property> + <property name="activates_default">False</property> + <signal name="changed" handler="OnIconNameChanged" last_modification_time="Fri, 10 Mar 2006 13:48:39 GMT"/> + </widget> + <packing> + <property name="padding">0</property> + <property name="expand">True</property> + <property name="fill">True</property> + </packing> + </child> + + <child> + <widget class="GtkComboBox" id="iconSizeCombo"> + <property name="visible">True</property> + <property name="items" translatable="yes"></property> + <property name="add_tearoffs">False</property> + <property name="focus_on_click">True</property> + <signal name="changed" handler="OnIconSizeChanged" last_modification_time="Fri, 10 Mar 2006 13:50:33 GMT"/> + </widget> + <packing> + <property name="padding">0</property> + <property name="expand">False</property> + <property name="fill">False</property> + </packing> + </child> + </widget> + <packing> + <property name="padding">0</property> + <property name="expand">False</property> + <property name="fill">False</property> + <property name="pack_type">GTK_PACK_END</property> + </packing> + </child> + + <child> + <placeholder/> + </child> + </widget> + <packing> + <property name="padding">0</property> + <property name="expand">True</property> + <property name="fill">True</property> + </packing> + </child> + </widget> + <packing> + <property name="padding">0</property> + <property name="expand">False</property> + <property name="fill">False</property> + </packing> + </child> + </widget> + <packing> + <property name="tab_expand">False</property> + <property name="tab_fill">True</property> + </packing> + </child> + + <child> + <widget class="GtkLabel" id="label2"> + <property name="visible">True</property> + <property name="label" translatable="yes">Themed Icons</property> + <property name="use_underline">False</property> + <property name="use_markup">False</property> + <property name="justify">GTK_JUSTIFY_LEFT</property> + <property name="wrap">False</property> + <property name="selectable">False</property> + <property name="xalign">0.5</property> + <property name="yalign">0.5</property> + <property name="xpad">0</property> + <property name="ypad">0</property> + <property name="ellipsize">PANGO_ELLIPSIZE_NONE</property> + <property name="width_chars">-1</property> + <property name="single_line_mode">False</property> + <property name="angle">0</property> + </widget> + <packing> + <property name="type">tab</property> + </packing> + </child> + + <child> + <widget class="GtkVBox" id="vbox2"> + <property name="border_width">6</property> + <property name="visible">True</property> + <property name="homogeneous">False</property> + <property name="spacing">6</property> + + <child> + <widget class="GtkHBox" id="hbox2"> + <property name="visible">True</property> + <property name="homogeneous">False</property> + <property name="spacing">6</property> + + <child> + <widget class="GtkScrolledWindow" id="scrolledwindow7"> + <property name="visible">True</property> + <property name="can_focus">True</property> + <property name="hscrollbar_policy">GTK_POLICY_AUTOMATIC</property> + <property name="vscrollbar_policy">GTK_POLICY_AUTOMATIC</property> + <property name="shadow_type">GTK_SHADOW_IN</property> + <property name="window_placement">GTK_CORNER_TOP_LEFT</property> + + <child> + <widget class="GtkTreeView" id="resourceList"> + <property name="visible">True</property> + <property name="can_focus">True</property> + <property name="headers_visible">False</property> + <property name="rules_hint">False</property> + <property name="reorderable">False</property> + <property name="enable_search">True</property> + <property name="fixed_height_mode">False</property> + <property name="hover_selection">False</property> + <property name="hover_expand">False</property> + </widget> + </child> + </widget> + <packing> + <property name="padding">0</property> + <property name="expand">True</property> + <property name="fill">True</property> + </packing> + </child> + + <child> + <widget class="GtkVButtonBox" id="vbuttonbox1"> + <property name="visible">True</property> + <property name="layout_style">GTK_BUTTONBOX_START</property> + <property name="spacing">6</property> + + <child> + <widget class="GtkButton" id="buttonAdd"> + <property name="visible">True</property> + <property name="can_default">True</property> + <property name="can_focus">True</property> + <property name="label">gtk-add</property> + <property name="use_stock">True</property> + <property name="relief">GTK_RELIEF_NORMAL</property> + <property name="focus_on_click">True</property> + <signal name="clicked" handler="OnAddResource" last_modification_time="Fri, 10 Mar 2006 11:17:29 GMT"/> + </widget> + </child> + + <child> + <widget class="GtkButton" id="buttonRemove"> + <property name="visible">True</property> + <property name="can_default">True</property> + <property name="can_focus">True</property> + <property name="label">gtk-delete</property> + <property name="use_stock">True</property> + <property name="relief">GTK_RELIEF_NORMAL</property> + <property name="focus_on_click">True</property> + <signal name="clicked" handler="OnRemoveResource" last_modification_time="Fri, 10 Mar 2006 11:17:42 GMT"/> + </widget> + </child> + </widget> + <packing> + <property name="padding">0</property> + <property name="expand">False</property> + <property name="fill">False</property> + </packing> + </child> + </widget> + <packing> + <property name="padding">0</property> + <property name="expand">True</property> + <property name="fill">True</property> + </packing> + </child> + + <child> + <widget class="GtkHBox" id="hbox4"> + <property name="visible">True</property> + <property name="homogeneous">False</property> + <property name="spacing">6</property> + + <child> + <widget class="GtkImage" id="previewResource"> + <property name="width_request">30</property> + <property name="height_request">30</property> + <property name="visible">True</property> + <property name="xalign">0.5</property> + <property name="yalign">0.5</property> + <property name="xpad">0</property> + <property name="ypad">0</property> + </widget> + <packing> + <property name="padding">0</property> + <property name="expand">False</property> + <property name="fill">False</property> + </packing> + </child> + + <child> + <widget class="GtkLabel" id="label6"> + <property name="visible">True</property> + <property name="label" translatable="yes">Resource Name:</property> + <property name="use_underline">False</property> + <property name="use_markup">False</property> + <property name="justify">GTK_JUSTIFY_LEFT</property> + <property name="wrap">False</property> + <property name="selectable">False</property> + <property name="xalign">0.5</property> + <property name="yalign">0.5</property> + <property name="xpad">0</property> + <property name="ypad">0</property> + <property name="ellipsize">PANGO_ELLIPSIZE_NONE</property> + <property name="width_chars">-1</property> + <property name="single_line_mode">False</property> + <property name="angle">0</property> + </widget> + <packing> + <property name="padding">0</property> + <property name="expand">False</property> + <property name="fill">False</property> + </packing> + </child> + + <child> + <widget class="GtkEntry" id="resourceNameEntry"> + <property name="visible">True</property> + <property name="can_focus">True</property> + <property name="editable">True</property> + <property name="visibility">True</property> + <property name="max_length">0</property> + <property name="text" translatable="yes"></property> + <property name="has_frame">True</property> + <property name="invisible_char">*</property> + <property name="activates_default">False</property> + <signal name="changed" handler="OnResourceNameChanged" last_modification_time="Fri, 10 Mar 2006 16:31:30 GMT"/> + </widget> + <packing> + <property name="padding">0</property> + <property name="expand">True</property> + <property name="fill">True</property> + </packing> + </child> + </widget> + <packing> + <property name="padding">0</property> + <property name="expand">False</property> + <property name="fill">False</property> + </packing> + </child> + </widget> + <packing> + <property name="tab_expand">False</property> + <property name="tab_fill">True</property> + </packing> + </child> + + <child> + <widget class="GtkLabel" id="label3"> + <property name="visible">True</property> + <property name="label" translatable="yes">Resources</property> + <property name="use_underline">False</property> + <property name="use_markup">False</property> + <property name="justify">GTK_JUSTIFY_LEFT</property> + <property name="wrap">False</property> + <property name="selectable">False</property> + <property name="xalign">0.5</property> + <property name="yalign">0.5</property> + <property name="xpad">0</property> + <property name="ypad">0</property> + <property name="ellipsize">PANGO_ELLIPSIZE_NONE</property> + <property name="width_chars">-1</property> + <property name="single_line_mode">False</property> + <property name="angle">0</property> + </widget> + <packing> + <property name="type">tab</property> + </packing> + </child> + + <child> + <widget class="GtkFileChooserWidget" id="fileChooser"> + <property name="border_width">12</property> + <property name="visible">True</property> + <property name="action">GTK_FILE_CHOOSER_ACTION_OPEN</property> + <property name="local_only">True</property> + <property name="select_multiple">False</property> + <property name="show_hidden">False</property> + </widget> + <packing> + <property name="tab_expand">False</property> + <property name="tab_fill">True</property> + </packing> + </child> + + <child> + <widget class="GtkLabel" id="label4"> + <property name="visible">True</property> + <property name="label" translatable="yes">Files</property> + <property name="use_underline">False</property> + <property name="use_markup">False</property> + <property name="justify">GTK_JUSTIFY_LEFT</property> + <property name="wrap">False</property> + <property name="selectable">False</property> + <property name="xalign">0.5</property> + <property name="yalign">0.5</property> + <property name="xpad">0</property> + <property name="ypad">0</property> + <property name="ellipsize">PANGO_ELLIPSIZE_NONE</property> + <property name="width_chars">-1</property> + <property name="single_line_mode">False</property> + <property name="angle">0</property> + </widget> + <packing> + <property name="type">tab</property> + </packing> + </child> + </widget> + <packing> + <property name="padding">0</property> + <property name="expand">True</property> + <property name="fill">True</property> + </packing> + </child> + </widget> + </child> +</widget> + +<widget class="GtkDialog" id="FlagsSelectorDialog"> + <property name="visible">True</property> + <property name="title" translatable="yes">Flags</property> + <property name="type">GTK_WINDOW_TOPLEVEL</property> + <property name="window_position">GTK_WIN_POS_NONE</property> + <property name="modal">False</property> + <property name="default_width">500</property> + <property name="default_height">450</property> + <property name="resizable">True</property> + <property name="destroy_with_parent">False</property> + <property name="decorated">True</property> + <property name="skip_taskbar_hint">False</property> + <property name="skip_pager_hint">False</property> + <property name="type_hint">GDK_WINDOW_TYPE_HINT_DIALOG</property> + <property name="gravity">GDK_GRAVITY_NORTH_WEST</property> + <property name="focus_on_map">True</property> + <property name="urgency_hint">False</property> + <property name="has_separator">True</property> + + <child internal-child="vbox"> + <widget class="GtkVBox" id="dialog-vbox2"> + <property name="visible">True</property> + <property name="homogeneous">False</property> + <property name="spacing">0</property> + + <child internal-child="action_area"> + <widget class="GtkHButtonBox" id="dialog-action_area2"> + <property name="visible">True</property> + <property name="layout_style">GTK_BUTTONBOX_END</property> + + <child> + <widget class="GtkButton" id="cancelbutton2"> + <property name="visible">True</property> + <property name="can_default">True</property> + <property name="can_focus">True</property> + <property name="label">gtk-cancel</property> + <property name="use_stock">True</property> + <property name="relief">GTK_RELIEF_NORMAL</property> + <property name="focus_on_click">True</property> + <property name="response_id">-6</property> + </widget> + </child> + + <child> + <widget class="GtkButton" id="okbutton1"> + <property name="visible">True</property> + <property name="can_default">True</property> + <property name="can_focus">True</property> + <property name="label">gtk-ok</property> + <property name="use_stock">True</property> + <property name="relief">GTK_RELIEF_NORMAL</property> + <property name="focus_on_click">True</property> + <property name="response_id">-5</property> + </widget> + </child> + </widget> + <packing> + <property name="padding">0</property> + <property name="expand">False</property> + <property name="fill">True</property> + <property name="pack_type">GTK_PACK_END</property> + </packing> + </child> + + <child> + <widget class="GtkScrolledWindow" id="scrolledwindow8"> + <property name="border_width">6</property> + <property name="visible">True</property> + <property name="can_focus">True</property> + <property name="hscrollbar_policy">GTK_POLICY_ALWAYS</property> + <property name="vscrollbar_policy">GTK_POLICY_ALWAYS</property> + <property name="shadow_type">GTK_SHADOW_IN</property> + <property name="window_placement">GTK_CORNER_TOP_LEFT</property> + + <child> + <widget class="GtkTreeView" id="treeView"> + <property name="visible">True</property> + <property name="can_focus">True</property> + <property name="headers_visible">False</property> + <property name="rules_hint">False</property> + <property name="reorderable">False</property> + <property name="enable_search">True</property> + <property name="fixed_height_mode">False</property> + <property name="hover_selection">False</property> + <property name="hover_expand">False</property> + </widget> + </child> + </widget> + <packing> + <property name="padding">0</property> + <property name="expand">True</property> + <property name="fill">True</property> + </packing> + </child> + </widget> + </child> +</widget> + +<widget class="GtkDialog" id="TextEditorDialog"> + <property name="visible">True</property> + <property name="title" translatable="yes">Text</property> + <property name="type">GTK_WINDOW_TOPLEVEL</property> + <property name="window_position">GTK_WIN_POS_NONE</property> + <property name="modal">False</property> + <property name="default_width">600</property> + <property name="default_height">350</property> + <property name="resizable">True</property> + <property name="destroy_with_parent">False</property> + <property name="decorated">True</property> + <property name="skip_taskbar_hint">False</property> + <property name="skip_pager_hint">False</property> + <property name="type_hint">GDK_WINDOW_TYPE_HINT_DIALOG</property> + <property name="gravity">GDK_GRAVITY_NORTH_WEST</property> + <property name="focus_on_map">True</property> + <property name="urgency_hint">False</property> + <property name="has_separator">True</property> + + <child internal-child="vbox"> + <widget class="GtkVBox" id="dialog-vbox3"> + <property name="visible">True</property> + <property name="homogeneous">False</property> + <property name="spacing">0</property> + + <child internal-child="action_area"> + <widget class="GtkHButtonBox" id="dialog-action_area3"> + <property name="visible">True</property> + <property name="layout_style">GTK_BUTTONBOX_END</property> + + <child> + <widget class="GtkButton" id="cancelbutton3"> + <property name="visible">True</property> + <property name="can_default">True</property> + <property name="can_focus">True</property> + <property name="label">gtk-cancel</property> + <property name="use_stock">True</property> + <property name="relief">GTK_RELIEF_NORMAL</property> + <property name="focus_on_click">True</property> + <property name="response_id">-6</property> + </widget> + </child> + + <child> + <widget class="GtkButton" id="okbutton2"> + <property name="visible">True</property> + <property name="can_default">True</property> + <property name="can_focus">True</property> + <property name="label">gtk-ok</property> + <property name="use_stock">True</property> + <property name="relief">GTK_RELIEF_NORMAL</property> + <property name="focus_on_click">True</property> + <property name="response_id">-5</property> + </widget> + </child> + </widget> + <packing> + <property name="padding">0</property> + <property name="expand">False</property> + <property name="fill">True</property> + <property name="pack_type">GTK_PACK_END</property> + </packing> + </child> + + <child> + <widget class="GtkVBox" id="vbox4"> + <property name="border_width">6</property> + <property name="visible">True</property> + <property name="homogeneous">False</property> + <property name="spacing">6</property> + + <child> + <widget class="GtkScrolledWindow" id="scrolledwindow9"> + <property name="visible">True</property> + <property name="can_focus">True</property> + <property name="hscrollbar_policy">GTK_POLICY_AUTOMATIC</property> + <property name="vscrollbar_policy">GTK_POLICY_AUTOMATIC</property> + <property name="shadow_type">GTK_SHADOW_IN</property> + <property name="window_placement">GTK_CORNER_TOP_LEFT</property> + + <child> + <widget class="GtkTextView" id="textview"> + <property name="visible">True</property> + <property name="can_focus">True</property> + <property name="editable">True</property> + <property name="overwrite">False</property> + <property name="accepts_tab">True</property> + <property name="justification">GTK_JUSTIFY_LEFT</property> + <property name="wrap_mode">GTK_WRAP_CHAR</property> + <property name="cursor_visible">True</property> + <property name="pixels_above_lines">0</property> + <property name="pixels_below_lines">0</property> + <property name="pixels_inside_wrap">0</property> + <property name="left_margin">0</property> + <property name="right_margin">0</property> + <property name="indent">0</property> + <property name="text" translatable="yes"></property> + </widget> + </child> + </widget> + <packing> + <property name="padding">0</property> + <property name="expand">True</property> + <property name="fill">True</property> + </packing> + </child> + + <child> + <widget class="GtkCheckButton" id="checkTranslatable"> + <property name="visible">True</property> + <property name="can_focus">True</property> + <property name="label" translatable="yes">Translatable</property> + <property name="use_underline">True</property> + <property name="relief">GTK_RELIEF_NORMAL</property> + <property name="focus_on_click">True</property> + <property name="active">False</property> + <property name="inconsistent">False</property> + <property name="draw_indicator">True</property> + <signal name="toggled" handler="OnTranslatableToggled" last_modification_time="Fri, 17 Mar 2006 16:37:34 GMT"/> + </widget> + <packing> + <property name="padding">0</property> + <property name="expand">False</property> + <property name="fill">False</property> + </packing> + </child> + + <child> + <widget class="GtkTable" id="translationTable"> + <property name="visible">True</property> + <property name="n_rows">2</property> + <property name="n_columns">2</property> + <property name="homogeneous">False</property> + <property name="row_spacing">6</property> + <property name="column_spacing">6</property> + + <child> + <widget class="GtkLabel" id="label7"> + <property name="visible">True</property> + <property name="label" translatable="yes">Translation Context Hint:</property> + <property name="use_underline">False</property> + <property name="use_markup">False</property> + <property name="justify">GTK_JUSTIFY_LEFT</property> + <property name="wrap">False</property> + <property name="selectable">False</property> + <property name="xalign">0</property> + <property name="yalign">0.5</property> + <property name="xpad">0</property> + <property name="ypad">0</property> + <property name="ellipsize">PANGO_ELLIPSIZE_NONE</property> + <property name="width_chars">-1</property> + <property name="single_line_mode">False</property> + <property name="angle">0</property> + </widget> + <packing> + <property name="left_attach">0</property> + <property name="right_attach">1</property> + <property name="top_attach">0</property> + <property name="bottom_attach">1</property> + <property name="x_options">fill</property> + <property name="y_options"></property> + </packing> + </child> + + <child> + <widget class="GtkLabel" id="label8"> + <property name="visible">True</property> + <property name="label" translatable="yes">Comment for Translators</property> + <property name="use_underline">False</property> + <property name="use_markup">False</property> + <property name="justify">GTK_JUSTIFY_LEFT</property> + <property name="wrap">False</property> + <property name="selectable">False</property> + <property name="xalign">0</property> + <property name="yalign">0.5</property> + <property name="xpad">0</property> + <property name="ypad">0</property> + <property name="ellipsize">PANGO_ELLIPSIZE_NONE</property> + <property name="width_chars">-1</property> + <property name="single_line_mode">False</property> + <property name="angle">0</property> + </widget> + <packing> + <property name="left_attach">0</property> + <property name="right_attach">1</property> + <property name="top_attach">1</property> + <property name="bottom_attach">2</property> + <property name="x_options">fill</property> + <property name="y_options"></property> + </packing> + </child> + + <child> + <widget class="GtkEntry" id="entryContext"> + <property name="visible">True</property> + <property name="can_focus">True</property> + <property name="editable">True</property> + <property name="visibility">True</property> + <property name="max_length">0</property> + <property name="text" translatable="yes"></property> + <property name="has_frame">True</property> + <property name="invisible_char">*</property> + <property name="activates_default">False</property> + </widget> + <packing> + <property name="left_attach">1</property> + <property name="right_attach">2</property> + <property name="top_attach">0</property> + <property name="bottom_attach">1</property> + <property name="y_options"></property> + </packing> + </child> + + <child> + <widget class="GtkEntry" id="entryComment"> + <property name="visible">True</property> + <property name="can_focus">True</property> + <property name="editable">True</property> + <property name="visibility">True</property> + <property name="max_length">0</property> + <property name="text" translatable="yes"></property> + <property name="has_frame">True</property> + <property name="invisible_char">*</property> + <property name="activates_default">False</property> + </widget> + <packing> + <property name="left_attach">1</property> + <property name="right_attach">2</property> + <property name="top_attach">1</property> + <property name="bottom_attach">2</property> + <property name="y_options"></property> + </packing> + </child> + </widget> + <packing> + <property name="padding">0</property> + <property name="expand">False</property> + <property name="fill">False</property> + </packing> + </child> + </widget> + <packing> + <property name="padding">0</property> + <property name="expand">True</property> + <property name="fill">True</property> + </packing> + </child> + </widget> + </child> +</widget> + +<widget class="GtkDialog" id="SelectIconDialog"> + <property name="visible">True</property> + <property name="title" translatable="yes">Select Image</property> + <property name="type">GTK_WINDOW_TOPLEVEL</property> + <property name="window_position">GTK_WIN_POS_NONE</property> + <property name="modal">False</property> + <property name="default_width">650</property> + <property name="default_height">450</property> + <property name="resizable">True</property> + <property name="destroy_with_parent">False</property> + <property name="decorated">True</property> + <property name="skip_taskbar_hint">False</property> + <property name="skip_pager_hint">False</property> + <property name="type_hint">GDK_WINDOW_TYPE_HINT_DIALOG</property> + <property name="gravity">GDK_GRAVITY_NORTH_WEST</property> + <property name="focus_on_map">True</property> + <property name="urgency_hint">False</property> + <property name="has_separator">True</property> + + <child internal-child="vbox"> + <widget class="GtkVBox" id="vbox5"> + <property name="visible">True</property> + <property name="homogeneous">False</property> + <property name="spacing">0</property> + + <child internal-child="action_area"> + <widget class="GtkHButtonBox" id="hbuttonbox1"> + <property name="visible">True</property> + <property name="layout_style">GTK_BUTTONBOX_END</property> + + <child> + <widget class="GtkButton" id="button1"> + <property name="visible">True</property> + <property name="can_default">True</property> + <property name="can_focus">True</property> + <property name="label">gtk-cancel</property> + <property name="use_stock">True</property> + <property name="relief">GTK_RELIEF_NORMAL</property> + <property name="focus_on_click">True</property> + <property name="response_id">-6</property> + </widget> + </child> + + <child> + <widget class="GtkButton" id="okButton"> + <property name="visible">True</property> + <property name="can_default">True</property> + <property name="can_focus">True</property> + <property name="label">gtk-ok</property> + <property name="use_stock">True</property> + <property name="relief">GTK_RELIEF_NORMAL</property> + <property name="focus_on_click">True</property> + <property name="response_id">-5</property> + </widget> + </child> + </widget> + <packing> + <property name="padding">0</property> + <property name="expand">False</property> + <property name="fill">True</property> + <property name="pack_type">GTK_PACK_END</property> + </packing> + </child> + + <child> + <widget class="GtkNotebook" id="notebook"> + <property name="border_width">6</property> + <property name="visible">True</property> + <property name="can_focus">True</property> + <property name="show_tabs">True</property> + <property name="show_border">True</property> + <property name="tab_pos">GTK_POS_TOP</property> + <property name="scrollable">False</property> + <property name="enable_popup">False</property> + <signal name="switch_page" handler="OnCurrentPageChanged" last_modification_time="Thu, 18 May 2006 12:05:33 GMT"/> + + <child> + <widget class="GtkVBox" id="vbox6"> + <property name="border_width">6</property> + <property name="visible">True</property> + <property name="homogeneous">False</property> + <property name="spacing">6</property> + + <child> + <widget class="GtkScrolledWindow" id="iconScrolledwindow"> + <property name="visible">True</property> + <property name="can_focus">True</property> + <property name="hscrollbar_policy">GTK_POLICY_NEVER</property> + <property name="vscrollbar_policy">GTK_POLICY_AUTOMATIC</property> + <property name="shadow_type">GTK_SHADOW_IN</property> + <property name="window_placement">GTK_CORNER_TOP_LEFT</property> + + <child> + <placeholder/> + </child> + </widget> + <packing> + <property name="padding">0</property> + <property name="expand">True</property> + <property name="fill">True</property> + </packing> + </child> + + <child> + <widget class="GtkHBox" id="hbox5"> + <property name="visible">True</property> + <property name="homogeneous">False</property> + <property name="spacing">6</property> + + <child> + <widget class="GtkImage" id="previewIcon"> + <property name="visible">True</property> + <property name="icon_size">4</property> + <property name="icon_name">gtk-missing-image</property> + <property name="xalign">0.5</property> + <property name="yalign">0</property> + <property name="xpad">3</property> + <property name="ypad">3</property> + </widget> + <packing> + <property name="padding">0</property> + <property name="expand">False</property> + <property name="fill">False</property> + </packing> + </child> + + <child> + <widget class="GtkVBox" id="vbox7"> + <property name="visible">True</property> + <property name="homogeneous">False</property> + <property name="spacing">0</property> + + <child> + <widget class="GtkHBox" id="hbox6"> + <property name="visible">True</property> + <property name="homogeneous">False</property> + <property name="spacing">6</property> + + <child> + <widget class="GtkLabel" id="label9"> + <property name="visible">True</property> + <property name="label" translatable="yes">_Icon Name:</property> + <property name="use_underline">True</property> + <property name="use_markup">False</property> + <property name="justify">GTK_JUSTIFY_LEFT</property> + <property name="wrap">False</property> + <property name="selectable">False</property> + <property name="xalign">0.5</property> + <property name="yalign">0.5</property> + <property name="xpad">0</property> + <property name="ypad">0</property> + <property name="mnemonic_widget">stockIconEntry</property> + <property name="ellipsize">PANGO_ELLIPSIZE_NONE</property> + <property name="width_chars">-1</property> + <property name="single_line_mode">False</property> + <property name="angle">0</property> + </widget> + <packing> + <property name="padding">0</property> + <property name="expand">False</property> + <property name="fill">False</property> + </packing> + </child> + + <child> + <widget class="GtkEntry" id="stockIconEntry"> + <property name="visible">True</property> + <property name="can_focus">True</property> + <property name="editable">True</property> + <property name="visibility">True</property> + <property name="max_length">0</property> + <property name="text" translatable="yes"></property> + <property name="has_frame">True</property> + <property name="invisible_char">*</property> + <property name="activates_default">False</property> + <signal name="changed" handler="OnIconNameChanged" last_modification_time="Fri, 10 Mar 2006 13:48:39 GMT"/> + </widget> + <packing> + <property name="padding">0</property> + <property name="expand">True</property> + <property name="fill">True</property> + </packing> + </child> + </widget> + <packing> + <property name="padding">0</property> + <property name="expand">False</property> + <property name="fill">False</property> + <property name="pack_type">GTK_PACK_END</property> + </packing> + </child> + + <child> + <placeholder/> + </child> + </widget> + <packing> + <property name="padding">0</property> + <property name="expand">True</property> + <property name="fill">True</property> + </packing> + </child> + </widget> + <packing> + <property name="padding">0</property> + <property name="expand">False</property> + <property name="fill">False</property> + </packing> + </child> + + <child> + <widget class="GtkVBox" id="labelWarningIcon"> + <property name="visible">True</property> + <property name="homogeneous">False</property> + <property name="spacing">0</property> + + <child> + <widget class="GtkHSeparator" id="hseparator2"> + <property name="visible">True</property> + </widget> + <packing> + <property name="padding">0</property> + <property name="expand">True</property> + <property name="fill">True</property> + </packing> + </child> + + <child> + <widget class="GtkHBox" id="hbox11"> + <property name="border_width">3</property> + <property name="visible">True</property> + <property name="homogeneous">False</property> + <property name="spacing">3</property> + + <child> + <widget class="GtkImage" id="image1"> + <property name="visible">True</property> + <property name="stock">gtk-dialog-warning</property> + <property name="icon_size">1</property> + <property name="xalign">0.5</property> + <property name="yalign">0</property> + <property name="xpad">0</property> + <property name="ypad">0</property> + </widget> + <packing> + <property name="padding">0</property> + <property name="expand">False</property> + <property name="fill">False</property> + </packing> + </child> + + <child> + <widget class="GtkLabel" id="labelWarning"> + <property name="width_request">513</property> + <property name="visible">True</property> + <property name="label" translatable="yes">The selected icon may not show at run time if the required icon factory is not properly initialized.</property> + <property name="use_underline">False</property> + <property name="use_markup">False</property> + <property name="justify">GTK_JUSTIFY_LEFT</property> + <property name="wrap">True</property> + <property name="selectable">False</property> + <property name="xalign">0</property> + <property name="yalign">0.5</property> + <property name="xpad">0</property> + <property name="ypad">0</property> + <property name="ellipsize">PANGO_ELLIPSIZE_NONE</property> + <property name="width_chars">-1</property> + <property name="single_line_mode">False</property> + <property name="angle">0</property> + </widget> + <packing> + <property name="padding">0</property> + <property name="expand">False</property> + <property name="fill">False</property> + </packing> + </child> + </widget> + <packing> + <property name="padding">0</property> + <property name="expand">False</property> + <property name="fill">False</property> + </packing> + </child> + </widget> + <packing> + <property name="padding">0</property> + <property name="expand">False</property> + <property name="fill">False</property> + </packing> + </child> + </widget> + <packing> + <property name="tab_expand">False</property> + <property name="tab_fill">True</property> + </packing> + </child> + + <child> + <widget class="GtkLabel" id="label10"> + <property name="visible">True</property> + <property name="label" translatable="yes">Stock Icons</property> + <property name="use_underline">False</property> + <property name="use_markup">False</property> + <property name="justify">GTK_JUSTIFY_LEFT</property> + <property name="wrap">False</property> + <property name="selectable">False</property> + <property name="xalign">0.5</property> + <property name="yalign">0.5</property> + <property name="xpad">0</property> + <property name="ypad">0</property> + <property name="ellipsize">PANGO_ELLIPSIZE_NONE</property> + <property name="width_chars">-1</property> + <property name="single_line_mode">False</property> + <property name="angle">0</property> + </widget> + <packing> + <property name="type">tab</property> + </packing> + </child> + + <child> + <widget class="GtkVBox" id="vbox8"> + <property name="border_width">6</property> + <property name="visible">True</property> + <property name="homogeneous">False</property> + <property name="spacing">6</property> + + <child> + <widget class="GtkHBox" id="hbox7"> + <property name="visible">True</property> + <property name="homogeneous">False</property> + <property name="spacing">6</property> + + <child> + <widget class="GtkScrolledWindow" id="customIconScrolledwindow"> + <property name="visible">True</property> + <property name="can_focus">True</property> + <property name="hscrollbar_policy">GTK_POLICY_AUTOMATIC</property> + <property name="vscrollbar_policy">GTK_POLICY_AUTOMATIC</property> + <property name="shadow_type">GTK_SHADOW_NONE</property> + <property name="window_placement">GTK_CORNER_TOP_LEFT</property> + + <child> + <placeholder/> + </child> + </widget> + <packing> + <property name="padding">0</property> + <property name="expand">True</property> + <property name="fill">True</property> + </packing> + </child> + + <child> + <widget class="GtkVButtonBox" id="vbuttonbox2"> + <property name="visible">True</property> + <property name="layout_style">GTK_BUTTONBOX_START</property> + <property name="spacing">6</property> + + <child> + <widget class="GtkButton" id="button3"> + <property name="visible">True</property> + <property name="can_default">True</property> + <property name="can_focus">True</property> + <property name="label">gtk-add</property> + <property name="use_stock">True</property> + <property name="relief">GTK_RELIEF_NORMAL</property> + <property name="focus_on_click">True</property> + <signal name="clicked" handler="OnAddIcon" last_modification_time="Wed, 17 May 2006 11:25:29 GMT"/> + </widget> + </child> + + <child> + <widget class="GtkButton" id="button4"> + <property name="visible">True</property> + <property name="can_default">True</property> + <property name="can_focus">True</property> + <property name="label">gtk-edit</property> + <property name="use_stock">True</property> + <property name="relief">GTK_RELIEF_NORMAL</property> + <property name="focus_on_click">True</property> + <signal name="clicked" handler="OnEditIcon" last_modification_time="Wed, 17 May 2006 11:24:58 GMT"/> + </widget> + </child> + + <child> + <widget class="GtkButton" id="button5"> + <property name="visible">True</property> + <property name="can_default">True</property> + <property name="can_focus">True</property> + <property name="label">gtk-delete</property> + <property name="use_stock">True</property> + <property name="relief">GTK_RELIEF_NORMAL</property> + <property name="focus_on_click">True</property> + <signal name="clicked" handler="OnRemoveIcon" last_modification_time="Wed, 17 May 2006 11:25:18 GMT"/> + </widget> + </child> + </widget> + <packing> + <property name="padding">0</property> + <property name="expand">False</property> + <property name="fill">False</property> + </packing> + </child> + </widget> + <packing> + <property name="padding">0</property> + <property name="expand">True</property> + <property name="fill">True</property> + </packing> + </child> + </widget> + <packing> + <property name="tab_expand">False</property> + <property name="tab_fill">True</property> + </packing> + </child> + + <child> + <widget class="GtkLabel" id="label12"> + <property name="visible">True</property> + <property name="label" translatable="yes">Project Icons</property> + <property name="use_underline">False</property> + <property name="use_markup">False</property> + <property name="justify">GTK_JUSTIFY_LEFT</property> + <property name="wrap">False</property> + <property name="selectable">False</property> + <property name="xalign">0.5</property> + <property name="yalign">0.5</property> + <property name="xpad">0</property> + <property name="ypad">0</property> + <property name="ellipsize">PANGO_ELLIPSIZE_NONE</property> + <property name="width_chars">-1</property> + <property name="single_line_mode">False</property> + <property name="angle">0</property> + </widget> + <packing> + <property name="type">tab</property> + </packing> + </child> + </widget> + <packing> + <property name="padding">0</property> + <property name="expand">True</property> + <property name="fill">True</property> + </packing> + </child> + </widget> + </child> +</widget> + +<widget class="GtkDialog" id="EditIconDialog"> + <property name="visible">True</property> + <property name="title" translatable="yes">Edit Icon</property> + <property name="type">GTK_WINDOW_TOPLEVEL</property> + <property name="window_position">GTK_WIN_POS_NONE</property> + <property name="modal">False</property> + <property name="default_width">650</property> + <property name="default_height">400</property> + <property name="resizable">True</property> + <property name="destroy_with_parent">False</property> + <property name="decorated">True</property> + <property name="skip_taskbar_hint">False</property> + <property name="skip_pager_hint">False</property> + <property name="type_hint">GDK_WINDOW_TYPE_HINT_DIALOG</property> + <property name="gravity">GDK_GRAVITY_NORTH_WEST</property> + <property name="focus_on_map">True</property> + <property name="urgency_hint">False</property> + <property name="has_separator">True</property> + + <child internal-child="vbox"> + <widget class="GtkVBox" id="dialog-vbox4"> + <property name="visible">True</property> + <property name="homogeneous">False</property> + <property name="spacing">0</property> + + <child internal-child="action_area"> + <widget class="GtkHButtonBox" id="dialog-action_area4"> + <property name="visible">True</property> + <property name="layout_style">GTK_BUTTONBOX_END</property> + + <child> + <widget class="GtkButton" id="cancelbutton4"> + <property name="visible">True</property> + <property name="can_default">True</property> + <property name="can_focus">True</property> + <property name="label">gtk-cancel</property> + <property name="use_stock">True</property> + <property name="relief">GTK_RELIEF_NORMAL</property> + <property name="focus_on_click">True</property> + <property name="response_id">-6</property> + </widget> + </child> + + <child> + <widget class="GtkButton" id="okButton"> + <property name="visible">True</property> + <property name="can_default">True</property> + <property name="can_focus">True</property> + <property name="label">gtk-ok</property> + <property name="use_stock">True</property> + <property name="relief">GTK_RELIEF_NORMAL</property> + <property name="focus_on_click">True</property> + <property name="response_id">-5</property> + </widget> + </child> + </widget> + <packing> + <property name="padding">0</property> + <property name="expand">False</property> + <property name="fill">True</property> + <property name="pack_type">GTK_PACK_END</property> + </packing> + </child> + + <child> + <widget class="GtkVBox" id="vbox12"> + <property name="border_width">6</property> + <property name="visible">True</property> + <property name="homogeneous">False</property> + <property name="spacing">6</property> + + <child> + <widget class="GtkHBox" id="hbox15"> + <property name="visible">True</property> + <property name="homogeneous">False</property> + <property name="spacing">6</property> + + <child> + <widget class="GtkLabel" id="label21"> + <property name="visible">True</property> + <property name="label" translatable="yes">Icon name:</property> + <property name="use_underline">False</property> + <property name="use_markup">False</property> + <property name="justify">GTK_JUSTIFY_LEFT</property> + <property name="wrap">False</property> + <property name="selectable">False</property> + <property name="xalign">0.5</property> + <property name="yalign">0.5</property> + <property name="xpad">0</property> + <property name="ypad">0</property> + <property name="ellipsize">PANGO_ELLIPSIZE_NONE</property> + <property name="width_chars">-1</property> + <property name="single_line_mode">False</property> + <property name="angle">0</property> + </widget> + <packing> + <property name="padding">0</property> + <property name="expand">False</property> + <property name="fill">False</property> + </packing> + </child> + + <child> + <widget class="GtkEntry" id="nameEntry"> + <property name="visible">True</property> + <property name="can_focus">True</property> + <property name="editable">True</property> + <property name="visibility">True</property> + <property name="max_length">0</property> + <property name="text" translatable="yes"></property> + <property name="has_frame">True</property> + <property name="invisible_char">*</property> + <property name="activates_default">False</property> + <property name="width_chars">20</property> + <signal name="changed" handler="OnNameChanged" last_modification_time="Wed, 17 May 2006 15:53:15 GMT"/> + </widget> + <packing> + <property name="padding">0</property> + <property name="expand">False</property> + <property name="fill">False</property> + </packing> + </child> + </widget> + <packing> + <property name="padding">0</property> + <property name="expand">False</property> + <property name="fill">False</property> + </packing> + </child> + + <child> + <widget class="GtkHSeparator" id="hseparator1"> + <property name="visible">True</property> + </widget> + <packing> + <property name="padding">0</property> + <property name="expand">False</property> + <property name="fill">False</property> + </packing> + </child> + + <child> + <widget class="GtkRadioButton" id="radioSingle"> + <property name="visible">True</property> + <property name="can_focus">True</property> + <property name="label" translatable="yes">Single source icon</property> + <property name="use_underline">True</property> + <property name="relief">GTK_RELIEF_NORMAL</property> + <property name="focus_on_click">True</property> + <property name="active">False</property> + <property name="inconsistent">False</property> + <property name="draw_indicator">True</property> + <signal name="clicked" handler="OnSingleClicked" last_modification_time="Wed, 17 May 2006 12:17:45 GMT"/> + </widget> + <packing> + <property name="padding">0</property> + <property name="expand">False</property> + <property name="fill">False</property> + </packing> + </child> + + <child> + <widget class="GtkHBox" id="hboxSingle"> + <property name="visible">True</property> + <property name="homogeneous">False</property> + <property name="spacing">6</property> + + <child> + <widget class="GtkLabel" id="label20"> + <property name="width_request">12</property> + <property name="visible">True</property> + <property name="label" translatable="yes"></property> + <property name="use_underline">False</property> + <property name="use_markup">False</property> + <property name="justify">GTK_JUSTIFY_LEFT</property> + <property name="wrap">False</property> + <property name="selectable">False</property> + <property name="xalign">0.5</property> + <property name="yalign">0.5</property> + <property name="xpad">0</property> + <property name="ypad">0</property> + <property name="ellipsize">PANGO_ELLIPSIZE_NONE</property> + <property name="width_chars">-1</property> + <property name="single_line_mode">False</property> + <property name="angle">0</property> + </widget> + <packing> + <property name="padding">0</property> + <property name="expand">False</property> + <property name="fill">False</property> + </packing> + </child> + + <child> + <widget class="GtkLabel" id="label17"> + <property name="visible">True</property> + <property name="label" translatable="yes">Image:</property> + <property name="use_underline">False</property> + <property name="use_markup">False</property> + <property name="justify">GTK_JUSTIFY_LEFT</property> + <property name="wrap">False</property> + <property name="selectable">False</property> + <property name="xalign">0.5</property> + <property name="yalign">0.5</property> + <property name="xpad">0</property> + <property name="ypad">0</property> + <property name="ellipsize">PANGO_ELLIPSIZE_NONE</property> + <property name="width_chars">-1</property> + <property name="single_line_mode">False</property> + <property name="angle">0</property> + </widget> + <packing> + <property name="padding">0</property> + <property name="expand">False</property> + <property name="fill">False</property> + </packing> + </child> + + <child> + <widget class="GtkFrame" id="frame1"> + <property name="visible">True</property> + <property name="label_xalign">0</property> + <property name="label_yalign">0.5</property> + <property name="shadow_type">GTK_SHADOW_ETCHED_IN</property> + + <child> + <widget class="GtkHBox" id="hbox14"> + <property name="visible">True</property> + <property name="homogeneous">False</property> + <property name="spacing">6</property> + + <child> + <widget class="GtkImage" id="imageImage"> + <property name="visible">True</property> + <property name="xalign">0.5</property> + <property name="yalign">0.5</property> + <property name="xpad">0</property> + <property name="ypad">0</property> + </widget> + <packing> + <property name="padding">6</property> + <property name="expand">False</property> + <property name="fill">False</property> + </packing> + </child> + + <child> + <widget class="GtkLabel" id="imageLabel"> + <property name="visible">True</property> + <property name="label">image name</property> + <property name="use_underline">False</property> + <property name="use_markup">False</property> + <property name="justify">GTK_JUSTIFY_LEFT</property> + <property name="wrap">False</property> + <property name="selectable">False</property> + <property name="xalign">0</property> + <property name="yalign">0.5</property> + <property name="xpad">0</property> + <property name="ypad">0</property> + <property name="ellipsize">PANGO_ELLIPSIZE_NONE</property> + <property name="width_chars">-1</property> + <property name="single_line_mode">False</property> + <property name="angle">0</property> + </widget> + <packing> + <property name="padding">0</property> + <property name="expand">False</property> + <property name="fill">False</property> + </packing> + </child> + </widget> + </child> + </widget> + <packing> + <property name="padding">0</property> + <property name="expand">True</property> + <property name="fill">True</property> + </packing> + </child> + + <child> + <widget class="GtkButton" id="button9"> + <property name="visible">True</property> + <property name="can_focus">True</property> + <property name="label" translatable="yes">Select Image...</property> + <property name="use_underline">True</property> + <property name="relief">GTK_RELIEF_NORMAL</property> + <property name="focus_on_click">True</property> + <signal name="clicked" handler="OnSelectImage" last_modification_time="Wed, 17 May 2006 12:11:57 GMT"/> + </widget> + <packing> + <property name="padding">0</property> + <property name="expand">False</property> + <property name="fill">False</property> + </packing> + </child> + </widget> + <packing> + <property name="padding">0</property> + <property name="expand">False</property> + <property name="fill">False</property> + </packing> + </child> + + <child> + <widget class="GtkRadioButton" id="radioMultiple"> + <property name="visible">True</property> + <property name="can_focus">True</property> + <property name="label" translatable="yes">Multiple source icon</property> + <property name="use_underline">True</property> + <property name="relief">GTK_RELIEF_NORMAL</property> + <property name="focus_on_click">True</property> + <property name="active">False</property> + <property name="inconsistent">False</property> + <property name="draw_indicator">True</property> + <property name="group">radioSingle</property> + <signal name="clicked" handler="OnMultipleClicked" last_modification_time="Wed, 17 May 2006 12:18:00 GMT"/> + </widget> + <packing> + <property name="padding">3</property> + <property name="expand">False</property> + <property name="fill">False</property> + </packing> + </child> + + <child> + <widget class="GtkHBox" id="hbox12"> + <property name="visible">True</property> + <property name="homogeneous">False</property> + <property name="spacing">0</property> + + <child> + <widget class="GtkLabel" id="label19"> + <property name="width_request">12</property> + <property name="visible">True</property> + <property name="label" translatable="yes"></property> + <property name="use_underline">False</property> + <property name="use_markup">False</property> + <property name="justify">GTK_JUSTIFY_LEFT</property> + <property name="wrap">False</property> + <property name="selectable">False</property> + <property name="xalign">0.5</property> + <property name="yalign">0.5</property> + <property name="xpad">0</property> + <property name="ypad">0</property> + <property name="ellipsize">PANGO_ELLIPSIZE_NONE</property> + <property name="width_chars">-1</property> + <property name="single_line_mode">False</property> + <property name="angle">0</property> + </widget> + <packing> + <property name="padding">0</property> + <property name="expand">False</property> + <property name="fill">False</property> + </packing> + </child> + + <child> + <widget class="GtkHBox" id="hboxMultiple"> + <property name="visible">True</property> + <property name="homogeneous">False</property> + <property name="spacing">6</property> + + <child> + <widget class="GtkScrolledWindow" id="scrolledwindow13"> + <property name="visible">True</property> + <property name="can_focus">True</property> + <property name="hscrollbar_policy">GTK_POLICY_AUTOMATIC</property> + <property name="vscrollbar_policy">GTK_POLICY_AUTOMATIC</property> + <property name="shadow_type">GTK_SHADOW_IN</property> + <property name="window_placement">GTK_CORNER_TOP_LEFT</property> + + <child> + <widget class="GtkTreeView" id="sourceList"> + <property name="visible">True</property> + <property name="can_focus">True</property> + <property name="headers_visible">True</property> + <property name="rules_hint">False</property> + <property name="reorderable">False</property> + <property name="enable_search">True</property> + <property name="fixed_height_mode">False</property> + <property name="hover_selection">False</property> + <property name="hover_expand">False</property> + </widget> + </child> + </widget> + <packing> + <property name="padding">0</property> + <property name="expand">True</property> + <property name="fill">True</property> + </packing> + </child> + + <child> + <widget class="GtkVButtonBox" id="vbuttonbox3"> + <property name="visible">True</property> + <property name="layout_style">GTK_BUTTONBOX_START</property> + <property name="spacing">3</property> + + <child> + <widget class="GtkButton" id="button10"> + <property name="visible">True</property> + <property name="can_default">True</property> + <property name="can_focus">True</property> + <property name="label">gtk-add</property> + <property name="use_stock">True</property> + <property name="relief">GTK_RELIEF_NORMAL</property> + <property name="focus_on_click">True</property> + <signal name="clicked" handler="OnAddSource" last_modification_time="Wed, 17 May 2006 12:12:11 GMT"/> + </widget> + </child> + + <child> + <widget class="GtkButton" id="button11"> + <property name="visible">True</property> + <property name="can_default">True</property> + <property name="can_focus">True</property> + <property name="label">gtk-delete</property> + <property name="use_stock">True</property> + <property name="relief">GTK_RELIEF_NORMAL</property> + <property name="focus_on_click">True</property> + <signal name="clicked" handler="OnRemoveSource" last_modification_time="Wed, 17 May 2006 12:12:21 GMT"/> + </widget> + </child> + </widget> + <packing> + <property name="padding">0</property> + <property name="expand">False</property> + <property name="fill">False</property> + </packing> + </child> + </widget> + <packing> + <property name="padding">0</property> + <property name="expand">True</property> + <property name="fill">True</property> + </packing> + </child> + </widget> + <packing> + <property name="padding">0</property> + <property name="expand">True</property> + <property name="fill">True</property> + </packing> + </child> + </widget> + <packing> + <property name="padding">0</property> + <property name="expand">True</property> + <property name="fill">True</property> + </packing> + </child> + </widget> + </child> +</widget> + +<widget class="GtkDialog" id="EditIconFactoryDialog"> + <property name="visible">True</property> + <property name="title" translatable="yes">Edit Icon Factory</property> + <property name="type">GTK_WINDOW_TOPLEVEL</property> + <property name="window_position">GTK_WIN_POS_NONE</property> + <property name="modal">False</property> + <property name="default_width">450</property> + <property name="default_height">460</property> + <property name="resizable">True</property> + <property name="destroy_with_parent">False</property> + <property name="decorated">True</property> + <property name="skip_taskbar_hint">False</property> + <property name="skip_pager_hint">False</property> + <property name="type_hint">GDK_WINDOW_TYPE_HINT_DIALOG</property> + <property name="gravity">GDK_GRAVITY_NORTH_WEST</property> + <property name="focus_on_map">True</property> + <property name="urgency_hint">False</property> + <property name="has_separator">True</property> + + <child internal-child="vbox"> + <widget class="GtkVBox" id="vbox14"> + <property name="visible">True</property> + <property name="homogeneous">False</property> + <property name="spacing">0</property> + + <child internal-child="action_area"> + <widget class="GtkHButtonBox" id="hbuttonbox2"> + <property name="visible">True</property> + <property name="layout_style">GTK_BUTTONBOX_END</property> + + <child> + <widget class="GtkButton" id="button17"> + <property name="visible">True</property> + <property name="can_default">True</property> + <property name="can_focus">True</property> + <property name="label">gtk-close</property> + <property name="use_stock">True</property> + <property name="relief">GTK_RELIEF_NORMAL</property> + <property name="focus_on_click">True</property> + <property name="response_id">-7</property> + </widget> + </child> + </widget> + <packing> + <property name="padding">0</property> + <property name="expand">False</property> + <property name="fill">True</property> + <property name="pack_type">GTK_PACK_END</property> + </packing> + </child> + + <child> + <widget class="GtkHBox" id="hbox22"> + <property name="border_width">12</property> + <property name="visible">True</property> + <property name="homogeneous">False</property> + <property name="spacing">6</property> + + <child> + <widget class="GtkScrolledWindow" id="iconListScrolledwindow"> + <property name="visible">True</property> + <property name="can_focus">True</property> + <property name="hscrollbar_policy">GTK_POLICY_AUTOMATIC</property> + <property name="vscrollbar_policy">GTK_POLICY_AUTOMATIC</property> + <property name="shadow_type">GTK_SHADOW_NONE</property> + <property name="window_placement">GTK_CORNER_TOP_LEFT</property> + + <child> + <placeholder/> + </child> + </widget> + <packing> + <property name="padding">0</property> + <property name="expand">True</property> + <property name="fill">True</property> + </packing> + </child> + + <child> + <widget class="GtkVButtonBox" id="vbuttonbox4"> + <property name="visible">True</property> + <property name="layout_style">GTK_BUTTONBOX_START</property> + <property name="spacing">6</property> + + <child> + <widget class="GtkButton" id="button18"> + <property name="visible">True</property> + <property name="can_default">True</property> + <property name="can_focus">True</property> + <property name="label">gtk-add</property> + <property name="use_stock">True</property> + <property name="relief">GTK_RELIEF_NORMAL</property> + <property name="focus_on_click">True</property> + <signal name="clicked" handler="OnAddIcon" last_modification_time="Wed, 17 May 2006 11:25:29 GMT"/> + </widget> + </child> + + <child> + <widget class="GtkButton" id="button19"> + <property name="visible">True</property> + <property name="can_default">True</property> + <property name="can_focus">True</property> + <property name="label">gtk-edit</property> + <property name="use_stock">True</property> + <property name="relief">GTK_RELIEF_NORMAL</property> + <property name="focus_on_click">True</property> + <signal name="clicked" handler="OnEditIcon" last_modification_time="Wed, 17 May 2006 11:24:58 GMT"/> + </widget> + </child> + + <child> + <widget class="GtkButton" id="button20"> + <property name="visible">True</property> + <property name="can_default">True</property> + <property name="can_focus">True</property> + <property name="label">gtk-delete</property> + <property name="use_stock">True</property> + <property name="relief">GTK_RELIEF_NORMAL</property> + <property name="focus_on_click">True</property> + <signal name="clicked" handler="OnRemoveIcon" last_modification_time="Wed, 17 May 2006 11:25:18 GMT"/> + </widget> + </child> + </widget> + <packing> + <property name="padding">0</property> + <property name="expand">False</property> + <property name="fill">False</property> + </packing> + </child> + </widget> + <packing> + <property name="padding">0</property> + <property name="expand">True</property> + <property name="fill">True</property> + </packing> + </child> + </widget> + </child> +</widget> + +<widget class="GtkDialog" id="AddNonContainerDialog"> + <property name="visible">True</property> + <property name="title" translatable="yes">Widget Designer</property> + <property name="type">GTK_WINDOW_TOPLEVEL</property> + <property name="window_position">GTK_WIN_POS_NONE</property> + <property name="modal">True</property> + <property name="resizable">False</property> + <property name="destroy_with_parent">False</property> + <property name="decorated">True</property> + <property name="skip_taskbar_hint">False</property> + <property name="skip_pager_hint">False</property> + <property name="type_hint">GDK_WINDOW_TYPE_HINT_DIALOG</property> + <property name="gravity">GDK_GRAVITY_NORTH_WEST</property> + <property name="focus_on_map">True</property> + <property name="urgency_hint">False</property> + <property name="has_separator">True</property> + + <child internal-child="vbox"> + <widget class="GtkVBox" id="dialog-vbox5"> + <property name="visible">True</property> + <property name="homogeneous">False</property> + <property name="spacing">0</property> + + <child internal-child="action_area"> + <widget class="GtkHButtonBox" id="dialog-action_area5"> + <property name="visible">True</property> + <property name="layout_style">GTK_BUTTONBOX_END</property> + + <child> + <widget class="GtkButton" id="cancelbutton5"> + <property name="visible">True</property> + <property name="can_default">True</property> + <property name="can_focus">True</property> + <property name="label">gtk-cancel</property> + <property name="use_stock">True</property> + <property name="relief">GTK_RELIEF_NORMAL</property> + <property name="focus_on_click">True</property> + <property name="response_id">-6</property> + </widget> + </child> + + <child> + <widget class="GtkButton" id="okbutton"> + <property name="visible">True</property> + <property name="can_default">True</property> + <property name="has_default">True</property> + <property name="can_focus">True</property> + <property name="label">gtk-ok</property> + <property name="use_stock">True</property> + <property name="relief">GTK_RELIEF_NORMAL</property> + <property name="focus_on_click">True</property> + <property name="response_id">-5</property> + </widget> + </child> + </widget> + <packing> + <property name="padding">0</property> + <property name="expand">False</property> + <property name="fill">True</property> + <property name="pack_type">GTK_PACK_END</property> + </packing> + </child> + + <child> + <widget class="GtkHBox" id="hbox23"> + <property name="visible">True</property> + <property name="homogeneous">False</property> + <property name="spacing">0</property> + + <child> + <widget class="GtkImage" id="image2"> + <property name="visible">True</property> + <property name="stock">gtk-dialog-warning</property> + <property name="icon_size">6</property> + <property name="xalign">0</property> + <property name="yalign">0</property> + <property name="xpad">0</property> + <property name="ypad">0</property> + </widget> + <packing> + <property name="padding">0</property> + <property name="expand">False</property> + <property name="fill">False</property> + </packing> + </child> + + <child> + <widget class="GtkVBox" id="mainBox"> + <property name="border_width">6</property> + <property name="visible">True</property> + <property name="homogeneous">False</property> + <property name="spacing">6</property> + + <child> + <widget class="GtkLabel" id="label22"> + <property name="width_request">449</property> + <property name="visible">True</property> + <property name="label" translatable="yes">You are trying to add a non-container widget into the main window. In <b>GTK#</b>, widget positioning is controlled by a special type of widgets called <b>Container</b> widgets. If you don't place the widget into a container, it will fill the all the available space in the window. Are you sure you want to continue?</property> + <property name="use_underline">False</property> + <property name="use_markup">True</property> + <property name="justify">GTK_JUSTIFY_LEFT</property> + <property name="wrap">True</property> + <property name="selectable">False</property> + <property name="xalign">0</property> + <property name="yalign">0.5</property> + <property name="xpad">0</property> + <property name="ypad">0</property> + <property name="ellipsize">PANGO_ELLIPSIZE_NONE</property> + <property name="width_chars">-1</property> + <property name="single_line_mode">False</property> + <property name="angle">0</property> + </widget> + <packing> + <property name="padding">0</property> + <property name="expand">False</property> + <property name="fill">False</property> + </packing> + </child> + + <child> + <widget class="GtkHBox" id="hbox24"> + <property name="visible">True</property> + <property name="homogeneous">False</property> + <property name="spacing">6</property> + + <child> + <widget class="GtkLabel" id="label23"> + <property name="visible">True</property> + <property name="label" translatable="yes">To know more about this topic see the article:</property> + <property name="use_underline">False</property> + <property name="use_markup">False</property> + <property name="justify">GTK_JUSTIFY_LEFT</property> + <property name="wrap">False</property> + <property name="selectable">False</property> + <property name="xalign">0.5</property> + <property name="yalign">0.5</property> + <property name="xpad">0</property> + <property name="ypad">0</property> + <property name="ellipsize">PANGO_ELLIPSIZE_NONE</property> + <property name="width_chars">-1</property> + <property name="single_line_mode">False</property> + <property name="angle">0</property> + </widget> + <packing> + <property name="padding">0</property> + <property name="expand">False</property> + <property name="fill">False</property> + </packing> + </child> + + <child> + <widget class="GtkButton" id="linkButton"> + <property name="visible">True</property> + <property name="can_focus">True</property> + <property name="label" translatable="yes">GTK# Widget Layout and Packing</property> + <property name="use_underline">True</property> + <property name="relief">GTK_RELIEF_NONE</property> + <property name="focus_on_click">True</property> + </widget> + <packing> + <property name="padding">0</property> + <property name="expand">False</property> + <property name="fill">False</property> + </packing> + </child> + </widget> + <packing> + <property name="padding">0</property> + <property name="expand">True</property> + <property name="fill">True</property> + </packing> + </child> + + <child> + <widget class="GtkCheckButton" id="showCheck"> + <property name="visible">True</property> + <property name="can_focus">True</property> + <property name="label" translatable="yes">Don't show this message again</property> + <property name="use_underline">True</property> + <property name="relief">GTK_RELIEF_NORMAL</property> + <property name="focus_on_click">True</property> + <property name="active">False</property> + <property name="inconsistent">False</property> + <property name="draw_indicator">True</property> + </widget> + <packing> + <property name="padding">0</property> + <property name="expand">False</property> + <property name="fill">False</property> + <property name="pack_type">GTK_PACK_END</property> + </packing> + </child> + </widget> + <packing> + <property name="padding">0</property> + <property name="expand">True</property> + <property name="fill">True</property> + </packing> + </child> + </widget> + <packing> + <property name="padding">0</property> + <property name="expand">False</property> + <property name="fill">False</property> + </packing> + </child> + </widget> + </child> +</widget> + +</glade-interface> diff --git a/main/src/addins/MonoDevelop.GtkCore2/libstetic/undo/ActionDiffAdaptor.cs b/main/src/addins/MonoDevelop.GtkCore2/libstetic/undo/ActionDiffAdaptor.cs new file mode 100644 index 0000000000..880aaea21a --- /dev/null +++ b/main/src/addins/MonoDevelop.GtkCore2/libstetic/undo/ActionDiffAdaptor.cs @@ -0,0 +1,273 @@ + +using System; +using System.Xml; +using System.Collections; +using Stetic.Wrapper; + +namespace Stetic.Undo +{ + class ActionDiffAdaptor: IDiffAdaptor + { + IProject project; + + public ActionDiffAdaptor (IProject project) + { + this.project = project; + } + + public IEnumerable GetChildren (object parent) + { + if (parent is Wrapper.Action) + yield break; + else if (parent is ActionGroup) { + foreach (Wrapper.Action ac in ((ActionGroup)parent).Actions) + if (ac.Name.Length > 0) + yield return ac; + } + else if (parent is ActionGroupCollection) { + foreach (ActionGroup ag in (ActionGroupCollection) parent) + yield return ag; + } + else + throw new NotImplementedException (); + } + + public string GetUndoId (object childObject) + { + if (childObject is ActionGroup) + return ((ActionGroup)childObject).UndoId; + if (childObject is Wrapper.Action) + return ((Wrapper.Action)childObject).UndoId; + + throw new NotImplementedException (); + } + + public object FindChild (object parent, string undoId) + { + foreach (object ob in GetChildren (parent)) + if (GetUndoId (ob) == undoId) { + if ((ob is Wrapper.Action) && ((Wrapper.Action)ob).Name.Length == 0) + continue; + return ob; + } + return null; + } + + public void RemoveChild (object parent, string undoId) + { + object child = FindChild (parent, undoId); + if (child == null) + return; + if (parent is ActionGroup) { + ((ActionGroup)parent).Actions.Remove ((Wrapper.Action)child); + } else if (parent is ActionGroupCollection) { + ((ActionGroupCollection)parent).Remove ((ActionGroup)child); + } else + throw new NotImplementedException (); + } + + public void AddChild (object parent, XmlElement node, string insertAfter) + { + object data = DeserializeChild (node); + if (parent is ActionGroup) { + ActionGroup group = (ActionGroup) parent; + if (insertAfter == null) + group.Actions.Insert (0, (Wrapper.Action) data); + else { + for (int n=0; n<group.Actions.Count; n++) { + if (group.Actions [n].UndoId == insertAfter) { + group.Actions.Insert (n+1, (Wrapper.Action) data); + return; + } + } + group.Actions.Add ((Wrapper.Action) data); + } + } + if (parent is ActionGroupCollection) { + ActionGroupCollection col = (ActionGroupCollection) parent; + if (insertAfter == null) + col.Insert (0, (ActionGroup) data); + else { + for (int n=0; n<col.Count; n++) { + if (col [n].UndoId == insertAfter) { + col.Insert (n+1, (ActionGroup) data); + return; + } + } + col.Add ((ActionGroup) data); + } + } + } + + public IEnumerable GetProperties (object obj) + { + Wrapper.Action action = obj as Wrapper.Action; + if (action != null) { + foreach (ItemGroup iset in action.ClassDescriptor.ItemGroups) { + foreach (ItemDescriptor it in iset) { + PropertyDescriptor prop = it as PropertyDescriptor; + + if (!prop.VisibleFor (action.Wrapped) || !prop.CanWrite) + continue; + + object value = prop.GetValue (action.Wrapped); + + // If the property has its default value, we don't need to check it + if (value == null || (prop.HasDefault && prop.IsDefaultValue (value))) + continue; + + yield return it; + } + } + } + else if (obj is ActionGroup) + yield return "name"; // ActionGroup only has one property, the name + else + yield break; + } + + public XmlElement SerializeChild (object child) + { + XmlDocument doc = new XmlDocument (); + ObjectWriter ow = new ObjectWriter (doc, FileFormat.Native); + + if (child is Wrapper.Action) { + return ((Wrapper.Action)child).Write (ow); + } else if (child is ActionGroup) { + return ((ActionGroup)child).Write (ow); + } + throw new NotImplementedException (); + } + + public object DeserializeChild (XmlElement data) + { + ObjectReader or = new ObjectReader (project, FileFormat.Native); + if (data.LocalName == "action") { + Wrapper.Action ac = new Wrapper.Action (); + ac.Read (or, data); + return ac; + } else if (data.LocalName == "action-group") { + ActionGroup ac = new ActionGroup (); + ac.Read (or, data); + return ac; + } + throw new NotImplementedException (); + } + + public IDiffAdaptor GetChildAdaptor (object child) + { + return this; + } + + public object GetPropertyByName (object obj, string name) + { + if (obj is Wrapper.Action) { + if (name == "id") name = "Name"; + return ((Wrapper.Action)obj).ClassDescriptor [name]; + } + else if (obj is ActionGroup) { + if (name == "name") return name; + } + throw new NotImplementedException (); + } + + public string GetPropertyName (object property) + { + if (property is PropertyDescriptor) { + PropertyDescriptor prop = (PropertyDescriptor) property; + if (prop.Name == "Name") return "id"; + return prop.Name; + } + else if (property is string) + return (string) property; + + throw new NotImplementedException (); + } + + public string GetPropertyValue (object obj, object property) + { + if (obj is Wrapper.Action) { + PropertyDescriptor prop = (PropertyDescriptor) property; + object val = prop.GetValue (((Wrapper.Action)obj).Wrapped); + return prop.ValueToString (val); + } + else if (obj is ActionGroup) { + if (((string)property) == "name") + return ((ActionGroup)obj).Name; + } + throw new NotImplementedException (); + } + + public void SetPropertyValue (object obj, string name, string value) + { + if (obj is Wrapper.Action) { + if (name == "id") name = "Name"; + PropertyDescriptor prop = (PropertyDescriptor) GetPropertyByName (obj, name); + if (prop == null) + throw new InvalidOperationException ("Property '" + name + "' not found in object of type: " + obj.GetType ()); + prop.SetValue (((Wrapper.Action)obj).Wrapped, prop.StringToValue (value)); + return; + } + else if (obj is ActionGroup) { + if (name == "name") { + ((ActionGroup)obj).Name = value; + return; + } + } + throw new NotImplementedException (); + } + + public void ResetPropertyValue (object obj, string name) + { + if (obj is Wrapper.Action) { + if (name == "id") name = "Name"; + PropertyDescriptor prop = (PropertyDescriptor) GetPropertyByName (obj, name); + prop.ResetValue (((Wrapper.Action)obj).Wrapped); + } + } + + public IEnumerable GetSignals (object obj) + { + if (obj is Wrapper.Action) { + foreach (Signal s in ((Wrapper.Action)obj).Signals) + yield return s; + } + else + yield break; + } + + public object GetSignal (object obj, string name, string handler) + { + foreach (Signal s in ((Wrapper.Action)obj).Signals) { + if (s.SignalDescriptor.Name == name && s.Handler == handler) + return s; + } + return null; + } + + public void GetSignalInfo (object signal, out string name, out string handler) + { + Signal s = (Signal) signal; + name = s.SignalDescriptor.Name; + handler = s.Handler; + } + + public void AddSignal (object obj, string name, string handler) + { + SignalDescriptor sd = (SignalDescriptor) ((Wrapper.Action)obj).ClassDescriptor.SignalGroups.GetItem (name); + Signal sig = new Signal (sd); + sig.Handler = handler; + ((Wrapper.Action)obj).Signals.Add (sig); + } + + public void RemoveSignal (object obj, string name, string handler) + { + foreach (Signal sig in ((Wrapper.Action)obj).Signals) { + if (sig.SignalDescriptor.Name == name && sig.Handler == handler) { + ((Wrapper.Action)obj).Signals.Remove (sig); + return; + } + } + } + } +} diff --git a/main/src/addins/MonoDevelop.GtkCore2/libstetic/undo/DiffGenerator.cs b/main/src/addins/MonoDevelop.GtkCore2/libstetic/undo/DiffGenerator.cs new file mode 100644 index 0000000000..3db856c08b --- /dev/null +++ b/main/src/addins/MonoDevelop.GtkCore2/libstetic/undo/DiffGenerator.cs @@ -0,0 +1,319 @@ + +using System; +using System.Collections; +using System.Xml; +using Stetic.Wrapper; + +namespace Stetic.Undo +{ + class DiffGenerator + { + IDiffAdaptor currentStatusAdaptor; + IDiffAdaptor newStatusAdaptor; + + public DiffGenerator () + { + } + + public DiffGenerator (IDiffAdaptor currentStatusAdaptor, IDiffAdaptor newStatusAdaptor) + { + this.currentStatusAdaptor = currentStatusAdaptor; + this.newStatusAdaptor = newStatusAdaptor; + } + + public IDiffAdaptor CurrentStatusAdaptor { + get { return currentStatusAdaptor; } + set { currentStatusAdaptor = value; } + } + + public IDiffAdaptor NewStatusAdaptor { + get { return newStatusAdaptor; } + set { newStatusAdaptor = value; } + } + + internal ObjectDiff GetDiff (object oldStatus, object newStatus) + { + PropertyDiff[] propChanges = GetPropertyDiff (currentStatusAdaptor, oldStatus, newStatusAdaptor, newStatus); + PropertyDiff[] signalChanges = GetSignalDiff (currentStatusAdaptor, oldStatus, newStatusAdaptor, newStatus); + + ArrayList changes = new ArrayList (); + Hashtable foundChildren = new Hashtable (); + + // Register changed and deleted child elements + foreach (object oldChild in currentStatusAdaptor.GetChildren (oldStatus)) { + string cid = currentStatusAdaptor.GetUndoId (oldChild); + if (cid != null && cid.Length > 0) { + object newChild = newStatusAdaptor.FindChild (newStatus, cid); + if (newChild != null) { + // ChildCreate will work even if the packing element is null + ObjectDiff odiff = GetChildDiff (oldChild, newChild); + if (odiff != null) { + ChildDiff cdiff = new ChildDiff (); + cdiff.Id = cid; + cdiff.Operation = DiffOperation.Update; + cdiff.Diff = odiff; + changes.Add (cdiff); + } + foundChildren [cid] = cid; + } else { + ChildDiff cdiff = new ChildDiff (); + cdiff.Id = cid; + cdiff.Operation = DiffOperation.Remove; + changes.Add (cdiff); + } + } else { + throw new InvalidOperationException ("Found an element of type '" + oldChild.GetType () + "' without ID"); + } + } + + // Register new elements + + string lastWidgetId = null; + foreach (object newChildElem in newStatusAdaptor.GetChildren (newStatus)) { + string cid = newStatusAdaptor.GetUndoId (newChildElem); + if (cid.Length > 0) { + if (!foundChildren.ContainsKey (cid)) { + ChildDiff cdiff = new ChildDiff (); + cdiff.Id = cid; + cdiff.Operation = DiffOperation.Add; + cdiff.AddContent = newStatusAdaptor.SerializeChild (newChildElem); + cdiff.InsertAfter = lastWidgetId; + changes.Add (cdiff); + } + } else + throw new InvalidOperationException ("Found an element of type '" + newChildElem.GetType () + "' without ID"); + + lastWidgetId = cid; + } + + ChildDiff[] childChanges = null; + if (changes.Count > 0) + childChanges = (ChildDiff[]) changes.ToArray (typeof(ChildDiff)); + + if (childChanges != null || propChanges != null || signalChanges != null) { + ObjectDiff dif = new ObjectDiff (); + dif.PropertyChanges = propChanges; + dif.SignalChanges = signalChanges; + dif.ChildChanges = childChanges; + return dif; + } + else + return null; + } + + public void ApplyDiff (object status, ObjectDiff diff) + { + if (diff.PropertyChanges != null) + ApplyPropertyChanges (diff.PropertyChanges, currentStatusAdaptor, status); + + if (diff.SignalChanges != null) + ApplySignalChanges (diff.SignalChanges, currentStatusAdaptor, status); + + if (diff.ChildChanges != null) { + foreach (ChildDiff cdiff in diff.ChildChanges) { + if (cdiff.Operation == DiffOperation.Update) { + object statusChild = currentStatusAdaptor.FindChild (status, cdiff.Id); + ApplyChildDiff (statusChild, cdiff.Diff); + } else if (cdiff.Operation == DiffOperation.Remove) { + // Remove the child + currentStatusAdaptor.RemoveChild (status, cdiff.Id); + } else { + // Add the child at the correct position + currentStatusAdaptor.AddChild (status, cdiff.AddContent, cdiff.InsertAfter); + } + } + } + } + + protected virtual ObjectDiff GetChildDiff (object oldChild, object newChild) + { + DiffGenerator childGenerator = new DiffGenerator (); + childGenerator.CurrentStatusAdaptor = currentStatusAdaptor.GetChildAdaptor (oldChild); + childGenerator.NewStatusAdaptor = newStatusAdaptor.GetChildAdaptor (newChild); + + return childGenerator.GetDiff (oldChild, newChild); + } + + protected virtual void ApplyChildDiff (object child, ObjectDiff cdiff) + { + DiffGenerator childGenerator = new DiffGenerator (); + childGenerator.CurrentStatusAdaptor = currentStatusAdaptor.GetChildAdaptor (child); + childGenerator.ApplyDiff (child, cdiff); + } + + protected virtual PropertyDiff[] GetPropertyDiff (IDiffAdaptor currentAdaptor, object currentObject, IDiffAdaptor newAdaptor, object newObject) + { + ArrayList changes = new ArrayList (); + Hashtable found = new Hashtable (); + + // Look for modified and deleted elements + if (currentObject != null) { + foreach (object oldProp in currentAdaptor.GetProperties (currentObject)) { + string name = currentAdaptor.GetPropertyName (oldProp); + object newProp = newObject != null ? newAdaptor.GetPropertyByName (newObject, name) : null; + if (newProp == null) + changes.Add (new PropertyDiff (DiffOperation.Remove, name, null)); + else { + found [name] = found; + string newValue = newAdaptor.GetPropertyValue (newObject, newProp); + if (newValue != currentAdaptor.GetPropertyValue (currentObject, oldProp)) + changes.Add (new PropertyDiff (DiffOperation.Update, name, newValue)); + } + } + } + + // Look for new elements + if (newObject != null) { + foreach (object newProp in newAdaptor.GetProperties (newObject)) { + string name = newAdaptor.GetPropertyName (newProp); + if (!found.ContainsKey (name)) + changes.Add (new PropertyDiff (DiffOperation.Add, name, newAdaptor.GetPropertyValue (newObject, newProp))); + } + } + + if (changes.Count == 0) + return null; + return (PropertyDiff[]) changes.ToArray (typeof(PropertyDiff)); + } + + protected virtual PropertyDiff[] GetSignalDiff (IDiffAdaptor currentAdaptor, object currentObject, IDiffAdaptor newAdaptor, object newObject) + { + ArrayList changes = new ArrayList (); + Hashtable found = new Hashtable (); + + // Look for modified and deleted elements + if (currentObject != null) { + foreach (object oldProp in currentAdaptor.GetSignals (currentObject)) { + string name; + string handler; + currentAdaptor.GetSignalInfo (oldProp, out name, out handler); + object newProp = newObject != null ? newAdaptor.GetSignal (newObject, name, handler) : null; + if (newProp == null) + changes.Add (new PropertyDiff (DiffOperation.Remove, name, handler)); + found [name + " " + handler] = found; + } + } + + // Look for new elements + if (newObject != null) { + foreach (object newProp in newAdaptor.GetSignals (newObject)) { + string name; + string handler; + newAdaptor.GetSignalInfo (newProp, out name, out handler); + if (!found.ContainsKey (name + " " + handler)) + changes.Add (new PropertyDiff (DiffOperation.Add, name, handler)); + } + } + + if (changes.Count == 0) + return null; + return (PropertyDiff[]) changes.ToArray (typeof(PropertyDiff)); + } + + public virtual void ApplyPropertyChanges (PropertyDiff[] changes, IDiffAdaptor adaptor, object obj) + { + foreach (PropertyDiff pdif in changes) { + if (pdif.Operation == DiffOperation.Add || pdif.Operation == DiffOperation.Update) + adaptor.SetPropertyValue (obj, pdif.Name, pdif.Text); + else + adaptor.ResetPropertyValue (obj, pdif.Name); + } + } + + public virtual void ApplySignalChanges (PropertyDiff[] changes, IDiffAdaptor adaptor, object obj) + { + foreach (PropertyDiff pdif in changes) { + if (pdif.Operation == DiffOperation.Add) + adaptor.AddSignal (obj, pdif.Name, pdif.Text); + else + adaptor.RemoveSignal (obj, pdif.Name, pdif.Text); + } + } + } + + + class PropertyDiff + { + public PropertyDiff (DiffOperation Operation, string Name, string Text) + { + this.Operation = Operation; + this.Name = Name; + this.Text = Text; + } + + public DiffOperation Operation; + public string Name; + public string Text; + } + + enum DiffOperation + { + Add, + Remove, + Update + } + + class ChildDiff + { + public string Id; + public DiffOperation Operation; + public XmlElement AddContent; + public string InsertAfter; + public ObjectDiff Diff; + + public string ToString (int indent) + { + string ind = new string (' ', indent); + string s = ind + Operation + " id:" + Id + "\n"; + if (Operation == DiffOperation.Update) + s += Diff.ToString (indent + 2) + "\n"; + if (Operation == DiffOperation.Add) { + s += ind + " InsertAfter: " + InsertAfter + "\n"; + s += ind + " Content: " + AddContent.OuterXml + "\n"; + } + return s; + } + } + + class ObjectDiff + { + public PropertyDiff[] PropertyChanges; + public PropertyDiff[] SignalChanges; + public ChildDiff[] ChildChanges; + + public override string ToString () + { + return ToString (0); + } + + internal string ToString (int indent) + { + string ind = new string (' ', indent); + string s = ind + "ObjectDiff:\n"; + + if (PropertyChanges != null) { + s += ind + " Properties:\n"; + foreach (PropertyDiff d in PropertyChanges) { + s += ind + " " + d.Operation + ": " + d.Name; + if (d.Operation != DiffOperation.Remove) + s += " = " + d.Text; + s += "\n"; + } + } + + if (SignalChanges != null) { + s += ind + " Signals:\n"; + foreach (PropertyDiff d in SignalChanges) + s += ind + " " + d.Operation + ": " + d.Name + " - " + d.Text + "\n"; + } + + if (ChildChanges != null) { + s += ind + " Children:\n"; + foreach (ChildDiff cd in ChildChanges) + s += cd.ToString (indent + 4); + } + + return s; + } + } +} diff --git a/main/src/addins/MonoDevelop.GtkCore2/libstetic/undo/IDiffAdaptor.cs b/main/src/addins/MonoDevelop.GtkCore2/libstetic/undo/IDiffAdaptor.cs new file mode 100644 index 0000000000..aab6567c81 --- /dev/null +++ b/main/src/addins/MonoDevelop.GtkCore2/libstetic/undo/IDiffAdaptor.cs @@ -0,0 +1,31 @@ + +using System; +using System.Collections; +using System.Xml; + +namespace Stetic.Undo +{ + interface IDiffAdaptor + { + IEnumerable GetChildren (object parent); + string GetUndoId (object childObject); + object FindChild (object parent, string undoId); + void RemoveChild (object parent, string undoId); + void AddChild (object parent, XmlElement data, string insertAfter); + XmlElement SerializeChild (object child); + IDiffAdaptor GetChildAdaptor (object child); + + IEnumerable GetProperties (object obj); + object GetPropertyByName (object obj, string name); + string GetPropertyName (object property); + string GetPropertyValue (object obj, object property); + void SetPropertyValue (object obj, string name, string value); + void ResetPropertyValue (object obj, string name); + + IEnumerable GetSignals (object obj); + object GetSignal (object obj, string name, string handler); + void GetSignalInfo (object signal, out string name, out string handler); + void AddSignal (object obj, string name, string handler); + void RemoveSignal (object obj, string name, string handler); + } +} diff --git a/main/src/addins/MonoDevelop.GtkCore2/libstetic/undo/UndoManager.cs b/main/src/addins/MonoDevelop.GtkCore2/libstetic/undo/UndoManager.cs new file mode 100644 index 0000000000..12e5f14d84 --- /dev/null +++ b/main/src/addins/MonoDevelop.GtkCore2/libstetic/undo/UndoManager.cs @@ -0,0 +1,315 @@ + +using System; +using System.Xml; +using System.Collections; +using Stetic.Wrapper; + +namespace Stetic +{ + // This class holds an xml tree which describes the whole widget structure being designed. + // It is used by the Undo/Redo infrastructure to keep track of changes in widgets. + public class UndoManager + { + Hashtable elements = new Hashtable (); + XmlDocument doc; + ObjectWrapper root; + AtomicChangeTracker atomicChangeTracker; + bool isDefaultManager; + + public event UndoCheckpointHandler UndoCheckpoint; + + public UndoManager () + { + atomicChangeTracker = new AtomicChangeTracker (); + atomicChangeTracker.undoManager = this; + } + + internal UndoManager (bool isDefaultManager): this () + { + this.isDefaultManager = isDefaultManager; + } + + public void SetRoot (ObjectWrapper wrapper) + { + root = wrapper; + wrapper.UndoManager = this; + elements.Clear (); + + doc = new XmlDocument (); + UndoWriter writer = new UndoWriter (doc, this); + writer.WriteObject (wrapper); + } + + internal bool CanNotifyChanged (ObjectWrapper wrapper) + { + if (!InAtomicChange) { + if (IsRegistered (wrapper) && UndoCheckpoint != null) + UndoCheckpoint (this, new UndoCheckpointEventArgs (new ObjectWrapper[] { wrapper })); + return true; + } else + return atomicChangeTracker.ProcessChange (wrapper); + } + + public IAtomicChange AtomicChange { + get { + atomicChangeTracker.Count++; + return atomicChangeTracker; + } + } + + public bool InAtomicChange { + get { return atomicChangeTracker.InAtomicChange; } + } + + // This method can be called by containers to register new objects in the tree. + // Unless an object is registered in this way, no status will be tracked for it. + // The provided status element must be a direct or indirect child of the parent status. + internal void RegisterObject (ObjectWrapper w, XmlElement status) + { + VerifyManager (); + + if (IsRegistered (w)) + throw new InvalidOperationException ("Object already registered: " + w.GetType ()); + + elements [w] = GetLocalElement (status); + + w.Disposed += OnObjectDisposed; + } + + void OnObjectDisposed (object s, EventArgs a) + { + ObjectWrapper w = (ObjectWrapper) s; + UnregisterObject (w); + w.Disposed -= OnObjectDisposed; + } + + // This method can be called to update the xml tree, for example when a change in the + // object is detected. + internal void UpdateObjectStatus (ObjectWrapper w, XmlElement status) + { + VerifyManager (); + + XmlElement oldElem = (XmlElement) elements [w]; + if (oldElem == null) + throw new InvalidOperationException ("Could not update unregistered object of type " + w.GetType ()); + + if (oldElem != status) { + XmlElement newElem = GetLocalElement (status); + if (oldElem.ParentNode != null) { + oldElem.ParentNode.ReplaceChild (newElem, oldElem); + elements [w] = newElem; + } else { + if (w != root) + throw new InvalidOperationException ("Root element does not match the root widget: " + w.GetType ()); + elements [w] = newElem; + } + } + } + + // Returns the xml that describes the specified widget (including information for all + // children of the widget). + internal XmlElement GetObjectStatus (ObjectWrapper w) + { + VerifyManager (); + + XmlElement elem = (XmlElement) elements [w]; + if (elem == null) + throw new InvalidOperationException ("No status found for object of type " + w.GetType ()); + return elem; + } + + internal bool IsRegistered (ObjectWrapper w) + { + return elements.ContainsKey (w); + } + + internal void UnregisterObject (ObjectWrapper w) + { + VerifyManager (); + elements.Remove (w); + } + + void VerifyManager () + { + if (isDefaultManager) + throw new InvalidOperationException ("The default UndoManager can't track changes in objects."); + } + + XmlElement GetLocalElement (XmlElement elem) + { + if (elem.OwnerDocument != doc) + throw new InvalidOperationException ("Invalid document owner."); + return elem; + } + + internal void NotifyUndoCheckpoint (ObjectWrapper[] obs) + { + if (UndoCheckpoint != null) + UndoCheckpoint (this, new UndoCheckpointEventArgs (obs)); + } + + internal void Dump () + { + Console.WriteLine ("--------------------------------------"); + Console.WriteLine ("UNDO STATUS:"); + Console.WriteLine (GetObjectStatus (root).OuterXml); + Console.WriteLine ("--------------------------------------"); + } + } + + public delegate void UndoCheckpointHandler (object sender, UndoCheckpointEventArgs args); + + public class UndoCheckpointEventArgs: EventArgs + { + ObjectWrapper[] objects; + + internal UndoCheckpointEventArgs (ObjectWrapper[] objects) + { + this.objects = objects; + } + + public ObjectWrapper[] ModifiedObjects { + get { return objects; } + } + } + + // This is a special writer use to generate status info from widgets. + // This writer won't recurse through objects which are already registered + // in the provided UndoManager. + class UndoWriter: ObjectWriter + { + UndoManager undoManager; + bool allowMarkers = true; + + public UndoWriter (XmlDocument doc, UndoManager undoManager): base (doc, FileFormat.Native) + { + this.undoManager = undoManager; + CreateUndoInfo = true; + } + + public override XmlElement WriteObject (ObjectWrapper wrapper) + { + Wrapper.Widget ww = wrapper as Wrapper.Widget; + + // If the object is already registered, skip it (just create a dummy object) + if (allowMarkers && ww != null && undoManager.IsRegistered (ww) && !ww.RequiresUndoStatusUpdate) { + XmlElement marker = XmlDocument.CreateElement ("widget"); + marker.SetAttribute ("unchanged_marker","yes"); + return marker; + } + + // Don't allow markers in indirect children, since those are not checked + // when creating the diff + bool oldAllow = allowMarkers; + allowMarkers = false; + XmlElement elem = base.WriteObject (wrapper); + allowMarkers = oldAllow; + + if (ww != null) { + ww.RequiresUndoStatusUpdate = false; + } + + // Register the object, so it is correctly bound to this xml element + if (undoManager.IsRegistered (wrapper)) + undoManager.UnregisterObject (wrapper); + undoManager.RegisterObject (wrapper, elem); + + return elem; + } + } + + class UndoReader: ObjectReader + { + UndoManager undoManager; + + public UndoReader (IProject proj, FileFormat format, UndoManager undoManager): base (proj, format) + { + this.undoManager = undoManager; + } + + public override ObjectWrapper ReadObject (XmlElement elem, ObjectWrapper root) + { + ObjectWrapper ww = base.ReadObject (elem, root); + if (ww is Widget) + undoManager.RegisterObject ((Widget)ww, elem); + return ww; + } + + public override void ReadExistingObject (ObjectWrapper wrapper, XmlElement elem) + { + base.ReadExistingObject (wrapper, elem); + if (wrapper is Widget) + undoManager.RegisterObject ((Widget)wrapper, elem); + } + } + + public interface IAtomicChange: IDisposable + { + void Delay (); + } + + class AtomicChangeTracker: IAtomicChange + { + public int Count; + public ArrayList ChangeEventPending = new ArrayList (); + public UndoManager undoManager; + bool delayed; + + public bool InAtomicChange { + get { return Count > 0; } + } + + public bool ProcessChange (ObjectWrapper wrapper) + { + if (!ChangeEventPending.Contains (wrapper)) { + ChangeEventPending.Add (wrapper); + delayed = false; + } + return false; + } + + public void Delay () + { + delayed = true; + } + + public void Dispose () + { + if (Count == 0) + return; + + if (Count == 1) { + // The change events fired here may generate changes in other + // objects. Those changes will also be included in the transaction. + // So, the ChangeEventPending array may grow while calling NotifyChanged, + // and that's ok. + + for (int n=0; n < ChangeEventPending.Count; n++) { + ((ObjectWrapper)ChangeEventPending[n]).FireObjectChangedEvent (); + } + + // Remove from the list the widgets that have been disposed. It means that + // they have been deleted. That change will be recorded by their parents. + // Remove as well wrappers that are not registered, since there won't be + // status information for them. + for (int n=0; n<ChangeEventPending.Count; n++) { + ObjectWrapper w = (ObjectWrapper)ChangeEventPending[n]; + if (w.IsDisposed || !undoManager.IsRegistered (w)) { + ChangeEventPending.RemoveAt (n); + n--; + } + } + + ObjectWrapper[] obs = (ObjectWrapper[]) ChangeEventPending.ToArray (typeof(ObjectWrapper)); + ChangeEventPending.Clear (); + Count = 0; + + if (!delayed) + undoManager.NotifyUndoCheckpoint (obs); + delayed = false; + } + else + Count--; + } + } +} diff --git a/main/src/addins/MonoDevelop.GtkCore2/libstetic/undo/XmlDiffAdaptor.cs b/main/src/addins/MonoDevelop.GtkCore2/libstetic/undo/XmlDiffAdaptor.cs new file mode 100644 index 0000000000..5d30c15078 --- /dev/null +++ b/main/src/addins/MonoDevelop.GtkCore2/libstetic/undo/XmlDiffAdaptor.cs @@ -0,0 +1,230 @@ + +using System; +using System.Collections; +using System.Xml; + +namespace Stetic.Undo +{ + class XmlDiffAdaptor: IDiffAdaptor + { + string childElementName; + string propsElementName; + bool processProperties = true; + XmlDiffAdaptor childAdaptor; + + public XmlDiffAdaptor ChildAdaptor { + get { return childAdaptor; } + set { childAdaptor = value; } + } + + public string ChildElementName { + get { return childElementName; } + set { childElementName = value; } + } + + public string PropsElementName { + get { return propsElementName; } + set { propsElementName = value; } + } + + public bool ProcessProperties { + get { return processProperties; } + set { processProperties = value; } + } + + public IEnumerable GetChildren (object parent) + { + if (childElementName != null) + return ((XmlElement)parent).SelectNodes (childElementName); + else + return new object[0]; + } + + public string GetUndoId (object childObject) + { + return ((XmlElement)childObject).GetAttribute ("undoId"); + } + + public object FindChild (object parent, string undoId) + { + return ((XmlElement) parent).SelectSingleNode (childElementName + "[@undoId='" + undoId + "']"); + } + + public void RemoveChild (object parent, string undoId) + { + XmlElement elem = (XmlElement) parent; + XmlElement child = (XmlElement) elem.SelectSingleNode (childElementName + "[@undoId='" + undoId + "']"); + if (child != null) + elem.RemoveChild (child); + } + + public void AddChild (object parent, XmlElement newNode, string insertAfter) + { + XmlElement status = (XmlElement) parent; + if (newNode.OwnerDocument != status.OwnerDocument) + newNode = (XmlElement) status.OwnerDocument.ImportNode (newNode, true); + + if (insertAfter != null) { + XmlElement statusChild = (XmlElement) status.SelectSingleNode (childElementName + "[@undoId='" + insertAfter + "']"); + if (statusChild != null) + status.InsertAfter (newNode, statusChild); + else + status.AppendChild (newNode); + } else { + if (status.FirstChild != null) + status.InsertBefore (newNode, status.FirstChild); + else + status.AppendChild (newNode); + } + } + + public XmlElement SerializeChild (object child) + { + return (XmlElement) child; + } + + public object DeserializeChild (XmlElement data) + { + return data; + } + + public IDiffAdaptor GetChildAdaptor (object child) + { + if (childAdaptor != null) + return childAdaptor; + else + return this; + } + + XmlElement GetPropsElem (object obj, bool create) + { + if (propsElementName != null) { + XmlElement elem = ((XmlElement)obj) [propsElementName]; + if (elem == null && create) { + elem = ((XmlElement)obj).OwnerDocument.CreateElement (propsElementName); + ((XmlElement)obj).AppendChild (elem); + } + return elem; + } + else + return (XmlElement) obj; + } + + public IEnumerable GetProperties (object obj) + { + XmlElement elem = GetPropsElem (obj, false); + if (elem != null && processProperties) { + XmlAttribute at = elem.Attributes ["name"]; + if (at != null) + yield return at; + at = elem.Attributes ["id"]; + if (at != null) + yield return at; + foreach (XmlElement e in elem.SelectNodes ("property")) + yield return e; + } else + yield break; + } + + public object GetPropertyByName (object obj, string name) + { + XmlElement elem = GetPropsElem (obj, false); + if (elem == null) + return null; + XmlElement prop = (XmlElement) elem.SelectSingleNode ("property[@name='" + name + "']"); + if (prop != null) + return prop; + return elem.Attributes [name]; + } + + public string GetPropertyName (object property) + { + if (property is XmlElement) + return ((XmlElement)property).GetAttribute ("name"); + else + return ((XmlAttribute)property).LocalName; + } + + public string GetPropertyValue (object obj, object property) + { + if (property is XmlElement) + return ((XmlElement)property).InnerText; + else + return ((XmlAttribute)property).Value; + } + + public void SetPropertyValue (object obj, string name, string value) + { + XmlElement elem = GetPropsElem (obj, true); + if (name == "id" || name == "name") { + elem.SetAttribute (name, value); + } else { + XmlElement prop = (XmlElement) elem.SelectSingleNode ("property[@name='" + name + "']"); + if (prop == null) { + prop = elem.OwnerDocument.CreateElement ("property"); + prop.SetAttribute ("name", name); + elem.AppendChild (prop); + } + prop.InnerText = value; + } + } + + public void ResetPropertyValue (object obj, string name) + { + XmlElement elem = GetPropsElem (obj, false); + if (elem == null) + return; + XmlElement prop = (XmlElement) elem.SelectSingleNode ("property[@name='" + name + "']"); + if (prop != null) + elem.RemoveChild (prop); + else { + XmlAttribute at = elem.Attributes [name]; + if (at != null) + elem.Attributes.Remove (at); + } + } + + public IEnumerable GetSignals (object obj) + { + XmlElement elem = GetPropsElem (obj, false); + if (elem != null && processProperties) + return elem.SelectNodes ("signal"); + else + return Type.EmptyTypes; + } + + public object GetSignal (object obj, string name, string handler) + { + XmlElement elem = GetPropsElem (obj, false); + if (elem == null) + return null; + return elem.SelectSingleNode ("signal[@name='" + name + "' and @handler='" + handler + "']"); + } + + public void GetSignalInfo (object signal, out string name, out string handler) + { + XmlElement elem = (XmlElement) signal; + name = elem.GetAttribute ("name"); + handler = elem.GetAttribute ("handler"); + } + + public void AddSignal (object obj, string name, string handler) + { + XmlElement elem = GetPropsElem (obj, true); + XmlElement signal = elem.OwnerDocument.CreateElement ("signal"); + signal.SetAttribute ("name", name); + signal.SetAttribute ("handler", handler); + elem.AppendChild (signal); + } + + public void RemoveSignal (object obj, string name, string handler) + { + XmlElement elem = GetPropsElem (obj, false); + if (elem == null) + return; + XmlElement prop = (XmlElement) elem.SelectSingleNode ("signal[@name='" + name + "' && @handler='" + handler + "']"); + if (prop != null) + elem.RemoveChild (prop); + } + } +} diff --git a/main/src/addins/MonoDevelop.GtkCore2/libstetic/wrapper/AboutDialog.cs b/main/src/addins/MonoDevelop.GtkCore2/libstetic/wrapper/AboutDialog.cs new file mode 100644 index 0000000000..52da310dbf --- /dev/null +++ b/main/src/addins/MonoDevelop.GtkCore2/libstetic/wrapper/AboutDialog.cs @@ -0,0 +1,75 @@ +using System; + +namespace Stetic.Wrapper { + + public class AboutDialog : Window { + + public override void Wrap (object obj, bool initialized) + { + base.Wrap (obj, initialized); + + if (!initialized) { + // FIXME; set from Project eventually + about.Name = "My Application"; + } + } + + Gtk.AboutDialog about { + get { + return (Gtk.AboutDialog)Wrapped; + } + } + + string logo; + public string Logo { + get { + return logo; + } + set { + logo = value; + about.Logo = new Gdk.Pixbuf (logo); + } + } + + // In the underlying representation, WebsiteLabel is always set + // if Website is; if you set Website to something, and WebsiteLabel + // is null, then WebsiteLabel gets set to match Website. There are + // two problems with this for us: + // + // 1. If you type "http..." into Website while WebsiteLabel is + // blank, WebsiteLabel ends up being forcibly set to just "h". + // + // 2. If the user decides s/he wants to get rid of WebsiteLabel, + // they have to actually copy the URL from Website over it. + // + // In Stetic's representation, WebsiteLabel is always "what to show + // *instead of* Website", and if it's empty, then you see the raw URL. + + public string Website { + get { + return about.Website; + } + set { + if (website_label == null) + about.WebsiteLabel = value; + about.Website = value; + } + } + + string website_label; + public string WebsiteLabel { + get { + return website_label; + } + set { + if (value == "" || value == null) { + about.WebsiteLabel = about.Website; + website_label = null; + } else { + about.WebsiteLabel = value; + website_label = value; + } + } + } + } +} diff --git a/main/src/addins/MonoDevelop.GtkCore2/libstetic/wrapper/Action.cs b/main/src/addins/MonoDevelop.GtkCore2/libstetic/wrapper/Action.cs new file mode 100644 index 0000000000..bc6dd51c91 --- /dev/null +++ b/main/src/addins/MonoDevelop.GtkCore2/libstetic/wrapper/Action.cs @@ -0,0 +1,504 @@ + +using System; +using System.Text; +using System.Xml; +using System.CodeDom; +using System.Collections; +using Stetic.Undo; + +namespace Stetic.Wrapper +{ + public sealed class Action: Stetic.Wrapper.Object, IRadioGroupManagerProvider + { + ActionType type; + bool drawAsRadio; + int radioValue; + bool active; + string name; + string accelerator; + ActionGroup group; + + string oldDefaultName; + string nameRoot; + + static RadioActionGroupManager GroupManager = new RadioActionGroupManager (); + + public enum ActionType { + Action, + Toggle, + Radio + } + + public event EventHandler Activated; + public event EventHandler Toggled; + public event Gtk.ChangedHandler Changed; + public event EventHandler Deleted; + + public override void Wrap (object obj, bool initialized) + { + base.Wrap (obj, initialized); + } + + public Gtk.Action GtkAction { + get { return (Gtk.Action) Wrapped; } + } + + public override string Name { + get { + if (name == null || name.Length == 0) { + name = nameRoot = oldDefaultName = GetDefaultName (); + if (group != null) + name = group.GetValidName (this, name); + } + return name; + } + set { + name = nameRoot = value; + if (group != null) + name = group.GetValidName (this, name); + EmitNotify ("Name"); + } + } + + public string Label { + get { return GtkAction.Label; } + set { GtkAction.Label = value; EmitNotify ("Label"); } + } + + public string StockId { + get { return GtkAction.StockId; } + set { GtkAction.StockId = value; EmitNotify ("StockId"); } + } + + public override string WrappedTypeName { + get { + if (type == ActionType.Action) + return "Gtk.Action"; + else if (type == ActionType.Toggle) + return "Gtk.ToggleAction"; + else + return "Gtk.RadioAction"; + } + } + + IRadioGroupManager IRadioGroupManagerProvider.GetGroupManager () + { + return GroupManager; + } + + internal void UpdateNameIndex () + { + // Adds a number to the action name if the current name already + // exists in the action group. + + string vname = group.GetValidName (this, Name); + if (vname != Name) { + name = vname; + EmitNotify ("Name"); + } + } + + string GetDefaultName () + { + // Don't use the label for stock actions, since it depends on the current locale + if (!string.IsNullOrEmpty (GtkAction.StockId)) { + if (GtkAction.StockId.StartsWith ("gtk-")) + return GetIdentifier (GtkAction.StockId.Substring (4)); + if (GtkAction.StockId.StartsWith ("gnome-stock-")) + return GetIdentifier (GtkAction.StockId.Substring (12)); + } + + if (!string.IsNullOrEmpty (GtkAction.Label)) + return GetIdentifier (GtkAction.Label); + + if (!string.IsNullOrEmpty (GtkAction.StockId)) + return GetIdentifier (GtkAction.StockId); + + return "Action"; + } + + public ActionType Type { + get { return type; } + set { + if (type == value) + return; + type = value; + if (type == ActionType.Radio) + Group = GroupManager.LastGroup; + else + Group = null; + + EmitNotify ("Type"); + } + } + + public bool DrawAsRadio { + get { return drawAsRadio; } + set { drawAsRadio = value; EmitNotify ("DrawAsRadio"); } + } + + public int Value { + get { return radioValue; } + set { radioValue = value; EmitNotify ("Value"); } + } + + public string Accelerator { + get { return accelerator; } + set { accelerator = value; EmitNotify ("Accelerator"); } + } + + public bool Active { + get { return active; } + set { + active = value; + if (Activated != null) + Activated (this, EventArgs.Empty); + if (Toggled != null) + Toggled (this, EventArgs.Empty); + if (Changed != null) + Changed (this, new Gtk.ChangedArgs ()); + } + } + + public string MenuLabel { + get { + if (GtkAction.Label != null && GtkAction.Label.Length > 0) + return GtkAction.Label; + + if (GtkAction.StockId == null) + return ""; + + Gtk.StockItem item = Gtk.Stock.Lookup (GtkAction.StockId); + if (item.Label != null) + return item.Label; + + return ""; + } + } + + public string ToolLabel { + get { + if (GtkAction.ShortLabel != null && GtkAction.ShortLabel.Length > 0) + return GtkAction.ShortLabel; + else + return MenuLabel; + } + } + + public ActionGroup ActionGroup { + get { return group; } + } + + public string Group { + get { + return GroupManager.GetGroup (this); + } + set { + if (value != null && value.Length > 0) + Type = ActionType.Radio; + GroupManager.SetGroup (this, value); + EmitNotify ("Group"); + } + } + + public void Delete () + { + if (group != null) + group.Actions.Remove (this); + if (Deleted != null) + Deleted (this, EventArgs.Empty); + Dispose (); + } + + protected override void EmitNotify (string propertyName) + { + if (propertyName == "Label" || propertyName == "StockId") { + // If the current name is a name generated from label or stockid, + // we update here the name again + if (nameRoot == oldDefaultName) + Name = GetDefaultName (); + oldDefaultName = GetDefaultName (); + } + base.EmitNotify (propertyName); + } + + public override XmlElement Write (ObjectWriter writer) + { + XmlElement elem = writer.XmlDocument.CreateElement ("action"); + elem.SetAttribute ("id", Name); + WidgetUtils.GetProps (this, elem); + WidgetUtils.GetSignals (this, elem); + if (writer.CreateUndoInfo) + elem.SetAttribute ("undoId", UndoId); + return elem; + } + + public override void Read (ObjectReader reader, XmlElement elem) + { + Gtk.Action ac = new Gtk.Action ("", ""); + + ClassDescriptor klass = Registry.LookupClassByName ("Gtk.Action"); + ObjectWrapper.Bind (reader.Project, klass, this, ac, true); + + WidgetUtils.ReadMembers (klass, this, ac, elem); + name = nameRoot = oldDefaultName = elem.GetAttribute ("id"); + + string uid = elem.GetAttribute ("undoId"); + if (uid.Length > 0) + UndoId = uid; + } + + public Action Clone () + { + Action a = (Action) ObjectWrapper.Create (Project, new Gtk.Action ("", ""), this); + a.CopyFrom (this); + return a; + } + + public void CopyFrom (Action action) + { + type = action.type; + drawAsRadio = action.drawAsRadio; + radioValue = action.radioValue; + active = action.active; + name = action.name; + GtkAction.HideIfEmpty = action.GtkAction.HideIfEmpty; + GtkAction.IsImportant = action.GtkAction.IsImportant; + GtkAction.Label = action.GtkAction.Label; + GtkAction.Sensitive = action.GtkAction.Sensitive; + GtkAction.ShortLabel = action.GtkAction.ShortLabel; + GtkAction.StockId = action.GtkAction.StockId; + GtkAction.Tooltip = action.GtkAction.Tooltip; + GtkAction.Visible = action.GtkAction.Visible; + GtkAction.VisibleHorizontal = action.GtkAction.VisibleHorizontal; + GtkAction.VisibleVertical = action.GtkAction.VisibleVertical; + + Signals.Clear (); + foreach (Signal s in action.Signals) + Signals.Add (new Signal (s.SignalDescriptor, s.Handler, s.After)); + + NotifyChanged (); + } + + public Gtk.Widget CreateIcon (Gtk.IconSize size) + { + if (GtkAction.StockId == null) + return null; + + Gdk.Pixbuf px = Project.IconFactory.RenderIcon (Project, GtkAction.StockId, size); + if (px != null) + return new Gtk.Image (px); + else + return GtkAction.CreateIcon (size); + } + + public Gdk.Pixbuf RenderIcon (Gtk.IconSize size) + { + if (GtkAction.StockId == null) + return null; + + Gdk.Pixbuf px = Project.IconFactory.RenderIcon (Project, GtkAction.StockId, size); + if (px != null) + return px; + + Gtk.IconSet iset = Gtk.IconFactory.LookupDefault (GtkAction.StockId); + if (iset == null) + return WidgetUtils.MissingIcon; + else + return iset.RenderIcon (new Gtk.Style (), Gtk.TextDirection.Ltr, Gtk.StateType.Normal, size, null, ""); + } + + internal protected override CodeExpression GenerateObjectCreation (GeneratorContext ctx) + { + CodeObjectCreateExpression exp = new CodeObjectCreateExpression (); + + PropertyDescriptor prop = (PropertyDescriptor) ClassDescriptor ["Name"]; + exp.Parameters.Add (ctx.GenerateValue (prop.GetValue (Wrapped), prop.RuntimePropertyType)); + + prop = (PropertyDescriptor) ClassDescriptor ["Label"]; + string lab = (string) prop.GetValue (Wrapped); + if (lab == "") lab = null; + exp.Parameters.Add (ctx.GenerateValue (lab, prop.RuntimePropertyType, prop.Translatable)); + + prop = (PropertyDescriptor) ClassDescriptor ["Tooltip"]; + exp.Parameters.Add (ctx.GenerateValue (prop.GetValue (Wrapped), prop.RuntimePropertyType, prop.Translatable)); + + prop = (PropertyDescriptor) ClassDescriptor ["StockId"]; + exp.Parameters.Add (ctx.GenerateValue (prop.GetValue (Wrapped), prop.RuntimePropertyType, prop.Translatable)); + + if (type == ActionType.Action) + exp.CreateType = new CodeTypeReference ("Gtk.Action", CodeTypeReferenceOptions.GlobalReference); + else if (type == ActionType.Toggle) + exp.CreateType = new CodeTypeReference ("Gtk.ToggleAction", CodeTypeReferenceOptions.GlobalReference); + else { + exp.CreateType = new CodeTypeReference ("Gtk.RadioAction", CodeTypeReferenceOptions.GlobalReference); + prop = (PropertyDescriptor) ClassDescriptor ["Value"]; + exp.Parameters.Add (ctx.GenerateValue (prop.GetValue (Wrapped), typeof(int))); + } + return exp; + } + + internal protected override void GenerateBuildCode (GeneratorContext ctx, CodeExpression var) + { + if (Type == ActionType.Radio) { + CodeExpression groupExp = GroupManager.GenerateGroupExpression (ctx, this); + ctx.Statements.Add ( + new CodeAssignStatement ( + new CodePropertyReferenceExpression (var, "Group"), + groupExp) + ); + } + else if (type == ActionType.Toggle) { + if (Active) { + ctx.Statements.Add ( + new CodeAssignStatement ( + new CodePropertyReferenceExpression (var, "Active"), + new CodePrimitiveExpression (true)) + ); + } + if (DrawAsRadio) { + ctx.Statements.Add ( + new CodeAssignStatement ( + new CodePropertyReferenceExpression (var, "DrawAsRadio"), + new CodePrimitiveExpression (true)) + ); + } + } + base.GenerateBuildCode (ctx, var); + } + + internal void SetActionGroup (ActionGroup g) + { + group = g; + } + + string GetIdentifier (string name) + { + StringBuilder sb = new StringBuilder (); + + bool wstart = false; + foreach (char c in name) { + if (c == '_' || (int)c > 127) // No underline, no unicode + continue; + if (c == '-' || c == ' ' || !char.IsLetterOrDigit (c)) { + wstart = true; + continue; + } + if (wstart) { + sb.Append (char.ToUpper (c)); + wstart = false; + } else + sb.Append (c); + } + return sb.ToString () + "Action"; + } + + internal override UndoManager GetUndoManagerInternal () + { + if (group != null) + return group.GetUndoManagerInternal (); + else + return base.GetUndoManagerInternal (); + } + + DiffGenerator GetDiffGenerator () + { + DiffGenerator gen = new DiffGenerator (); + gen.CurrentStatusAdaptor = new ActionDiffAdaptor (Project); + gen.NewStatusAdaptor = new XmlDiffAdaptor (); + return gen; + } + + public override object GetUndoDiff () + { + XmlElement oldElem = UndoManager.GetObjectStatus (this); + UndoWriter writer = new UndoWriter (oldElem.OwnerDocument, UndoManager); + XmlElement newElem = Write (writer); + ObjectDiff actionsDiff = GetDiffGenerator().GetDiff (this, oldElem); + UndoManager.UpdateObjectStatus (this, newElem); + return actionsDiff; + } + + public override object ApplyUndoRedoDiff (object diff) + { + ObjectDiff actionsDiff = (ObjectDiff) diff; + + XmlElement status = UndoManager.GetObjectStatus (this); + + DiffGenerator differ = GetDiffGenerator(); + differ.ApplyDiff (this, actionsDiff); + actionsDiff = differ.GetDiff (this, status); + + UndoWriter writer = new UndoWriter (status.OwnerDocument, UndoManager); + XmlElement newElem = Write (writer); + UndoManager.UpdateObjectStatus (this, newElem); + + return actionsDiff; + } + } + + [Serializable] + public class ActionCollection: CollectionBase + { + [NonSerialized] + ActionGroup group; + + public ActionCollection () + { + } + + internal ActionCollection (ActionGroup group) + { + this.group = group; + } + + public void Add (Action action) + { + List.Add (action); + } + + public void Insert (int i, Action action) + { + List.Insert (i, action); + } + + public Action this [int n] { + get { return (Action) List [n]; } + } + + public void Remove (Action action) + { + List.Remove (action); + } + + public bool Contains (Action action) + { + return List.Contains (action); + } + + public void CopyTo (Action[] array, int index) + { + List.CopyTo (array, index); + } + + protected override void OnInsertComplete (int index, object val) + { + if (group != null) + group.NotifyActionAdded ((Action) val); + } + + protected override void OnRemoveComplete (int index, object val) + { + if (group != null) + group.NotifyActionRemoved ((Action)val); + } + + protected override void OnSetComplete (int index, object oldv, object newv) + { + if (group != null) { + group.NotifyActionRemoved ((Action) oldv); + group.NotifyActionAdded ((Action) newv); + } + } + } +} diff --git a/main/src/addins/MonoDevelop.GtkCore2/libstetic/wrapper/ActionGroup.cs b/main/src/addins/MonoDevelop.GtkCore2/libstetic/wrapper/ActionGroup.cs new file mode 100644 index 0000000000..1e3c7dbf1b --- /dev/null +++ b/main/src/addins/MonoDevelop.GtkCore2/libstetic/wrapper/ActionGroup.cs @@ -0,0 +1,425 @@ + +using System; +using System.CodeDom; +using System.Xml; +using System.Collections; +using Stetic.Undo; + +namespace Stetic.Wrapper +{ + public sealed class ActionGroup: ObjectWrapper + { + string name; + ActionCollection actions; + ObjectWrapper owner; + bool generatePublic = true; + + public event ActionEventHandler ActionAdded; + public event ActionEventHandler ActionRemoved; + public event ActionEventHandler ActionChanged; + + public ActionGroup () + { + actions = new ActionCollection (this); + } + + public ActionGroup (string name): this () + { + this.name = name; + } + + public override void Dispose () + { + foreach (Action a in actions) + a.Dispose (); + base.Dispose (); + } + + public ActionCollection Actions { + get { return actions; } + } + + public override string Name { + get { return name; } + set { + name = value; + NotifyChanged (); + } + } + + public bool GeneratePublic { + get { return generatePublic; } + set { generatePublic = value; } + } + + public Action GetAction (string name) + { + foreach (Action ac in actions) + if (ac.Name == name) + return ac; + return null; + } + + internal string GetValidName (Action reqAction, string name) + { + int max = 0; + bool found = false; + foreach (Action ac in Actions) { + if (ac == reqAction) + continue; + + string bname; + int index; + WidgetUtils.ParseWidgetName (ac.Name, out bname, out index); + + if (name == ac.Name) + found = true; + if (name == bname && index > max) + max = index; + } + if (found) + return name + (max+1); + else + return name; + } + + public override XmlElement Write (ObjectWriter writer) + { + XmlElement group = writer.XmlDocument.CreateElement ("action-group"); + group.SetAttribute ("name", name); + if (writer.CreateUndoInfo) + group.SetAttribute ("undoId", UndoId); + foreach (Action ac in actions) { + if (ac.Name.Length > 0) + group.AppendChild (writer.WriteObject (ac)); + } + return group; + } + + public override void Read (ObjectReader reader, XmlElement elem) + { + name = elem.GetAttribute ("name"); + string uid = elem.GetAttribute ("undoId"); + if (uid.Length > 0) + UndoId = uid; + foreach (XmlElement child in elem.SelectNodes ("action")) { + Action ac = new Action (); + ac.Read (reader, child); + actions.Add (ac); + } + } + + internal protected override CodeExpression GenerateObjectCreation (GeneratorContext ctx) + { + return new CodeObjectCreateExpression ( + typeof(Gtk.ActionGroup).ToGlobalTypeRef (), + new CodePrimitiveExpression (Name) + ); + } + + internal protected override void GenerateBuildCode (GeneratorContext ctx, CodeExpression var) + { + foreach (Action action in Actions) { + // Create the action + CodeExpression acVarExp = ctx.GenerateInstanceExpression (action, action.GenerateObjectCreation (ctx)); + ctx.GenerateBuildCode (action, acVarExp); + ctx.Statements.Add ( + new CodeMethodInvokeExpression ( + var, + "Add", + acVarExp, + new CodePrimitiveExpression (action.Accelerator) + ) + ); + } + } + + internal void SetOwner (ObjectWrapper owner) + { + this.owner = owner; + } + + internal override UndoManager GetUndoManagerInternal () + { + if (owner != null) + return owner.UndoManager; + else + return base.GetUndoManagerInternal (); + } + + public override ObjectWrapper FindObjectByUndoId (string id) + { + ObjectWrapper ow = base.FindObjectByUndoId (id); + if (ow != null) return ow; + + foreach (Action ac in Actions) { + ow = ac.FindObjectByUndoId (id); + if (ow != null) + return ow; + } + return null; + } + + DiffGenerator GetDiffGenerator () + { + DiffGenerator gen = new DiffGenerator (); + gen.CurrentStatusAdaptor = new ActionDiffAdaptor (Project); + XmlDiffAdaptor xad = new XmlDiffAdaptor (); + xad.ChildElementName = "action"; + gen.NewStatusAdaptor = xad; + return gen; + } + + public override object GetUndoDiff () + { + XmlElement oldElem = UndoManager.GetObjectStatus (this); + UndoWriter writer = new UndoWriter (oldElem.OwnerDocument, UndoManager); + + XmlElement newElem = Write (writer); + ObjectDiff actionsDiff = GetDiffGenerator().GetDiff (this, oldElem); + UndoManager.UpdateObjectStatus (this, newElem); + return actionsDiff; + } + + public override object ApplyUndoRedoDiff (object diff) + { + ObjectDiff actionsDiff = (ObjectDiff) diff; + + XmlElement status = UndoManager.GetObjectStatus (this); + + DiffGenerator differ = GetDiffGenerator(); + differ.ApplyDiff (this, actionsDiff); + actionsDiff = differ.GetDiff (this, status); + + UndoWriter writer = new UndoWriter (status.OwnerDocument, UndoManager); + XmlElement newElem = Write (writer); + UndoManager.UpdateObjectStatus (this, newElem); + + return actionsDiff; + } + + internal void NotifyActionAdded (Action ac) + { + ac.SetActionGroup (this); + ac.ObjectChanged += OnActionChanged; + ac.SignalAdded += OnSignalAdded; + ac.SignalRemoved += OnSignalRemoved; + ac.SignalChanged += OnSignalChanged; + + ac.UpdateNameIndex (); + + NotifyChanged (); + + if (ActionAdded != null) + ActionAdded (this, new ActionEventArgs (ac)); + } + + internal void NotifyActionRemoved (Action ac) + { + ac.SetActionGroup (null); + ac.ObjectChanged -= OnActionChanged; + ac.SignalAdded -= OnSignalAdded; + ac.SignalRemoved -= OnSignalRemoved; + ac.SignalChanged -= OnSignalChanged; + + NotifyChanged (); + + if (ActionRemoved != null) + ActionRemoved (this, new ActionEventArgs (ac)); + } + + void OnActionChanged (object s, ObjectWrapperEventArgs args) + { + NotifyChanged (); + if (ActionChanged != null) + ActionChanged (this, new ActionEventArgs ((Action) args.Wrapper)); + } + + void OnSignalAdded (object s, SignalEventArgs args) + { + OnSignalAdded (args); + } + + void OnSignalRemoved (object s, SignalEventArgs args) + { + OnSignalRemoved (args); + } + + void OnSignalChanged (object s, SignalChangedEventArgs args) + { + OnSignalChanged (args); + } + } + + public class ActionGroupCollection: CollectionBase + { + ActionGroup[] toClear; + ObjectWrapper owner; + + internal void SetOwner (ObjectWrapper owner) + { + this.owner = owner; + } + + public void Add (ActionGroup group) + { + List.Add (group); + } + + public void Insert (int n, ActionGroup group) + { + List.Insert (n, group); + } + + public ActionGroup this [int n] { + get { return (ActionGroup) List [n]; } + } + + public ActionGroup this [string name] { + get { + foreach (ActionGroup grp in List) + if (grp.Name == name) + return grp; + return null; + } + } + + internal ObjectWrapper FindObjectByUndoId (string id) + { + foreach (ActionGroup ag in List) { + ObjectWrapper ow = ag.FindObjectByUndoId (id); + if (ow != null) + return ow; + } + return null; + } + + DiffGenerator GetDiffGenerator (IProject prj) + { + DiffGenerator gen = new DiffGenerator (); + gen.CurrentStatusAdaptor = new ActionDiffAdaptor (prj); + XmlDiffAdaptor xad = new XmlDiffAdaptor (); + xad.ChildElementName = "action-group"; + xad.ProcessProperties = false; + xad.ChildAdaptor = new XmlDiffAdaptor (); + xad.ChildAdaptor.ChildElementName = "action"; + gen.NewStatusAdaptor = xad; + return gen; + } + + internal ObjectDiff GetDiff (IProject prj, XmlElement elem) + { + return GetDiffGenerator (prj).GetDiff (this, elem); + } + + internal void ApplyDiff (IProject prj, ObjectDiff diff) + { + GetDiffGenerator (prj).ApplyDiff (this, diff); + } + + public int IndexOf (ActionGroup group) + { + return List.IndexOf (group); + } + + public void Remove (ActionGroup group) + { + List.Remove (group); + } + + protected override void OnInsertComplete (int index, object val) + { + NotifyGroupAdded ((ActionGroup) val); + } + + protected override void OnRemoveComplete (int index, object val) + { + NotifyGroupRemoved ((ActionGroup)val); + } + + protected override void OnSetComplete (int index, object oldv, object newv) + { + NotifyGroupRemoved ((ActionGroup) oldv); + NotifyGroupAdded ((ActionGroup) newv); + } + + protected override void OnClear () + { + toClear = new ActionGroup [Count]; + List.CopyTo (toClear, 0); + } + + protected override void OnClearComplete () + { + foreach (ActionGroup a in toClear) + NotifyGroupRemoved (a); + toClear = null; + } + + void NotifyGroupAdded (ActionGroup grp) + { + grp.SetOwner (owner); + grp.ObjectChanged += OnGroupChanged; + if (ActionGroupAdded != null) + ActionGroupAdded (this, new ActionGroupEventArgs (grp)); + } + + void NotifyGroupRemoved (ActionGroup grp) + { + grp.SetOwner (null); + grp.ObjectChanged -= OnGroupChanged; + if (ActionGroupRemoved != null) + ActionGroupRemoved (this, new ActionGroupEventArgs (grp)); + } + + void OnGroupChanged (object s, ObjectWrapperEventArgs a) + { + if (ActionGroupChanged != null) + ActionGroupChanged (this, new ActionGroupEventArgs ((ActionGroup)s)); + } + + public ActionGroup[] ToArray () + { + ActionGroup[] groups = new ActionGroup [Count]; + List.CopyTo (groups, 0); + return groups; + } + + public event ActionGroupEventHandler ActionGroupAdded; + public event ActionGroupEventHandler ActionGroupRemoved; + public event ActionGroupEventHandler ActionGroupChanged; + } + + + public delegate void ActionEventHandler (object sender, ActionEventArgs args); + + public class ActionEventArgs: EventArgs + { + readonly Action action; + + public ActionEventArgs (Action ac) + { + action = ac; + } + + public Action Action { + get { return action; } + } + } + + public delegate void ActionGroupEventHandler (object sender, ActionGroupEventArgs args); + + public class ActionGroupEventArgs: EventArgs + { + readonly ActionGroup action; + + public ActionGroupEventArgs (ActionGroup ac) + { + action = ac; + } + + public ActionGroup ActionGroup { + get { return action; } + } + } +} diff --git a/main/src/addins/MonoDevelop.GtkCore2/libstetic/wrapper/ActionToolbarWrapper.cs b/main/src/addins/MonoDevelop.GtkCore2/libstetic/wrapper/ActionToolbarWrapper.cs new file mode 100644 index 0000000000..1b973b8660 --- /dev/null +++ b/main/src/addins/MonoDevelop.GtkCore2/libstetic/wrapper/ActionToolbarWrapper.cs @@ -0,0 +1,294 @@ + +using System; +using System.CodeDom; +using System.Xml; +using System.Collections; +using Stetic.Editor; + +namespace Stetic.Wrapper +{ + public class ActionToolbarWrapper: Container + { + ActionTree actionTree; + XmlElement toolbarInfo; + ToolbarStyle toolbarStyle; + bool treeChanged; + static Gtk.ToolbarStyle defaultStyle; + static bool gotDefault; + + public enum ToolbarStyle { + Icons, + Text, + Both, + BothHoriz, + Default + } + + public ActionToolbarWrapper() + { + } + + public override void Dispose () + { + DisposeTree (); + base.Dispose (); + } + + public static Gtk.Toolbar CreateInstance () + { + ActionToolbar t = new ActionToolbar (); + return t; + } + + ActionToolbar toolbar { + get { return (ActionToolbar) Wrapped; } + } + + protected override bool AllowPlaceholders { + get { return false; } + } + + public override void Wrap (object obj, bool initialized) + { + base.Wrap (obj, initialized); + CreateTree (); + toolbar.FillMenu (actionTree); + } + + public override bool HExpandable { + get { + return toolbar.Orientation == Gtk.Orientation.Horizontal; + } + } + + public override bool VExpandable { + get { + return toolbar.Orientation == Gtk.Orientation.Vertical; + } + } + + public Gtk.Orientation Orientation { + get { + return toolbar.Orientation; + } + set { + toolbar.Orientation = value; + EmitContentsChanged (); + } + } + + public Gtk.IconSize IconSize { + get { return toolbar.IconSize; } + set { toolbar.IconSize = value; EmitNotify ("IconSize"); } + } + + public ToolbarStyle ButtonStyle { + get { return toolbarStyle; } + set { + toolbarStyle = value; + if (value == ToolbarStyle.Default) { + if (!gotDefault) { + // Is there a better way of getting the default? + Gtk.Window d = new Gtk.Window (""); + Gtk.Toolbar t = new Gtk.Toolbar (); + d.Add (t); + defaultStyle = t.ToolbarStyle; + d.Destroy (); + gotDefault = true; + } + toolbar.ToolbarStyle = defaultStyle; + } else { + toolbar.ToolbarStyle = (Gtk.ToolbarStyle) ((int)value); + } + EmitNotify ("ButtonStyle"); + } + } + + internal protected override void OnSelected () + { + Loading = true; + toolbar.ShowInsertPlaceholder = true; + Loading = false; + } + + internal protected override void OnUnselected () + { + base.OnUnselected (); + Loading = true; + toolbar.ShowInsertPlaceholder = false; + toolbar.Unselect (); + Loading = false; + } + + protected override XmlElement WriteProperties (ObjectWriter writer) + { + XmlElement elem = base.WriteProperties (writer); + if (writer.Format == FileFormat.Native) { + // The style is already stored in ButtonStyle + GladeUtils.ExtractProperty (elem, "ToolbarStyle", ""); + if (toolbarInfo != null) + elem.AppendChild (writer.XmlDocument.ImportNode (toolbarInfo, true)); + else + elem.AppendChild (actionTree.Write (writer.XmlDocument, writer.Format)); + } + return elem; + } + + protected override void ReadProperties (ObjectReader reader, XmlElement elem) + { + base.ReadProperties (reader, elem); + toolbarInfo = elem ["node"]; + } + + protected override void OnNameChanged (WidgetNameChangedArgs args) + { + base.OnNameChanged (args); + if (actionTree != null) + actionTree.Name = Name; + } + + internal protected override CodeExpression GenerateObjectCreation (GeneratorContext ctx) + { + BuildTree (); + actionTree.Type = Gtk.UIManagerItemType.Toolbar; + actionTree.Name = Name; + + CodeExpression exp = GenerateUiManagerElement (ctx, actionTree); + if (exp != null) + return new CodeCastExpression (typeof(Gtk.Toolbar).ToGlobalTypeRef (), exp); + else + return base.GenerateObjectCreation (ctx); + } + + protected override void GeneratePropertySet (GeneratorContext ctx, CodeExpression var, PropertyDescriptor prop) + { + if (toolbarStyle == ToolbarStyle.Default && prop.Name == "ToolbarStyle") + return; + else + base.GeneratePropertySet (ctx, var, prop); + } + + internal protected override void OnDesignerAttach (IDesignArea designer) + { + base.OnDesignerAttach (designer); + BuildTree (); + + Loading = true; + toolbar.FillMenu (actionTree); + Loading = false; + + if (LocalActionGroups.Count == 0) + LocalActionGroups.Add (new ActionGroup ("Default")); + } + + protected override void EmitNotify (string propertyName) + { + base.EmitNotify (propertyName); + toolbar.FillMenu (actionTree); + } + + public override object GetUndoDiff () + { + XmlElement oldElem = treeChanged ? UndoManager.GetObjectStatus (this) ["node"] : null; + if (oldElem != null) + oldElem = (XmlElement) oldElem.CloneNode (true); + + treeChanged = false; + object baseDiff = base.GetUndoDiff (); + + if (oldElem != null) { + XmlElement newElem = UndoManager.GetObjectStatus (this) ["node"]; + if (newElem != null && oldElem.OuterXml == newElem.OuterXml) + oldElem = null; + } + + if (baseDiff == null && oldElem == null) + return null; + else { + object stat = toolbar.SaveStatus (); + return new object[] { baseDiff, oldElem, stat }; + } + } + + public override object ApplyUndoRedoDiff (object diff) + { + object[] data = (object[]) diff; + object retBaseDiff; + XmlElement oldNode = null; + + if (actionTree != null) { + XmlElement status = UndoManager.GetObjectStatus (this); + oldNode = status ["node"]; + if (oldNode != null) + oldNode = (XmlElement) oldNode.CloneNode (true); + } + object oldStat = toolbar.SaveStatus (); + + if (data [0] != null) + retBaseDiff = base.ApplyUndoRedoDiff (data [0]); + else + retBaseDiff = null; + + XmlElement xdiff = (XmlElement) data [1]; + + if (xdiff != null) { + XmlElement status = UndoManager.GetObjectStatus (this); + XmlElement prevNode = status ["node"]; + if (prevNode != null) + status.RemoveChild (prevNode); + status.AppendChild (xdiff); + + if (actionTree != null) { + Loading = true; + DisposeTree (); + CreateTree (); + actionTree.Read (this, xdiff); + toolbar.FillMenu (actionTree); + Loading = false; + } + } + + // Restore the status after all menu structure has been properly built + GLib.Timeout.Add (50, delegate { + toolbar.RestoreStatus (data[2]); + return false; + }); + + return new object [] { retBaseDiff, oldNode, oldStat }; + } + + + void BuildTree () + { + if (toolbarInfo != null) { + DisposeTree (); + CreateTree (); + actionTree.Read (this, toolbarInfo); + toolbarInfo = null; + } + } + + void CreateTree () + { + actionTree = new ActionTree (); + actionTree.Name = Name; + actionTree.Type = Gtk.UIManagerItemType.Toolbar; + actionTree.Changed += OnTreeChanged; + } + + void DisposeTree () + { + if (actionTree != null) { + actionTree.Dispose (); + actionTree.Changed -= OnTreeChanged; + actionTree = null; + } + } + + void OnTreeChanged (object s, EventArgs a) + { + treeChanged = true; + NotifyChanged (); + } + } +} diff --git a/main/src/addins/MonoDevelop.GtkCore2/libstetic/wrapper/ActionTree.cs b/main/src/addins/MonoDevelop.GtkCore2/libstetic/wrapper/ActionTree.cs new file mode 100644 index 0000000000..82eae3e23d --- /dev/null +++ b/main/src/addins/MonoDevelop.GtkCore2/libstetic/wrapper/ActionTree.cs @@ -0,0 +1,351 @@ + +using System; +using System.Text; +using System.Xml; +using System.CodeDom; +using System.Collections; + +namespace Stetic.Wrapper +{ + + public class ActionTree: ActionTreeNode + { + public event EventHandler Changed; + + public ActionTree() + { + } + + public void GenerateBuildCode (GeneratorContext ctx, CodeFieldReferenceExpression uiManager) + { + StringBuilder sb = new StringBuilder (); + sb.Append ("<ui>"); + GenerateUiString (sb); + sb.Append ("</ui>"); + + CodeMethodInvokeExpression exp = new CodeMethodInvokeExpression ( + uiManager, + "AddUiFromString", + new CodePrimitiveExpression (sb.ToString ()) + ); + ctx.Statements.Add (exp); + } + + public ActionGroup[] GetRequiredGroups () + { + ArrayList list = new ArrayList (); + GetRequiredGroups (list); + return (ActionGroup[]) list.ToArray (typeof(ActionGroup)); + } + + internal override void NotifyChanged () + { + if (Changed != null) + Changed (this, EventArgs.Empty); + } + } + + public class ActionTreeNode: IDisposable + { + Gtk.UIManagerItemType type; + string name; + Action action; + ActionTreeNodeCollection children; + ActionTreeNode parentNode; + bool loading; + string lastActionName; + + public ActionTreeNode () + { + } + + public ActionTreeNode Clone () + { + return new ActionTreeNode (type, name, action); + } + + public ActionTreeNode (Gtk.UIManagerItemType type, string name, Action action) + { + this.type = type; + this.name = name; + this.action = action; + if (this.action != null) { + lastActionName = this.action.Name; + this.action.Deleted += OnActionDeleted; + this.action.ObjectChanged += OnActionChanged; + } + } + + public virtual void Dispose () + { + if (action != null) { + action.Deleted -= OnActionDeleted; + action.ObjectChanged -= OnActionChanged; + } + if (children != null) + foreach (ActionTreeNode node in children) + node.Dispose (); + } + + void OnActionDeleted (object s, EventArgs args) + { + if (parentNode != null) + parentNode.Children.Remove (this); + } + + void OnActionChanged (object s, ObjectWrapperEventArgs args) + { + // If the name of the action changes, consider it a change in + // the node, since the generated xml will be different + + Action ac = (Action) args.Wrapper; + if (ac.Name != lastActionName) { + lastActionName = ac.Name; + NotifyChanged (); + } + } + + internal virtual void NotifyChanged () + { + if (parentNode != null) + parentNode.NotifyChanged (); + } + + public XmlElement Write (XmlDocument doc, FileFormat format) + { + XmlElement elem = doc.CreateElement ("node"); + if (name != null && name.Length > 0) + elem.SetAttribute ("name", name); + elem.SetAttribute ("type", type.ToString ()); + if (action != null) + elem.SetAttribute ("action", action.Name); + + if (children != null) { + foreach (ActionTreeNode child in children) { + if (child.Action != null && child.Action.Name.Length == 0) + continue; + elem.AppendChild (child.Write (doc, format)); + } + } + return elem; + } + + public void Read (Wrapper.Widget baseWidget, XmlElement elem) + { + name = elem.GetAttribute ("name"); + if (elem.HasAttribute ("type")) + type = (Gtk.UIManagerItemType) Enum.Parse (typeof(Gtk.UIManagerItemType), elem.GetAttribute ("type")); + + // The name of an action may be empty in some situations (e.g. when adding a new action but before entering the name) + XmlAttribute actionAt = elem.Attributes ["action"]; + if (actionAt != null) { + string aname = actionAt.Value; + foreach (ActionGroup grp in baseWidget.LocalActionGroups) { + action = grp.GetAction (aname); + if (action != null) + break; + } + if (action == null) { + foreach (ActionGroup group in baseWidget.Project.ActionGroups) { + action = group.GetAction (aname); + if (action != null) + break; + } + } + if (action != null) { + lastActionName = action.Name; + action.Deleted += OnActionDeleted; + action.ObjectChanged += OnActionChanged; + } + } + + try { + loading = true; + foreach (XmlElement child in elem.SelectNodes ("node")) { + ActionTreeNode node = new ActionTreeNode (); + node.Read (baseWidget, child); + Children.Add (node); + } + } finally { + loading = false; + } + } + + public virtual void GenerateBuildCode (GeneratorContext ctx, CodeVariableReferenceExpression uiManager, string path) + { + CodeMethodInvokeExpression exp = new CodeMethodInvokeExpression ( + uiManager, + "AddUi", + new CodePrimitiveExpression (0), + new CodePrimitiveExpression (path), + new CodePrimitiveExpression (name), + new CodePrimitiveExpression (action != null ? action.Name : null), + new CodeFieldReferenceExpression ( + new CodeTypeReferenceExpression (new CodeTypeReference (typeof(Gtk.UIManagerItemType), CodeTypeReferenceOptions.GlobalReference)), + type.ToString() + ), + new CodePrimitiveExpression (false) + ); + ctx.Statements.Add (exp); + + string localName = (name != null && name.Length > 0 ? name : (action != null ? action.Name : null)); + if (localName != null) { + if (path != "/") + path = path + "/" + localName; + else + path += localName; + } + + foreach (ActionTreeNode node in Children) + node.GenerateBuildCode (ctx, uiManager, path); + } + + public void GenerateUiString (StringBuilder sb) + { + sb.Append ('<').Append (type.ToString().ToLower()); + + string name = this.name; + if (String.IsNullOrEmpty (name) && action != null) + name = action.Name; + + if (!String.IsNullOrEmpty (name)) + sb.Append (' ').Append ("name='").Append (name).Append ("'"); + if (action != null) + sb.Append (' ').Append ("action='").Append (action.Name).Append ("'"); + + if (Children.Count > 0) { + sb.Append ('>'); + foreach (ActionTreeNode node in Children) + node.GenerateUiString (sb); + sb.Append ("</").Append (type.ToString().ToLower()).Append ('>'); + } else + sb.Append ("/>"); + } + + protected void GetRequiredGroups (ArrayList list) + { + if (action != null && action.ActionGroup != null && !list.Contains (action.ActionGroup)) + list.Add (action.ActionGroup); + foreach (ActionTreeNode node in Children) + node.GetRequiredGroups (list); + } + + public Gtk.UIManagerItemType Type { + get { return type; } + set { type = value; NotifyChanged (); } + } + + public string Name { + get { return name; } + set { name = value; NotifyChanged (); } + } + + public Action Action { + get { return action; } + } + + public ActionTreeNode ParentNode { + get { return parentNode; } + } + + public ActionTreeNodeCollection Children { + get { + if (children == null) + children = new ActionTreeNodeCollection (this); + return children; + } + } + + internal void NotifyChildAdded (ActionTreeNode node) + { + node.parentNode = this; + if (!loading) { + NotifyChanged (); + if (ChildNodeAdded != null) + ChildNodeAdded (this, new ActionTreeNodeArgs (node)); + } + } + + internal void NotifyChildRemoved (ActionTreeNode node) + { + node.parentNode = null; + if (!loading) { + NotifyChanged (); + if (ChildNodeRemoved != null) + ChildNodeRemoved (this, new ActionTreeNodeArgs (node)); + } + } + + public event ActionTreeNodeHanlder ChildNodeAdded; + public event ActionTreeNodeHanlder ChildNodeRemoved; + } + + public class ActionTreeNodeCollection: CollectionBase + { + ActionTreeNode parent; + + public ActionTreeNodeCollection (ActionTreeNode parent) + { + this.parent = parent; + } + + public void Add (ActionTreeNode node) + { + List.Add (node); + } + + public void Insert (int index, ActionTreeNode node) + { + List.Insert (index, node); + } + + public int IndexOf (ActionTreeNode node) + { + return List.IndexOf (node); + } + + public void Remove (ActionTreeNode node) + { + if (List.Contains (node)) + List.Remove (node); + } + + public ActionTreeNode this [int n] { + get { return (ActionTreeNode) List [n]; } + set { List [n] = value; } + } + + protected override void OnInsertComplete (int index, object val) + { + parent.NotifyChildAdded ((ActionTreeNode) val); + } + + protected override void OnRemoveComplete (int index, object val) + { + parent.NotifyChildRemoved ((ActionTreeNode)val); + } + + protected override void OnSetComplete (int index, object oldv, object newv) + { + parent.NotifyChildRemoved ((ActionTreeNode) oldv); + parent.NotifyChildAdded ((ActionTreeNode) newv); + } + } + + public delegate void ActionTreeNodeHanlder (object ob, ActionTreeNodeArgs args); + + public class ActionTreeNodeArgs: EventArgs + { + readonly ActionTreeNode node; + + public ActionTreeNodeArgs (ActionTreeNode node) + { + this.node = node; + } + + public ActionTreeNode Node { + get { return node; } + } + } + +} diff --git a/main/src/addins/MonoDevelop.GtkCore2/libstetic/wrapper/Bin.cs b/main/src/addins/MonoDevelop.GtkCore2/libstetic/wrapper/Bin.cs new file mode 100644 index 0000000000..4fd3ab2bee --- /dev/null +++ b/main/src/addins/MonoDevelop.GtkCore2/libstetic/wrapper/Bin.cs @@ -0,0 +1,388 @@ +using System; +using System.CodeDom; +using System.Reflection; + +namespace Stetic.Wrapper +{ + public class Bin: Container + { + public static Gtk.Bin CreateInstance (ClassDescriptor klass) + { + if (klass.Name == "Gtk.Bin") + return new CustomWidget (); + else + return null; + } + + internal protected override void GenerateBuildCode (GeneratorContext ctx, CodeExpression var) + { + if (ClassDescriptor.WrappedTypeName == "Gtk.Bin") { + + // Gtk.Bin needs a helper class which handles child allocation. + // This class needs to be generated since Stetic won't be linked with + // the app. + + bool found = false; + foreach (CodeTypeDeclaration dec in ctx.GlobalCodeNamespace.Types) { + if (dec.Name == "BinContainer") { + found = true; + break; + } + } + + if (!found) + GenerateHelperClass (ctx); + + CodeMethodInvokeExpression attachExp = new CodeMethodInvokeExpression ( + new CodeTypeReferenceExpression (new CodeTypeReference (ctx.GlobalCodeNamespace.Name + ".BinContainer", CodeTypeReferenceOptions.GlobalReference)), + "Attach", + var + ); + + // If the Bin has its own action groups, we need to register + // the resulting UIManager in the BinContainer, but it needs to be done + // after generating it. Right now, we only keep a reference to + // the BinContainer. + + string binContainerVar = null; + + if (IsTopLevel && LocalActionGroups.Count > 0) { + binContainerVar = ctx.NewId (); + ctx.Statements.Add ( + new CodeVariableDeclarationStatement ( + (ctx.GlobalCodeNamespace.Name + ".BinContainer"), + binContainerVar, + attachExp + ) + ); + } else { + ctx.Statements.Add (attachExp); + } + + base.GenerateBuildCode (ctx, var); + + // Register the UIManager, if the Bin has one + + if (binContainerVar != null && UIManagerName != null) { + ctx.Statements.Add ( + new CodeMethodInvokeExpression ( + new CodeVariableReferenceExpression (binContainerVar), + "SetUiManager", + new CodeVariableReferenceExpression (UIManagerName) + ) + ); + } + + } else + base.GenerateBuildCode (ctx, var); + } + + void GenerateHelperClass (GeneratorContext ctx) + { + CodeTypeDeclaration type = new CodeTypeDeclaration ("BinContainer"); + type.Attributes = MemberAttributes.Private; + type.TypeAttributes = TypeAttributes.NestedAssembly; + ctx.GlobalCodeNamespace.Types.Add (type); + + CodeMemberField field = new CodeMemberField ("Gtk.Widget", "child"); + field.Attributes = MemberAttributes.Private; + type.Members.Add (field); + + field = new CodeMemberField ("Gtk.UIManager", "uimanager"); + field.Attributes = MemberAttributes.Private; + type.Members.Add (field); + + CodeExpression child = new CodeFieldReferenceExpression ( + new CodeThisReferenceExpression (), + "child" + ); + + CodeExpression uimanager = new CodeFieldReferenceExpression ( + new CodeThisReferenceExpression (), + "uimanager" + ); + + // Attach method + + CodeMemberMethod met = new CodeMemberMethod (); + type.Members.Add (met); + met.Name = "Attach"; + met.Attributes = MemberAttributes.Public | MemberAttributes.Static; + met.ReturnType = new CodeTypeReference ("BinContainer"); + met.Parameters.Add (new CodeParameterDeclarationExpression ("Gtk.Bin", "bin")); + + CodeVariableDeclarationStatement bcDec = new CodeVariableDeclarationStatement ("BinContainer", "bc"); + bcDec.InitExpression = new CodeObjectCreateExpression ("BinContainer"); + met.Statements.Add (bcDec); + CodeVariableReferenceExpression bc = new CodeVariableReferenceExpression ("bc"); + CodeArgumentReferenceExpression bin = new CodeArgumentReferenceExpression ("bin"); + + met.Statements.Add ( + new CodeAttachEventStatement ( + bin, + "SizeRequested", + new CodeDelegateCreateExpression ( + new CodeTypeReference ("Gtk.SizeRequestedHandler"), bc, "OnSizeRequested" + ) + ) + ); + + met.Statements.Add ( + new CodeAttachEventStatement ( + bin, + "SizeAllocated", + new CodeDelegateCreateExpression ( + new CodeTypeReference ("Gtk.SizeAllocatedHandler"), bc, "OnSizeAllocated" + ) + ) + ); + + met.Statements.Add ( + new CodeAttachEventStatement ( + bin, + "Added", + new CodeDelegateCreateExpression ( + new CodeTypeReference ("Gtk.AddedHandler"), bc, "OnAdded" + ) + ) + ); + met.Statements.Add (new CodeMethodReturnStatement (bc)); + + // OnSizeRequested override + + met = new CodeMemberMethod (); + type.Members.Add (met); + met.Name = "OnSizeRequested"; + met.ReturnType = new CodeTypeReference (typeof(void)); + met.Parameters.Add (new CodeParameterDeclarationExpression (typeof(object), "sender")); + met.Parameters.Add (new CodeParameterDeclarationExpression ("Gtk.SizeRequestedArgs", "args")); + + CodeConditionStatement cond = new CodeConditionStatement (); + cond.Condition = new CodeBinaryOperatorExpression ( + child, + CodeBinaryOperatorType.IdentityInequality, + new CodePrimitiveExpression (null) + ); + cond.TrueStatements.Add ( + new CodeAssignStatement ( + new CodePropertyReferenceExpression ( + new CodeArgumentReferenceExpression ("args"), + "Requisition" + ), + new CodeMethodInvokeExpression ( + child, + "SizeRequest" + ) + ) + ); + met.Statements.Add (cond); + + // OnSizeAllocated method + + met = new CodeMemberMethod (); + type.Members.Add (met); + met.Name = "OnSizeAllocated"; + met.ReturnType = new CodeTypeReference (typeof(void)); + met.Parameters.Add (new CodeParameterDeclarationExpression (typeof(object), "sender")); + met.Parameters.Add (new CodeParameterDeclarationExpression ("Gtk.SizeAllocatedArgs", "args")); + + cond = new CodeConditionStatement (); + cond.Condition = new CodeBinaryOperatorExpression ( + child, + CodeBinaryOperatorType.IdentityInequality, + new CodePrimitiveExpression (null) + ); + cond.TrueStatements.Add ( + new CodeAssignStatement ( + new CodePropertyReferenceExpression ( + child, + "Allocation" + ), + new CodePropertyReferenceExpression ( + new CodeArgumentReferenceExpression ("args"), + "Allocation" + ) + ) + ); + met.Statements.Add (cond); + + // OnAdded method + + met = new CodeMemberMethod (); + type.Members.Add (met); + met.Name = "OnAdded"; + met.ReturnType = new CodeTypeReference (typeof(void)); + met.Parameters.Add (new CodeParameterDeclarationExpression (typeof(object), "sender")); + met.Parameters.Add (new CodeParameterDeclarationExpression ("Gtk.AddedArgs", "args")); + + met.Statements.Add ( + new CodeAssignStatement ( + child, + new CodePropertyReferenceExpression ( + new CodeArgumentReferenceExpression ("args"), + "Widget" + ) + ) + ); + + // SetUiManager method + + met = new CodeMemberMethod (); + type.Members.Add (met); + met.Name = "SetUiManager"; + met.Attributes = MemberAttributes.Public | MemberAttributes.Final; + met.ReturnType = new CodeTypeReference (typeof(void)); + met.Parameters.Add (new CodeParameterDeclarationExpression (typeof(Gtk.UIManager), "uim")); + + met.Statements.Add ( + new CodeAssignStatement ( + uimanager, + new CodeArgumentReferenceExpression ("uim") + ) + ); + met.Statements.Add ( + new CodeAttachEventStatement ( + child, + "Realized", + new CodeDelegateCreateExpression ( + new CodeTypeReference ("System.EventHandler"), new CodeThisReferenceExpression(), "OnRealized" + ) + ) + ); + + // OnRealized method + + met = new CodeMemberMethod (); + type.Members.Add (met); + met.Name = "OnRealized"; + met.ReturnType = new CodeTypeReference (typeof(void)); + met.Parameters.Add (new CodeParameterDeclarationExpression (typeof(object), "sender")); + met.Parameters.Add (new CodeParameterDeclarationExpression ("System.EventArgs", "args")); + + cond = new CodeConditionStatement (); + cond.Condition = new CodeBinaryOperatorExpression ( + uimanager, + CodeBinaryOperatorType.IdentityInequality, + new CodePrimitiveExpression (null) + ); + + cond.TrueStatements.Add ( + new CodeVariableDeclarationStatement ( + typeof(Gtk.Widget), + "w" + ) + ); + + CodeExpression wexp = new CodeVariableReferenceExpression ("w"); + + cond.TrueStatements.Add ( + new CodeAssignStatement ( + wexp, + new CodePropertyReferenceExpression ( + child, + "Toplevel" + ) + ) + ); + + CodeConditionStatement cond2 = new CodeConditionStatement (); + cond2.Condition = new CodeBinaryOperatorExpression ( + new CodeBinaryOperatorExpression ( + wexp, + CodeBinaryOperatorType.IdentityInequality, + new CodePrimitiveExpression (null) + ), + CodeBinaryOperatorType.BooleanAnd, + new CodeMethodInvokeExpression ( + new CodeTypeOfExpression ("Gtk.Window"), + "IsInstanceOfType", + wexp + ) + ); + + cond2.TrueStatements.Add ( + new CodeMethodInvokeExpression ( + new CodeCastExpression ("Gtk.Window", wexp), + "AddAccelGroup", + new CodePropertyReferenceExpression ( + uimanager, + "AccelGroup" + ) + ) + ); + cond2.TrueStatements.Add ( + new CodeAssignStatement ( + uimanager, + new CodePrimitiveExpression (null) + ) + ); + cond.TrueStatements.Add (cond2); + + met.Statements.Add (cond); + } + + public override void Wrap (object obj, bool initialized) + { + CustomWidget custom = obj as CustomWidget; + if (custom != null) { + RootWrapperName = custom.Name; + } + //during Wrap RootWrapperName will be set in the children widgets + base.Wrap (obj, initialized); + } + } + +/* + This is a model of what GenerateHelperClass generates: + + class BinContainer + { + Gtk.Widget child; + UIManager uimanager; + + public static BinContainer Attach (Gtk.Bin bin) + { + BinContainer bc = new BinContainer (); + bin.SizeRequested += new Gtk.SizeRequestedHandler (bc.OnSizeRequested); + bin.SizeAllocated += new Gtk.SizeAllocatedHandler (bc.OnSizeAllocated); + bin.Added += new Gtk.AddedHandler (bc.OnAdded); + return bin; + } + + void OnSizeRequested (object s, Gtk.SizeRequestedArgs args) + { + if (child != null) + args.Requisition = child.SizeRequest (); + } + + void OnSizeAllocated (object s, Gtk.SizeAllocatedArgs args) + { + if (child != null) + child.Allocation = args.Allocation; + } + + void OnAdded (object s, Gtk.AddedArgs args) + { + child = args.Widget; + } + + public void SetUiManager (UIManager manager) + { + uimanager = manager; + child.Realized += new System.EventHandler (OnRealized); + } + + void OnRealized () + { + if (uimanager != null) { + Gtk.Widget w = child.Toplevel; + if (w != null && w is Gtk.Window) { + ((Gtk.Window)w).AddAccelGroup (uimanager.AccelGroup); + uimanager = null; + } + } + } + } +*/ + +} diff --git a/main/src/addins/MonoDevelop.GtkCore2/libstetic/wrapper/Box.cs b/main/src/addins/MonoDevelop.GtkCore2/libstetic/wrapper/Box.cs new file mode 100644 index 0000000000..8e57f4b80f --- /dev/null +++ b/main/src/addins/MonoDevelop.GtkCore2/libstetic/wrapper/Box.cs @@ -0,0 +1,276 @@ +using System; +using System.Collections; + +namespace Stetic.Wrapper { + + public class Box : Container { + + public override void Wrap (object obj, bool initialized) + { + base.Wrap (obj, initialized); + if (!initialized && AllowPlaceholders) { + Placeholder ph = CreatePlaceholder (); + box.PackStart (ph); + NotifyChildAdded (ph); + ph = CreatePlaceholder (); + box.PackStart (ph); + NotifyChildAdded (ph); + box.Spacing = 6; + } + box.SizeAllocated += box_SizeAllocated; + ContainerOrientation = obj is Gtk.HBox ? Gtk.Orientation.Horizontal : Gtk.Orientation.Vertical; + DND.ClearFaults (this); + } + + public override void Dispose () + { + box.SizeAllocated -= box_SizeAllocated; + base.Dispose (); + } + + protected Gtk.Box box { + get { + return (Gtk.Box)Wrapped; + } + } + +/* + FIXME: why was this needed? + protected override bool AllowPlaceholders { + get { + return InternalChildProperty != null; + } + } +*/ + // DoSync() does two things: first, it makes sure that all of the + // PackStart widgets have Position numbers less than all of the + // PackEnd widgets. Second, it creates faults anywhere two widgets + // could be split apart. The fault IDs correspond to the Position + // a widget would have to be assigned to end up in that slot + // (negated for PackEnd slots). + // + // Position/PackType: 0S 1S 2S 4E 3E + // +----------------------+ + // | AA BB CC DD EE | + // +----------------------+ + // Fault Id: 0 1 2 3 -5 -4 -3 + + protected override void DoSync () + { + if (!box.IsRealized) + return; + + DND.ClearFaults (this); + + Gtk.Widget[] children = box.Children; + if (children.Length == 0) + return; + + Gtk.Widget[] sorted = new Gtk.Widget[children.Length]; + int last_start = -1; + bool hbox = ContainerOrientation == Gtk.Orientation.Horizontal; + + foreach (Gtk.Widget child in children) { + Gtk.Box.BoxChild bc = box[child] as Gtk.Box.BoxChild; + if (AutoSize[child]) { + bool exp = hbox ? ChildHExpandable (child) : ChildVExpandable (child); + if (bc.Expand != exp) + bc.Expand = exp; + if (bc.Fill != exp) + bc.Fill = exp; + } + + // Make sure all of the PackStart widgets are before + // any PackEnd widgets in the list. + if (bc.PackType == Gtk.PackType.Start) { + if (bc.Position != ++last_start) { + Array.Copy (sorted, last_start, sorted, last_start + 1, bc.Position - last_start); + box.ReorderChild (child, last_start); + } + } + + if (!(child is Placeholder)) + sorted[bc.Position] = child; + } + + // The orientation of the faults is the opposite of the + // orientation of the box + Gtk.Orientation orientation = hbox ? Gtk.Orientation.Vertical : Gtk.Orientation.Horizontal; + Gtk.SideType before = hbox ? Gtk.SideType.Left : Gtk.SideType.Top; + Gtk.SideType after = hbox ? Gtk.SideType.Right : Gtk.SideType.Bottom; + + if (!Unselectable) { + // If there are no PackStart widgets, we need a fault at the leading + // edge. Otherwise if there's a widget at the leading edge, we need a + // fault before it. + if (last_start == -1) + DND.AddFault (this, 0, before, null); + else if (sorted[0] != null) + DND.AddFault (this, 0, before, sorted[0]); + + // Add a fault between each pair of (non-placeholder) start widgets + for (int i = 1; i <= last_start; i++) { + if (sorted[i - 1] != null && sorted[i] != null) + DND.AddFault (this, i, orientation, sorted[i - 1], sorted[i]); + } + + // If there's a non-placeholder at the end of the PackStart + // range, add a fault after it + if (last_start > -1 && sorted[last_start] != null) + DND.AddFault (this, last_start + 1, after, sorted[last_start]); + + // Now the PackEnd widgets + if (last_start == sorted.Length - 1) + DND.AddFault (this, -(last_start + 1), after, null); + else if (sorted[last_start + 1] != null) + DND.AddFault (this, -(last_start + 1), after, sorted[last_start + 1]); + + for (int i = last_start + 2; i < sorted.Length; i++) { + if (sorted[i - 1] != null && sorted[i] != null) + DND.AddFault (this, -i, orientation, sorted[i - 1], sorted[i]); + } + + if (sorted.Length > last_start + 1 && sorted[sorted.Length - 1] != null) + DND.AddFault (this, -sorted.Length, before, sorted[sorted.Length - 1]); + } + } + + internal void InsertBefore (Gtk.Widget context) + { + int position; + Gtk.PackType type; + + if (context == box) { + position = 0; + type = Gtk.PackType.Start; + } else { + Gtk.Box.BoxChild bc = (Gtk.Box.BoxChild)ContextChildProps (context); + position = bc.Position; + type = bc.PackType; + } + + Placeholder ph = CreatePlaceholder (); + if (type == Gtk.PackType.Start) { + box.PackStart (ph); + box.ReorderChild (ph, position); + } else { + box.PackEnd (ph); + box.ReorderChild (ph, position + 1); + } + NotifyChildAdded (ph); + } + + internal void InsertAfter (Gtk.Widget context) + { + int position; + Gtk.PackType type; + + if (context == box) { + position = 0; + type = Gtk.PackType.End; + } else { + Gtk.Box.BoxChild bc = (Gtk.Box.BoxChild)ContextChildProps (context); + position = bc.Position; + type = bc.PackType; + } + + Placeholder ph = CreatePlaceholder (); + if (type == Gtk.PackType.Start) { + box.PackStart (ph); + box.ReorderChild (ph, position + 1); + } else { + box.PackEnd (ph); + box.ReorderChild (ph, position); + } + NotifyChildAdded (ph); + } + + protected override void ChildContentsChanged (Container child) { + Gtk.Widget widget = child.Wrapped; + + if (widget != null && AutoSize[widget]) { + Gtk.Box.BoxChild bc = box[widget] as Gtk.Box.BoxChild; + bool newExp = (ContainerOrientation == Gtk.Orientation.Horizontal) ? ChildHExpandable (widget) : ChildVExpandable (widget); + if (newExp != bc.Expand) + bc.Expand = newExp; + if (newExp != bc.Fill) + bc.Fill = newExp; + } + base.ChildContentsChanged (child); + } + + protected override void ReplaceChild (Gtk.Widget oldChild, Gtk.Widget newChild) + { + base.ReplaceChild (oldChild, newChild); + + Container container = Stetic.Wrapper.Container.Lookup (newChild); + if (container != null) + ChildContentsChanged (container); + } + + void box_SizeAllocated (object obj, Gtk.SizeAllocatedArgs args) + { + Sync (); + } + + public override IEnumerable GladeChildren { + get { + // Return childs using the position order. + // This is needed to make sure children are + // added in the right order to the box while loading + // or building the box. + object[] obs = new object [box.Children.Length]; + foreach (Gtk.Widget child in box.Children) { + Gtk.Box.BoxChild bc = (Gtk.Box.BoxChild) box [child]; + obs [bc.Position] = child; + } + return obs; + } + } + + public override void Drop (Gtk.Widget w, object faultId) + { + AutoSize[w] = true; + int pos = (int)faultId; + + Freeze (); + if (pos >= 0) { + box.Add (w); + box.ReorderChild (w, pos); + } else { + box.Add (w); + box.ReorderChild (w, -pos); + } + EmitContentsChanged (); + Thaw (); + } + + public class BoxChild : Container.ContainerChild { + + public bool BoxExpand { + get { return ((Gtk.Box.BoxChild)Wrapped).Expand; } + set { + AutoSize = false; + ((Gtk.Box.BoxChild)Wrapped).Expand = value; + } + } + + public bool BoxFill { + get { return ((Gtk.Box.BoxChild)Wrapped).Fill; } + set { + AutoSize = false; + ((Gtk.Box.BoxChild)Wrapped).Fill = value; + } + } + + protected override void EmitNotify (string propertyName) + { + if (propertyName == "AutoSize") { + base.EmitNotify ("Expand"); + base.EmitNotify ("Fill"); + } + base.EmitNotify (propertyName); + } + } + } +} diff --git a/main/src/addins/MonoDevelop.GtkCore2/libstetic/wrapper/Button.cs b/main/src/addins/MonoDevelop.GtkCore2/libstetic/wrapper/Button.cs new file mode 100644 index 0000000000..fc78a59531 --- /dev/null +++ b/main/src/addins/MonoDevelop.GtkCore2/libstetic/wrapper/Button.cs @@ -0,0 +1,339 @@ +using System; +using System.CodeDom; +using System.Collections; +using System.Xml; + +namespace Stetic.Wrapper { + + public class Button : Container { + + ImageInfo imageInfo; + + public override void Wrap (object obj, bool initialized) + { + base.Wrap (obj, initialized); + + if (!initialized) + UseUnderline = true; + + if (button.UseStock) { + type = ButtonType.StockItem; + StockId = button.Label; + } else if (!initialized) { + type = ButtonType.TextOnly; + Label = button.Name; + } else if (button.Child is Gtk.Label) { + type = ButtonType.TextOnly; + label = button.Label; + useUnderline = button.UseUnderline; + } else { + type = ButtonType.Custom; + FixupGladeChildren (); + } + } + + public override void Read (ObjectReader reader, XmlElement elem) + { + base.Read (reader, elem); + if (reader.Format == FileFormat.Glade) + UseUnderline = true; + } + protected override ObjectWrapper ReadChild (ObjectReader reader, XmlElement child_elem) + { + ObjectWrapper ret = null; + if (Type == ButtonType.Custom || reader.Format == FileFormat.Glade) { + if (button.Child != null) + button.Remove (button.Child); + ret = base.ReadChild (reader, child_elem); + FixupGladeChildren (); + } else if (Type == ButtonType.TextAndIcon) + ConstructContents (); + return ret; + } + + protected override XmlElement WriteChild (ObjectWriter writer, Widget wrapper) + { + if (writer.Format == FileFormat.Glade || Type == ButtonType.Custom) + return base.WriteChild (writer, wrapper); + else + return null; + } + + void FixupGladeChildren () + { + Gtk.Alignment alignment = button.Child as Gtk.Alignment; + if (alignment == null) + return; + Gtk.HBox box = alignment.Child as Gtk.HBox; + if (box == null) + return; + + Gtk.Widget[] children = box.Children; + if (children == null || children.Length != 2) + return; + + Gtk.Image image = children[0] as Gtk.Image; + Gtk.Label label = children[1] as Gtk.Label; + if (image == null || label == null) + return; + Stetic.Wrapper.Image iwrap = Stetic.ObjectWrapper.Lookup (image) as Stetic.Wrapper.Image; + if (iwrap == null) + return; + + this.label = label.LabelProp; + button.UseUnderline = label.UseUnderline; + + imageInfo = iwrap.Pixbuf; + Type = ButtonType.TextAndIcon; + } + + protected override XmlElement WriteProperties (ObjectWriter writer) + { + XmlElement elem = base.WriteProperties (writer); + if (Type == ButtonType.StockItem) + GladeUtils.SetProperty (elem, "label", stockId); + return elem; + } + + public override IEnumerable RealChildren { + get { + if (type == ButtonType.Custom) + return base.RealChildren; + else + return new Gtk.Widget[0]; + } + } + + public override IEnumerable GladeChildren { + get { + if (type == ButtonType.StockItem || type == ButtonType.TextOnly) + return new Gtk.Widget[0]; + else + return base.GladeChildren; + } + } + + private Gtk.Button button { + get { + return (Gtk.Button)Wrapped; + } + } + + public enum ButtonType { + StockItem, + TextOnly, + TextAndIcon, + Custom + }; + + ButtonType type; + public ButtonType Type { + get { + return type; + } + set { + type = value; + EmitNotify ("Type"); + switch (type) { + case ButtonType.StockItem: + button.UseStock = true; + StockId = stockId; + break; + case ButtonType.TextOnly: + labelWidget = null; + button.UseStock = false; + Label = label; + UseUnderline = useUnderline; + break; + case ButtonType.TextAndIcon: + button.UseStock = false; + Label = label; + UseUnderline = useUnderline; + Icon = imageInfo; + break; + case ButtonType.Custom: + button.UseStock = false; + if (button.Child != null) + ReplaceChild (button.Child, CreatePlaceholder (), true); + break; + } + } + } + + public ImageInfo Icon { + get { return imageInfo; } + set { + imageInfo = value; + if (!Loading) { + ConstructContents (); + EmitNotify ("Image"); + } + } + } + + Gtk.Label labelWidget; + + protected override void OnEndRead (FileFormat format) + { + base.OnEndRead (format); + if (format == FileFormat.Native && Type == ButtonType.TextAndIcon) { + Loading = true; + ConstructContents (); + Loading = false; + } + } + + void ConstructContents () + { + if (button.Child != null) + button.Remove (button.Child); + + if (useUnderline) { + labelWidget = new Gtk.Label (label); + labelWidget.MnemonicWidget = button; + } else + labelWidget = Gtk.Label.New (label); + + Gtk.Image imageWidget = (Gtk.Image)Registry.NewInstance ("Gtk.Image", proj); + Image imageWrapper = (Image)Widget.Lookup (imageWidget); + imageWrapper.Unselectable = true; + if (type != ButtonType.StockItem) { + imageWrapper.Pixbuf = imageInfo; + } + + Gtk.HBox box = new Gtk.HBox (false, 2); + box.PackStart (imageWidget, false, false, 0); + box.PackEnd (labelWidget, false, false, 0); + + Gtk.Alignment alignment = new Gtk.Alignment (button.Xalign, button.Yalign, 0.0f, 0.0f); + alignment.Add (box); + + ObjectWrapper buttonWrapper = ObjectWrapper.Lookup (this); + Widget wrapper = (Widget)ObjectWrapper.Create (proj, labelWidget, buttonWrapper); + wrapper.Unselectable = true; + wrapper = (Widget)ObjectWrapper.Create (proj, box, buttonWrapper); + wrapper.Unselectable = true; + wrapper = (Widget)ObjectWrapper.Create (proj, alignment, buttonWrapper); + wrapper.Unselectable = true; + + alignment.ShowAll (); + button.Add (alignment); + } + + string stockId = Gtk.Stock.Ok; + public string StockId { + get { + return stockId; + } + set { + if (responseId == ResponseIdForStockId (stockId)) + responseId = 0; + + if (value != null) { + string sid = value; + if (sid.StartsWith ("stock:")) + sid = sid.Substring (6); + button.Label = stockId = sid; + button.UseStock = true; + Gtk.StockItem item = Gtk.Stock.Lookup (sid); + if (item.StockId == sid) { + label = item.Label; + useUnderline = true; + } + } else { + stockId = value; + } + + EmitNotify ("StockId"); + + if (responseId == 0) + ResponseId = ResponseIdForStockId (stockId); + } + } + + string label; + public string Label { + get { + return label; + } + set { + label = value; + if (labelWidget != null) + labelWidget.LabelProp = value; + else + button.Label = value; + } + } + + bool useUnderline; + public bool UseUnderline { + get { + return useUnderline; + } + set { + useUnderline = value; + if (labelWidget != null) + labelWidget.UseUnderline = value; + else + button.UseUnderline = value; + } + } + + public bool IsDialogButton { + get { + ButtonBox box = this.ParentWrapper as ButtonBox; + return (box != null && box.InternalChildProperty != null && box.InternalChildProperty.Name == "ActionArea"); + } + } + + int responseId; + public int ResponseId { + get { + return responseId; + } + set { + responseId = value; + EmitNotify ("ResponseId"); + } + } + + int ResponseIdForStockId (string stockId) + { + if (stockId == Gtk.Stock.Ok) + return (int)Gtk.ResponseType.Ok; + else if (stockId == Gtk.Stock.Cancel) + return (int)Gtk.ResponseType.Cancel; + else if (stockId == Gtk.Stock.Close) + return (int)Gtk.ResponseType.Close; + else if (stockId == Gtk.Stock.Yes) + return (int)Gtk.ResponseType.Yes; + else if (stockId == Gtk.Stock.No) + return (int)Gtk.ResponseType.No; + else if (stockId == Gtk.Stock.Apply) + return (int)Gtk.ResponseType.Apply; + else if (stockId == Gtk.Stock.Help) + return (int)Gtk.ResponseType.Help; + else + return 0; + } + + internal protected override void GenerateBuildCode (GeneratorContext ctx, CodeExpression var) + { + base.GenerateBuildCode (ctx, var); + + if (Type != ButtonType.TextAndIcon) { + CodePropertyReferenceExpression cprop = new CodePropertyReferenceExpression (var, "Label"); + PropertyDescriptor prop = (PropertyDescriptor) this.ClassDescriptor ["Label"]; + bool trans = Type != ButtonType.StockItem && prop.IsTranslated (Wrapped); + CodeExpression val = ctx.GenerateValue (button.Label, typeof(string), trans); + ctx.Statements.Add (new CodeAssignStatement (cprop, val)); + } + } + + protected override void GeneratePropertySet (GeneratorContext ctx, CodeExpression var, PropertyDescriptor prop) + { + if (prop.Name != "Label") + base.GeneratePropertySet (ctx, var, prop); + } + } +} diff --git a/main/src/addins/MonoDevelop.GtkCore2/libstetic/wrapper/ButtonBox.cs b/main/src/addins/MonoDevelop.GtkCore2/libstetic/wrapper/ButtonBox.cs new file mode 100644 index 0000000000..37b8b60e7f --- /dev/null +++ b/main/src/addins/MonoDevelop.GtkCore2/libstetic/wrapper/ButtonBox.cs @@ -0,0 +1,161 @@ +using System; +using System.Xml; +using System.Collections; +using System.CodeDom; + +namespace Stetic.Wrapper { + + public class ButtonBox : Box { + + Dialog actionDialog; + + public override void Wrap (object obj, bool initialized) + { + base.Wrap (obj, initialized); + foreach (Gtk.Widget child in buttonbox.Children) { + if (child is Placeholder) + ReplaceChild (child, NewButton (), true); + } + } + + public void SetActionDialog (Dialog dialog) + { + actionDialog = dialog; + } + + Gtk.Button NewButton () + { + Gtk.Button button = (Gtk.Button)Registry.NewInstance ("Gtk.Button", proj); + button.CanDefault = true; + return button; + } + + protected Gtk.ButtonBox buttonbox { + get { + return (Gtk.ButtonBox)Wrapped; + } + } + + protected override bool AllowPlaceholders { + get { + return false; + } + } + internal new void InsertBefore (Gtk.Widget context) + { + int position; + bool secondary; + + if (context == buttonbox) { + position = 0; + secondary = false; + } else { + Gtk.ButtonBox.ButtonBoxChild bbc = (Gtk.ButtonBox.ButtonBoxChild)ContextChildProps (context); + position = bbc.Position; + secondary = bbc.Secondary; + } + + Gtk.Button button = NewButton (); + buttonbox.PackStart (button, false, false, 0); + buttonbox.ReorderChild (button, position); + buttonbox.SetChildSecondary (button, secondary); + EmitContentsChanged (); + } + + internal new void InsertAfter (Gtk.Widget context) + { + int position; + bool secondary; + + if (context == buttonbox) { + position = buttonbox.Children.Length - 1; + secondary = false; + } else { + Gtk.ButtonBox.ButtonBoxChild bbc = (Gtk.ButtonBox.ButtonBoxChild)ContextChildProps (context); + position = bbc.Position; + secondary = bbc.Secondary; + } + + Gtk.Button button = NewButton (); + buttonbox.PackStart (button, false, false, 0); + buttonbox.ReorderChild (button, position + 1); + buttonbox.SetChildSecondary (button, secondary); + EmitContentsChanged (); + } + + public int Size { + get { + return buttonbox.Children.Length; + } + set { + Gtk.Widget[] children = buttonbox.Children; + int cursize = children.Length; + + while (cursize > value) { + Gtk.Widget w = children[--cursize]; + buttonbox.Remove (w); + w.Destroy (); + } + while (cursize < value) { + buttonbox.PackStart (NewButton (), false, false, 0); + cursize++; + } + } + } + + protected override void ReadChildren (ObjectReader reader, XmlElement elem) + { + // Reset the button count + Size = 0; + base.ReadChildren (reader, elem); + } + + protected override void GenerateChildBuildCode (GeneratorContext ctx, CodeExpression parentVar, Widget wrapper) + { + if (actionDialog != null && wrapper is Button) { + + // If this is the action area of a dialog, buttons must be added using AddActionWidget, + // so they are properly registered. + + ObjectWrapper childwrapper = ChildWrapper (wrapper); + Button button = wrapper as Button; + + if (childwrapper != null) { + CodeExpression dialogVar = ctx.WidgetMap.GetWidgetExp (actionDialog); + ctx.Statements.Add (new CodeCommentStatement ("Container child " + Wrapped.Name + "." + childwrapper.Wrapped.GetType ())); + CodeExpression var = ctx.GenerateNewInstanceCode (wrapper); + if (button.ResponseId != (int) Gtk.ResponseType.None) { + CodeMethodInvokeExpression invoke = new CodeMethodInvokeExpression ( + dialogVar, + "AddActionWidget", + var, + new CodePrimitiveExpression (button.ResponseId) + ); + ctx.Statements.Add (invoke); + } + else { + CodeMethodInvokeExpression invoke = new CodeMethodInvokeExpression ( + parentVar, + "Add", + var + ); + ctx.Statements.Add (invoke); + } + GenerateSetPacking (ctx, parentVar, var, childwrapper); + } + } else + base.GenerateChildBuildCode (ctx, parentVar, wrapper); + } + + public class ButtonBoxChild : Box.BoxChild { + + public bool InDialog { + get { + if (ParentWrapper == null) + return false; + return ParentWrapper.InternalChildProperty != null && ParentWrapper.InternalChildProperty.Name == "ActionArea"; + } + } + } + } +} diff --git a/main/src/addins/MonoDevelop.GtkCore2/libstetic/wrapper/ChangeLog b/main/src/addins/MonoDevelop.GtkCore2/libstetic/wrapper/ChangeLog new file mode 100644 index 0000000000..b9ccf74b8f --- /dev/null +++ b/main/src/addins/MonoDevelop.GtkCore2/libstetic/wrapper/ChangeLog @@ -0,0 +1,12 @@ +2010-08-03 Krzysztof Marecki <marecki.krzysztof@gmail.com> + + * Frame.cs: Pass root wrapper as an argument for ObjectWrapper.Create + * Action.cs: + * Window.cs: + * Button.cs: + * Widget.cs: + * Expander.cs: + * Container.cs: + * ActionGroup.cs: + * ScrolledWindow.cs: + diff --git a/main/src/addins/MonoDevelop.GtkCore2/libstetic/wrapper/CheckButton.cs b/main/src/addins/MonoDevelop.GtkCore2/libstetic/wrapper/CheckButton.cs new file mode 100644 index 0000000000..cd2fd6e88b --- /dev/null +++ b/main/src/addins/MonoDevelop.GtkCore2/libstetic/wrapper/CheckButton.cs @@ -0,0 +1,90 @@ +using System; +using System.Xml; +using System.CodeDom; + +namespace Stetic.Wrapper { + + public class CheckButton : Container { + + public override void Wrap (object obj, bool initialized) + { + base.Wrap (obj, initialized); + if (!initialized) + checkbutton.UseUnderline = true; + } + + public override void Read (ObjectReader reader, XmlElement elem) + { + base.Read (reader, elem); + if (reader.Format == FileFormat.Glade) + checkbutton.UseUnderline = true; + } + protected override ObjectWrapper ReadChild (ObjectReader reader, XmlElement child_elem) + { + hasLabel = false; + if (checkbutton.Child != null) + checkbutton.Remove (checkbutton.Child); + return base.ReadChild (reader, child_elem); + } + + public Gtk.CheckButton checkbutton { + get { + return (Gtk.CheckButton)Wrapped; + } + } + + bool hasLabel = true; + public bool HasLabel { + get { + return hasLabel; + } + set { + hasLabel = value; + EmitNotify ("HasLabel"); + } + } + + internal void RemoveLabel () + { + AddPlaceholder (); + HasLabel = false; + } + + public override Placeholder AddPlaceholder () + { + if (checkbutton.Child != null) + checkbutton.Remove (checkbutton.Child); + return base.AddPlaceholder (); + } + + internal void RestoreLabel () + { + checkbutton.Label = checkbutton.Name; + HasLabel = true; + } + + protected override void ReplaceChild (Gtk.Widget oldChild, Gtk.Widget newChild) + { + base.ReplaceChild (oldChild, newChild); + EmitNotify ("HasContents"); + } + + protected override void GenerateChildBuildCode (GeneratorContext ctx, CodeExpression parentVar, Widget wrapper) + { + if (!HasLabel) { + // CheckButton generates a label by default. Remove it if it is not required. + ctx.Statements.Add ( + new CodeMethodInvokeExpression ( + parentVar, + "Remove", + new CodePropertyReferenceExpression ( + parentVar, + "Child" + ) + ) + ); + } + base.GenerateChildBuildCode (ctx, parentVar, wrapper); + } + } +} diff --git a/main/src/addins/MonoDevelop.GtkCore2/libstetic/wrapper/ColorButton.cs b/main/src/addins/MonoDevelop.GtkCore2/libstetic/wrapper/ColorButton.cs new file mode 100644 index 0000000000..1cf71351aa --- /dev/null +++ b/main/src/addins/MonoDevelop.GtkCore2/libstetic/wrapper/ColorButton.cs @@ -0,0 +1,37 @@ +using System; +using System.CodeDom; + +namespace Stetic.Wrapper { + + public class ColorButton : Container { + + public int Alpha { + get { + Gtk.ColorButton cb = (Gtk.ColorButton)Wrapped; + + if (cb.UseAlpha) + return cb.Alpha; + else + return -1; + } + set { + Gtk.ColorButton cb = (Gtk.ColorButton)Wrapped; + + if (value == -1) + cb.UseAlpha = false; + else { + cb.UseAlpha = true; + cb.Alpha = (ushort)value; + } + } + } + + protected override void GeneratePropertySet (GeneratorContext ctx, CodeExpression var, PropertyDescriptor prop) + { + if (prop.Name == "Alpha" && Alpha == -1) + return; + else + base.GeneratePropertySet (ctx, var, prop); + } + } +} diff --git a/main/src/addins/MonoDevelop.GtkCore2/libstetic/wrapper/ComboBox.cs b/main/src/addins/MonoDevelop.GtkCore2/libstetic/wrapper/ComboBox.cs new file mode 100644 index 0000000000..5d196c5bc4 --- /dev/null +++ b/main/src/addins/MonoDevelop.GtkCore2/libstetic/wrapper/ComboBox.cs @@ -0,0 +1,122 @@ +using System; +using System.Xml; +using System.CodeDom; +using System.Runtime.InteropServices; + +namespace Stetic.Wrapper { + + public class ComboBox : Container { + + public static Gtk.ComboBox CreateInstance () + { + Gtk.ComboBox c = Gtk.ComboBox.NewText (); + // Make sure all children are created, so the mouse events can be + // bound and the widget can be selected. + c.EnsureStyle (); + try { + FixSensitivity (c); + } catch { + } + return c; + } + + public override void Wrap (object obj, bool initialized) + { + base.Wrap (obj, initialized); + if (!initialized) + textCombo = true; + } + + + string[] items = new string[0]; + bool textCombo; + + public string[] Items { + get { return items; } + set { + Gtk.ComboBox combobox = (Gtk.ComboBox)Wrapped; + int active = combobox.Active; + + int row = 0, oi = 0, ni = 0; + while (value != null && oi < items.Length && ni < value.Length) { + if (items [oi] == value [ni]) { + oi++; + ni++; + row++; + } else if (ni < value.Length - 1 && + items [oi] == value [ni + 1]) { + combobox.InsertText (row++, value [ni++]); + if (active > row) + active++; + } else { + combobox.RemoveText (row); + if (active > row) + active--; + oi++; + } + } + + while (oi < items.Length) { + combobox.RemoveText (row); + oi++; + } + + while (value != null && ni < value.Length) + combobox.InsertText (row++, value [ni++]); + + items = value == null ? new string [0] : value; + combobox.Active = active; + + EmitNotify ("Items"); + } + } + + public bool IsTextCombo { + get { return textCombo; } + set { textCombo = value; EmitNotify ("IsTextCombo"); } + } + + internal protected override CodeExpression GenerateObjectCreation (GeneratorContext ctx) + { + if (textCombo) { + return new CodeMethodInvokeExpression ( + new CodeTypeReferenceExpression (new CodeTypeReference ("Gtk.ComboBox", CodeTypeReferenceOptions.GlobalReference)), + "NewText" + ); + } else + return base.GenerateObjectCreation (ctx); + } + + internal protected override void GenerateBuildCode (GeneratorContext ctx, CodeExpression var) + { + if (textCombo && Items != null && Items.Length > 0) { + foreach (string str in Items) { + ctx.Statements.Add (new CodeMethodInvokeExpression ( + var, + "AppendText", + ctx.GenerateValue (str, typeof(string), true) + )); + } + } + + base.GenerateBuildCode (ctx, var); + } + + public override void Read (ObjectReader reader, XmlElement element) + { + base.Read (reader, element); + if (reader.Format == FileFormat.Glade && items.Length > 0) + IsTextCombo = true; + } + + internal static void FixSensitivity (Gtk.ComboBox c) + { + // Since gtk+ 2.14, empty combos are disabled by default + // This method disables this behavior + gtk_combo_box_set_button_sensitivity (c.Handle, 1); + } + + [DllImport("libgtk-win32-2.0-0.dll")] + extern static void gtk_combo_box_set_button_sensitivity (IntPtr combo, int mode); + } +} diff --git a/main/src/addins/MonoDevelop.GtkCore2/libstetic/wrapper/ComboBoxEntry.cs b/main/src/addins/MonoDevelop.GtkCore2/libstetic/wrapper/ComboBoxEntry.cs new file mode 100644 index 0000000000..9461b7422f --- /dev/null +++ b/main/src/addins/MonoDevelop.GtkCore2/libstetic/wrapper/ComboBoxEntry.cs @@ -0,0 +1,32 @@ +using System; +using System.CodeDom; + +namespace Stetic.Wrapper { + + public class ComboBoxEntry : ComboBox { + + public static new Gtk.ComboBoxEntry CreateInstance () + { + Gtk.ComboBoxEntry c = Gtk.ComboBoxEntry.NewText (); + // Make sure all children are created, so the mouse events can be + // bound and the widget can be selected. + c.EnsureStyle (); + try { + FixSensitivity (c); + } catch { + } + return c; + } + + internal protected override CodeExpression GenerateObjectCreation (GeneratorContext ctx) + { + if (IsTextCombo) { + return new CodeMethodInvokeExpression ( + new CodeTypeReferenceExpression (new CodeTypeReference ("Gtk.ComboBoxEntry", CodeTypeReferenceOptions.GlobalReference)), + "NewText" + ); + } else + return base.GenerateObjectCreation (ctx); + } + } +} diff --git a/main/src/addins/MonoDevelop.GtkCore2/libstetic/wrapper/Container.cs b/main/src/addins/MonoDevelop.GtkCore2/libstetic/wrapper/Container.cs new file mode 100644 index 0000000000..8fd16191ef --- /dev/null +++ b/main/src/addins/MonoDevelop.GtkCore2/libstetic/wrapper/Container.cs @@ -0,0 +1,1456 @@ +using System; +using System.CodeDom; +using System.Collections; +using System.Reflection; +using System.Runtime.InteropServices; +using System.Xml; +using Stetic.Undo; +using Stetic.Editor; + +namespace Stetic.Wrapper +{ + public class Container : Widget + { + int designWidth; + int designHeight; + IDesignArea designer; + CodeExpression generatedTooltips; + bool internalAdd; + + static DiffGenerator containerDiffGenerator; + static bool showNonContainerWarning = true; + + static Container () + { + XmlDiffAdaptor adaptor = new XmlDiffAdaptor (); + adaptor.ChildElementName = "child"; + adaptor.ChildAdaptor = new XmlDiffAdaptor (); + adaptor.ChildAdaptor.PropsElementName = "packing"; + + containerDiffGenerator = new DiffGenerator (); + containerDiffGenerator.CurrentStatusAdaptor = adaptor; + containerDiffGenerator.NewStatusAdaptor = adaptor; + } + + public override void Wrap (object obj, bool initialized) + { + base.Wrap (obj, initialized); + + 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, this) as Stetic.Wrapper.Widget; + wrapper.InternalChildProperty = prop; + if (child.Name == ((GLib.GType)child.GetType ()).ToString ()) + child.Name = container.Name + "_" + prop.Name; + } + + container.Removed += ChildRemoved; + container.Added += OnChildAdded; + + if (!initialized && container.Children.Length == 0 && AllowPlaceholders) + AddPlaceholder (); + + if (Wrapped.GetType ().ToString ()[0] == 'H') + ContainerOrientation = Gtk.Orientation.Horizontal; + else + ContainerOrientation = Gtk.Orientation.Vertical; + + if (!Loading) + ValidateChildNames (Wrapped); + } + + public override void Dispose () + { + container.Removed -= ChildRemoved; + container.Added -= OnChildAdded; + AutoSize.Clear (); + base.Dispose (); + } + + void OnChildAdded (object o, Gtk.AddedArgs args) + { + if (!internalAdd) + HandleNewChild (args.Widget); + } + + protected void NotifyChildAdded (Gtk.Widget child) + { + HandleNewChild (child); + EmitContentsChanged (); + } + + void HandleNewChild (Gtk.Widget child) + { + // Make sure children's IDs don't conflict with other widgets + // in the parent container. + if (!Loading) + ValidateChildNames (child); + + Widget w = Widget.Lookup (child); + if (w != null) { + w.RequiresUndoStatusUpdate = true; + if (designer != null) + w.OnDesignerAttach (designer); + + // If the ShowScrollbars flag is set, make sure the scrolled window is created. + if (w.ShowScrollbars) + w.UpdateScrolledWindow (); + } + + Placeholder ph = child as Placeholder; + if (ph != null) { + ph.DragDrop += PlaceholderDragDrop; + ph.DragDataReceived += PlaceholderDragDataReceived; + ph.ButtonPressEvent += PlaceholderButtonPress; + AutoSize[ph] = true; + } + } + + Gtk.Container container { + get { + return (Gtk.Container)Wrapped; + } + } + + protected virtual bool AllowPlaceholders { + get { + return true && this.ClassDescriptor.AllowChildren; + } + } + + public int DesignWidth { + get { return designWidth; } + set { designWidth = value; NotifyChanged (); } + } + + public int DesignHeight { + get { return designHeight; } + set { designHeight = value; NotifyChanged (); } + } + + public void IncreaseBorderWidth () + { + container.BorderWidth += 3; + } + + public void DecreaseBorderWidth () + { + if (container.BorderWidth >= 3) + container.BorderWidth -= 3; + else + container.BorderWidth = 0; + } + + internal bool ChildrenAllowed () + { + return this.ClassDescriptor.AllowChildren; + } + + int freeze; + protected void Freeze () + { + freeze++; + } + + protected void Thaw () + { + if (--freeze == 0) + Sync (); + } + + protected virtual void DoSync () + { + ; + } + + protected void Sync () + { + if (freeze > 0 || Loading) + return; + freeze = 1; + DoSync (); + freeze = 0; + } + + public override object GetUndoDiff () + { + XmlElement oldElem = UndoManager.GetObjectStatus (this); + +// Console.WriteLine ("UNDO status: "); +// Console.WriteLine (oldElem.OuterXml); + + // Write the new status of the object. This is going to replace the old status in undoManager. + // In the process, register new objects found. + + UndoWriter writer = new UndoWriter (oldElem.OwnerDocument, UndoManager); + XmlElement newElem = Write (writer); + +// Console.WriteLine ("CURRENT status: "); +// Console.WriteLine (newElem.OuterXml); + + // Get the changes since the last undo checkpoint + + ObjectDiff actionsDiff = null; + ObjectDiff objectDiff = containerDiffGenerator.GetDiff (newElem, oldElem); + + // If there are child changes there is no need to look for changes in the + // actions, since the whole widget will be read again + + if (IsTopLevel && (objectDiff == null || objectDiff.ChildChanges == null)) + actionsDiff = LocalActionGroups.GetDiff (Project, oldElem); + + // The undo writer skips children which are already registered in the undo manager + // to avoid writing information we already have. Now it's the moment to fill the gaps + + foreach (XmlElement newChild in newElem.SelectNodes ("child[widget/@unchanged_marker='yes']")) { + string cid = newChild.GetAttribute ("undoId"); + XmlElement oldChild = (XmlElement) oldElem.SelectSingleNode ("child[@undoId='" + cid + "']"); + if (oldChild == null) + throw new InvalidOperationException ("Child not found when filling widget info gaps."); + + XmlElement oldWidgetChild = oldChild ["widget"]; + XmlElement newWidgetChild = newChild ["widget"]; + + oldChild.RemoveChild (oldWidgetChild); + if (newWidgetChild != null) + newChild.ReplaceChild (oldWidgetChild, newWidgetChild); + } + + // Update the status tree + + UndoManager.UpdateObjectStatus (this, newElem); + +// UndoManager.Dump (); + + if (objectDiff != null || actionsDiff != null) + return new ObjectDiff[] { objectDiff, actionsDiff }; + else + return null; + } + + public override object ApplyUndoRedoDiff (object data) + { + ObjectDiff diff = ((ObjectDiff[]) data)[0]; + ObjectDiff actionsDiff = ((ObjectDiff[]) data)[1]; + + ObjectDiff reverseDiff = null; + ObjectDiff reverseActionsDiff = null; + + XmlElement status = UndoManager.GetObjectStatus (this); + XmlElement oldStatus = (XmlElement) status.CloneNode (true); + UndoReader reader = new UndoReader (Project, FileFormat.Native, UndoManager); + + // Only apply the actions diff if the widget has not been completely reloaded + if (actionsDiff != null && !(diff != null && diff.ChildChanges != null)) { + // Apply the patch + LocalActionGroups.ApplyDiff (Project, actionsDiff); + + // Get the redo patch + reverseActionsDiff = LocalActionGroups.GetDiff (Project, oldStatus); + + // Update the status of the action group list in the undo status tree. + // It has to remove all action groups and then write them again + foreach (XmlElement group in status.SelectNodes ("action-group")) + status.RemoveChild (group); + + UndoWriter writer = new UndoWriter (status.OwnerDocument, UndoManager); + foreach (ActionGroup actionGroup in LocalActionGroups) + status.InsertBefore (actionGroup.Write (writer), status.FirstChild); + } + + if (diff != null) { + containerDiffGenerator.ApplyDiff (status, diff); + reverseDiff = containerDiffGenerator.GetDiff (status, oldStatus); + + // Avoid reading the whole widget tree if only the properties have changed. + if (diff.ChildChanges == null) { + ReadProperties (reader, status); + } else { +// Console.WriteLine ("BEFORE PATCH: " + status.OuterXml); + Read (reader, status); +// Console.WriteLine ("\nAFTER PATCH:"); +// UndoManager.Dump (); + EmitContentsChanged (); + } + } + + if (reverseDiff != null || reverseActionsDiff != null) + return new ObjectDiff[] { reverseDiff, reverseActionsDiff }; + else + return null; + } + + public override void Read (ObjectReader reader, XmlElement elem) + { + // Remove all existing children + if (ClassDescriptor.AllowChildren && Wrapped != null) { + foreach (Gtk.Widget child in GladeChildren) { + Widget wrapper = Widget.Lookup (child); + + if (wrapper != null) { + if (wrapper.InternalChildProperty != null) + continue; + container.Remove (child); + child.Destroy (); + } else if (child is Stetic.Placeholder) { + container.Remove (child); + child.Destroy (); + } + } + } + + try { + Loading = true; + ReadActionGroups (reader, elem); + ReadProperties (reader, elem); + ReadChildren (reader, elem); + DoSync (); + } finally { + Loading = false; + } + } + + protected virtual void ReadChildren (ObjectReader reader, XmlElement elem) + { + int gladeChildStackPos = reader.GladeChildStack.Count; + + foreach (XmlElement child_elem in elem.SelectNodes ("./child")) { + try { + if (child_elem.HasAttribute ("internal-child")) + ReadInternalChild (reader, child_elem); + else if (child_elem["widget"] == null) + ReadPlaceholder (reader, child_elem); + else { + ObjectWrapper cw = ReadChild (reader, child_elem); + + // Set a temporary id used for the undo/redo operations + ObjectWrapper ccw = ChildWrapper ((Widget)cw); + if (ccw != null) { + string cid = child_elem.GetAttribute ("undoId"); + if (cid.Length > 0) + ChildWrapper ((Widget)cw).UndoId = cid; + else + child_elem.SetAttribute ("undoId", ChildWrapper ((Widget)cw).UndoId); + } + } + } catch (GladeException ge) { + Console.Error.WriteLine (ge.Message); + } + } + + if (reader.Format == FileFormat.Glade) { + for (int n = reader.GladeChildStack.Count - 1; n >= gladeChildStackPos; n--) { + ObjectWrapper ob = ReadInternalChild (reader, (XmlElement) reader.GladeChildStack [n]); + if (ob != null) + reader.GladeChildStack.RemoveAt (n); + } + } + + string ds = elem.GetAttribute ("design-size"); + if (ds.Length > 0) { + int i = ds.IndexOf (' '); + DesignWidth = int.Parse (ds.Substring (0, i)); + DesignHeight = int.Parse (ds.Substring (i+1)); + } + + Sync (); + } + + protected virtual ObjectWrapper ReadChild (ObjectReader reader, XmlElement child_elem) + { + ObjectWrapper wrapper = reader.ReadObject (child_elem["widget"], this); + Container.ContainerChild childwrapper = null; + + try { + wrapper.Loading = true; + + Gtk.Widget child = (Gtk.Widget)wrapper.Wrapped; + + AutoSize[child] = false; + container.Add (child); + + childwrapper = ChildWrapper ((Widget)wrapper); + if (childwrapper != null) + childwrapper.Loading = true; + + if (reader.Format == FileFormat.Glade) + GladeUtils.SetPacking (childwrapper, child_elem); + else + WidgetUtils.SetPacking (childwrapper, child_elem); + return wrapper; + } finally { + wrapper.Loading = false; + if (childwrapper != null) + childwrapper.Loading = false; + } + } + + void ReadPlaceholder (ObjectReader reader, XmlElement child_elem) + { + Placeholder ph = AddPlaceholder (); + if (ph != null) { + string cid = child_elem.GetAttribute ("undoId"); + if (cid.Length > 0) + ph.UndoId = cid; + else + child_elem.SetAttribute ("undoId", ph.UndoId); + } + } + + protected virtual ObjectWrapper ReadInternalChild (ObjectReader reader, XmlElement child_elem) + { + ClassDescriptor klass = base.ClassDescriptor; + string childId = child_elem.GetAttribute ("internal-child"); + + foreach (PropertyDescriptor prop in klass.InternalChildren) { + if (reader.Format == FileFormat.Glade && ((TypedPropertyDescriptor)prop).GladeName != childId) + continue; + else if (reader.Format == FileFormat.Native && prop.Name != childId) + continue; + + Gtk.Widget child = prop.GetValue (container) as Gtk.Widget; + Widget wrapper = Widget.Lookup (child); + if (wrapper != null) { + reader.ReadExistingObject (wrapper, child_elem["widget"]); + if (reader.Format == FileFormat.Glade) + GladeUtils.SetPacking (ChildWrapper (wrapper), child_elem); + else + WidgetUtils.SetPacking (ChildWrapper (wrapper), child_elem); + return wrapper; + } + } + + // In Glade, internal children may not be direct children of the root container. This is handled in a special way. + if (reader.Format == FileFormat.Glade) { + if (!reader.GladeChildStack.Contains (child_elem)) + reader.GladeChildStack.Add (child_elem); + return null; + } + else + throw new GladeException ("Unrecognized internal child name", Wrapped.GetType ().FullName, false, "internal-child", childId); + } + + public override XmlElement Write (ObjectWriter writer) + { + XmlElement elem = WriteProperties (writer); + WriteActionGroups (writer, elem); + XmlElement child_elem; + + if (ClassDescriptor.AllowChildren) { + foreach (Gtk.Widget child in GladeChildren) { + Widget wrapper = Widget.Lookup (child); + + if (wrapper != null) { + // Iternal children are written later + if (wrapper.InternalChildProperty != null) + continue; + child_elem = WriteChild (writer, wrapper); + if (child_elem != null) + elem.AppendChild (child_elem); + } else if (child is Stetic.Placeholder) { + child_elem = writer.XmlDocument.CreateElement ("child"); + if (writer.CreateUndoInfo) + child_elem.SetAttribute ("undoId", ((Stetic.Placeholder)child).UndoId); + child_elem.AppendChild (writer.XmlDocument.CreateElement ("placeholder")); + elem.AppendChild (child_elem); + } + } + } + + foreach (PropertyDescriptor prop in this.ClassDescriptor.InternalChildren) { + Gtk.Widget child = prop.GetValue (Wrapped) as Gtk.Widget; + if (child == null) + continue; + + child_elem = writer.XmlDocument.CreateElement ("child"); + Widget wrapper = Widget.Lookup (child); + if (wrapper == null) { + child_elem.AppendChild (writer.XmlDocument.CreateElement ("placeholder")); + elem.AppendChild (child_elem); + continue; + } + + string cid = writer.Format == FileFormat.Glade ? prop.InternalChildId : prop.Name; + + XmlElement widget_elem = writer.WriteObject (wrapper); + child_elem.SetAttribute ("internal-child", cid); + // Sets the child Id to be used in undo/redo operations + if (writer.CreateUndoInfo) + child_elem.SetAttribute ("undoId", cid); + + child_elem.AppendChild (widget_elem); + elem.AppendChild (child_elem); + } + + if (DesignWidth != 0 || DesignHeight != 0) + elem.SetAttribute ("design-size", DesignWidth + " " + DesignHeight); + + return elem; + } + + protected virtual XmlElement WriteChild (ObjectWriter writer, Widget wrapper) + { + XmlElement child_elem = writer.XmlDocument.CreateElement ("child"); + XmlElement widget_elem = writer.WriteObject (wrapper); + child_elem.AppendChild (widget_elem); + + Container.ContainerChild childwrapper = ChildWrapper (wrapper); + if (childwrapper != null) { + XmlElement packing_elem; + + if (writer.Format == FileFormat.Glade) + packing_elem = GladeUtils.CreatePacking (writer.XmlDocument, childwrapper); + else + packing_elem = WidgetUtils.CreatePacking (writer.XmlDocument, childwrapper); + + // Sets the child Id to be used in undo/redo operations + if (writer.CreateUndoInfo) + child_elem.SetAttribute ("undoId", childwrapper.UndoId); + + if (packing_elem.HasChildNodes) + child_elem.AppendChild (packing_elem); + } else { + // There is no container child, so make up an id. + if (writer.CreateUndoInfo) + child_elem.SetAttribute ("undoId", "0"); + } + + return child_elem; + } + + public XmlElement WriteContainerChild (ObjectWriter writer, Widget wrapper) + { + return WriteChild (writer, wrapper); + } + + internal protected override void GenerateBuildCode (GeneratorContext ctx, CodeExpression var) + { + generatedTooltips = null; + + base.GenerateBuildCode (ctx, var); + + if (ClassDescriptor.AllowChildren) { + foreach (Gtk.Widget child in GladeChildren) { + Widget wrapper = Widget.Lookup (child); + + if (wrapper != null && wrapper.InternalChildProperty == null) + // Iternal children are written later + GenerateChildBuildCode (ctx, var, wrapper); + } + } + + foreach (TypedPropertyDescriptor prop in this.ClassDescriptor.InternalChildren) { + GenerateSetInternalChild (ctx, var, prop); + } + + + if (IsTopLevel && Wrapped is Gtk.Bin) { + CodeExpression childExp = new CodePropertyReferenceExpression (var, "Child"); + CodeConditionStatement cond = new CodeConditionStatement (); + cond.Condition = + new CodeBinaryOperatorExpression ( + childExp, + CodeBinaryOperatorType.IdentityInequality, + new CodePrimitiveExpression (null) + ); + cond.TrueStatements.Add ( + new CodeMethodInvokeExpression ( + childExp, + "ShowAll" + ) + ); + ctx.Statements.Add (cond); + } + } + + protected virtual void GenerateChildBuildCode (GeneratorContext ctx, CodeExpression parentVar, Widget wrapper) + { + ObjectWrapper childwrapper = ChildWrapper (wrapper); + if (childwrapper != null) { + ctx.Statements.Add (new CodeCommentStatement ("Container child " + Wrapped.Name + "." + childwrapper.Wrapped.GetType ())); + CodeExpression var = ctx.GenerateNewInstanceCode (wrapper); + CodeMethodInvokeExpression invoke = new CodeMethodInvokeExpression ( + parentVar, + "Add", + var + ); + ctx.Statements.Add (invoke); + + GenerateSetPacking (ctx, parentVar, var, childwrapper); + } + } + + void GenerateSetInternalChild (GeneratorContext ctx, CodeExpression parentVar, TypedPropertyDescriptor prop) + { + Gtk.Widget child = prop.GetValue (container) as Gtk.Widget; + Widget cwrapper = Widget.Lookup (child); + if (cwrapper != null) { + ctx.Statements.Add (new CodeCommentStatement ("Internal child " + Wrapped.Name + "." + prop.Name)); + string childVar = ctx.NewId (); + CodeVariableDeclarationStatement varDec = new CodeVariableDeclarationStatement (child.GetType().ToGlobalTypeRef (), childVar); + ctx.Statements.Add (varDec); + varDec.InitExpression = new CodePropertyReferenceExpression (parentVar, prop.Name); + + ctx.GenerateBuildCode (cwrapper, new CodeVariableReferenceExpression (childVar)); + return; + } + } + + protected void GenerateSetPacking (GeneratorContext ctx, CodeExpression parentVar, CodeExpression childVar, ObjectWrapper containerChildWrapper) + { + 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().ToGlobalTypeRef (), contChildVar); + varDec.InitExpression = new CodeCastExpression ( + cc.GetType ().ToGlobalTypeRef (), + new CodeIndexerExpression (parentVar, childVar) + ); + + CodeVariableReferenceExpression var = new CodeVariableReferenceExpression (contChildVar); + + // Set the container child properties + + ctx.Statements.Add (varDec); + int count = ctx.Statements.Count; + + foreach (ItemGroup group in klass.ItemGroups) { + foreach (ItemDescriptor item in group) { + PropertyDescriptor prop = item as PropertyDescriptor; + if (prop == null || !prop.IsRuntimeProperty) + continue; + GenerateChildPropertySet (ctx, var, klass, prop, cc); + } + } + + if (ctx.Statements.Count == count) { + ctx.Statements.Remove (varDec); + } + } + + protected virtual void GenerateChildPropertySet (GeneratorContext ctx, 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, prop.RuntimePropertyType, prop.Translatable); + ctx.Statements.Add (new CodeAssignStatement (cprop, val)); + } + + internal protected override void GeneratePostBuildCode (GeneratorContext ctx, CodeExpression var) + { + base.GeneratePostBuildCode (ctx, var); + + if (IsTopLevel && (Wrapped is Gtk.Bin) && Visible) { + ctx.Statements.Add ( + new CodeMethodInvokeExpression ( + var, + "Show" + ) + ); + } + } + + internal void GenerateTooltip (GeneratorContext ctx, Widget widget) + { + if (WidgetUtils.CompareVersions (Project.TargetGtkVersion, "2.12") <= 0) { + ctx.Statements.Add ( + new CodeAssignStatement ( + new CodePropertyReferenceExpression (ctx.WidgetMap.GetWidgetExp (widget), "TooltipMarkup"), + new CodePrimitiveExpression (widget.Tooltip) + ) + ); + return; + } + + if (generatedTooltips == null) { + string tid = ctx.NewId (); + Type t = typeof(Gtk.Widget).Assembly.GetType ("Gtk.Tooltips"); + CodeVariableDeclarationStatement vardec = new CodeVariableDeclarationStatement ( + t.ToGlobalTypeRef (), tid, new CodeObjectCreateExpression (t) + ); + ctx.Statements.Add (vardec); + generatedTooltips = new CodeVariableReferenceExpression (tid); + } + ctx.Statements.Add ( + new CodeMethodInvokeExpression ( + generatedTooltips, + "SetTip", + ctx.WidgetMap.GetWidgetExp (widget), + new CodePrimitiveExpression (widget.Tooltip), + new CodePrimitiveExpression (widget.Tooltip) + ) + ); + } + + internal protected override void OnDesignerAttach (IDesignArea designer) + { + base.OnDesignerAttach (designer); + this.designer = designer; + foreach (Gtk.Widget w in RealChildren) { + ObjectWrapper wr = ObjectWrapper.Lookup (w); + if (wr != null) + wr.OnDesignerAttach (designer); + } + } + + internal protected override void OnDesignerDetach (IDesignArea designer) + { + base.OnDesignerDetach (designer); + foreach (Gtk.Widget w in RealChildren) { + ObjectWrapper wr = ObjectWrapper.Lookup (w); + if (wr != null) + wr.OnDesignerDetach (designer); + } + this.designer = null; + } + + public virtual Placeholder AddPlaceholder () + { + Placeholder ph = CreatePlaceholder (); + container.Add (ph); + return ph; + } + + public virtual void Add (Gtk.Widget child) + { + container.Add (child); + } + + public static new Container Lookup (GLib.Object obj) + { + return Stetic.ObjectWrapper.Lookup (obj) as Stetic.Wrapper.Container; + } + + public static Container LookupParent (Gtk.Widget widget) + { + if (widget == null) + return null; + Gtk.Widget parent = widget.Parent; + Container wrapper = null; + while ((wrapper == null || wrapper.Unselectable) && parent != null) { + wrapper = Lookup (parent); + parent = parent.Parent; + } + return wrapper; + } + + public static Stetic.Wrapper.Container.ContainerChild ChildWrapper (Stetic.Wrapper.Widget wrapper) { + Stetic.Wrapper.Container parentWrapper = wrapper.ParentWrapper; + if (parentWrapper == null) + return null; + + Gtk.Container parent = parentWrapper.Wrapped as Gtk.Container; + if (parent == null) + return null; + + Gtk.Widget child = (Gtk.Widget)wrapper.Wrapped; + while (child != null && child.Parent != parent) + child = child.Parent; + if (child == null) + return null; + + Gtk.Container.ContainerChild cc = parent[child]; + Container.ContainerChild cwrap = ObjectWrapper.Lookup (cc) as Container.ContainerChild; + if (cwrap != null) + return cwrap; + else + return Stetic.ObjectWrapper.Create (parentWrapper.proj, cc, parentWrapper) as ContainerChild; + } + + protected Gtk.Container.ContainerChild ContextChildProps (Gtk.Widget context) + { + if (context == container) + return null; + + do { + if (context.Parent == container) + return container[context]; + context = context.Parent; + } while (context != null); + + return null; + } + + public delegate void ContentsChangedHandler (Container container); + public event ContentsChangedHandler ContentsChanged; + + protected void EmitContentsChanged () + { + if (Loading) + return; + if (ContentsChanged != null) + ContentsChanged (this); + if (ParentWrapper != null) + ParentWrapper.ChildContentsChanged (this); + if (Project != null) + Project.NotifyWidgetContentsChanged (this); + NotifyChanged (); + } + + protected Set AutoSize = new Set (); + + protected virtual Placeholder CreatePlaceholder () + { + Placeholder ph = new Placeholder (); + ph.Show (); + return ph; + } + + void PlaceholderButtonPress (object obj, Gtk.ButtonPressEventArgs args) + { + if (args.Event.Type != Gdk.EventType.ButtonPress) + return; + + Placeholder ph = obj as Placeholder; + + if (args.Event.Button == 1) { + proj.Selection = ph; + args.RetVal = true; + } else if (args.Event.Button == 3) { + proj.PopupContextMenu (ph); + args.RetVal = true; + } + } + + public static bool ShowNonContainerWarning { + get { return showNonContainerWarning; } + set { showNonContainerWarning = value; } + } + + static IList nonContainers = new string[] { + "Gtk.Button", "Gtk.Entry", "Gtk.Label", "Gtk.Arrow", "Gtk.Calendar", "Gtk.CheckButton", + "Gtk.ColorButton", "Gtk.ComboBox", "Gtk.ComboBoxEntry", "Gtk.Entry", "Gtk.FontButton", + "Gtk.HScale", "Gtk.VScale", "Gtk.Image", "Gtk.MenuBar", "Gtk.Toolbar", "Gtk.RadioButton", + "Gtk.ProgressBar", "Stetic.Editor.ActionToolbar", "Stetic.Editor.ActionMenuBar", + "Gtk.ToggleButton", "Gtk.TextView", "Gtk.VScrollbar", "Gtk.HScrollbar", "Gtk.SpinButton", + "Gtk.Statusbar", "Gtk.HSeparator", "Gtk.VSeparator" + }; + + void PlaceholderDrop (Placeholder ph, Stetic.Wrapper.Widget wrapper) + { + Gtk.Dialog parentDialog = Wrapped.Parent as Gtk.Dialog; + if (showNonContainerWarning && (IsTopLevel || (parentDialog != null && parentDialog.VBox == Wrapped))) { + if (nonContainers.Contains (wrapper.Wrapped.GetType ().ToString ())) { + using (NonContainerWarningDialog dlg = new NonContainerWarningDialog ()) { + int res = dlg.Run (); + showNonContainerWarning = dlg.ShowAgain; + if (res != (int) Gtk.ResponseType.Ok) + return; + } + } + } + using (UndoManager.AtomicChange) { + ReplaceChild (ph, wrapper.Wrapped, true); + wrapper.Select (); + } + } + + void PlaceholderDragDrop (object obj, Gtk.DragDropArgs args) + { + Placeholder ph = (Placeholder)obj; + // This Drop call will end calling DropObject() + DND.Drop (args.Context, args.Time, this, ph.UndoId); + args.RetVal = true; + } + + internal protected override void DropObject (string data, Gtk.Widget w) + { + Placeholder ph = FindPlaceholder (container, data); + if (ph != null) { + Widget dropped = Stetic.Wrapper.Widget.Lookup (w); + if (dropped != null) + PlaceholderDrop (ph, dropped); + } + } + + Placeholder FindPlaceholder (Gtk.Container c, string pid) + { + foreach (Gtk.Widget cw in c.AllChildren) { + Placeholder ph = cw as Placeholder; + if (ph != null && ph.UndoId == pid) + return ph; + Gtk.Container cc = cw as Gtk.Container; + if (cc != null) { + ph = FindPlaceholder (cc, pid); + if (ph != null) + return ph; + } + } + return null; + } + + void PlaceholderDragDataReceived (object obj, Gtk.DragDataReceivedArgs args) + { + Widget dropped = WidgetUtils.Paste (proj, args.SelectionData); + Gtk.Drag.Finish (args.Context, dropped != null, + dropped != null, args.Time); + if (dropped != null) { + dropped.RequiresUndoStatusUpdate = true; + PlaceholderDrop ((Placeholder)obj, dropped); + } + } + + protected virtual void ChildContentsChanged (Container child) + { + } + + void ChildRemoved (object obj, Gtk.RemovedArgs args) + { + NotifyChildRemoved (args.Widget); + } + + protected void NotifyChildRemoved (Gtk.Widget child) + { + if (Loading) + return; + + ObjectWrapper w = ObjectWrapper.Lookup (child); + if (w != null) { + if (w.Loading) + return; + if (designer != null) + w.OnDesignerDetach (designer); + } + ChildRemoved (child); + } + + protected virtual void ChildRemoved (Gtk.Widget w) + { + AutoSize[w] = false; + EmitContentsChanged (); + } + + public virtual IEnumerable RealChildren { + get { + ArrayList children = new ArrayList (); + foreach (Gtk.Widget widget in container.AllChildren) { + if (!(widget is Placeholder)) + children.Add (widget); + } + return children; + } + } + + public virtual IEnumerable GladeChildren { + get { + return container.AllChildren; + } + } + + public void PasteChild (Gtk.Widget oldChild, Gtk.Widget newChild) + { + using (UndoManager.AtomicChange) { + Widget w = Widget.Lookup (newChild); + w.RequiresUndoStatusUpdate = true; + ReplaceChild (oldChild, newChild, true); + } + } + + internal protected void ReplaceChild (Gtk.Widget oldChild, Gtk.Widget newChild, bool destroyOld) + { + ReplaceChild (oldChild, newChild); + if (destroyOld) + oldChild.Destroy (); + } + + protected virtual void ReplaceChild (Gtk.Widget oldChild, Gtk.Widget newChild) + { + using (UndoManager.AtomicChange) + { + Gtk.Container.ContainerChild cc; + Hashtable props = new Hashtable (); + + cc = container[oldChild]; + foreach (PropertyInfo pinfo in cc.GetType ().GetProperties ()) { + if (!pinfo.IsDefined (typeof (Gtk.ChildPropertyAttribute), true)) + continue; + props[pinfo] = pinfo.GetValue (cc, null); + } + + container.Remove (oldChild); + AutoSize[oldChild] = false; + AutoSize[newChild] = true; + + try { + // Don't fire the child added event until the packing info is set + internalAdd = true; + container.Add (newChild); + } finally { + internalAdd = false; + } + + cc = container[newChild]; + foreach (PropertyInfo pinfo in props.Keys) + pinfo.SetValue (cc, props[pinfo], null); + + Sync (); + NotifyChildAdded (newChild); + if (Project != null) + Project.Selection = newChild; + } + } + + Gtk.Widget selection; + + public virtual void Select (Gtk.Widget widget) + { + if (widget == null) { + Select (null, false); + } else { + Widget wrapper = Widget.Lookup (widget); + bool allowDrag = wrapper != null && wrapper.InternalChildProperty == null && !wrapper.IsTopLevel; + Select (widget, allowDrag); + } + } + + public virtual void UnSelect (Gtk.Widget widget) + { + if (selection == widget) + Select (null, false); + } + + void Select (Gtk.Widget widget, bool dragHandles) + { + if (widget == selection) + return; + + Gtk.Window win = GetParentWindow (); + + if (selection != null) { + selection.Destroyed -= SelectionDestroyed; + HideSelectionBox (selection); + Widget wr = Widget.Lookup (selection); + if (wr != null) + wr.OnUnselected (); + } + + selection = widget; + if (win != null) { + if (widget != null) { + if (widget.CanFocus) + win.Focus = widget; + else { + // Look for a focusable parent container + Widget wr = GetTopLevel (); + Gtk.Widget w = wr.Wrapped; + while (w != null && !w.CanFocus) + w = w.Parent; + + // If the widget is not focusable, + // 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. + win.Focus = w; + } + } else { + if (designer != null) + designer.ResetSelection (null); + } + } + + if (selection != null) { + selection.Destroyed += SelectionDestroyed; + + // FIXME: if the selection isn't mapped, we should try to force it + // 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.IsDrawable && selection.Visible) { + ShowSelectionBox (selection, dragHandles); + } + + Widget wr = Widget.Lookup (selection); + if (wr != null) + wr.OnSelected (); + } + } + + void ShowSelectionBox (Gtk.Widget widget, bool dragHandles) + { + HideSelectionBox (selection); + + IDesignArea designArea = GetDesignArea (widget); + if (designArea != null) { + IObjectSelection sel = designArea.SetSelection (widget, widget, dragHandles); + sel.Drag += HandleWindowDrag; + return; + } + } + + void HideSelectionBox (Gtk.Widget widget) + { + if (widget != null) { + IDesignArea designArea = GetDesignArea (widget); + if (designArea != null) + designArea.ResetSelection (widget); + } + } + + 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) + { + if (!IsDisposed) + UnSelect (selection); + } + + Gtk.Widget dragSource; + + void HandleWindowDrag (Gdk.EventMotion evt, int dx, int dy) + { + Gtk.Widget dragWidget = selection; + + Project.Selection = null; + + using (UndoManager.AtomicChange) { + dragSource = CreateDragSource (dragWidget); + } + + DND.Drag (dragSource, evt, dragWidget); + } + + protected virtual Gtk.Widget CreateDragSource (Gtk.Widget dragWidget) + { + Placeholder ph = CreatePlaceholder (); + Gdk.Rectangle alloc = dragWidget.Allocation; + ph.SetSizeRequest (alloc.Width, alloc.Height); + ph.DragEnd += DragEnd; + ReplaceChild (dragWidget, ph, false); + return ph; + } + + void DragEnd (object obj, Gtk.DragEndArgs args) + { + using (UndoManager.AtomicChange) { + Placeholder ph = obj as Placeholder; + ph.DragEnd -= DragEnd; + + dragSource = null; + if (DND.DragWidget == null) { + if (AllowPlaceholders) + ph.SetSizeRequest (-1, -1); + else + container.Remove (ph); + Sync (); + } else + ReplaceChild (ph, DND.Cancel (), true); + } + } + + public virtual void Delete (Stetic.Wrapper.Widget wrapper) + { + using (UndoManager.AtomicChange) { + if (AllowPlaceholders) + ReplaceChild (wrapper.Wrapped, CreatePlaceholder (), true); + else { + container.Remove (wrapper.Wrapped); + wrapper.Wrapped.Destroy (); + } + } + } + + public virtual void Delete (Stetic.Placeholder ph) + { + if (AllowPlaceholders) { + // Don't allow deleting the only placeholder of a top level container + if (IsTopLevel && container.Children.Length == 1) + return; + using (UndoManager.AtomicChange) { + container.Remove (ph); + ph.Destroy (); + // If there aren't more placeholders in this container, just delete the container + if (container.Children.Length == 0) + Delete (); + } + } + } + + protected bool ChildHExpandable (Gtk.Widget child) + { + if (child == dragSource) + child = DND.DragWidget; + else if (child is Placeholder) + return true; + + Stetic.Wrapper.Widget wrapper = Stetic.Wrapper.Widget.Lookup (child); + if (wrapper != null) + return wrapper.HExpandable; + else + return false; + } + + protected bool ChildVExpandable (Gtk.Widget child) + { + if (child == dragSource) + child = DND.DragWidget; + else if (child is Placeholder) + return true; + + Stetic.Wrapper.Widget wrapper = Stetic.Wrapper.Widget.Lookup (child); + if (wrapper != null) + return wrapper.VExpandable; + else + return false; + } + + // Note that this will be invalid/random for non-H/V-paired classes + protected Gtk.Orientation ContainerOrientation; + + public override bool HExpandable { + get { + if (base.HExpandable) + return true; + + // A horizontally-oriented container is HExpandable if any + // child is. A vertically-oriented container is HExpandable + // if *every* child is. + + foreach (Gtk.Widget w in container) { + if (ChildHExpandable (w)) { + if (ContainerOrientation == Gtk.Orientation.Horizontal) + return true; + } else if (ContainerOrientation == Gtk.Orientation.Vertical) + return false; + } + return (ContainerOrientation == Gtk.Orientation.Vertical); + } + } + + public override bool VExpandable { + get { + if (base.VExpandable) + return true; + + // Opposite of above + + foreach (Gtk.Widget w in container) { + if (ChildVExpandable (w)) { + if (ContainerOrientation == Gtk.Orientation.Vertical) + return true; + } else if (ContainerOrientation == Gtk.Orientation.Horizontal) + return false; + } + return (ContainerOrientation == Gtk.Orientation.Horizontal); + } + } + + void ValidateChildNames (Gtk.Widget newWidget) + { + // newWidget is the widget which triggered the name check. + // It will be the last widget to check, so if there are + // name conflicts, the name to change to avoid the conflict + // will be the name of that widget. + + if (!IsTopLevel) { + ParentWrapper.ValidateChildNames (newWidget); + return; + } + + Hashtable names = new Hashtable (); + + // Validate all names excluding the new widget + ValidateChildName (names, container, newWidget); + + if (newWidget != null) { + // Now validate names in the new widget. + ValidateChildName (names, newWidget, null); + } + } + + void ValidateChildName (Hashtable names, Gtk.Widget w, Gtk.Widget newWidget) + { + if (w == newWidget) + return; + + if (names.Contains (w.Name)) { + // There is a widget with the same name. If the widget + // has a numeric suffix, just increase it. + string name; int idx; + WidgetUtils.ParseWidgetName (w.Name, out name, out idx); + + string compName = idx != 0 ? name + idx : name; + while (names.Contains (compName)) { + idx++; + compName = name + idx; + } + w.Name = compName; + Widget ww = Widget.Lookup (w); + if (ww != null) + ww.InitializeName (compName); + else + w.Name = compName; + + } + + names [w.Name] = w; + + if (w is Gtk.Container) { + foreach (Gtk.Widget cw in ((Gtk.Container)w).AllChildren) + ValidateChildName (names, cw, newWidget); + } + } + + internal string GetValidWidgetName (Gtk.Widget widget) + { + // Get a valid name for a widget (a name that doesn't + // exist in the parent container. + + if (!IsTopLevel) + return ParentWrapper.GetValidWidgetName (widget); + + string name; + int idx; + + WidgetUtils.ParseWidgetName (widget.Name, out name, out idx); + + string compName = idx != 0 ? name + idx : name; + + Gtk.Widget fw = FindWidget (compName, widget); + while (fw != null) { + idx++; + compName = name + idx; + fw = FindWidget (compName, widget); + } + + return compName; + } + + public Widget FindChild (string name) + { + Gtk.Widget w = FindWidget (name, null); + return Widget.Lookup (w); + } + + Gtk.Widget FindWidget (string name, Gtk.Widget skipwidget) + { + if (Wrapped != skipwidget && Wrapped.Name == name) + return Wrapped; + else + return FindWidget ((Gtk.Container)Wrapped, name, skipwidget); + } + + Gtk.Widget FindWidget (Gtk.Container parent, string name, Gtk.Widget skipwidget) + { + foreach (Gtk.Widget w in parent.AllChildren) { + if (w.Name == name && w != skipwidget) + return w; + if (w is Gtk.Container) { + Gtk.Widget res = FindWidget ((Gtk.Container)w, name, skipwidget); + if (res != null) + return res; + } + } + return null; + } + + public override ObjectWrapper FindObjectByUndoId (string id) + { + ObjectWrapper c = base.FindObjectByUndoId (id); + if (c != null) + return c; + + foreach (Gtk.Widget w in container.AllChildren) { + Widget ww = Widget.Lookup (w); + if (ww == null) + continue; + ObjectWrapper ow = ww.FindObjectByUndoId (id); + if (ow != null) + return ow; + } + return null; + } + + + + public class ContainerChild : Stetic.ObjectWrapper + { + internal static void Register () + { + // FIXME? + } + + public override void Wrap (object obj, bool initialized) + { + base.Wrap (obj, initialized); + cc.Child.ChildNotified += ChildNotifyHandler; + cc.Child.ParentSet += OnParentSet; + } + + [GLib.ConnectBefore] + void OnParentSet (object ob, Gtk.ParentSetArgs args) + { + // Dispose the wrapper if the child is removed from the parent + Gtk.Widget w = (Gtk.Widget)ob; + if (w.Parent == null) { + Dispose (); + w.ParentSet -= OnParentSet; + } + } + + public override void Dispose () + { + cc.Child.ChildNotified -= ChildNotifyHandler; + base.Dispose (); + } + + protected virtual void ChildNotifyHandler (object obj, Gtk.ChildNotifiedArgs args) + { + ParamSpec pspec = new ParamSpec (args.Pspec); + EmitNotify (pspec.Name); + } + + protected override void EmitNotify (string propertyName) + { + base.EmitNotify (propertyName); + ParentWrapper.Sync (); + ParentWrapper.NotifyChanged (); + } + + Gtk.Container.ContainerChild cc { + get { + return (Gtk.Container.ContainerChild)Wrapped; + } + } + + protected Stetic.Wrapper.Container ParentWrapper { + get { + return Stetic.Wrapper.Container.Lookup (cc.Parent); + } + } + + public bool AutoSize { + get { + return ParentWrapper.AutoSize[cc.Child]; + } + set { + ParentWrapper.AutoSize[cc.Child] = value; + EmitNotify ("AutoSize"); + } + } + + public override string Name { get; set; } + } + } +} diff --git a/main/src/addins/MonoDevelop.GtkCore2/libstetic/wrapper/Custom.cs b/main/src/addins/MonoDevelop.GtkCore2/libstetic/wrapper/Custom.cs new file mode 100644 index 0000000000..5f73164b8e --- /dev/null +++ b/main/src/addins/MonoDevelop.GtkCore2/libstetic/wrapper/Custom.cs @@ -0,0 +1,123 @@ +using System; +using Gtk; + +namespace Stetic +{ + public class Custom : Gtk.DrawingArea + { + public Custom () {} + + public Custom (IntPtr raw) : base (raw) {} + + // from glade + static private string[] custom_bg_xpm = { + "8 8 4 1", + " c None", + ". c #BBBBBB", + "+ c #D6D6D6", + "@ c #6B5EFF", + ".+..+...", + "+..@@@..", + "..@...++", + "..@...++", + "+.@..+..", + ".++@@@..", + "..++....", + "..++...." + }; + + Gdk.Pixmap pixmap; + + protected override void OnRealized () + { + base.OnRealized (); + + Gdk.Pixmap mask; + pixmap = Gdk.Pixmap.CreateFromXpmD (GdkWindow, out mask, new Gdk.Color (99, 99, 99), custom_bg_xpm); + } + + string creationFunction, string1, string2; + int int1, int2; + + public string CreationFunction { + get { + return creationFunction; + } + set { + creationFunction = value; + } + } + + public string LastModificationTime { + get { + return null; + } + set { + ; + } + } + + public string String1 { + get { + return string1; + } + set { + string1 = value; + } + } + + public string String2 { + get { + return string2; + } + set { + string2 = value; + } + } + + public int Int1 { + get { + return int1; + } + set { + int1 = value; + } + } + + public int Int2 { + get { + return int2; + } + set { + int2 = value; + } + } + + protected override bool OnExposeEvent (Gdk.EventExpose evt) + { + if (!IsDrawable) + return false; + + int width, height; + GdkWindow.GetSize (out width, out height); + + Gdk.GC light, dark; + 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); + GdkWindow.DrawLine (dark, width - 1, 0, width - 1, height - 1); + + return base.OnExposeEvent (evt); + } + } +} diff --git a/main/src/addins/MonoDevelop.GtkCore2/libstetic/wrapper/Dialog.cs b/main/src/addins/MonoDevelop.GtkCore2/libstetic/wrapper/Dialog.cs new file mode 100644 index 0000000000..82312cfd4d --- /dev/null +++ b/main/src/addins/MonoDevelop.GtkCore2/libstetic/wrapper/Dialog.cs @@ -0,0 +1,183 @@ +using System; +using System.Xml; +using System.Collections; + +namespace Stetic.Wrapper { + + public class Dialog : Window { + + Stetic.Wrapper.ButtonBox actionArea; + + public override void Wrap (object obj, bool initialized) + { + base.Wrap (obj, initialized); + + actionArea = (ButtonBox)Container.Lookup (dialog.ActionArea); + actionArea.SetActionDialog (this); + + if (!initialized) { + dialog.HasSeparator = false; + if (!initialized && dialog.VBox.Children.Length == 1) { + Container vbox = Container.Lookup (dialog.VBox); + Placeholder ph = vbox.AddPlaceholder (); + ph.SetSizeRequest (200, 200); + Buttons = 1; + } + } else + ButtonsChanged (actionArea); + + actionArea.ContentsChanged += ButtonsChanged; + } + + internal static new TopLevelDialog CreateInstance ( ) + { + return new TopLevelDialog (); + } + + public override void Dispose ( ) + { + actionArea.ContentsChanged -= ButtonsChanged; + actionArea.SetActionDialog (null); + base.Dispose (); + } + + protected override void ReadChildren (ObjectReader reader, XmlElement elem) + { + // Ignore changes in the buttons while loading + actionArea.ContentsChanged -= ButtonsChanged; + base.ReadChildren (reader, elem); + actionArea.ContentsChanged += ButtonsChanged; + actionArea.SetActionDialog (this); + } + + TopLevelDialog dialog { + get { + return (TopLevelDialog) Wrapped; + } + } + + public Gtk.HButtonBox ActionArea { + get { return dialog.ActionArea; } + } + + public Gtk.VBox VBox + { + get { return dialog.VBox; } + } + + public bool HasSeparator { + get { return dialog.HasSeparator; } + set { dialog.HasSeparator = value; EmitNotify ("HasSeparator"); } + } + + public int Buttons + { + get { + return actionArea.Size - ExtraButtons; + } + set { + actionArea.Size = value + ExtraButtons; + EmitNotify ("Buttons"); + } + } + + int ExtraButtons { + get { + return helpButton == null ? 0 : 1; + } + } + + Gtk.Button helpButton; + + public bool HelpButton { + get { + return helpButton != null; + } + set { + if (HelpButton == value) + return; + + if (value) { + helpButton = AddButton (Gtk.Stock.Help, Gtk.ResponseType.Help, false); + // Make it the first child, so that decreasing + // Buttons won't delete it + dialog.ActionArea.ReorderChild (helpButton, 0); + } else { + helpButton.Destroy (); + helpButton = null; + } + + EmitNotify ("HelpButton"); + } + } + + // Check that a button is the Help button + bool ButtonIsHelp (Gtk.Button button) + { + return (button.UseStock && + button.Label == Gtk.Stock.Help && + dialog.ActionArea.GetChildSecondary (button)); + } + + Gtk.Button AddButton (string stockId, Gtk.ResponseType response, bool hasDefault) + { + Stetic.Wrapper.Button wrapper; + Gtk.Button button; + + button = (Gtk.Button)Registry.NewInstance ("Gtk.Button", proj); + wrapper = (Stetic.Wrapper.Button) ObjectWrapper.Lookup (button); + if (stockId != null) { + wrapper.Type = Button.ButtonType.StockItem; + wrapper.StockId = stockId; + } else { + wrapper.Type = Button.ButtonType.TextOnly; + wrapper.Label = button.Name; + } + wrapper.ResponseId = (int)response; + + Stetic.Wrapper.Container actionArea = Stetic.Wrapper.Container.Lookup (dialog.ActionArea); + actionArea.Add (button); + + button.CanDefault = true; + wrapper.HasDefault = hasDefault; + + if (stockId == Gtk.Stock.Help) + ((Gtk.ButtonBox)actionArea.Wrapped).SetChildSecondary (button, true); + + return button; + } + + void ButtonsChanged (Container container) + { + Gtk.Widget[] children = dialog.ActionArea.Children; + + // If the user manually removes (or breaks) the Help button, + // uncheck the corresponding property + if (helpButton != null) { + if (Array.IndexOf (children, helpButton) == -1 || + !ButtonIsHelp (helpButton)) { + helpButton = null; + EmitNotify ("HelpButton"); + } + } + + // If the user manually creates a Help button, set the property + if (helpButton == null) { + foreach (Gtk.Widget w in children) { + Gtk.Button button = w as Gtk.Button; + if (button != null && ButtonIsHelp (button)) { + helpButton = button; + dialog.ActionArea.ReorderChild (helpButton, 0); + EmitNotify ("HelpButton"); + break; + } + } + } + + // If the user removed all (non-Secondary) buttons, add back a + // single custom button + if (Buttons == 0) + Buttons = 1; + } + } +} diff --git a/main/src/addins/MonoDevelop.GtkCore2/libstetic/wrapper/Entry.cs b/main/src/addins/MonoDevelop.GtkCore2/libstetic/wrapper/Entry.cs new file mode 100644 index 0000000000..64a9b068b2 --- /dev/null +++ b/main/src/addins/MonoDevelop.GtkCore2/libstetic/wrapper/Entry.cs @@ -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; } + } + } + +} diff --git a/main/src/addins/MonoDevelop.GtkCore2/libstetic/wrapper/Expander.cs b/main/src/addins/MonoDevelop.GtkCore2/libstetic/wrapper/Expander.cs new file mode 100644 index 0000000000..7ea5d73acf --- /dev/null +++ b/main/src/addins/MonoDevelop.GtkCore2/libstetic/wrapper/Expander.cs @@ -0,0 +1,80 @@ +using System; +using System.Collections; +using System.Xml; +using System.CodeDom; + +namespace Stetic.Wrapper { + + public class Expander : Container { + + public static Gtk.Expander CreateInstance () + { + return new Gtk.Expander (""); + } + + public override void Wrap (object obj, bool initialized) + { + base.Wrap (obj, initialized); + if (!initialized) { + expander.Label = expander.Name; + if (AllowPlaceholders) + AddPlaceholder (); + } + if (expander.LabelWidget != null) + ObjectWrapper.Create (proj, expander.LabelWidget, this); + } + + protected override ObjectWrapper ReadChild (ObjectReader reader, XmlElement child_elem) + { + if ((string)GladeUtils.GetChildProperty (child_elem, "type", "") == "label_item") { + ObjectWrapper wrapper = reader.ReadObject (child_elem["widget"], this); + expander.LabelWidget = (Gtk.Widget)wrapper.Wrapped; + return wrapper; + } else + return base.ReadChild (reader, child_elem); + } + + protected override XmlElement WriteChild (ObjectWriter writer, Widget wrapper) + { + XmlElement child_elem = base.WriteChild (writer, wrapper); + if (wrapper.Wrapped == expander.LabelWidget) + GladeUtils.SetChildProperty (child_elem, "type", "label_item"); + return child_elem; + } + + Gtk.Expander expander { + get { + return (Gtk.Expander)Wrapped; + } + } + + protected override void ReplaceChild (Gtk.Widget oldChild, Gtk.Widget newChild) + { + if (oldChild == expander.LabelWidget) + expander.LabelWidget = newChild; + else + base.ReplaceChild (oldChild, newChild); + } + + internal protected override CodeExpression GenerateObjectCreation (GeneratorContext ctx) + { + return new CodeObjectCreateExpression (ClassDescriptor.WrappedTypeName.ToGlobalTypeRef (), new CodePrimitiveExpression (null)); + } + + protected override void GenerateChildBuildCode (GeneratorContext ctx, CodeExpression parentVar, Widget wrapper) + { + if (wrapper.Wrapped == expander.LabelWidget) { + CodeExpression var = ctx.GenerateNewInstanceCode (wrapper); + CodeAssignStatement assign = new CodeAssignStatement ( + new CodePropertyReferenceExpression ( + parentVar, + "LabelWidget" + ), + var + ); + ctx.Statements.Add (assign); + } else + base.GenerateChildBuildCode (ctx, parentVar, wrapper); + } + } +} diff --git a/main/src/addins/MonoDevelop.GtkCore2/libstetic/wrapper/Fixed.cs b/main/src/addins/MonoDevelop.GtkCore2/libstetic/wrapper/Fixed.cs new file mode 100644 index 0000000000..840c050dcc --- /dev/null +++ b/main/src/addins/MonoDevelop.GtkCore2/libstetic/wrapper/Fixed.cs @@ -0,0 +1,91 @@ + +using System; + +namespace Stetic.Wrapper +{ + public class Fixed: Container + { + public override void Wrap (object obj, bool initialized) + { + base.Wrap (obj, initialized); + + DND.DestSet (gtkfixed, true); + gtkfixed.DragDrop += FixedDragDrop; + gtkfixed.DragDataReceived += FixedDragDataReceived; + } + + public override void Dispose () + { + gtkfixed.DragDrop -= FixedDragDrop; + gtkfixed.DragDataReceived -= FixedDragDataReceived; + } + + Gtk.Fixed gtkfixed { + get { + return (Gtk.Fixed)Wrapped; + } + } + + protected override bool AllowPlaceholders { + get { + return false; + } + } + + void FixedDragDrop (object obj, Gtk.DragDropArgs args) + { + Gtk.Widget w = DND.Drop (args.Context, gtkfixed, args.Time); + Widget ww = Widget.Lookup (w); + if (ww != null) { + gtkfixed.Put (w, args.X - DND.DragHotX, args.Y - DND.DragHotY); + NotifyChildAdded (w); + args.RetVal = true; + ww.Select (); + } + } + + void FixedDragDataReceived (object obj, Gtk.DragDataReceivedArgs args) + { + Widget dropped = WidgetUtils.Paste (proj, args.SelectionData); + Gtk.Drag.Finish (args.Context, dropped != null, dropped != null, args.Time); + if (dropped != null) { + gtkfixed.Put (dropped.Wrapped, 0, 0); + NotifyChildAdded (dropped.Wrapped); + dropped.Select (); + } + } + + int dragX, dragY; + + protected override Gtk.Widget CreateDragSource (Gtk.Widget dragWidget) + { + Gtk.Fixed.FixedChild fc = (Gtk.Fixed.FixedChild) gtkfixed [dragWidget]; + if (fc == null) + return null; + + dragX = fc.X; + dragY = fc.Y; + + gtkfixed.Remove (dragWidget); + gtkfixed.DragEnd += DragEnd; + return gtkfixed; + } + + void DragEnd (object obj, Gtk.DragEndArgs args) + { + using (UndoManager.AtomicChange) { + gtkfixed.DragEnd -= DragEnd; + if (DND.DragWidget != null) { + DND.DragWidget.Unparent (); + gtkfixed.Put (DND.DragWidget, dragX, dragY); + NotifyChildAdded (DND.DragWidget); + Widget ww = Widget.Lookup (DND.DragWidget); + ww.Select (); + } + } + } + + public class FixedChild : Container.ContainerChild { + } + } +} diff --git a/main/src/addins/MonoDevelop.GtkCore2/libstetic/wrapper/FontButton.cs b/main/src/addins/MonoDevelop.GtkCore2/libstetic/wrapper/FontButton.cs new file mode 100644 index 0000000000..c005e23e4e --- /dev/null +++ b/main/src/addins/MonoDevelop.GtkCore2/libstetic/wrapper/FontButton.cs @@ -0,0 +1,22 @@ +using System; + +namespace Stetic.Wrapper { + + public class FontButton : Widget { + + public bool UseFont { + get { + return ((Gtk.FontButton)Wrapped).UseFont; + } + set { + Gtk.FontButton fb = (Gtk.FontButton)Wrapped; + + fb.UseFont = value; + + // Force it to update + fb.ShowSize = !fb.ShowSize; + fb.ShowSize = !fb.ShowSize; + } + } + } +} diff --git a/main/src/addins/MonoDevelop.GtkCore2/libstetic/wrapper/FontSelectionDialog.cs b/main/src/addins/MonoDevelop.GtkCore2/libstetic/wrapper/FontSelectionDialog.cs new file mode 100644 index 0000000000..f0b1cf000e --- /dev/null +++ b/main/src/addins/MonoDevelop.GtkCore2/libstetic/wrapper/FontSelectionDialog.cs @@ -0,0 +1,19 @@ +using System; + +namespace Stetic.Wrapper { + + public class FontSelectionDialog : Dialog { + + public Gtk.FontSelection FontSelection { + get { + Gtk.Dialog dialog = (Gtk.Dialog)Wrapped; + + foreach (Gtk.Widget w in dialog.VBox) { + if (w is Gtk.FontSelection) + return (Gtk.FontSelection)w; + } + return null; + } + } + } +} diff --git a/main/src/addins/MonoDevelop.GtkCore2/libstetic/wrapper/Frame.cs b/main/src/addins/MonoDevelop.GtkCore2/libstetic/wrapper/Frame.cs new file mode 100644 index 0000000000..4478c0ff36 --- /dev/null +++ b/main/src/addins/MonoDevelop.GtkCore2/libstetic/wrapper/Frame.cs @@ -0,0 +1,92 @@ +using System; +using System.Collections; +using System.Xml; +using System.CodeDom; + +namespace Stetic.Wrapper { + + public class Frame : Container { + + public override void Wrap (object obj, bool initialized) + { + base.Wrap (obj, initialized); + if (!initialized) { + frame.Label = "<b>" + frame.Name + "</b>"; + ((Gtk.Label)frame.LabelWidget).UseMarkup = true; + frame.Shadow = Gtk.ShadowType.None; + if (AllowPlaceholders) { + Gtk.Alignment align = new Gtk.Alignment (0, 0, 1, 1); + align.LeftPadding = 12; + Container align_wrapper = (Container)ObjectWrapper.Create (proj, align, this); + align_wrapper.AddPlaceholder (); + ReplaceChild (frame.Child, (Gtk.Widget)align_wrapper.Wrapped, true); + } + } + + if (frame.LabelWidget != null) + ObjectWrapper.Create (proj, frame.LabelWidget, this); + frame.AddNotification ("label-widget", LabelWidgetChanged); + } + + void LabelWidgetChanged (object obj, GLib.NotifyArgs args) + { + if (!IsDisposed && frame.LabelWidget != null && !(frame.LabelWidget is Stetic.Placeholder)) + ObjectWrapper.Create (proj, frame.LabelWidget, this); + } + + Gtk.Frame frame { + get { + return (Gtk.Frame)Wrapped; + } + } + + protected override ObjectWrapper ReadChild (ObjectReader reader, XmlElement child_elem) + { + if ((string)GladeUtils.GetChildProperty (child_elem, "type", "") == "label_item") { + ObjectWrapper wrapper = reader.ReadObject (child_elem["widget"], this); + frame.LabelWidget = (Gtk.Widget)wrapper.Wrapped; + return wrapper; + } else + return base.ReadChild (reader, child_elem); + } + + protected override XmlElement WriteChild (ObjectWriter writer, Widget wrapper) + { + XmlElement child_elem = base.WriteChild (writer, wrapper); + if (wrapper.Wrapped == frame.LabelWidget) + GladeUtils.SetChildProperty (child_elem, "type", "label_item"); + return child_elem; + } + + protected override void GenerateChildBuildCode (GeneratorContext ctx, CodeExpression parentVar, Widget wrapper) + { + if (wrapper.Wrapped == frame.LabelWidget) { + CodeExpression var = ctx.GenerateNewInstanceCode (wrapper); + CodeAssignStatement assign = new CodeAssignStatement ( + new CodePropertyReferenceExpression ( + parentVar, + "LabelWidget" + ), + var + ); + ctx.Statements.Add (assign); + } else + base.GenerateChildBuildCode (ctx, parentVar, wrapper); + } + + protected override void ReplaceChild (Gtk.Widget oldChild, Gtk.Widget newChild) + { + if (oldChild == frame.LabelWidget) + frame.LabelWidget = newChild; + else + base.ReplaceChild (oldChild, newChild); + } + + public override void Delete (Stetic.Placeholder ph) + { + using (UndoManager.AtomicChange) { + Delete (); + } + } + } +} diff --git a/main/src/addins/MonoDevelop.GtkCore2/libstetic/wrapper/HScale.cs b/main/src/addins/MonoDevelop.GtkCore2/libstetic/wrapper/HScale.cs new file mode 100644 index 0000000000..0af92c7a5f --- /dev/null +++ b/main/src/addins/MonoDevelop.GtkCore2/libstetic/wrapper/HScale.cs @@ -0,0 +1,18 @@ +using System; +using System.CodeDom; + +namespace Stetic.Wrapper { + + public class HScale : Scale { + + public static Gtk.HScale CreateInstance () + { + return new Gtk.HScale (0.0, 100.0, 1.0); + } + + internal protected override CodeExpression GenerateObjectCreation (GeneratorContext ctx) + { + return new CodeObjectCreateExpression (ClassDescriptor.WrappedTypeName.ToGlobalTypeRef (), new CodePrimitiveExpression (null)); + } + } +} diff --git a/main/src/addins/MonoDevelop.GtkCore2/libstetic/wrapper/HScrollbar.cs b/main/src/addins/MonoDevelop.GtkCore2/libstetic/wrapper/HScrollbar.cs new file mode 100644 index 0000000000..696ccee6b8 --- /dev/null +++ b/main/src/addins/MonoDevelop.GtkCore2/libstetic/wrapper/HScrollbar.cs @@ -0,0 +1,18 @@ +using System; +using System.CodeDom; + +namespace Stetic.Wrapper { + + public class HScrollbar : Range { + + public static Gtk.HScrollbar CreateInstance () + { + return new Gtk.HScrollbar (new Gtk.Adjustment (0.0, 0.0, 100.0, 1.0, 10.0, 10.0)); + } + + internal protected override CodeExpression GenerateObjectCreation (GeneratorContext ctx) + { + return new CodeObjectCreateExpression (ClassDescriptor.WrappedTypeName.ToGlobalTypeRef (), new CodePrimitiveExpression (null)); + } + } +} diff --git a/main/src/addins/MonoDevelop.GtkCore2/libstetic/wrapper/IconView.cs b/main/src/addins/MonoDevelop.GtkCore2/libstetic/wrapper/IconView.cs new file mode 100644 index 0000000000..592b005e54 --- /dev/null +++ b/main/src/addins/MonoDevelop.GtkCore2/libstetic/wrapper/IconView.cs @@ -0,0 +1,39 @@ +// IconView.cs +// +// Author: +// Lluis Sanchez Gual +// +// Copyright (c) 2007 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. +// +// + +namespace Stetic.Wrapper +{ + public class IconView: Container + { + protected override bool AllowPlaceholders { + get { + return false; + } + } + } +} + diff --git a/main/src/addins/MonoDevelop.GtkCore2/libstetic/wrapper/Image.cs b/main/src/addins/MonoDevelop.GtkCore2/libstetic/wrapper/Image.cs new file mode 100644 index 0000000000..befbc1c642 --- /dev/null +++ b/main/src/addins/MonoDevelop.GtkCore2/libstetic/wrapper/Image.cs @@ -0,0 +1,80 @@ +using System; +using System.Xml; +using System.Collections; + +namespace Stetic.Wrapper { + + public class Image : Misc { + + ImageInfo imageInfo; + + public static Gtk.Image CreateInstance () + { + return new Gtk.Image (Gtk.Stock.Execute, Gtk.IconSize.Dialog); + } + + protected override void ReadProperties (ObjectReader reader, XmlElement elem) + { + if (reader.Format == FileFormat.Glade) { + string file = (string)GladeUtils.ExtractProperty (elem, "pixbuf", ""); + string stock = (string)GladeUtils.ExtractProperty (elem, "stock", ""); + string iconSize = (string)GladeUtils.ExtractProperty (elem, "icon_size", ""); + base.ReadProperties (reader, elem); + + if (stock != null && stock.Length > 0) { + Pixbuf = ImageInfo.FromTheme (stock, (Gtk.IconSize) int.Parse (iconSize)); + } else if (file != null && file != "") { + Pixbuf = ImageInfo.FromFile (file); + } + } else + base.ReadProperties (reader, elem); + } + + protected override XmlElement WriteProperties (ObjectWriter writer) + { + XmlElement elem = base.WriteProperties (writer); + if (imageInfo != null) { + if (writer.Format == FileFormat.Glade) { + // The generated pixbuf property doesn't have a valid value, it needs to be replaced. + GladeUtils.ExtractProperty (elem, "pixbuf", ""); + switch (imageInfo.Source) { + case ImageSource.File: + GladeUtils.SetProperty (elem, "pixbuf", imageInfo.Name); + break; + case ImageSource.Theme: + GladeUtils.SetProperty (elem, "stock", imageInfo.Name); + GladeUtils.SetProperty (elem, "icon_size", ((int)imageInfo.ThemeIconSize).ToString ()); + break; + default: + throw new System.NotSupportedException ("Image source not supported by Glade."); + } + } + } + return elem; + } + + Gtk.Image image { + get { + return (Gtk.Image)Wrapped; + } + } + + void BreakImage () + { + image.IconSize = (int)Gtk.IconSize.Button; + image.Stock = Gtk.Stock.MissingImage; + } + + public ImageInfo Pixbuf { + get { return imageInfo; } + set { + imageInfo = value; + if (imageInfo == null) + BreakImage (); + else + image.Pixbuf = imageInfo.GetImage (Project); + EmitNotify ("Pixbuf"); + } + } + } +} diff --git a/main/src/addins/MonoDevelop.GtkCore2/libstetic/wrapper/ImageMenuItem.cs b/main/src/addins/MonoDevelop.GtkCore2/libstetic/wrapper/ImageMenuItem.cs new file mode 100644 index 0000000000..24cfd01465 --- /dev/null +++ b/main/src/addins/MonoDevelop.GtkCore2/libstetic/wrapper/ImageMenuItem.cs @@ -0,0 +1,62 @@ +using System; +using System.Xml; + +namespace Stetic.Wrapper { + + public class ImageMenuItem : MenuItem { + + public static new Gtk.ImageMenuItem CreateInstance () + { + // Use the ctor that will create an AccelLabel + return new Gtk.ImageMenuItem (""); + } + + protected override void ReadProperties (ObjectReader reader, XmlElement elem) + { + Gtk.StockItem stockItem = Gtk.StockItem.Zero; + bool use_stock = (bool)GladeUtils.ExtractProperty (elem, "use_stock", false); + if (use_stock) { + string label = (string)GladeUtils.GetProperty (elem, "label", ""); + stockItem = Gtk.Stock.Lookup (label); + if (stockItem.Label != null) + GladeUtils.ExtractProperty (elem, "label", ""); + } + base.ReadProperties (reader, elem); + + if (stockItem.StockId != null) + Image = "stock:" + stockItem.StockId; + if (stockItem.Keyval != 0) + Accelerator = Gtk.Accelerator.Name (stockItem.Keyval, stockItem.Modifier); + } + + string image; + + public string Image { + get { + return image; + } + set { + image = value; + + Gtk.Widget icon; + Gtk.StockItem stockItem = Gtk.StockItem.Zero; + + if (image.StartsWith ("stock:")) + stockItem = Gtk.Stock.Lookup (image.Substring (6)); + + if (stockItem.StockId != null) { + icon = new Gtk.Image (stockItem.StockId, Gtk.IconSize.Menu); + Label = stockItem.Label; + UseUnderline = true; + } else if (image.StartsWith ("file:")) + icon = new Gtk.Image (image.Substring (5)); + else + icon = new Gtk.Image (WidgetUtils.MissingIcon); + + ((Gtk.ImageMenuItem)Wrapped).Image = icon; + + EmitNotify ("Image"); + } + } + } +} diff --git a/main/src/addins/MonoDevelop.GtkCore2/libstetic/wrapper/Label.cs b/main/src/addins/MonoDevelop.GtkCore2/libstetic/wrapper/Label.cs new file mode 100644 index 0000000000..e12944c6f1 --- /dev/null +++ b/main/src/addins/MonoDevelop.GtkCore2/libstetic/wrapper/Label.cs @@ -0,0 +1,49 @@ +using System; +using System.CodeDom; +using System.Collections; + +namespace Stetic.Wrapper { + + public class Label : Misc { + + public Label () {} + + string mnem; + public string MnemonicWidget { + get { + return mnem; + } + set { + mnem = value; + } + } + + protected override void GeneratePropertySet (GeneratorContext ctx, CodeExpression var, PropertyDescriptor prop) + { + if (prop.Name != "MnemonicWidget") + base.GeneratePropertySet (ctx, var, prop); + } + + internal protected override void GeneratePostBuildCode (GeneratorContext ctx, CodeExpression var) + { + if (mnem != null) { + Widget targetWidget = GetTopLevel ().FindChild (mnem); + if (targetWidget != null) { + CodeExpression memVar = ctx.WidgetMap.GetWidgetExp (targetWidget); + if (memVar != null) { + ctx.Statements.Add ( + new CodeAssignStatement ( + new CodePropertyReferenceExpression ( + var, + "MnemonicWidget" + ), + memVar + ) + ); + } + } + } + base.GeneratePostBuildCode (ctx, var); + } + } +} diff --git a/main/src/addins/MonoDevelop.GtkCore2/libstetic/wrapper/MenuBar.cs b/main/src/addins/MonoDevelop.GtkCore2/libstetic/wrapper/MenuBar.cs new file mode 100644 index 0000000000..fec2f29509 --- /dev/null +++ b/main/src/addins/MonoDevelop.GtkCore2/libstetic/wrapper/MenuBar.cs @@ -0,0 +1,261 @@ + +using System; +using System.CodeDom; +using System.Xml; +using System.Collections; +using Stetic.Editor; + +namespace Stetic.Wrapper +{ + public class MenuBar: Container + { + ActionTree actionTree; + XmlElement menuInfo; + bool treeChanged; + + public MenuBar() + { + } + + public override void Dispose () + { + DisposeTree (); + base.Dispose (); + } + + public static Gtk.MenuBar CreateInstance () + { + return new ActionMenuBar (); + } + + protected override bool AllowPlaceholders { + get { return false; } + } + + ActionMenuBar menu { + get { return (ActionMenuBar) Wrapped; } + } + + public override void Wrap (object obj, bool initialized) + { + base.Wrap (obj, initialized); + CreateTree (); + } + + internal protected override void OnSelected () + { + Loading = true; + menu.ShowInsertPlaceholder = true; + Loading = false; + } + + internal protected override void OnUnselected () + { + base.OnUnselected (); + Loading = true; + menu.ShowInsertPlaceholder = false; + menu.Unselect (); + Loading = false; + } + + protected override XmlElement WriteProperties (ObjectWriter writer) + { + XmlElement elem = base.WriteProperties (writer); + if (menuInfo != null) + elem.AppendChild (writer.XmlDocument.ImportNode (menuInfo, true)); + else + elem.AppendChild (actionTree.Write (writer.XmlDocument, writer.Format)); + return elem; + } + + protected override void ReadProperties (ObjectReader reader, XmlElement elem) + { + base.ReadProperties (reader, elem); + menuInfo = elem ["node"]; + treeChanged = false; + } + + public override object GetUndoDiff () + { + XmlElement oldElem = treeChanged ? UndoManager.GetObjectStatus (this) ["node"] : null; + if (oldElem != null) + oldElem = (XmlElement) oldElem.CloneNode (true); + + treeChanged = false; + object baseDiff = base.GetUndoDiff (); + + if (oldElem != null) { + XmlElement newElem = UndoManager.GetObjectStatus (this) ["node"]; + if (newElem != null && oldElem.OuterXml == newElem.OuterXml) + oldElem = null; + } + + if (baseDiff == null && oldElem == null) + return null; + else { + object stat = menu.SaveStatus (); + return new object[] { baseDiff, oldElem, stat }; + } + } + + public override object ApplyUndoRedoDiff (object diff) + { + object[] data = (object[]) diff; + object retBaseDiff; + XmlElement oldNode = null; + + if (actionTree != null) { + XmlElement status = UndoManager.GetObjectStatus (this); + oldNode = status ["node"]; + if (oldNode != null) + oldNode = (XmlElement) oldNode.CloneNode (true); + } + object oldStat = menu.SaveStatus (); + + if (data [0] != null) + retBaseDiff = base.ApplyUndoRedoDiff (data [0]); + else + retBaseDiff = null; + + XmlElement xdiff = (XmlElement) data [1]; + + if (xdiff != null) { + XmlElement status = UndoManager.GetObjectStatus (this); + XmlElement prevNode = status ["node"]; + if (prevNode != null) + status.RemoveChild (prevNode); + status.AppendChild (xdiff); + + if (actionTree != null) { + Loading = true; + menu.OpenSubmenu = null; + DisposeTree (); + CreateTree (); + actionTree.Read (this, xdiff); + menu.FillMenu (actionTree); + Loading = false; + } else + menuInfo = xdiff; + } + + // Restore the status after all menu structure has been properly built + GLib.Timeout.Add (50, delegate { + menu.RestoreStatus (data[2]); + return false; + }); + + return new object [] { retBaseDiff, oldNode, oldStat }; + } + + protected override void OnNameChanged (WidgetNameChangedArgs args) + { + base.OnNameChanged (args); + if (actionTree != null) + actionTree.Name = Name; + } + + internal protected override CodeExpression GenerateObjectCreation (GeneratorContext ctx) + { + BuildTree (); + actionTree.Name = Name; + CodeExpression exp = GenerateUiManagerElement (ctx, actionTree); + if (exp != null) + return new CodeCastExpression (typeof(Gtk.MenuBar).ToGlobalTypeRef (), exp); + else + return base.GenerateObjectCreation (ctx); + } + + internal protected override void OnDesignerAttach (IDesignArea designer) + { + base.OnDesignerAttach (designer); + BuildTree (); + Loading = true; + menu.FillMenu (actionTree); + Loading = false; + + if (LocalActionGroups.Count == 0) + LocalActionGroups.Add (new ActionGroup ("Default")); + } + + void BuildTree () + { + if (menuInfo != null) { + DisposeTree (); + CreateTree (); + actionTree.Read (this, menuInfo); + menuInfo = null; + } + } + + void CreateTree () + { + actionTree = new ActionTree (); + actionTree.Name = Name; + actionTree.Type = Gtk.UIManagerItemType.Menubar; + actionTree.Changed += OnTreeChanged; + } + + void DisposeTree () + { + if (actionTree != null) { + actionTree.Dispose (); + actionTree.Changed -= OnTreeChanged; + actionTree = null; + } + } + + void OnTreeChanged (object s, EventArgs a) + { + treeChanged = true; + NotifyChanged (); + } + } + + class CustomMenuBarItem: Gtk.MenuItem + { + public ActionMenuItem ActionMenuItem; +// public ActionTreeNode Node; + } + + public class ActionPaletteItem: Gtk.HBox + { + ActionTreeNode node; + bool disposeNode; + + public ActionPaletteItem (Gtk.UIManagerItemType type, string name, Action action) + : this (new ActionTreeNode (type, name, action)) + { + disposeNode = true; + } + + public ActionPaletteItem (ActionTreeNode node) + { + this.node = node; + Spacing = 3; + if (node.Type == Gtk.UIManagerItemType.Menu) { + PackStart (new Gtk.Label ("Menu"), true, true, 0); + } else if (node.Action != null && node.Action.GtkAction != null) { + if (node.Action.GtkAction.StockId != null) + PackStart (node.Action.CreateIcon (Gtk.IconSize.Menu), true, true, 0); + PackStart (new Gtk.Label (node.Action.GtkAction.Label), true, true, 0); + } else if (node.Type == Gtk.UIManagerItemType.Separator) { + PackStart (new Gtk.Label ("Separator"), true, true, 0); + } else { + PackStart (new Gtk.Label ("Empty Action"), true, true, 0); + } + ShowAll (); + } + + public ActionTreeNode Node { + get { return node; } + } + + public override void Dispose () + { + if (disposeNode) + node.Dispose (); + base.Dispose (); + } + + } +} diff --git a/main/src/addins/MonoDevelop.GtkCore2/libstetic/wrapper/MenuItem.cs b/main/src/addins/MonoDevelop.GtkCore2/libstetic/wrapper/MenuItem.cs new file mode 100644 index 0000000000..4321ce602e --- /dev/null +++ b/main/src/addins/MonoDevelop.GtkCore2/libstetic/wrapper/MenuItem.cs @@ -0,0 +1,110 @@ +using System; +using System.Xml; + +namespace Stetic.Wrapper { + + public class MenuItem : Container { + + public static Gtk.MenuItem CreateInstance () + { + // Use the ctor that will create an AccelLabel + return new Gtk.MenuItem (""); + } + + public override void Wrap (object obj, bool initialized) + { + base.Wrap (obj, initialized); + } + + protected override ObjectWrapper ReadChild (ObjectReader reader, XmlElement child_elem) + { + ObjectWrapper wrapper = reader.ReadObject (child_elem["widget"], this); + menuitem.Submenu = (Gtk.Menu)wrapper.Wrapped; + return wrapper; + } + + Gtk.MenuItem menuitem { + get { + return (Gtk.MenuItem)Wrapped; + } + } + + Gtk.Label label { + get { + Gtk.AccelLabel label = menuitem.Child as Gtk.AccelLabel; + if (label != null) + return label; + + if (menuitem.Child != null) + menuitem.Child.Destroy (); + + label = new Gtk.AccelLabel (""); + label.MnemonicWidget = menuitem; + label.AccelWidget = menuitem; + label.Xalign = 0.0f; + label.Show (); + menuitem.Add (label); + + return label; + } + } + + public bool HasSubmenu { + get { + return menuitem.Submenu != null; + } + } + + string labelText; + + public string Label { + get { + return labelText; + } + set { + label.LabelProp = labelText = value; + EmitNotify ("Label"); + } + } + + public bool UseUnderline { + get { + return label.UseUnderline; + } + set { + label.UseUnderline = value; + EmitNotify ("UseUnderline"); + } + } + + Gtk.AccelGroup accelGroup; + string accelerator; + public string Accelerator { + get { + return accelerator; + } + set { + uint key; + Gdk.ModifierType mods; + + if (accelGroup != null && accelerator != null) { + Gtk.Accelerator.Parse (accelerator, out key, out mods); + menuitem.RemoveAccelerator (accelGroup, key, mods); + } + + accelerator = value; + + if (accelerator != null) { + if (accelGroup == null) + accelGroup = new Gtk.AccelGroup (); + + Gtk.Accelerator.Parse (accelerator, out key, out mods); + menuitem.AddAccelerator ("activate", accelGroup, key, mods, + Gtk.AccelFlags.Visible); + } + + EmitNotify ("Accelerator"); + } + } + } +} diff --git a/main/src/addins/MonoDevelop.GtkCore2/libstetic/wrapper/MessageDialog.cs b/main/src/addins/MonoDevelop.GtkCore2/libstetic/wrapper/MessageDialog.cs new file mode 100644 index 0000000000..805b02932c --- /dev/null +++ b/main/src/addins/MonoDevelop.GtkCore2/libstetic/wrapper/MessageDialog.cs @@ -0,0 +1,141 @@ +using System; + +namespace Stetic { + + public class MessageDialog : Gtk.Dialog { + + public MessageDialog () + { + Resizable = false; + HasSeparator = false; + BorderWidth = 12; + + label = new Gtk.Label (); + label.LineWrap = true; + label.Selectable = true; + label.UseMarkup = true; + label.SetAlignment (0.0f, 0.0f); + + secondaryLabel = new Gtk.Label (); + secondaryLabel.LineWrap = true; + secondaryLabel.Selectable = true; + secondaryLabel.UseMarkup = true; + secondaryLabel.SetAlignment (0.0f, 0.0f); + + icon = new Gtk.Image (Gtk.Stock.DialogInfo, Gtk.IconSize.Dialog); + icon.SetAlignment (0.5f, 0.0f); + + Gtk.StockItem item = Gtk.Stock.Lookup (icon.Stock); + Title = item.Label; + + Gtk.HBox hbox = new Gtk.HBox (false, 12); + Gtk.VBox vbox = new Gtk.VBox (false, 12); + + vbox.PackStart (label, false, false, 0); + vbox.PackStart (secondaryLabel, true, true, 0); + + hbox.PackStart (icon, false, false, 0); + hbox.PackStart (vbox, true, true, 0); + + VBox.PackStart (hbox, false, false, 0); + hbox.ShowAll (); + + Buttons = Gtk.ButtonsType.OkCancel; + } + + Gtk.Label label, secondaryLabel; + Gtk.Image icon; + + public Gtk.MessageType MessageType { + get { + if (icon.Stock == Gtk.Stock.DialogInfo) + return Gtk.MessageType.Info; + else if (icon.Stock == Gtk.Stock.DialogQuestion) + return Gtk.MessageType.Question; + else if (icon.Stock == Gtk.Stock.DialogWarning) + return Gtk.MessageType.Warning; + else + return Gtk.MessageType.Error; + } + set { + Gtk.StockItem item = Gtk.Stock.Lookup (icon.Stock); + bool setTitle = (Title == "") || (Title == item.Label); + + if (value == Gtk.MessageType.Info) + icon.Stock = Gtk.Stock.DialogInfo; + else if (value == Gtk.MessageType.Question) + icon.Stock = Gtk.Stock.DialogQuestion; + else if (value == Gtk.MessageType.Warning) + icon.Stock = Gtk.Stock.DialogWarning; + else + icon.Stock = Gtk.Stock.DialogError; + + if (setTitle) { + item = Gtk.Stock.Lookup (icon.Stock); + Title = item.Label; + } + } + } + + public string primaryText; + public string PrimaryText { + get { + return primaryText; + } + set { + primaryText = value; + label.Markup = "<b>" + value + "</b>"; + } + } + + public string SecondaryText { + get { + return secondaryLabel.Text; + } + set { + secondaryLabel.Markup = value; + } + } + + Gtk.ButtonsType buttons; + public Gtk.ButtonsType Buttons { + get { + return buttons; + } + set { + Gtk.Widget[] oldButtons = ActionArea.Children; + foreach (Gtk.Widget w in oldButtons) + ActionArea.Remove (w); + + buttons = value; + switch (buttons) { + case Gtk.ButtonsType.None: + // nothing + break; + + case Gtk.ButtonsType.Ok: + AddButton (Gtk.Stock.Ok, Gtk.ResponseType.Ok); + break; + + case Gtk.ButtonsType.Close: + AddButton (Gtk.Stock.Close, Gtk.ResponseType.Close); + break; + + case Gtk.ButtonsType.Cancel: + AddButton (Gtk.Stock.Cancel, Gtk.ResponseType.Cancel); + break; + + case Gtk.ButtonsType.YesNo: + AddButton (Gtk.Stock.No, Gtk.ResponseType.No); + AddButton (Gtk.Stock.Yes, Gtk.ResponseType.Yes); + break; + + case Gtk.ButtonsType.OkCancel: + AddButton (Gtk.Stock.Cancel, Gtk.ResponseType.Cancel); + AddButton (Gtk.Stock.Ok, Gtk.ResponseType.Ok); + break; + } + } + } + } +} diff --git a/main/src/addins/MonoDevelop.GtkCore2/libstetic/wrapper/Misc.cs b/main/src/addins/MonoDevelop.GtkCore2/libstetic/wrapper/Misc.cs new file mode 100644 index 0000000000..44624a73d6 --- /dev/null +++ b/main/src/addins/MonoDevelop.GtkCore2/libstetic/wrapper/Misc.cs @@ -0,0 +1,35 @@ + +using System; + +namespace Stetic.Wrapper +{ + public class Misc: Widget + { + public bool AlignLeft { + get { + return ((Gtk.Misc)Wrapped).Xalign == 0; + } + set { + ((Gtk.Misc)Wrapped).Xalign = 0; + } + } + + public bool AlignRight { + get { + return ((Gtk.Misc)Wrapped).Xalign == 1; + } + set { + ((Gtk.Misc)Wrapped).Xalign = 1; + } + } + + public bool AlignCenter { + get { + return ((Gtk.Misc)Wrapped).Xalign == 0.5f; + } + set { + ((Gtk.Misc)Wrapped).Xalign = 0.5f; + } + } + } +} diff --git a/main/src/addins/MonoDevelop.GtkCore2/libstetic/wrapper/Notebook.cs b/main/src/addins/MonoDevelop.GtkCore2/libstetic/wrapper/Notebook.cs new file mode 100644 index 0000000000..978aae7502 --- /dev/null +++ b/main/src/addins/MonoDevelop.GtkCore2/libstetic/wrapper/Notebook.cs @@ -0,0 +1,269 @@ +using System; +using System.CodeDom; +using System.Collections; +using System.Xml; + +namespace Stetic.Wrapper { + + public class Notebook : Container { + + ArrayList tabs = new ArrayList (); + + public override void Wrap (object obj, bool initialized) + { + base.Wrap (obj, initialized); + if (!initialized && AllowPlaceholders) { + if (notebook.Children.Length != 0) { + // Remove the dummy page Container.Wrap added + notebook.Remove (notebook.Children[0]); + } + InsertPage (0); + } + notebook.SwitchPage += OnPageChanged; + } + + public override void Dispose () + { + notebook.SwitchPage -= OnPageChanged; + base.Dispose (); + } + + protected override ObjectWrapper ReadChild (ObjectReader reader, XmlElement child_elem) + { + if ((string)GladeUtils.GetChildProperty (child_elem, "type", "") == "tab") { + ObjectWrapper wrapper = reader.ReadObject (child_elem["widget"], this); + Gtk.Widget widget = (Gtk.Widget)wrapper.Wrapped; + notebook.SetTabLabel (notebook.GetNthPage (notebook.NPages - 1), widget); + tabs.Add (widget); + return wrapper; + } else + return base.ReadChild (reader, child_elem); + } + + protected override XmlElement WriteChild (ObjectWriter writer, Widget wrapper) + { + XmlElement child_elem = base.WriteChild (writer, wrapper); + if (tabs.Contains (wrapper.Wrapped)) + GladeUtils.SetChildProperty (child_elem, "type", "tab"); + return child_elem; + } + public override void Read (ObjectReader reader, XmlElement element) + { + object cp = GladeUtils.ExtractProperty (element, "CurrentPage", 0); + base.Read (reader, element); + notebook.CurrentPage = (int) cp; + } + + protected override void GenerateChildBuildCode (GeneratorContext ctx, CodeExpression parentExp, Widget wrapper) + { + Gtk.Widget child = (Gtk.Widget) wrapper.Wrapped; + + if (notebook.PageNum (child) == -1) { + // It's a tab + + ctx.Statements.Add (new CodeCommentStatement ("Notebook tab")); + Gtk.Widget page = null; + CodeExpression pageVar; + + // Look for the page widget contained in this tab + for (int n=0; n < notebook.NPages; n++) { + if (notebook.GetTabLabel (notebook.GetNthPage (n)) == child) { + page = notebook.GetNthPage (n); + break; + } + } + + // If the page contains a placeholder, generate a dummy page + if (page is Stetic.Placeholder) { + CodeVariableDeclarationStatement dvar = new CodeVariableDeclarationStatement ( + "Gtk.Label".ToGlobalTypeRef (), + ctx.NewId (), + new CodeObjectCreateExpression ("Gtk.Label".ToGlobalTypeRef ()) + ); + ctx.Statements.Add (dvar); + ctx.Statements.Add ( + new CodeAssignStatement ( + new CodePropertyReferenceExpression ( + new CodeVariableReferenceExpression (dvar.Name), + "Visible" + ), + new CodePrimitiveExpression (true) + ) + ); + ctx.Statements.Add ( + new CodeMethodInvokeExpression ( + parentExp, + "Add", + new CodeVariableReferenceExpression (dvar.Name) + ) + ); + pageVar = new CodeVariableReferenceExpression (dvar.Name); + } else + pageVar = ctx.WidgetMap.GetWidgetExp (page); + + // Generate code for the tab + CodeExpression var = ctx.GenerateNewInstanceCode (wrapper); + + // Assign the tab to the page + CodeMethodInvokeExpression invoke = new CodeMethodInvokeExpression ( + parentExp, + "SetTabLabel", + pageVar, + var + ); + ctx.Statements.Add (invoke); + + // Workaround for GTK bug. ShowAll is not propagated to tab labels. + invoke = new CodeMethodInvokeExpression ( + var, + "ShowAll" + ); + ctx.Statements.Add (invoke); + } else + base.GenerateChildBuildCode (ctx, parentExp, wrapper); + } + + + private Gtk.Notebook notebook { + get { + return (Gtk.Notebook)Wrapped; + } + } + + public override void Select (Gtk.Widget widget) + { + if (widget != null) { + int index = tabs.IndexOf (widget); + if (index != -1 && index != notebook.CurrentPage) + notebook.CurrentPage = index; + } + base.Select (widget); + } + + protected override void ReplaceChild (Gtk.Widget oldChild, Gtk.Widget newChild) + { + int index = tabs.IndexOf (oldChild); + if (index != -1) { + tabs[index] = newChild; + Gtk.Widget page = notebook.GetNthPage (index); + notebook.SetTabLabel (page, newChild); + } else { + Gtk.Widget tab = notebook.GetTabLabel (oldChild); + int current = notebook.CurrentPage; + int oldPageNum = ((Gtk.Notebook.NotebookChild)notebook [oldChild]).Position; + base.ReplaceChild (oldChild, newChild); + // Get the widget again because it may have changed (for example, if it is a text view + // and has the ShowScrollbars option set. + newChild = notebook.GetNthPage (oldPageNum); + notebook.CurrentPage = current; + notebook.SetTabLabel (newChild, tab); + Widget ww = Widget.Lookup (tab); + if (ww != null) + ww.RequiresUndoStatusUpdate = true; + } + } + + int InsertPage (int position) + { + Gtk.Label label = (Gtk.Label)Registry.NewInstance ("Gtk.Label", proj); + label.LabelProp = "page" + (notebook.NPages + 1).ToString (); + tabs.Insert (position, label); + + Placeholder ph = CreatePlaceholder (); + int i = notebook.InsertPage (ph, label, position); + NotifyChildAdded (ph); + return i; + } + + internal void PreviousPage () + { + notebook.PrevPage (); + } + + internal bool CheckPreviousPage () + { + return notebook.CurrentPage > 0; + } + + internal void NextPage () + { + notebook.NextPage (); + } + + internal bool CheckNextPage () + { + return notebook.CurrentPage < notebook.NPages - 1; + } + + internal void DeletePage () + { + tabs.RemoveAt (notebook.CurrentPage); + notebook.RemovePage (notebook.CurrentPage); + } + + internal bool CheckDeletePage () + { + return notebook.NPages > 0; + } + + internal void SwapPrevious () + { + object ob = tabs [notebook.CurrentPage]; + tabs [notebook.CurrentPage] = tabs [notebook.CurrentPage - 1]; + tabs [notebook.CurrentPage - 1] = ob; + + Gtk.Widget cp = notebook.GetNthPage (notebook.CurrentPage); + notebook.ReorderChild (cp, notebook.CurrentPage - 1); + } + + internal void SwapNext () + { + object ob = tabs [notebook.CurrentPage]; + tabs [notebook.CurrentPage] = tabs [notebook.CurrentPage + 1]; + tabs [notebook.CurrentPage + 1] = ob; + + Gtk.Widget cp = notebook.GetNthPage (notebook.CurrentPage); + notebook.ReorderChild (cp, notebook.CurrentPage + 1); + } + + internal void InsertBefore () + { + notebook.CurrentPage = InsertPage (notebook.CurrentPage); + } + + internal bool CheckInsertBefore () + { + return notebook.NPages > 0; + } + + internal void InsertAfter () + { + notebook.CurrentPage = InsertPage (notebook.CurrentPage + 1); + } + + public override bool HExpandable { + get { + foreach (Gtk.Widget w in notebook) { + if (ChildHExpandable (w)) + return true; + } + return false; + } + } + + public override bool VExpandable { + get { + foreach (Gtk.Widget w in notebook) { + if (ChildVExpandable (w)) + return true; + } + return false; + } + } + + void OnPageChanged (object s, Gtk.SwitchPageArgs args) + { + EmitNotify ("CurrentPage"); + } + } +} diff --git a/main/src/addins/MonoDevelop.GtkCore2/libstetic/wrapper/Object.cs b/main/src/addins/MonoDevelop.GtkCore2/libstetic/wrapper/Object.cs new file mode 100644 index 0000000000..4d8954c426 --- /dev/null +++ b/main/src/addins/MonoDevelop.GtkCore2/libstetic/wrapper/Object.cs @@ -0,0 +1,49 @@ +using System; +using System.Collections; + +namespace Stetic.Wrapper { + public abstract class Object : Stetic.ObjectWrapper { + + public override void Dispose () + { + if (Wrapped == null) + return; + ((GLib.Object)Wrapped).RemoveNotification (NotifyHandler); + base.Dispose (); + } + + internal protected override void OnDesignerAttach (IDesignArea designer) + { + base.OnDesignerAttach (designer); + ((GLib.Object)Wrapped).AddNotification (NotifyHandler); + } + + internal protected override void OnDesignerDetach (IDesignArea designer) + { + base.OnDesignerDetach (designer); + ((GLib.Object)Wrapped).RemoveNotification (NotifyHandler); + } + + public static Object Lookup (GLib.Object obj) + { + return Stetic.ObjectWrapper.Lookup (obj) as Stetic.Wrapper.Object; + } + + void NotifyHandler (object obj, GLib.NotifyArgs args) + { + if (Loading) + return; + + // Translate gtk names into descriptor names. + foreach (ItemGroup group in ClassDescriptor.ItemGroups) { + foreach (ItemDescriptor item in group) { + TypedPropertyDescriptor prop = item as TypedPropertyDescriptor; + if (prop != null && prop.GladeName == args.Property) { + EmitNotify (prop.Name); + return; + } + } + } + } + } +} diff --git a/main/src/addins/MonoDevelop.GtkCore2/libstetic/wrapper/OptionMenu.cs b/main/src/addins/MonoDevelop.GtkCore2/libstetic/wrapper/OptionMenu.cs new file mode 100644 index 0000000000..8234c595a1 --- /dev/null +++ b/main/src/addins/MonoDevelop.GtkCore2/libstetic/wrapper/OptionMenu.cs @@ -0,0 +1,79 @@ +using System; +using System.Collections; +using System.Xml; + +// Don't warn that OptionMenu is deprecated. We know that. +#pragma warning disable 612 + +namespace Stetic.Wrapper { + + public class OptionMenu : Container { + + public override void Wrap (object obj, bool initialized) + { + Gtk.OptionMenu omenu = (Gtk.OptionMenu)obj; + if (omenu.Menu == null) { + Gtk.Menu menu = new Gtk.Menu (); + menu.Show (); + omenu.Menu = menu; + } + + base.Wrap (obj, initialized); + } + + protected override void ReadProperties (ObjectReader reader, XmlElement elem) + { + int history = (int)GladeUtils.ExtractProperty (elem, "history", -1); + base.ReadProperties (reader, elem); + + // Fiddle with things to make the optionmenu resize itself correctly + Gtk.Widget menu = optionmenu.Menu; + optionmenu.Menu = new Gtk.Menu (); + optionmenu.Menu = menu; + + if (history != -1) + Active = history; + else + Active = 0; + } + + // Some versions of glade call the menu an internal child, some don't + + protected override ObjectWrapper ReadInternalChild (ObjectReader reader, XmlElement child_elem) + { + if (child_elem.GetAttribute ("internal-child") == "menu") + return ReadChild (reader, child_elem); + else + return base.ReadInternalChild (reader, child_elem); + } + + protected override ObjectWrapper ReadChild (ObjectReader reader, XmlElement child_elem) + { + Widget wrapper = Stetic.Wrapper.Widget.Lookup (optionmenu.Menu); + reader.ReadExistingObject (wrapper, child_elem["widget"]); + return wrapper; + } + + public override IEnumerable GladeChildren { + get { + return new Gtk.Widget[] { optionmenu.Menu }; + } + } + + Gtk.OptionMenu optionmenu { + get { + return (Gtk.OptionMenu)Wrapped; + } + } + + public int Active { + get { + return optionmenu.History; + } + set { + optionmenu.SetHistory ((uint)value); + EmitNotify ("Active"); + } + } + } +} diff --git a/main/src/addins/MonoDevelop.GtkCore2/libstetic/wrapper/Paned.cs b/main/src/addins/MonoDevelop.GtkCore2/libstetic/wrapper/Paned.cs new file mode 100644 index 0000000000..477923a27c --- /dev/null +++ b/main/src/addins/MonoDevelop.GtkCore2/libstetic/wrapper/Paned.cs @@ -0,0 +1,73 @@ +using System; + +namespace Stetic.Wrapper { + + public class Paned : Container { + + int position; + + public override void Wrap (object obj, bool initialized) + { + base.Wrap (obj, initialized); + if (!initialized && AllowPlaceholders) { + Placeholder ph = CreatePlaceholder (); + paned.Pack1 (ph, true, false); + NotifyChildAdded (ph); + ph = CreatePlaceholder (); + paned.Pack2 (ph, true, false); + NotifyChildAdded (ph); + } + position = paned.Position; + paned.Realized += PanedRealized; + } + + void PanedRealized (object sender, EventArgs e) + { + // The position may be reset while realizing the object, so + // we set it now here. See bug #542227. This seems to be Windows only. + bool old = Loading; + Loading = true; + paned.Position = position; + Loading = old; + } + + public override void Dispose () + { + base.Dispose (); + paned.Realized -= PanedRealized; + } + + protected Gtk.Paned paned { + get { + return (Gtk.Paned)Wrapped; + } + } + + public int Position { + get { + return paned.Position; + } + set { + position = value; + paned.Position = value; + } + } + + protected override void ReplaceChild (Gtk.Widget oldChild, Gtk.Widget newChild) + { + if (oldChild == paned.Child1) { + paned.Remove (oldChild); + paned.Add1 (newChild); + } else if (oldChild == paned.Child2) { + paned.Remove (oldChild); + paned.Add2 (newChild); + } + NotifyChildAdded (newChild); + } + + public override void Delete (Stetic.Placeholder ph) + { + // Don't allow deleting placeholders + } + } +} diff --git a/main/src/addins/MonoDevelop.GtkCore2/libstetic/wrapper/RadioActionGroupManager.cs b/main/src/addins/MonoDevelop.GtkCore2/libstetic/wrapper/RadioActionGroupManager.cs new file mode 100644 index 0000000000..0f67944ce4 --- /dev/null +++ b/main/src/addins/MonoDevelop.GtkCore2/libstetic/wrapper/RadioActionGroupManager.cs @@ -0,0 +1,144 @@ + +using System; +using System.Collections; +using System.CodeDom; + +namespace Stetic.Wrapper +{ + public class RadioActionGroupManager: IRadioGroupManager + { + public event GroupsChangedDelegate GroupsChanged; + Hashtable actions = new Hashtable (); + ArrayList groups = new ArrayList (); + + public IEnumerable GroupNames { + get { + foreach (string grp in groups) + yield return grp; + } + } + + public void Rename (string oldName, string newName) + { + int i = groups.IndexOf (oldName); + if (i == -1) + return; + + groups [i] = newName; + + ArrayList list = new ArrayList (); + foreach (Action a in FindActionsInGroup (oldName)) + list.Add (a); + + foreach (Action a in list) + actions [a] = newName; + + EmitGroupsChanged (); + } + + public void Add (string name) + { + groups.Add (name); + EmitGroupsChanged (); + } + + public RadioGroup FindGroup (string name) + { + for (int i = 0; i < groups.Count; i++) { + RadioGroup group = groups[i] as RadioGroup; + if (group.Name == name) + return group; + } + return null; + } + + public string GetGroup (Action action) + { + return actions [action] as string; + } + + public void SetGroup (Action action, string group) + { + if (group == null) { + if (actions.Contains (action)) { + actions.Remove (action); + action.Disposed -= OnActionDisposed; + } + return; + } + + if (!actions.Contains (action)) + action.Disposed += OnActionDisposed; + actions [action] = group; + if (!groups.Contains (group)) + groups.Add (group); + } + + void OnActionDisposed (object s, EventArgs a) + { + Action ac = (Action) s; + if (ac != null) { + ac.Disposed -= OnActionDisposed; + actions.Remove (ac); + } + } + + public string LastGroup { + get { + if (groups.Count == 0) + Add ("group1"); + return groups [groups.Count - 1] as string; + } + } + + void EmitGroupsChanged () + { + if (GroupsChanged != null) + GroupsChanged (); + } + + IEnumerable FindActionsInGroup (string grp) + { + foreach (DictionaryEntry e in actions) + if (((string)e.Value) == grp) + yield return e.Key; + } + + public CodeExpression GenerateGroupExpression (GeneratorContext ctx, Action action) + { + // Returns and expression that represents the group to which the radio belongs. + // This expression can be an empty SList, if this is the first radio of the + // group that has been generated, or an SList taken from previously generated + // radios from the same group. + + string group = actions [action] as string; + if (group == null) + return new CodePrimitiveExpression (null); + + CodeExpression var = null; + + foreach (Action a in FindActionsInGroup (group)) { + if (a == action) + continue; + var = ctx.WidgetMap.GetWidgetExp (a); + if (var != null) + break; + } + + if (var == null) { + return new CodeObjectCreateExpression ( + "GLib.SList".ToGlobalTypeRef (), + new CodePropertyReferenceExpression ( + new CodeTypeReferenceExpression (typeof(IntPtr).ToGlobalTypeRef ()), + "Zero" + ) + ); + } else { + return new CodePropertyReferenceExpression ( + var, + "Group" + ); + } + } + } +} diff --git a/main/src/addins/MonoDevelop.GtkCore2/libstetic/wrapper/RadioButton.cs b/main/src/addins/MonoDevelop.GtkCore2/libstetic/wrapper/RadioButton.cs new file mode 100644 index 0000000000..a58d70f31c --- /dev/null +++ b/main/src/addins/MonoDevelop.GtkCore2/libstetic/wrapper/RadioButton.cs @@ -0,0 +1,80 @@ +using System; +using System.Collections; +using System.Xml; +using System.CodeDom; + +namespace Stetic.Wrapper { + + public class RadioButton : CheckButton, IRadioGroupManagerProvider { + + static RadioGroupManager GroupManager = new RadioGroupManager (typeof (Gtk.RadioButton)); + + public override void Wrap (object obj, bool initialized) + { + base.Wrap (obj, initialized); + + Gtk.RadioButton radiobutton = (Gtk.RadioButton)Wrapped; + if (!initialized) + Group = GroupManager.LastGroup; + else if (radiobutton.Group == null) + Group = radiobutton.Name; + } + + IRadioGroupManager IRadioGroupManagerProvider.GetGroupManager () + { + return GroupManager; + } + + protected override void ReadProperties (ObjectReader reader, XmlElement elem) + { + bool active = (bool)GladeUtils.ExtractProperty (elem, "active", false); + string group = (string)GladeUtils.ExtractProperty (elem, "group", ""); + base.ReadProperties (reader, elem); + + if (reader.Format == FileFormat.Glade) { + if (group != "") + Group = group; + else + Group = Wrapped.Name; + } + + if (active) + ((Gtk.RadioButton)Wrapped).Active = true; + } + + protected override XmlElement WriteProperties (ObjectWriter writer) + { + XmlElement elem = base.WriteProperties (writer); + if (writer.Format == FileFormat.Glade) { + string group = GroupManager.GladeGroupName (Wrapped); + if (group != Wrapped.Name) + GladeUtils.SetProperty (elem, "group", group); + } + return elem; + } + + protected override void GeneratePropertySet (GeneratorContext ctx, CodeExpression var, PropertyDescriptor prop) + { + if (prop.Name == "Group") { + CodeExpression groupExp = GroupManager.GenerateGroupExpression (ctx, (Gtk.Widget) Wrapped); + ctx.Statements.Add ( + new CodeAssignStatement ( + new CodePropertyReferenceExpression (var, "Group"), + groupExp) + ); + } + else + base.GeneratePropertySet (ctx, var, prop); + } + + public string Group { + get { + return GroupManager[Wrapped]; + } + set { + GroupManager[Wrapped] = value; + EmitNotify ("Group"); + } + } + } +} diff --git a/main/src/addins/MonoDevelop.GtkCore2/libstetic/wrapper/RadioMenuItem.cs b/main/src/addins/MonoDevelop.GtkCore2/libstetic/wrapper/RadioMenuItem.cs new file mode 100644 index 0000000000..d8a232584b --- /dev/null +++ b/main/src/addins/MonoDevelop.GtkCore2/libstetic/wrapper/RadioMenuItem.cs @@ -0,0 +1,75 @@ +using System; +using System.Collections; +using System.Xml; +using System.CodeDom; + +namespace Stetic.Wrapper { + + public class RadioMenuItem : MenuItem, IRadioGroupManagerProvider { + + static RadioGroupManager GroupManager = new RadioGroupManager (typeof (Gtk.RadioMenuItem)); + + public override void Wrap (object obj, bool initialized) + { + base.Wrap (obj, initialized); + + Gtk.RadioMenuItem radio = (Gtk.RadioMenuItem)Wrapped; + if (!initialized) + Group = GroupManager.LastGroup; + else if (radio.Group == null) + Group = radio.Name; + } + + IRadioGroupManager IRadioGroupManagerProvider.GetGroupManager () + { + return GroupManager; + } + + protected override void ReadProperties (ObjectReader reader, XmlElement elem) + { + string group = (string)GladeUtils.ExtractProperty (elem, "group", ""); + bool active = (bool)GladeUtils.ExtractProperty (elem, "active", false); + base.ReadProperties (reader, elem); + + if (group != "") + Group = group; + else + Group = Wrapped.Name; + if (active) + ((Gtk.RadioMenuItem)Wrapped).Active = true; + } + + protected override XmlElement WriteProperties (ObjectWriter writer) + { + XmlElement elem = base.WriteProperties (writer); + string group = GroupManager.GladeGroupName (Wrapped); + if (group != Wrapped.Name) + GladeUtils.SetProperty (elem, "group", group); + return elem; + } + + protected override void GeneratePropertySet (GeneratorContext ctx, CodeExpression var, PropertyDescriptor prop) + { + if (prop.Name == "Group") { + CodeExpression groupExp = GroupManager.GenerateGroupExpression (ctx, (Gtk.Widget) Wrapped); + ctx.Statements.Add ( + new CodeAssignStatement ( + new CodePropertyReferenceExpression (var, "Group"), + groupExp) + ); + } + else + base.GeneratePropertySet (ctx, var, prop); + } + + public string Group { + get { + return GroupManager[Wrapped]; + } + set { + GroupManager[Wrapped] = value; + EmitNotify ("Group"); + } + } + } +} diff --git a/main/src/addins/MonoDevelop.GtkCore2/libstetic/wrapper/RadioToolButton.cs b/main/src/addins/MonoDevelop.GtkCore2/libstetic/wrapper/RadioToolButton.cs new file mode 100644 index 0000000000..986d2476cc --- /dev/null +++ b/main/src/addins/MonoDevelop.GtkCore2/libstetic/wrapper/RadioToolButton.cs @@ -0,0 +1,80 @@ +using System; +using System.Collections; +using System.Xml; +using System.CodeDom; + +namespace Stetic.Wrapper { + + public class RadioToolButton : ToggleToolButton, IRadioGroupManagerProvider { + + public static new Gtk.ToolButton CreateInstance () + { + return new Gtk.RadioToolButton (new GLib.SList (IntPtr.Zero), Gtk.Stock.SortAscending); + } + + static RadioGroupManager GroupManager = new RadioGroupManager (typeof (Gtk.RadioToolButton)); + + public override void Wrap (object obj, bool initialized) + { + base.Wrap (obj, initialized); + + Gtk.RadioToolButton radio = (Gtk.RadioToolButton)Wrapped; + if (!initialized) + Group = GroupManager.LastGroup; + else if (radio.Group == null) + Group = radio.Name; + } + + IRadioGroupManager IRadioGroupManagerProvider.GetGroupManager () + { + return GroupManager; + } + + protected override void ReadProperties (ObjectReader reader, XmlElement elem) + { + string group = (string)GladeUtils.ExtractProperty (elem, "group", ""); + bool active = (bool)GladeUtils.ExtractProperty (elem, "active", false); + base.ReadProperties (reader, elem); + + if (group != "") + Group = group; + else + Group = Wrapped.Name; + if (active) + ((Gtk.RadioToolButton)Wrapped).Active = true; + } + + protected override XmlElement WriteProperties (ObjectWriter writer) + { + XmlElement elem = base.WriteProperties (writer); + string group = GroupManager.GladeGroupName (Wrapped); + if (group != Wrapped.Name) + GladeUtils.SetProperty (elem, "group", group); + return elem; + } + + protected override void GeneratePropertySet (GeneratorContext ctx, CodeExpression var, PropertyDescriptor prop) + { + if (prop.Name == "Group") { + CodeExpression groupExp = GroupManager.GenerateGroupExpression (ctx, (Gtk.Widget) Wrapped); + ctx.Statements.Add ( + new CodeAssignStatement ( + new CodePropertyReferenceExpression (var, "Group"), + groupExp) + ); + } + else + base.GeneratePropertySet (ctx, var, prop); + } + + public string Group { + get { + return GroupManager[Wrapped]; + } + set { + GroupManager[Wrapped] = value; + EmitNotify ("Group"); + } + } + } +} diff --git a/main/src/addins/MonoDevelop.GtkCore2/libstetic/wrapper/Range.cs b/main/src/addins/MonoDevelop.GtkCore2/libstetic/wrapper/Range.cs new file mode 100644 index 0000000000..453e846004 --- /dev/null +++ b/main/src/addins/MonoDevelop.GtkCore2/libstetic/wrapper/Range.cs @@ -0,0 +1,24 @@ +using System; + +namespace Stetic.Wrapper { + + public abstract class Range : Widget { + + public override void Wrap (object obj, bool initialized) + { + base.Wrap (obj, initialized); + ((Gtk.Range)Wrapped).Adjustment.AddNotification (AdjustmentNotifyHandler); + } + + public override void Dispose () + { + ((Gtk.Range)Wrapped).Adjustment.RemoveNotification (AdjustmentNotifyHandler); + base.Dispose (); + } + + void AdjustmentNotifyHandler (object obj, GLib.NotifyArgs args) + { + EmitNotify (args.Property); + } + } +} diff --git a/main/src/addins/MonoDevelop.GtkCore2/libstetic/wrapper/Scale.cs b/main/src/addins/MonoDevelop.GtkCore2/libstetic/wrapper/Scale.cs new file mode 100644 index 0000000000..c43f6609bd --- /dev/null +++ b/main/src/addins/MonoDevelop.GtkCore2/libstetic/wrapper/Scale.cs @@ -0,0 +1,24 @@ +using System; + +namespace Stetic.Wrapper { + + public abstract class Scale : Widget { + + public override void Wrap (object obj, bool initialized) + { + base.Wrap (obj, initialized); + ((Gtk.Scale)Wrapped).Adjustment.AddNotification (AdjustmentNotifyHandler); + } + + public override void Dispose () + { + ((Gtk.Scale)Wrapped).Adjustment.RemoveNotification (AdjustmentNotifyHandler); + base.Dispose (); + } + + void AdjustmentNotifyHandler (object obj, GLib.NotifyArgs args) + { + EmitNotify (args.Property); + } + } +} diff --git a/main/src/addins/MonoDevelop.GtkCore2/libstetic/wrapper/ScrolledWindow.cs b/main/src/addins/MonoDevelop.GtkCore2/libstetic/wrapper/ScrolledWindow.cs new file mode 100644 index 0000000000..e574d6a726 --- /dev/null +++ b/main/src/addins/MonoDevelop.GtkCore2/libstetic/wrapper/ScrolledWindow.cs @@ -0,0 +1,112 @@ +using System; +using System.Collections; +using System.CodeDom; + +namespace Stetic.Wrapper { + + public class ScrolledWindow : Container { + + Gtk.PolicyType hpolicy = Gtk.PolicyType.Automatic; + Gtk.PolicyType vpolicy = Gtk.PolicyType.Automatic; + + public override void Wrap (object obj, bool initialized) + { + base.Wrap (obj, initialized); + if (!initialized) { + if (scrolled.Child == null && AllowPlaceholders) + AddPlaceholder (); + HscrollbarPolicy = VscrollbarPolicy = Gtk.PolicyType.Automatic; + scrolled.ShadowType = Gtk.ShadowType.In; + } + scrolled.SetPolicy (Gtk.PolicyType.Always, Gtk.PolicyType.Always); + } + + public Gtk.ScrolledWindow scrolled { + get { + return (Gtk.ScrolledWindow)Wrapped; + } + } + + public Gtk.PolicyType HscrollbarPolicy { + get { return hpolicy; } + set { + hpolicy = value; + EmitNotify ("HscrollbarPolicy"); + } + } + + public Gtk.PolicyType VscrollbarPolicy { + get { return vpolicy; } + set { + vpolicy = value; + EmitNotify ("VscrollbarPolicy"); + } + } + + public override IEnumerable RealChildren { + get { + if (scrolled.Child is Gtk.Viewport) + return ((Gtk.Viewport)scrolled.Child).Children; + else + return base.RealChildren; + } + } + + internal void AddWithViewport (Gtk.Widget child) + { + Gtk.Viewport viewport = new Gtk.Viewport (scrolled.Hadjustment, scrolled.Vadjustment); + ObjectWrapper.Create (proj, viewport, this); + viewport.ShadowType = Gtk.ShadowType.None; + viewport.Add (child); + viewport.Show (); + scrolled.Add (viewport); + } + + protected override void ReplaceChild (Gtk.Widget oldChild, Gtk.Widget newChild) + { + Widget ww = Widget.Lookup (oldChild); + if (ww != null && ww.ShowScrollbars && ParentWrapper != null) { + // The viewport is bound to the child widget. Remove it together with the child + ParentWrapper.ReplaceChild (Wrapped, newChild, false); + return; + } + + if (scrolled.Child is Gtk.Viewport && oldChild != scrolled.Child) { + Gtk.Viewport vp = (Gtk.Viewport)scrolled.Child; + vp.Remove (oldChild); + scrolled.Remove (vp); + vp.Destroy (); + } + else + scrolled.Remove (scrolled.Child); + + if (newChild.SetScrollAdjustments (null, null)) + scrolled.Add (newChild); + else + AddWithViewport (newChild); + + NotifyChildAdded (scrolled.Child); + } + + public override Placeholder AddPlaceholder () + { + Placeholder ph = CreatePlaceholder (); + AddWithViewport (ph); + return ph; + } + + protected override void GenerateChildBuildCode (GeneratorContext ctx, CodeExpression parentVar, Widget wrapper) + { + Gtk.Viewport vp = wrapper.Wrapped as Gtk.Viewport; + if (vp == null || (vp.Child != null && !(vp.Child is Placeholder))) + base.GenerateChildBuildCode (ctx, parentVar, wrapper); + } + + public override void Delete (Stetic.Placeholder ph) + { + using (UndoManager.AtomicChange) { + Delete (); + } + } + } +} diff --git a/main/src/addins/MonoDevelop.GtkCore2/libstetic/wrapper/Signal.cs b/main/src/addins/MonoDevelop.GtkCore2/libstetic/wrapper/Signal.cs new file mode 100644 index 0000000000..3c1700e805 --- /dev/null +++ b/main/src/addins/MonoDevelop.GtkCore2/libstetic/wrapper/Signal.cs @@ -0,0 +1,60 @@ + +using System; + +namespace Stetic +{ + [Serializable] + public class Signal + { + SignalDescriptor descriptor; + string handlerName; + bool after; + + [NonSerialized] + internal ObjectWrapper Owner; + + public Signal (SignalDescriptor descriptor): this (descriptor, null, false) + { + } + + public Signal (SignalDescriptor descriptor, string handlerName, bool after) + { + this.descriptor = descriptor; + this.handlerName = handlerName; + this.after = after; + } + + void NotifyChanged (Signal oldData) + { + if (Owner != null) + Owner.OnSignalChanged (new SignalChangedEventArgs (Owner, oldData, this)); + } + + Signal Clone () + { + return new Signal (descriptor, handlerName, after); + } + + public SignalDescriptor SignalDescriptor { + get { return descriptor; } + } + + public string Handler { + get { return handlerName; } + set { + Signal data = Clone (); + handlerName = value; + NotifyChanged (data); + } + } + + public bool After { + get { return after; } + set { + Signal data = Clone (); + after = value; + NotifyChanged (data); + } + } + } +} diff --git a/main/src/addins/MonoDevelop.GtkCore2/libstetic/wrapper/SignalChangedEventHandler.cs b/main/src/addins/MonoDevelop.GtkCore2/libstetic/wrapper/SignalChangedEventHandler.cs new file mode 100644 index 0000000000..1c2d138260 --- /dev/null +++ b/main/src/addins/MonoDevelop.GtkCore2/libstetic/wrapper/SignalChangedEventHandler.cs @@ -0,0 +1,19 @@ + +namespace Stetic +{ + public delegate void SignalChangedEventHandler (object sender, SignalChangedEventArgs args); + + public class SignalChangedEventArgs: SignalEventArgs + { + Signal oldSignal; + + public SignalChangedEventArgs (ObjectWrapper wrapper, Signal oldSignal, Signal signal): base (wrapper, signal) + { + this.oldSignal = oldSignal; + } + + public Signal OldSignal { + get { return oldSignal; } + } + } +} diff --git a/main/src/addins/MonoDevelop.GtkCore2/libstetic/wrapper/SignalCollection.cs b/main/src/addins/MonoDevelop.GtkCore2/libstetic/wrapper/SignalCollection.cs new file mode 100644 index 0000000000..c8b04ab33c --- /dev/null +++ b/main/src/addins/MonoDevelop.GtkCore2/libstetic/wrapper/SignalCollection.cs @@ -0,0 +1,89 @@ +using System; +using System.Collections; + +namespace Stetic +{ + [Serializable] + public class SignalCollection: CollectionBase + { + [NonSerialized] + ObjectWrapper owner; + + [NonSerialized] + Signal[] clearedData; + + public SignalCollection () + { + } + + internal SignalCollection (ObjectWrapper owner) + { + this.owner = owner; + } + + public int Add (Signal signal) + { + return List.Add (signal); + } + + public Signal this [int n] { + get { return (Signal) List [n]; } + } + + public void Remove (Signal signal) + { + List.Remove (signal); + } + + public void CopyTo (Signal[] signals, int index) + { + List.CopyTo (signals, index); + } + + protected override void OnClear () + { + if (owner != null) { + clearedData = new Signal [Count]; + List.CopyTo (clearedData, 0); + } + } + + protected override void OnClearComplete () + { + if (owner != null) { + Signal[] data = clearedData; + clearedData = null; + foreach (Signal s in data) { + s.Owner = null; + owner.OnSignalRemoved (new SignalEventArgs (owner, s)); + } + } + } + + protected override void OnInsertComplete (int index, object value) + { + if (owner != null) { + ((Signal)value).Owner = owner; + owner.OnSignalAdded (new SignalEventArgs (owner, (Signal) value)); + } + } + + protected override void OnRemoveComplete (int index, object value) + { + if (owner != null) { + ((Signal)value).Owner = null; + owner.OnSignalRemoved (new SignalEventArgs (owner, (Signal) value)); + } + } + + protected override void OnSetComplete (int index, object oldValue, object newValue) + { + if (owner != null) { + ((Signal)oldValue).Owner = null; + owner.OnSignalRemoved (new SignalEventArgs (owner, (Signal) oldValue)); + ((Signal)newValue).Owner = owner; + owner.OnSignalAdded (new SignalEventArgs (owner, (Signal) newValue)); + } + } + } +} diff --git a/main/src/addins/MonoDevelop.GtkCore2/libstetic/wrapper/SignalEventHandler.cs b/main/src/addins/MonoDevelop.GtkCore2/libstetic/wrapper/SignalEventHandler.cs new file mode 100644 index 0000000000..da56c35156 --- /dev/null +++ b/main/src/addins/MonoDevelop.GtkCore2/libstetic/wrapper/SignalEventHandler.cs @@ -0,0 +1,19 @@ + +namespace Stetic +{ + public delegate void SignalEventHandler (object sender, SignalEventArgs args); + + public class SignalEventArgs: ObjectWrapperEventArgs + { + Signal signal; + + public SignalEventArgs (ObjectWrapper wrapper, Signal signal): base (wrapper) + { + this.signal = signal; + } + + public Signal Signal { + get { return signal; } + } + } +} diff --git a/main/src/addins/MonoDevelop.GtkCore2/libstetic/wrapper/SpinButton.cs b/main/src/addins/MonoDevelop.GtkCore2/libstetic/wrapper/SpinButton.cs new file mode 100644 index 0000000000..fa9e200f7b --- /dev/null +++ b/main/src/addins/MonoDevelop.GtkCore2/libstetic/wrapper/SpinButton.cs @@ -0,0 +1,12 @@ +using System; + +namespace Stetic.Wrapper { + + public class SpinButton : Widget { + + public static Gtk.SpinButton CreateInstance () + { + return new Gtk.SpinButton (0.0, 100.0, 1.0); + } + } +} diff --git a/main/src/addins/MonoDevelop.GtkCore2/libstetic/wrapper/Table.cs b/main/src/addins/MonoDevelop.GtkCore2/libstetic/wrapper/Table.cs new file mode 100644 index 0000000000..f765aa847d --- /dev/null +++ b/main/src/addins/MonoDevelop.GtkCore2/libstetic/wrapper/Table.cs @@ -0,0 +1,520 @@ +using System; +using System.Collections; +using System.Text.RegularExpressions; +using System.Xml; + +namespace Stetic.Wrapper { + + public class Table : Container { + + const Gtk.AttachOptions expandOpts = Gtk.AttachOptions.Expand | Gtk.AttachOptions.Fill; + const Gtk.AttachOptions fillOpts = Gtk.AttachOptions.Fill; + + public override void Wrap (object obj, bool initialized) + { + base.Wrap (obj, initialized); + if (!initialized) { + table.NRows = 3; + table.NColumns = 3; + table.RowSpacing = 6; + table.ColumnSpacing = 6; + } + DoSync (); + } + + private Gtk.Table table { + get { + return (Gtk.Table)Wrapped; + } + } + + public override void Delete (Stetic.Placeholder ph) + { + // Placeholders are deleted using commands. + } + + protected override void DoSync () + { + if (!AllowPlaceholders) + return; + using (UndoManager.AtomicChange) { + uint left, right, top, bottom; + uint row, col; + Gtk.Widget w; + Gtk.Widget[,] grid; + Gtk.Table.TableChild tc; + Gtk.Widget[] children; + bool addedPlaceholders = false; + + children = table.Children; + grid = new Gtk.Widget[NRows,NColumns]; + + // 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) { + if (!(child is Placeholder)) + continue; + + 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; + else { + table.Remove (child); + child.Destroy (); + } + } + + // Now fill in the real widgets, knocking out any placeholders + // they overlap. (If there are real widgets that overlap + // 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) { + 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++) { + w = grid[row,col]; + if (w is Placeholder) { + table.Remove (w); + w.Destroy (); + } + 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 + // set them all to expand vertically so the row won't collapse. + // OTOH, if the row contains any real widget, set any placeholders + // in that row to not expand vertically, so they don't force the + // real widgets to expand further than they should. If any row + // is vertically expandable, then the table as a whole is. + vexpandable = false; + for (row = 0; row < NRows; row++) { + bool allPlaceholders = true; + + for (col = 0; col < NColumns; col++) { + w = grid[row,col]; + if (w == null) { + w = CreatePlaceholder (); + table.Attach (w, col, col + 1, row, row + 1); + NotifyChildAdded (w); + grid[row,col] = w; + addedPlaceholders = true; + } else if (!ChildVExpandable (w) || !AutoSize[w]) + allPlaceholders = false; + } + + for (col = 0; col < NColumns; col++) { + w = grid[row,col]; + if (!AutoSize[w]) + continue; + tc = table[w] as Gtk.Table.TableChild; + // We can't play with the vertical expansion property of + // widgets which span more than one row + if (tc.BottomAttach != tc.TopAttach + 1) + continue; + Gtk.AttachOptions opts = allPlaceholders ? expandOpts : fillOpts; + if (tc.YOptions != opts) + tc.YOptions = opts; + } + + if (allPlaceholders) + vexpandable = true; + } + + // Now do the same for columns and horizontal expansion (but we + // don't have to worry about empty cells this time). + hexpandable = false; + for (col = 0; col < NColumns; col++) { + bool allPlaceholders = true; + + for (row = 0; row < NRows; row++) { + w = grid[row,col]; + if (!ChildHExpandable (w) || !AutoSize[w]) { + allPlaceholders = false; + break; + } + } + + for (row = 0; row < NRows; row++) { + w = grid[row,col]; + if (!AutoSize[w]) + continue; + tc = table[w] as Gtk.Table.TableChild; + // We can't play with the horizontal expansion property of + // widgets which span more than one column + if (tc.RightAttach != tc.LeftAttach + 1) + continue; + Gtk.AttachOptions opts = allPlaceholders ? expandOpts : fillOpts; + if (tc.XOptions != opts) + tc.XOptions = opts; + } + + if (allPlaceholders) + hexpandable = true; + } + + if (addedPlaceholders) + EmitContentsChanged (); + } + } + + public override Placeholder AddPlaceholder () + { + // Placeholders are added by Sync () + return null; + } + + public uint NRows { + get { + return table.NRows; + } + set { + using (UndoManager.AtomicChange) { + Freeze (); + while (value < table.NRows) + DeleteRow (table.NRows - 1); + table.NRows = value; + Thaw (); + } + } + } + + public uint NColumns { + get { + return table.NColumns; + } + set { + using (UndoManager.AtomicChange) { + Freeze (); + while (value < table.NColumns) + DeleteColumn (table.NColumns - 1); + table.NColumns = value; + Thaw (); + } + } + } + + void AddRow (uint row) + { + using (UndoManager.AtomicChange) { + Freeze (); + table.NRows++; + foreach (Gtk.Widget w in table.Children) { + Gtk.Table.TableChild tc = table[w] as Gtk.Table.TableChild; + + if (tc.BottomAttach > row) + tc.BottomAttach++; + if (tc.TopAttach >= row) + tc.TopAttach++; + } + Thaw (); + } + } + + void DeleteRow (uint row) + { + Gtk.Widget[] children = table.Children; + Gtk.Table.TableChild tc; + + using (UndoManager.AtomicChange) { + Freeze (); + foreach (Gtk.Widget child in children) { + tc = table[child] as Gtk.Table.TableChild; + + if (tc.TopAttach == row) { + if (tc.BottomAttach == tc.TopAttach + 1) { + table.Remove (child); + child.Destroy (); + } + else + tc.BottomAttach--; + } else { + if (tc.TopAttach > row) + tc.TopAttach--; + if (tc.BottomAttach > row) + tc.BottomAttach--; + } + } + table.NRows--; + Thaw (); + } + } + + void AddColumn (uint col) + { + using (UndoManager.AtomicChange) { + Freeze (); + table.NColumns++; + foreach (Gtk.Widget w in table.Children) { + Gtk.Table.TableChild tc = table[w] as Gtk.Table.TableChild; + + if (tc.RightAttach > col) + tc.RightAttach++; + if (tc.LeftAttach >= col) + tc.LeftAttach++; + } + Thaw (); + } + } + + void DeleteColumn (uint col) + { + using (UndoManager.AtomicChange) { + Gtk.Widget[] children = table.Children; + Gtk.Table.TableChild tc; + + Freeze (); + foreach (Gtk.Widget child in children) { + tc = table[child] as Gtk.Table.TableChild; + + if (tc.LeftAttach == col) { + if (tc.RightAttach == tc.LeftAttach + 1) { + table.Remove (child); + child.Destroy (); + } + else + tc.RightAttach--; + } else { + if (tc.LeftAttach > col) + tc.LeftAttach--; + if (tc.RightAttach > col) + tc.RightAttach--; + } + } + table.NColumns--; + Thaw (); + } + } + + public override IEnumerable GladeChildren { + get { + ArrayList list = new ArrayList (); + foreach (object ob in base.GladeChildren) + list.Add (ob); + list.Sort (new NameComparer ()); + return list; + } + } + + class NameComparer: IComparer + { + public int Compare (object x, object y) + { + return string.Compare (((Gtk.Widget)x).Name, ((Gtk.Widget)y).Name); + } + } + + internal void InsertRowBefore (Gtk.Widget context) + { + Gtk.Table.TableChild tc = table[context] as Gtk.Table.TableChild; + AddRow (tc.TopAttach); + } + + internal void InsertRowAfter (Gtk.Widget context) + { + Gtk.Table.TableChild tc = table[context] as Gtk.Table.TableChild; + AddRow (tc.BottomAttach); + } + + internal void InsertColumnBefore (Gtk.Widget context) + { + Gtk.Table.TableChild tc = table[context] as Gtk.Table.TableChild; + AddColumn (tc.LeftAttach); + } + + internal void InsertColumnAfter (Gtk.Widget context) + { + Gtk.Table.TableChild tc = table[context] as Gtk.Table.TableChild; + AddColumn (tc.RightAttach); + } + + internal void DeleteRow (Gtk.Widget context) + { + Gtk.Table.TableChild tc = table[context] as Gtk.Table.TableChild; + DeleteRow (tc.TopAttach); + } + + internal void DeleteColumn (Gtk.Widget context) + { + Gtk.Table.TableChild tc = table[context] as Gtk.Table.TableChild; + DeleteColumn (tc.LeftAttach); + } + + private bool hexpandable, vexpandable; + public override bool HExpandable { get { return hexpandable; } } + public override bool VExpandable { get { return vexpandable; } } + + protected override void ChildContentsChanged (Container child) + { + using (UndoManager.AtomicChange) { + Gtk.Widget widget = child.Wrapped; + Freeze (); + if (AutoSize[widget]) { + Gtk.Table.TableChild tc = table[widget] as Gtk.Table.TableChild; + tc.XOptions = 0; + tc.YOptions = 0; + } + Thaw (); + } + + base.ChildContentsChanged (child); + } + + public class TableChild : Container.ContainerChild { + + bool freeze; + + Gtk.Table.TableChild tc { + get { + return (Gtk.Table.TableChild)Wrapped; + } + } + + public bool XExpand { + get { + return (tc.XOptions & Gtk.AttachOptions.Expand) != 0; + } + set { + freeze = true; + if (value) + tc.XOptions |= Gtk.AttachOptions.Expand; + else + tc.XOptions &= ~Gtk.AttachOptions.Expand; + freeze = false; + EmitNotify ("XExpand"); + } + } + + public bool XFill { + get { + return (tc.XOptions & Gtk.AttachOptions.Fill) != 0; + } + set { + freeze = true; + if (value) + tc.XOptions |= Gtk.AttachOptions.Fill; + else + tc.XOptions &= ~Gtk.AttachOptions.Fill; + freeze = false; + EmitNotify ("XFill"); + } + } + + public bool XShrink { + get { + return (tc.XOptions & Gtk.AttachOptions.Shrink) != 0; + } + set { + freeze = true; + if (value) + tc.XOptions |= Gtk.AttachOptions.Shrink; + else + tc.XOptions &= ~Gtk.AttachOptions.Shrink; + freeze = false; + EmitNotify ("XShrink"); + } + } + + public bool YExpand { + get { + return (tc.YOptions & Gtk.AttachOptions.Expand) != 0; + } + set { + freeze = true; + if (value) + tc.YOptions |= Gtk.AttachOptions.Expand; + else + tc.YOptions &= ~Gtk.AttachOptions.Expand; + freeze = false; + EmitNotify ("YExpand"); + } + } + + public bool YFill { + get { + return (tc.YOptions & Gtk.AttachOptions.Fill) != 0; + } + set { + freeze = true; + if (value) + tc.YOptions |= Gtk.AttachOptions.Fill; + else + tc.YOptions &= ~Gtk.AttachOptions.Fill; + freeze = false; + EmitNotify ("YFill"); + } + } + + public bool YShrink { + get { + return (tc.YOptions & Gtk.AttachOptions.Shrink) != 0; + } + set { + freeze = true; + if (value) + tc.YOptions |= Gtk.AttachOptions.Shrink; + else + tc.YOptions &= ~Gtk.AttachOptions.Shrink; + freeze = false; + EmitNotify ("YShrink"); + } + } + + protected override void EmitNotify (string propertyName) + { + if (freeze || Loading) return; + + if (propertyName == "x-options" || propertyName == "AutoSize") { + base.EmitNotify ("XExpand"); + base.EmitNotify ("XFill"); + base.EmitNotify ("XShrink"); + } + if (propertyName == "y-options" || propertyName == "AutoSize") { + base.EmitNotify ("YExpand"); + base.EmitNotify ("YFill"); + base.EmitNotify ("YShrink"); + } + base.EmitNotify (propertyName); + } + + // Properties to be used by the wrapper commands + + public bool CellXExpand { + get { return XExpand; } + set { AutoSize = false; XExpand = value; } + } + + public bool CellXFill{ + get { return XFill; } + set { AutoSize = false; XFill = value; } + } + + public bool CellYExpand { + get { return YExpand; } + set { AutoSize = false; YExpand = value; } + } + + public bool CellYFill{ + get { return YFill; } + set { AutoSize = false; YFill = value; } + } + } + } +} diff --git a/main/src/addins/MonoDevelop.GtkCore2/libstetic/wrapper/TextView.cs b/main/src/addins/MonoDevelop.GtkCore2/libstetic/wrapper/TextView.cs new file mode 100644 index 0000000000..1fbc09e0b6 --- /dev/null +++ b/main/src/addins/MonoDevelop.GtkCore2/libstetic/wrapper/TextView.cs @@ -0,0 +1,62 @@ +using System; +using System.CodeDom; +using System.Collections; + +namespace Stetic.Wrapper { + + public class TextView : Container { + + public override void Wrap (object obj, bool initialized) + { + base.Wrap (obj, initialized); + ((Gtk.TextView)Wrapped).Buffer.Changed += Buffer_Changed; + if (!initialized) + ShowScrollbars = true; + } + + public override void Dispose () + { + ((Gtk.TextView)Wrapped).Buffer.Changed -= Buffer_Changed; + base.Dispose (); + } + + public string Text { + get { + return ((Gtk.TextView)Wrapped).Buffer.Text; + } + set { + ((Gtk.TextView)Wrapped).Buffer.Text = value; + } + } + + public void Buffer_Changed (object obj, EventArgs args) + { + EmitNotify ("Text"); + } + + protected override bool AllowPlaceholders { + get { + return false; + } + } + + internal protected override void GenerateBuildCode (GeneratorContext ctx, CodeExpression var) + { + if (Text.Length > 0) { + ctx.Statements.Add ( + new CodeAssignStatement ( + new CodePropertyReferenceExpression ( + new CodePropertyReferenceExpression ( + var, + "Buffer" + ), + "Text" + ), + new CodePrimitiveExpression (Text) + ) + ); + } + base.GenerateBuildCode (ctx, var); + } + } +} diff --git a/main/src/addins/MonoDevelop.GtkCore2/libstetic/wrapper/ToggleToolButton.cs b/main/src/addins/MonoDevelop.GtkCore2/libstetic/wrapper/ToggleToolButton.cs new file mode 100644 index 0000000000..a8a0654f1f --- /dev/null +++ b/main/src/addins/MonoDevelop.GtkCore2/libstetic/wrapper/ToggleToolButton.cs @@ -0,0 +1,12 @@ +using System; + +namespace Stetic.Wrapper { + + public class ToggleToolButton : ToolButton { + + public static new Gtk.ToolButton CreateInstance () + { + return new Gtk.ToggleToolButton (Gtk.Stock.Bold); + } + } +} diff --git a/main/src/addins/MonoDevelop.GtkCore2/libstetic/wrapper/ToolButton.cs b/main/src/addins/MonoDevelop.GtkCore2/libstetic/wrapper/ToolButton.cs new file mode 100644 index 0000000000..76bb51faf7 --- /dev/null +++ b/main/src/addins/MonoDevelop.GtkCore2/libstetic/wrapper/ToolButton.cs @@ -0,0 +1,147 @@ +using System; +using System.CodeDom; +using System.Xml; + +namespace Stetic.Wrapper { + + public class ToolButton : Widget { + + ButtonType type; + string stockId; + string label; + ImageInfo imageInfo; + + public enum ButtonType { + StockItem, + TextAndIcon + }; + + public static Gtk.ToolButton CreateInstance () + { + return new Gtk.ToolButton (Gtk.Stock.New); + } + + public override void Wrap (object obj, bool initialized) + { + base.Wrap (obj, initialized); + Gtk.ToolButton toolbutton = (Gtk.ToolButton)Wrapped; + + if (toolbutton.StockId != null) { + stockId = toolbutton.StockId; + type = ButtonType.StockItem; + } else { + type = ButtonType.TextAndIcon; + } + } + + protected override void ReadProperties (ObjectReader reader, XmlElement elem) + { + if (reader.Format == FileFormat.Glade) { + string icon = (string)GladeUtils.ExtractProperty (elem, "icon", ""); + stockId = (string)GladeUtils.ExtractProperty (elem, "stock_id", ""); + label = (string)GladeUtils.ExtractProperty (elem, "label", ""); + base.ReadProperties (reader, elem); + + if (stockId != null && stockId.Length > 0) { + Type = ButtonType.StockItem; + } else if (icon != null && icon != "") { + imageInfo = ImageInfo.FromFile (icon); + Type = ButtonType.TextAndIcon; + } + } else + base.ReadProperties (reader, elem); + } + + protected override XmlElement WriteProperties (ObjectWriter writer) + { + XmlElement elem = base.WriteProperties (writer); + if (type != ButtonType.StockItem && imageInfo != null) { + if (writer.Format == FileFormat.Glade) { + switch (imageInfo.Source) { + case ImageSource.File: + GladeUtils.SetProperty (elem, "icon", imageInfo.Name); + break; + case ImageSource.Theme: + GladeUtils.SetProperty (elem, "stock_id", imageInfo.Name); + break; + default: + throw new System.NotSupportedException ("Image source not supported by Glade."); + } + } + } + return elem; + } + + internal protected override CodeExpression GenerateObjectCreation (GeneratorContext ctx) + { + return new CodeObjectCreateExpression ( + ClassDescriptor.WrappedTypeName.ToGlobalTypeRef (), + new CodePrimitiveExpression (null), + new CodePrimitiveExpression (null) + ); + } + + Gtk.ToolButton button { + get { return (Gtk.ToolButton) Wrapped; } + } + + public ButtonType Type { + get { + return type; + } + set { + type = value; + switch (type) { + case ButtonType.StockItem: + button.IconWidget = null; + StockId = stockId; + Label = label; + break; + case ButtonType.TextAndIcon: + button.StockId = null; + Icon = imageInfo; + Label = label; + break; + } + EmitNotify ("Type"); + } + } + + public string Label { + get { return label; } + set { + if (type == ButtonType.StockItem && value != null) { + label = value.Length == 0 ? null : value; + } else + label = value; + + button.Label = label; + } + } + + public string StockId { + get { return stockId; } + set { + stockId = value; + if (stockId != null && stockId.StartsWith ("stock:")) + stockId = stockId.Substring (6); + button.StockId = stockId; + button.ShowAll (); + } + } + + public ImageInfo Icon { + get { return imageInfo; } + set { + imageInfo = value; + if (imageInfo != null) { + button.IconWidget = new Gtk.Image (imageInfo.GetImage (Project)); + button.ShowAll (); + } + else + button.IconWidget = null; + EmitNotify ("Icon"); + } + } + } +} diff --git a/main/src/addins/MonoDevelop.GtkCore2/libstetic/wrapper/Toolbar.cs b/main/src/addins/MonoDevelop.GtkCore2/libstetic/wrapper/Toolbar.cs new file mode 100644 index 0000000000..cc15543888 --- /dev/null +++ b/main/src/addins/MonoDevelop.GtkCore2/libstetic/wrapper/Toolbar.cs @@ -0,0 +1,178 @@ +using System; +using System.Collections; + +namespace Stetic.Wrapper { + + public class Toolbar : Container { + + public override void Wrap (object obj, bool initialized) + { + base.Wrap (obj, initialized); + toolbar.SizeAllocated += toolbar_SizeAllocated; + } + + public override void Dispose () + { + toolbar.SizeAllocated -= toolbar_SizeAllocated; + base.Dispose (); + } + + public override IEnumerable RealChildren { + get { + // Don't return Gtk.ToolItems that are only being used + // to hold other non-ToolItem widgets. Just return the + // contained widgets themselves. + + Gtk.Widget[] children = toolbar.Children; + for (int i = 0; i < children.Length; i++) { + if (children[i].GetType () == typeof (Gtk.ToolItem)) + children[i] = ((Gtk.ToolItem)children[i]).Child; + } + return children; + } + } + + Gtk.Toolbar toolbar { + get { + return (Gtk.Toolbar)Wrapped; + } + } + + public override bool HExpandable { + get { + return toolbar.Orientation == Gtk.Orientation.Horizontal; + } + } + + public override bool VExpandable { + get { + return toolbar.Orientation == Gtk.Orientation.Vertical; + } + } + + public Gtk.Orientation Orientation { + get { + return toolbar.Orientation; + } + set { + toolbar.Orientation = value; + EmitContentsChanged (); + } + } + + protected override void DoSync () + { + DND.ClearFaults (this); + Gtk.Orientation faultOrientation = + Orientation == Gtk.Orientation.Horizontal ? Gtk.Orientation.Vertical : Gtk.Orientation.Horizontal; + Gdk.Rectangle tbAlloc = toolbar.Allocation; + + Gtk.Widget[] children = toolbar.Children; + if (children.Length == 0) { + DND.AddFault (this, 0, faultOrientation, tbAlloc); + return; + } + + if (faultOrientation == Gtk.Orientation.Horizontal) { + DND.AddHFault (this, 0, null, children[0]); + DND.AddHFault (this, children.Length, children[children.Length - 1], null); + } else { + DND.AddVFault (this, 0, null, children[0]); + DND.AddVFault (this, children.Length, children[children.Length - 1], null); + } + + for (int i = 1; i < children.Length; i++) { + if (faultOrientation == Gtk.Orientation.Horizontal) + DND.AddHFault (this, i, children[i - 1], children[i]); + else + DND.AddVFault (this, i, children[i - 1], children[i]); + } + } + + void toolbar_SizeAllocated (object obj, Gtk.SizeAllocatedArgs args) + { + Sync (); + } + + // Insert widget at index, wrapping a ToolItem around it if needed + void ToolItemize (Gtk.Widget widget, int index) + { + Gtk.ToolItem toolItem = widget as Gtk.ToolItem; + if (toolItem == null) { + toolItem = new Gtk.ToolItem (); + toolItem.Show (); + toolItem.Add (widget); + } + toolbar.Insert (toolItem, index); + } + + // Remove widget (or its ToolItem parent), returning its position + int ToolDeItemize (Gtk.Widget widget) + { + Gtk.ToolItem toolItem = widget as Gtk.ToolItem; + if (toolItem == null) { + toolItem = (Gtk.ToolItem)widget.Parent; + toolItem.Remove (widget); + } + + int index = toolbar.GetItemIndex (toolItem); + + toolbar.Remove (toolItem); + if (toolItem != (widget as Gtk.ToolItem)) + toolItem.Destroy (); + + return index; + } + + protected override void ReplaceChild (Gtk.Widget oldChild, Gtk.Widget newChild) + { + ToolItemize (newChild, ToolDeItemize (oldChild)); + } + + public override Placeholder AddPlaceholder () + { + Placeholder ph = CreatePlaceholder (); + ToolItemize (ph, 0); + return ph; + } + + int dragIndex; + + protected override Gtk.Widget CreateDragSource (Gtk.Widget dragWidget) + { + Gtk.Invisible invis = new Gtk.Invisible (); + invis.Show (); + invis.DragEnd += DragEnd; + + dragIndex = ToolDeItemize (dragWidget); + return invis; + } + + void DragEnd (object obj, Gtk.DragEndArgs args) + { + Gtk.Invisible invis = obj as Gtk.Invisible; + invis.DragEnd -= DragEnd; + invis.Destroy (); + + if (DND.DragWidget != null) + ToolItemize (DND.Cancel (), dragIndex); + dragIndex = -1; + } + + public override void Drop (Gtk.Widget w, object faultId) + { + ToolItemize (w, (int)faultId); + EmitContentsChanged (); + Sync (); + } + + public class ToolbarChild : Container.ContainerChild { + public Gtk.ToolItem ToolItem { + get { + Gtk.Container.ContainerChild cc = (Gtk.Container.ContainerChild)Wrapped; + return (Gtk.ToolItem)cc.Child; + } + } + } + } +} diff --git a/main/src/addins/MonoDevelop.GtkCore2/libstetic/wrapper/TreeView.cs b/main/src/addins/MonoDevelop.GtkCore2/libstetic/wrapper/TreeView.cs new file mode 100644 index 0000000000..0444f4f4b1 --- /dev/null +++ b/main/src/addins/MonoDevelop.GtkCore2/libstetic/wrapper/TreeView.cs @@ -0,0 +1,21 @@ + +using System; + +namespace Stetic.Wrapper +{ + public class TreeView: Container + { + public override void Wrap (object obj, bool initialized) + { + base.Wrap (obj, initialized); + if (!initialized) + ShowScrollbars = true; + } + + protected override bool AllowPlaceholders { + get { + return false; + } + } + } +} diff --git a/main/src/addins/MonoDevelop.GtkCore2/libstetic/wrapper/VScale.cs b/main/src/addins/MonoDevelop.GtkCore2/libstetic/wrapper/VScale.cs new file mode 100644 index 0000000000..e0fb10677c --- /dev/null +++ b/main/src/addins/MonoDevelop.GtkCore2/libstetic/wrapper/VScale.cs @@ -0,0 +1,18 @@ +using System; +using System.CodeDom; + +namespace Stetic.Wrapper { + + public class VScale : Scale { + + public static Gtk.VScale CreateInstance () + { + return new Gtk.VScale (0.0, 100.0, 1.0); + } + + internal protected override CodeExpression GenerateObjectCreation (GeneratorContext ctx) + { + return new CodeObjectCreateExpression (ClassDescriptor.WrappedTypeName.ToGlobalTypeRef (), new CodePrimitiveExpression (null)); + } + } +} diff --git a/main/src/addins/MonoDevelop.GtkCore2/libstetic/wrapper/VScrollbar.cs b/main/src/addins/MonoDevelop.GtkCore2/libstetic/wrapper/VScrollbar.cs new file mode 100644 index 0000000000..8270c97a4e --- /dev/null +++ b/main/src/addins/MonoDevelop.GtkCore2/libstetic/wrapper/VScrollbar.cs @@ -0,0 +1,18 @@ +using System; +using System.CodeDom; + +namespace Stetic.Wrapper { + + public class VScrollbar : Range { + + public static Gtk.VScrollbar CreateInstance () + { + return new Gtk.VScrollbar (new Gtk.Adjustment (0.0, 0.0, 100.0, 1.0, 10.0, 10.0)); + } + + internal protected override CodeExpression GenerateObjectCreation (GeneratorContext ctx) + { + return new CodeObjectCreateExpression (ClassDescriptor.WrappedTypeName.ToGlobalTypeRef (), new CodePrimitiveExpression (null)); + } + } +} diff --git a/main/src/addins/MonoDevelop.GtkCore2/libstetic/wrapper/Viewport.cs b/main/src/addins/MonoDevelop.GtkCore2/libstetic/wrapper/Viewport.cs new file mode 100644 index 0000000000..41dbacc161 --- /dev/null +++ b/main/src/addins/MonoDevelop.GtkCore2/libstetic/wrapper/Viewport.cs @@ -0,0 +1,28 @@ +using System; +using System.Collections; + +namespace Stetic.Wrapper { + + public class Viewport : Container { + + public override void Wrap (object obj, bool initialized) + { + base.Wrap (obj, initialized); + Unselectable = true; + } + + protected override void ReplaceChild (Gtk.Widget oldChild, Gtk.Widget newChild) + { + Widget ww = Widget.Lookup (oldChild); + if ((oldChild is Placeholder) && (ParentWrapper is ScrolledWindow) && newChild.SetScrollAdjustments (null, null)) { + Widget wrapper = Widget.Lookup (newChild); + wrapper.ShowScrollbars = false; + ParentWrapper.ReplaceChild (Wrapped, newChild, false); + } else if (ww != null && ww.ShowScrollbars && (ParentWrapper is ScrolledWindow) && ParentWrapper.ParentWrapper != null) { + // The viewport is bound to the child widget. Remove it together with the child + ParentWrapper.ParentWrapper.ReplaceChild (ParentWrapper.Wrapped, newChild, false); + } else + base.ReplaceChild (oldChild, newChild); + } + } +} diff --git a/main/src/addins/MonoDevelop.GtkCore2/libstetic/wrapper/Widget.cs b/main/src/addins/MonoDevelop.GtkCore2/libstetic/wrapper/Widget.cs new file mode 100644 index 0000000000..80f5ab8e33 --- /dev/null +++ b/main/src/addins/MonoDevelop.GtkCore2/libstetic/wrapper/Widget.cs @@ -0,0 +1,1094 @@ +using System; +using System.Collections; +using System.Xml; +using System.CodeDom; +using Stetic.Undo; + +namespace Stetic.Wrapper { + + public class Widget : Object, IEditableObject + { + static DiffGenerator propDiffGenerator; + + string oldName; + string oldMemberName; + bool hexpandable, vexpandable; + bool generatePublic = true; + + bool window_visible = true; + bool hasDefault; + bool canDefault; + Gdk.EventMask events; + bool canFocus; + + ActionGroupCollection actionGroups; + string member; + string tooltip; + + bool requiresUndoStatusUpdate; + + // List of groups added to the UIManager + ArrayList includedActionGroups; + + bool unselectable; + bool boundToScrollWindow; + + public event EventHandler Destroyed; + + // Fired when the name of the widget changes. + public event WidgetNameChangedHandler NameChanged; + // Fired when the member name of the widget changes. + public event WidgetNameChangedHandler MemberNameChanged; + + static Widget () + { + propDiffGenerator = new DiffGenerator (); + propDiffGenerator.CurrentStatusAdaptor = new XmlDiffAdaptor (); + propDiffGenerator.NewStatusAdaptor = propDiffGenerator.CurrentStatusAdaptor; + } + + public override void Wrap (object obj, bool initialized) + { + base.Wrap (obj, initialized); + + oldName = ((Gtk.Widget)obj).Name; + + if (!initialized) { + events = Wrapped.Events; + canFocus = Wrapped.CanFocus; + } + + if (!(Wrapped is Gtk.Window)) + Wrapped.ShowAll (); + + Wrapped.PopupMenu += PopupMenu; + Wrapped.FocusInEvent += OnFocusIn; + InterceptClicks (Wrapped); + + hexpandable = this.ClassDescriptor.HExpandable; + vexpandable = this.ClassDescriptor.VExpandable; + + if (ParentWrapper != null) { + // Make sure the widget's name is not already being used. + string nn = ParentWrapper.GetValidWidgetName (Wrapped); + if (nn != Wrapped.Name) + Wrapped.Name = nn; + } + + Wrapped.Destroyed += OnDestroyed; + + if (Wrapped.Parent != null) { + // The object was added to the parent before creating the wrapper. + // Since it's now a wrapped object, the parent don't need to + // intercept clicks for it anymore + Widget w = GetInterceptorParent (); + if (w != null) + w.UninterceptClicks (Wrapped); + } + } + + void OnDestroyed (object on, EventArgs a) + { + if (Destroyed != null) + Destroyed (this, a); + Dispose (); + } + + public override void Dispose () + { + if (Wrapped == null) + return; + + if (Project != null && Project.Selection == Wrapped) + Project.Selection = null; + + Wrapped.Destroyed -= OnDestroyed; + Wrapped.PopupMenu -= PopupMenu; + Wrapped.FocusInEvent -= OnFocusIn; + UninterceptClicks (Wrapped); + + if (actionGroups != null) { + foreach (ActionGroup ag in actionGroups) + ag.Dispose (); + actionGroups = null; + } + base.Dispose (); + } + + void OnFocusIn (object s, Gtk.FocusInEventArgs a) + { + if (!Unselectable) + Select (); + else if (ParentWrapper != null) + ParentWrapper.Select (); + } + + internal override UndoManager GetUndoManagerInternal () + { + if (ParentWrapper != null) + return ParentWrapper.UndoManager; + else + return base.GetUndoManagerInternal (); + } + + public bool GeneratePublic { + get { return generatePublic; } + set { generatePublic = value; } + } + + public bool Unselectable { + get { + return unselectable; + } + set { + if (value == unselectable) + return; + unselectable = value; + Widget w = GetInterceptorParent (); + if (w != null) { + // If a widget becomes unselectable, then the parent must intercept + // their clicks. + if (unselectable) + w.InterceptClicks (Wrapped); + else + w.UninterceptClicks (Wrapped); + } + } + } + + Widget GetInterceptorParent () + { + Gtk.Widget wp = Wrapped.Parent; + while (wp != null && Lookup (wp) == null) + wp = wp.Parent; + return Lookup (wp); + } + + void InterceptClicks (Gtk.Widget widget) + { + if (widget is Stetic.Placeholder) + return; + + if (!widget.IsRealized) + widget.Events |= Gdk.EventMask.ButtonPressMask; + widget.WidgetEvent += WidgetEvent; + + Gtk.Container container = widget as Gtk.Container; + if (container != null) { + container.Added += OnInterceptedChildAdded; + container.Removed += OnInterceptedChildRemoved; + foreach (Gtk.Widget child in container.AllChildren) { + Widget w = Lookup (child); + if (w == null || w.Unselectable) + InterceptClicks (child); + } + } + } + + [GLib.ConnectBefore] + void OnInterceptedChildAdded (object o, Gtk.AddedArgs args) + { + Widget w = Lookup (args.Widget); + if (w == null || w.Unselectable) + InterceptClicks (args.Widget); + } + + void OnInterceptedChildRemoved (object o, Gtk.RemovedArgs args) + { + UninterceptClicks (args.Widget); + } + + void UninterceptClicks (Gtk.Widget widget) + { + widget.WidgetEvent -= WidgetEvent; + + Gtk.Container container = widget as Gtk.Container; + if (container != null) { + container.Added -= OnInterceptedChildAdded; + container.Removed -= OnInterceptedChildRemoved; + foreach (Gtk.Widget child in container.AllChildren) { + if (Lookup (child) == null) + UninterceptClicks (child); + } + } + } + + public new Gtk.Widget Wrapped { + get { + return base.Wrapped as Gtk.Widget; + } + } + + public Stetic.Wrapper.Container ParentWrapper { + get { + return Container.LookupParent (Wrapped); + } + } + + public bool IsTopLevel { + get { return Wrapped.Parent == null || Widget.Lookup (Wrapped.Parent) == null; } + } + + public string UIManagerName { + get { + return actionGroups != null && actionGroups.Count > 0 ? "UIManager" : String.Empty; + } + } + + internal void InitializeName (string name) + { + oldName = name; + Wrapped.Name = name; + } + + public override string Name { + get { return Wrapped.Name; } + set { Wrapped.Name = value; EmitNotify ("Name"); } + } + + public string MemberName { + get { return member != null ? member : ""; } + set { member = value; EmitNotify ("MemberName"); } + } + + public Container GetTopLevel () + { + Widget c = this; + while (!c.IsTopLevel) + c = c.ParentWrapper; + return c as Container; + } + + public ActionGroupCollection LocalActionGroups { + get { + if (IsTopLevel) { + if (actionGroups == null) { + actionGroups = new ActionGroupCollection (); + actionGroups.SetOwner (this); + actionGroups.ActionGroupAdded += OnGroupAdded; + actionGroups.ActionGroupRemoved += OnGroupRemoved; + actionGroups.ActionGroupChanged += OnGroupChanged; + } + return actionGroups; + } else { + return ParentWrapper.LocalActionGroups; + } + } + } + + void OnGroupAdded (object s, Stetic.Wrapper.ActionGroupEventArgs args) + { + args.ActionGroup.SignalAdded += OnSignalAdded; + args.ActionGroup.SignalRemoved += OnSignalRemoved; + args.ActionGroup.SignalChanged += OnSignalChanged; + NotifyChanged (); + } + + void OnGroupRemoved (object s, Stetic.Wrapper.ActionGroupEventArgs args) + { + args.ActionGroup.SignalAdded -= OnSignalAdded; + args.ActionGroup.SignalRemoved -= OnSignalRemoved; + args.ActionGroup.SignalChanged -= OnSignalChanged; + NotifyChanged (); + } + + void OnGroupChanged (object s, Stetic.Wrapper.ActionGroupEventArgs args) + { + NotifyChanged (); + } + + void OnSignalAdded (object sender, SignalEventArgs args) + { + OnSignalAdded (args); + } + + void OnSignalRemoved (object sender, SignalEventArgs args) + { + OnSignalRemoved (args); + } + + void OnSignalChanged (object sender, SignalChangedEventArgs args) + { + OnSignalChanged (args); + } + + [GLib.ConnectBefore] + void WidgetEvent (object obj, Gtk.WidgetEventArgs args) + { + if (args.Event.Type == Gdk.EventType.ButtonPress) + args.RetVal = HandleClick ((Gdk.EventButton)args.Event); + } + + internal bool HandleClick (Gdk.EventButton evb) + { + int x = (int)evb.X, y = (int)evb.Y; + int erx, ery, wrx, wry; + + // Translate from event window to widget window coords + evb.Window.GetOrigin (out erx, out ery); + Wrapped.GdkWindow.GetOrigin (out wrx, out wry); + x += erx - wrx; + y += ery - wry; + + Widget wrapper = FindWrapper (Wrapped, x, y); + if (wrapper == null) + return false; + + if (wrapper.Wrapped != proj.Selection) { + wrapper.Select (); + return true; + } else if (evb.Button == 3) { + proj.PopupContextMenu (wrapper); + return true; + } else + return false; + } + + Widget FindWrapper (Gtk.Widget top, int x, int y) + { + Widget wrapper; + + Gtk.Container container = top as Gtk.Container; + if (container != null) { + foreach (Gtk.Widget child in container.AllChildren) { + if (!child.IsDrawable) + continue; + + Gdk.Rectangle alloc = child.Allocation; + if (alloc.Contains (x, y)) { + if (child.GdkWindow == top.GdkWindow) + wrapper = FindWrapper (child, x, y); + else + wrapper = FindWrapper (child, x - alloc.X, y - alloc.Y); + if (wrapper != null) + return wrapper; + } + } + } + + wrapper = Lookup (top); + if (wrapper == null || wrapper.Unselectable) + return null; + return wrapper; + } + + void PopupMenu (object obj, EventArgs args) + { + proj.PopupContextMenu (this); + } + + public void Select () + { + proj.Selection = Wrapped; + } + + public void Unselect () + { + if (proj.Selection == Wrapped) + proj.Selection = null; + } + + internal protected virtual void OnSelected () + { + } + + internal protected virtual void OnUnselected () + { + } + + public void Delete () + { + if (Project.Selection == Wrapped) + Project.Selection = null; + + if (ParentWrapper != null) + ParentWrapper.Delete (this); + else + Wrapped.Destroy (); + } + + internal bool RequiresUndoStatusUpdate { + get { return requiresUndoStatusUpdate; } + set { requiresUndoStatusUpdate = value; } + } + + public override ObjectWrapper FindObjectByUndoId (string id) + { + ObjectWrapper c = base.FindObjectByUndoId (id); + if (c != null) + return c; + + if (actionGroups != null) + return actionGroups.FindObjectByUndoId (id); + else + return null; + } + + public override object GetUndoDiff () + { + XmlElement oldElem = UndoManager.GetObjectStatus (this); + XmlElement newElem = WriteProperties (new ObjectWriter (oldElem.OwnerDocument, FileFormat.Native)); + + ObjectDiff propsDiff = propDiffGenerator.GetDiff (newElem, oldElem); + ObjectDiff actionsDiff = LocalActionGroups.GetDiff (Project, oldElem); + + UndoManager.UpdateObjectStatus (this, newElem); + + if (propsDiff == null && actionsDiff == null) + return null; + else + return new ObjectDiff[] { propsDiff, actionsDiff }; + } + + public override object ApplyUndoRedoDiff (object diff) + { + ObjectDiff[] data = (ObjectDiff[]) diff; + + XmlElement status = UndoManager.GetObjectStatus (this); + XmlElement oldElem = (XmlElement) status.CloneNode (true); + + ObjectDiff propsDiff = data [0]; + + if (propsDiff != null) { + propDiffGenerator.ApplyDiff (status, propsDiff); + ReadProperties (new ObjectReader (Project, FileFormat.Native), status); + data [0] = propDiffGenerator.GetDiff (status, oldElem); + } + + ObjectDiff actionsDiff = data [1]; + if (actionsDiff != null) { + LocalActionGroups.ApplyDiff (Project, actionsDiff); + data [1] = LocalActionGroups.GetDiff (Project, oldElem); + } + + return data; + } + + public override void Read (ObjectReader reader, XmlElement elem) + { + ReadActionGroups (reader, elem); + ReadProperties (reader, elem); + } + + protected void ReadActionGroups (ObjectReader reader, XmlElement elem) + { + if (reader.Format == FileFormat.Native) { + if (actionGroups == null) { + actionGroups = new ActionGroupCollection (); + actionGroups.SetOwner (this); + actionGroups.ActionGroupAdded += OnGroupAdded; + actionGroups.ActionGroupRemoved += OnGroupRemoved; + actionGroups.ActionGroupChanged += OnGroupChanged; + } else + actionGroups.Clear (); + foreach (XmlElement groupElem in elem.SelectNodes ("action-group")) { + ActionGroup actionGroup = new ActionGroup (); + actionGroup.Read (reader, groupElem); + actionGroups.Add (actionGroup); + } + } + } + + protected virtual void ReadProperties (ObjectReader reader, XmlElement elem) + { + if (Wrapped != null) { + // There is already an instance. Load the default values. + this.ClassDescriptor.ResetInstance (Wrapped); + Signals.Clear (); + } + + if (reader.Format == FileFormat.Native) + WidgetUtils.Read (this, elem); + else + GladeUtils.ImportWidget (this, elem); + + string uid = elem.GetAttribute ("undoId"); + if (uid.Length > 0) + UndoId = uid; + oldName = Wrapped.Name; + } + + public override XmlElement Write (ObjectWriter writer) + { + XmlElement elem = WriteProperties (writer); + WriteActionGroups (writer, elem); + return elem; + } + + protected virtual XmlElement WriteProperties (ObjectWriter writer) + { + if (writer.Format == FileFormat.Native) { + XmlElement elem = WidgetUtils.Write (this, writer.XmlDocument); + if (writer.CreateUndoInfo) + elem.SetAttribute ("undoId", UndoId); + return elem; + } + else { + XmlElement elem = GladeUtils.ExportWidget (this, writer.XmlDocument); + GladeUtils.ExtractProperty (elem, "name", ""); + return elem; + } + } + + protected void WriteActionGroups (ObjectWriter writer, XmlElement elem) + { + if (writer.Format == FileFormat.Native) { + if (actionGroups != null) { + foreach (ActionGroup actionGroup in actionGroups) + elem.InsertBefore (actionGroup.Write (writer), elem.FirstChild); + } + } + } + + internal protected override void GenerateBuildCode (GeneratorContext ctx, CodeExpression var) + { + if (!String.IsNullOrEmpty (UIManagerName)) { + // Create an UI manager + CodeFieldReferenceExpression uixp = new CodeFieldReferenceExpression (new CodeThisReferenceExpression (), UIManagerName); + CodeAssignStatement uim_init = new CodeAssignStatement (uixp, new CodeObjectCreateExpression (typeof (Gtk.UIManager).ToGlobalTypeRef ())); + ctx.Statements.Add (uim_init); + + includedActionGroups = new ArrayList (); + + // Generate action group creation + foreach (ActionGroup actionGroup in actionGroups) { + + // Create the action group + string grpVar = ctx.NewId (); + CodeVariableDeclarationStatement uidec = new CodeVariableDeclarationStatement ( + typeof (Gtk.ActionGroup).ToGlobalTypeRef (), + grpVar, + actionGroup.GenerateObjectCreation (ctx) + ); + ctx.Statements.Add (uidec); + actionGroup.GenerateBuildCode (ctx, new CodeVariableReferenceExpression (grpVar)); + + // Insert the action group in the UIManager + CodeMethodInvokeExpression mi = new CodeMethodInvokeExpression ( + uixp, + "InsertActionGroup", + new CodeVariableReferenceExpression (grpVar), + new CodePrimitiveExpression (includedActionGroups.Count) + ); + ctx.Statements.Add (mi); + + includedActionGroups.Add (actionGroup); + } + + // Adds the accel group to the window + Window w = GetTopLevel () as Window; + if (w != null) { + CodeMethodInvokeExpression ami = new CodeMethodInvokeExpression ( + ctx.WidgetMap.GetWidgetExp (w), + "AddAccelGroup", + new CodePropertyReferenceExpression ( + uixp, + "AccelGroup" + ) + ); + ctx.Statements.Add (ami); + } else { + // There is no top level window, this must be a custom widget. + // The only option is to register the accel group when + // the widget is realized. This is done by the Bin wrapper. + } + } + + if (tooltip != null && tooltip.Length > 0) + GetTopLevel().GenerateTooltip (ctx, this); + + base.GenerateBuildCode (ctx, var); + } + + internal protected override void GeneratePostBuildCode (GeneratorContext ctx, CodeExpression var) + { + base.GeneratePostBuildCode (ctx, var); + + // The visible property is generated here to ensure that widgets are made visible + // after they have been fully built + + PropertyDescriptor prop = ClassDescriptor ["Visible"] as PropertyDescriptor; + if (prop != null && prop.PropertyType == typeof(bool) && !(bool) prop.GetValue (Wrapped)) { + ctx.Statements.Add ( + new CodeMethodInvokeExpression ( + var, + "Hide" + ) + ); + } + + // The HasDefault property can only be assigned when the widget is added to the window + prop = ClassDescriptor ["HasDefault"] as PropertyDescriptor; + if (prop != null && (bool) prop.GetValue (Wrapped)) { + ctx.Statements.Add ( + new CodeAssignStatement ( + new CodePropertyReferenceExpression ( + var, + "HasDefault" + ), + new CodePrimitiveExpression (true) + ) + ); + } + } + + protected override void GeneratePropertySet (GeneratorContext ctx, CodeExpression var, PropertyDescriptor prop) + { + // Those properties are handled in GeneratePostBuildCode + if (prop.Name == "Visible" || prop.Name == "HasDefault") + return; + + // Don't generate a name for unselectable widgets + if (prop.Name == "Name" && Unselectable) + return; + + base.GeneratePropertySet (ctx, var, prop); + } + + protected CodeExpression GenerateUiManagerElement (GeneratorContext ctx, ActionTree tree) + { + Widget topLevel = GetTopLevel (); + string uiName = topLevel.UIManagerName; + if (uiName != null) { + CodeFieldReferenceExpression uiManager = new CodeFieldReferenceExpression (new CodeThisReferenceExpression (), uiName); + if (topLevel.includedActionGroups == null) + topLevel.includedActionGroups = new ArrayList (); + + // Add to the uimanager all action groups required by the + // actions of the tree + + foreach (ActionGroup grp in tree.GetRequiredGroups ()) { + if (!topLevel.includedActionGroups.Contains (grp)) { + // Insert the action group in the UIManager + CodeMethodInvokeExpression mi = new CodeMethodInvokeExpression ( + uiManager, + "InsertActionGroup", + ctx.GenerateValue (grp, typeof(ActionGroup)), + new CodePrimitiveExpression (topLevel.includedActionGroups.Count) + ); + ctx.Statements.Add (mi); + topLevel.includedActionGroups.Add (grp); + } + } + + tree.GenerateBuildCode (ctx, uiManager); + return new CodeMethodInvokeExpression ( + uiManager, + "GetWidget", + new CodePrimitiveExpression ("/" + Wrapped.Name) + ); + } + return null; + } + + public static new Widget Lookup (GLib.Object obj) + { + return Stetic.ObjectWrapper.Lookup (obj) as Stetic.Wrapper.Widget; + } + + PropertyDescriptor internalChildProperty; + public PropertyDescriptor InternalChildProperty { + get { + return internalChildProperty; + } + set { + internalChildProperty = value; + } + } + + public virtual void Drop (Gtk.Widget widget, object faultId) + { + widget.Destroy (); + } + + public virtual bool HExpandable { get { return hexpandable; } } + public virtual bool VExpandable { get { return vexpandable; } } + + public bool Visible { + get { + return window_visible; + } + set { + window_visible = value; + EmitNotify ("Visible"); + } + } + + public bool HasDefault { + get { + return hasDefault; + } + set { + hasDefault = value; + EmitNotify ("HasDefault"); + if (hasDefault && !CanDefault) + CanDefault = true; + } + } + + public bool CanDefault { + get { + return canDefault; + } + set { + canDefault = value; + EmitNotify ("CanDefault"); + if (!canDefault && HasDefault) + HasDefault = false; + } + } + + public bool Sensitive { + get { + return Wrapped.Sensitive; + } + set { + if (Wrapped.Sensitive == value) + return; + + Wrapped.Sensitive = value; + if (Wrapped.Sensitive) + InsensitiveManager.Remove (this); + else + InsensitiveManager.Add (this); + EmitNotify ("Sensitive"); + } + } + + public Gdk.EventMask Events { + get { + return events; + } + set { + events = value; + EmitNotify ("Events"); + } + } + + public bool CanFocus { + get { + return canFocus; + } + set { + canFocus = value; + EmitNotify ("CanFocus"); + } + } + + public string Tooltip { + get { + return tooltip; + } + set { + tooltip = value; + } + } + + public bool ShowScrollbars { + get { + return boundToScrollWindow; + } + set { + if (boundToScrollWindow != value) { + boundToScrollWindow = value; + UpdateScrolledWindow (); + EmitNotify ("ShowScrollbars"); + } + } + } + + internal void UpdateScrolledWindow () + { + if (ParentWrapper == null) + return; + if (boundToScrollWindow) { + if (!(Wrapped.Parent is Gtk.Viewport) && !(Wrapped.Parent is Gtk.ScrolledWindow)) { + Gtk.ScrolledWindow scw = new Gtk.ScrolledWindow (); + scw.HscrollbarPolicy = scw.VscrollbarPolicy = Gtk.PolicyType.Automatic; + scw.ShadowType = Gtk.ShadowType.In; + ScrolledWindow wrapper = (ScrolledWindow) ObjectWrapper.Create (Project, scw, ParentWrapper); + ParentWrapper.ReplaceChild (Wrapped, scw, false); + if (Wrapped.SetScrollAdjustments (null, null)) + scw.Add (Wrapped); + else + wrapper.AddWithViewport (Wrapped); + Select (); + } + } + else if (((Wrapped.Parent is Gtk.Viewport) || (Wrapped.Parent is Gtk.ScrolledWindow)) && ParentWrapper.ParentWrapper != null) { + Gtk.Container parent = (Gtk.Container) Wrapped.Parent; + parent.Remove (Wrapped); + Container grandParent; + if (parent is Gtk.Viewport) { + parent = (Gtk.Container) parent.Parent; + grandParent = Container.LookupParent (parent); + } + else + grandParent = Container.LookupParent (parent); + grandParent.ReplaceChild (parent, Wrapped, true); + } + } + + public bool InWindow { + get { + return this.GetTopLevel ().Wrapped is TopLevelWindow; + } + } + + public bool IsScrollable { + get { + return !IsTopLevel && !(Wrapped is Gtk.ScrolledWindow); + } + } + + public override string ToString () + { + if (Wrapped == null) + return base.ToString (); + else if (Wrapped.Name != null) + return "[" + Wrapped.GetType ().Name + " '" + Wrapped.Name + "' " + Wrapped.GetHashCode ().ToString () + "]"; + else + return "[" + Wrapped.GetType ().Name + " " + Wrapped.GetHashCode ().ToString () + "]"; + } + + public IDesignArea GetDesignArea () + { + return GetDesignArea (Wrapped); + } + + protected IDesignArea GetDesignArea (Gtk.Widget w) + { + while (w != null && !(w is IDesignArea)) + w = w.Parent; + return w as IDesignArea; + } + + protected override void EmitNotify (string propertyName) + { + // 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 == "style" || + propertyName == "Visible" || propertyName == "scroll-offset") + return; + + if (propertyName == "Name") { + if (Wrapped.Name != oldName) { + if (ParentWrapper != null) { + string nn = ParentWrapper.GetValidWidgetName (Wrapped); + if (nn != Wrapped.Name) { + // The name was not valid, so it has to be changed again. + // Don't fire the changed event now, will be fired after the following change + Wrapped.Name = nn; + return; + } + } + + // This fires the changed event + base.EmitNotify (propertyName); + + string on = oldName; + oldName = Wrapped.Name; + if (!Loading) + OnNameChanged (new WidgetNameChangedArgs (this, on, Wrapped.Name)); + + // Keep the member name in sync with the widget name + if (on == MemberName) + MemberName = Wrapped.Name; + } + } + else if (propertyName == "MemberName") { + if (MemberName != oldMemberName) { + base.EmitNotify (propertyName); + string on = oldMemberName; + oldMemberName = MemberName; + if (!Loading) + OnMemberNameChanged (new WidgetNameChangedArgs (this, on, MemberName)); + } + } + else { +// Console.WriteLine ("PROP: " + propertyName); + base.EmitNotify (propertyName); + } + } + + protected virtual void OnNameChanged (WidgetNameChangedArgs args) + { + if (Project != null) + Project.NotifyNameChanged (args); + if (NameChanged != null) + NameChanged (this, args); + } + + protected virtual void OnMemberNameChanged (WidgetNameChangedArgs args) + { + if (MemberNameChanged != null) + MemberNameChanged (this, args); + } + + bool IEditableObject.CanCopy { + get { return ClipboardCanCopy; } + } + + bool IEditableObject.CanCut { + get { return ClipboardCanCut; } + } + + bool IEditableObject.CanPaste { + get { return ClipboardCanPaste; } + } + + bool IEditableObject.CanDelete { + get { return CanDelete; } + } + + void IEditableObject.Copy () + { + ClipboardCopy (); + } + + void IEditableObject.Cut () + { + ClipboardCut (); + } + + void IEditableObject.Paste () + { + ClipboardPaste (); + } + + void IEditableObject.Delete () + { + Delete (); + } + + protected virtual bool ClipboardCanCopy { + get { return !IsTopLevel; } + } + + protected virtual bool ClipboardCanCut { + get { return InternalChildProperty == null && !IsTopLevel; } + } + + protected virtual bool ClipboardCanPaste { + get { return false; } + } + + protected virtual bool CanDelete { + get { return ClipboardCanCut; } + } + + protected virtual void ClipboardCopy () + { + Clipboard.Copy (Wrapped); + } + + protected virtual void ClipboardCut () + { + Clipboard.Cut (Wrapped); + } + + protected virtual void ClipboardPaste () + { + } + } + + internal static class InsensitiveManager { + + static Gtk.Invisible invis; + static Hashtable map; + + static InsensitiveManager () + { + map = new Hashtable (); + invis = new Gtk.Invisible (); + invis.ButtonPressEvent += ButtonPress; + } + + static void ButtonPress (object obj, Gtk.ButtonPressEventArgs args) + { + Gtk.Widget widget = (Gtk.Widget)map[args.Event.Window]; + if (widget == null) + return; + + Widget wrapper = Widget.Lookup (widget); + args.RetVal = wrapper.HandleClick (args.Event); + } + + public static void Add (Widget wrapper) + { + Gtk.Widget widget = wrapper.Wrapped; + + widget.SizeAllocated += Insensitive_SizeAllocate; + widget.Realized += Insensitive_Realized; + widget.Unrealized += Insensitive_Unrealized; + widget.Mapped += Insensitive_Mapped; + widget.Unmapped += Insensitive_Unmapped; + + if (widget.IsRealized) + Insensitive_Realized (widget, EventArgs.Empty); + if (widget.IsMapped) + Insensitive_Mapped (widget, EventArgs.Empty); + } + + public static void Remove (Widget wrapper) + { + Gtk.Widget widget = wrapper.Wrapped; + Gdk.Window win = (Gdk.Window)map[widget]; + if (win != null) { + map.Remove (widget); + map.Remove (win); + win.Destroy (); + } + widget.SizeAllocated -= Insensitive_SizeAllocate; + widget.Realized -= Insensitive_Realized; + widget.Unrealized -= Insensitive_Unrealized; + widget.Mapped -= Insensitive_Mapped; + widget.Unmapped -= Insensitive_Unmapped; + } + + static void Insensitive_SizeAllocate (object obj, Gtk.SizeAllocatedArgs args) + { + Gdk.Window win = (Gdk.Window)map[obj]; + if (win != null) + win.MoveResize (args.Allocation); + } + + static void Insensitive_Realized (object obj, EventArgs args) + { + Gtk.Widget widget = (Gtk.Widget)obj; + + Gdk.WindowAttr attributes = new Gdk.WindowAttr (); + attributes.WindowType = Gdk.WindowType.Child; + attributes.Wclass = Gdk.WindowClass.InputOnly; + attributes.Mask = Gdk.EventMask.ButtonPressMask; + + Gdk.Window win = new Gdk.Window (widget.GdkWindow, attributes, 0); + win.UserData = invis.Handle; + win.MoveResize (widget.Allocation); + + map[widget] = win; + map[win] = widget; + } + + static void Insensitive_Mapped (object obj, EventArgs args) + { + Gdk.Window win = (Gdk.Window)map[obj]; + win.Show (); + } + + static void Insensitive_Unmapped (object obj, EventArgs args) + { + Gdk.Window win = (Gdk.Window)map[obj]; + win.Hide (); + } + + static void Insensitive_Unrealized (object obj, EventArgs args) + { + Gdk.Window win = (Gdk.Window)map[obj]; + win.Destroy (); + map.Remove (obj); + map.Remove (win); + } + } +} diff --git a/main/src/addins/MonoDevelop.GtkCore2/libstetic/wrapper/WidgetEventHandler.cs b/main/src/addins/MonoDevelop.GtkCore2/libstetic/wrapper/WidgetEventHandler.cs new file mode 100644 index 0000000000..e6af45e1f6 --- /dev/null +++ b/main/src/addins/MonoDevelop.GtkCore2/libstetic/wrapper/WidgetEventHandler.cs @@ -0,0 +1,33 @@ +using System; + +namespace Stetic.Wrapper +{ + public delegate void WidgetEventHandler (object sender, WidgetEventArgs args); + + public class WidgetEventArgs: EventArgs + { + Stetic.Wrapper.Widget wrapper; + Gtk.Widget widget; + + public WidgetEventArgs (Gtk.Widget widget) + { + this.widget = widget; + wrapper = Stetic.Wrapper.Widget.Lookup (widget); + } + + public WidgetEventArgs (Stetic.Wrapper.Widget wrapper) + { + this.wrapper = wrapper; + if (wrapper != null) + this.widget = wrapper.Wrapped; + } + + public Gtk.Widget Widget { + get { return widget; } + } + + public Widget WidgetWrapper { + get { return wrapper; } + } + } +} diff --git a/main/src/addins/MonoDevelop.GtkCore2/libstetic/wrapper/WidgetNameChangedHandler.cs b/main/src/addins/MonoDevelop.GtkCore2/libstetic/wrapper/WidgetNameChangedHandler.cs new file mode 100644 index 0000000000..0d2df19114 --- /dev/null +++ b/main/src/addins/MonoDevelop.GtkCore2/libstetic/wrapper/WidgetNameChangedHandler.cs @@ -0,0 +1,25 @@ + +namespace Stetic.Wrapper +{ + public delegate void WidgetNameChangedHandler (object sender, WidgetNameChangedArgs args); + + public class WidgetNameChangedArgs: WidgetEventArgs + { + string oldName; + string newName; + + public WidgetNameChangedArgs (Stetic.Wrapper.Widget widget, string oldName, string newName): base (widget) + { + this.oldName = oldName; + this.newName = newName; + } + + public string OldName { + get { return oldName; } + } + + public string NewName { + get { return newName; } + } + } +} diff --git a/main/src/addins/MonoDevelop.GtkCore2/libstetic/wrapper/Window.cs b/main/src/addins/MonoDevelop.GtkCore2/libstetic/wrapper/Window.cs new file mode 100644 index 0000000000..5210e47a42 --- /dev/null +++ b/main/src/addins/MonoDevelop.GtkCore2/libstetic/wrapper/Window.cs @@ -0,0 +1,223 @@ +using GLib; +using System; +using System.CodeDom; +using System.Collections; + +namespace Stetic.Wrapper { + + public class Window : Container { + + public override void Wrap (object obj, bool initialized) + { + TopLevelWindow window = (TopLevelWindow) obj; + RootWrapperName = window.Name; + + //during Wrap RootWrapperName will be set in the children widgets + base.Wrap (obj, initialized); + + if (!initialized) { + if (window.Child is Placeholder) + window.Child.SetSizeRequest (200, 200); + } + + window.DeleteEvent += DeleteEvent; + } + + public static TopLevelWindow CreateInstance ( ) + { + TopLevelWindow t = new TopLevelWindow (); + return t; + } + + public override void Dispose ( ) + { + Wrapped.DeleteEvent -= DeleteEvent; + base.Dispose (); + } + + [ConnectBefore] + void DeleteEvent (object obj, Gtk.DeleteEventArgs args) + { + Wrapped.Hide (); + args.RetVal = true; + } + + public override bool HExpandable { get { return true; } } + public override bool VExpandable { get { return true; } } + + public bool Modal { + get { + return window.Modal; + } + set { + window.Modal = value; + EmitNotify ("Modal"); + } + } + + public Gdk.WindowTypeHint TypeHint { + get { + return window.TypeHint; + } + set { + window.TypeHint = value; + EmitNotify ("TypeHint"); + } + } + + Gtk.WindowType type; + public Gtk.WindowType Type { + get { + return type; + } + set { + type = value; + EmitNotify ("Type"); + } + } + + Gtk.WindowPosition windowPosition; + public Gtk.WindowPosition WindowPosition { + get { + return windowPosition; + } + set { + windowPosition = value; + EmitNotify ("WindowPosition"); + } + } + + ImageInfo icon; + public ImageInfo Icon { + get { + return icon; + } + set { + icon = value; + EmitNotify ("Icon"); + } + } + + TopLevelWindow window { + get { return (TopLevelWindow) Wrapped; } + } + + public string Title { + get { return window.Title; } + set { window.Title = value; EmitNotify ("Title"); } + } + + public bool Resizable + { + get { return window.Resizable; } + set { window.Resizable = value; EmitNotify ("Resizable"); } + } + + bool allowGrow = true; + public bool AllowGrow { + get { return allowGrow; } + set { allowGrow = value; EmitNotify ("AllowGrow"); } + } + + bool allowShrink = false; + public bool AllowShrink { + get { return allowShrink; } + set { allowShrink = value; EmitNotify ("AllowShrink"); } + } + + int defaultWidth = -1; + public int DefaultWidth { + get { return defaultWidth; } + set { defaultWidth = value; EmitNotify ("DefaultWidth"); } + } + + int defaultHeight = -1; + public int DefaultHeight { + get { return defaultHeight; } + set { defaultHeight = value; EmitNotify ("DefaultHeight"); } + } + + bool acceptFocus = true; + public bool AcceptFocus { + get { return acceptFocus; } + set { acceptFocus = value; EmitNotify ("AcceptFocus"); } + } + + bool decorated = true; + public bool Decorated { + get { return decorated; } + set { decorated = value; EmitNotify ("Decorated"); } + } + + bool destroyWithParent; + public bool DestroyWithParent { + get { return destroyWithParent; } + set { destroyWithParent = value; EmitNotify ("DestroyWithParent"); } + } + + Gdk.Gravity gravity = Gdk.Gravity.NorthWest; + public Gdk.Gravity Gravity { + get { return gravity; } + set { gravity = value; EmitNotify ("Gravity"); } + } + + string role; + public string Role { + get { return role; } + set { role = value; EmitNotify ("Role"); } + } + + bool skipPagerHint; + public bool SkipPagerHint { + get { return skipPagerHint; } + set { skipPagerHint = value; EmitNotify ("SkipPagerHint"); } + } + + bool skipTaskbarHint; + public bool SkipTaskbarHint { + get { return skipTaskbarHint; } + set { skipTaskbarHint = value; EmitNotify ("SkipTaskbarHint"); } + } + + bool focusOnMap = true; + public bool FocusOnMap { + get { return focusOnMap; } + set { focusOnMap = value; EmitNotify ("FocusOnMap"); } + } + + internal protected override void GenerateBuildCode (GeneratorContext ctx, CodeExpression var) + { + base.GenerateBuildCode (ctx, var); + + if (DefaultWidth == -1) { + ctx.Statements.Add ( + new CodeAssignStatement ( + new CodePropertyReferenceExpression ( + var, + "DefaultWidth" + ), + new CodePrimitiveExpression (DesignWidth) + ) + ); + } + + if (DefaultHeight == -1) { + ctx.Statements.Add ( + new CodeAssignStatement ( + new CodePropertyReferenceExpression ( + var, + "DefaultHeight" + ), + new CodePrimitiveExpression (DesignHeight) + ) + ); + } + } + + protected override void GeneratePropertySet (GeneratorContext ctx, CodeExpression var, PropertyDescriptor prop) + { + if (prop.Name != "Type") + base.GeneratePropertySet (ctx, var, prop); + } + } +} diff --git a/main/src/addins/MonoDevelop.GtkCore2/libstetic/wrapper/objects.xml b/main/src/addins/MonoDevelop.GtkCore2/libstetic/wrapper/objects.xml new file mode 100644 index 0000000000..9fd1d2a919 --- /dev/null +++ b/main/src/addins/MonoDevelop.GtkCore2/libstetic/wrapper/objects.xml @@ -0,0 +1,2274 @@ +<?xml version="1.0" encoding="utf-8" ?> +<objects xmlns:xsl="http://www.w3.org/1999/XSL/Transform" gtk-version="2.4"> + + <object type="Gtk.Widget,gtk-sharp" wrapper="Stetic.Wrapper.Widget"> + <itemgroups> + <itemgroup label="Common Widget Properties"> + <property name="MemberName" + editor="Stetic.Editor.Identifier" + description="Name of the member to which this widget is bound." /> + <property name="WidthRequest" min="-1" /> + <property name="HeightRequest" min="-1" /> + <property name="Visible" glade-override="true" default="true"/> + <property name="Sensitive" glade-override="true" /> + <property name="Tooltip" label="Tooltip" glade-name="tooltip" + description="Tooltip for this widget" + translatable="true" /> + <property name="CanDefault" /> + <property name="InWindow" internal="true"/> + <property name="HasDefault" glade-override="true"> + <invisible-if name="InWindow" value="false" /> + </property> + <property name="CanFocus" /> + <property name="Events" default="0"/> + <property name="ExtensionEvents" /> + <property name="IsScrollable" internal="true"/> + <property name="ShowScrollbars" label="Show Scrollbars" default="false"> + <invisible-if name="IsScrollable" value="false" /> + </property> + <property name="GeneratePublic" internal="true" default="true"/> + <property name="Name" internal="true" + min="1" + init-with-name="true" + editor="Stetic.Editor.Identifier"/> + </itemgroup> + </itemgroups> + <signals> + <itemgroup label="Common Widget Signals"> + <signal name="AccelCanActivate" /> + <signal name="AccelClosuresChanged" /> + <signal name="ButtonPressEvent" /> + <signal name="ButtonReleaseEvent" /> + <signal name="ChildNotified" /> + <signal name="ClientEvent" /> + <signal name="ConfigureEvent" /> + <signal name="DeleteEvent" /> + <signal name="DestroyEvent" /> + <signal name="DirectionChanged" /> + <signal name="DragBegin" /> + <signal name="DragDataDelete"/> + <signal name="DragDataGet" /> + <signal name="DragDataReceived" /> + <signal name="DragDrop" /> + <signal name="DragEnd" /> + <signal name="DragLeave" /> + <signal name="DragMotion" /> + <signal name="EnterNotifyEvent" /> + <signal name="ExposeEvent" /> + <signal name="Focused" /> + <signal name="FocusGrabbed" /> + <signal name="FocusInEvent" /> + <signal name="FocusOutEvent" /> + <signal name="GrabBrokenEvent" gtk-version="2.8"/> + <signal name="GrabNotify" /> + <signal name="HelpShown" /> + <signal name="Hidden" /> + <signal name="HierarchyChanged" /> + <signal name="KeyPressEvent" /> + <signal name="KeyReleaseEvent" /> + <signal name="LeaveNotifyEvent" /> + <signal name="MapEvent" /> + <signal name="Mapped" /> + <signal name="MnemonicActivated" /> + <signal name="MotionNotifyEvent" /> + <signal name="NoExposeEvent" /> + <signal name="ParentSet" /> + <signal name="PopupMenu" /> + <signal name="PropertyNotifyEvent" /> + <signal name="ProximityInEvent" /> + <signal name="ProximityOutEvent" /> + <signal name="Realized" /> + <signal name="ScreenChanged" /> + <signal name="ScrollEvent" /> + <signal name="SelectionClearEvent" /> + <signal name="SelectionGet" /> + <signal name="SelectionNotifyEvent" /> + <signal name="SelectionReceived" /> + <signal name="SelectionRequestEvent" /> + <signal name="Shown" /> + <signal name="SizeAllocated" /> + <signal name="SizeRequested" /> + <signal name="StateChanged" /> + <signal name="StyleSet" /> + <signal name="UnmapEvent" /> + <signal name="Unmapped" /> + <signal name="Unrealized" /> + <signal name="VisibilityNotifyEvent" /> + <signal name="WidgetEvent" /> + <signal name="WidgetEventAfter" /> + <signal name="WindowStateEvent" /> + </itemgroup> + </signals> + + <glade-transform> + <!-- "events" property has extra spaces around "|"s --> + <import> + <xsl:template match="widget/property[@name='events']/text()"> + <xsl:call-template name="GtkWidget_fixevents2"> + <xsl:with-param name="string" select="." /> + </xsl:call-template> + </xsl:template> + <xsl:template name="GtkWidget_fixevents2"> + <xsl:param name="string"/> + <xsl:choose> + <xsl:when test="contains($string, ' | ')"> + <xsl:value-of select="substring-before($string, ' | ')"/> + <xsl:text>|</xsl:text> + <xsl:call-template name="GtkWidget_fixevents2"> + <xsl:with-param name="string" select="substring-after($string, ' | ')"/> + </xsl:call-template> + </xsl:when> + <xsl:otherwise> + <xsl:value-of select="$string" /> + </xsl:otherwise> + </xsl:choose> + </xsl:template> + </import> + <export> + <xsl:template match="widget/property[@name='events']/text()"> + <xsl:call-template name="GtkWidget_breakevents2"> + <xsl:with-param name="string" select="." /> + </xsl:call-template> + </xsl:template> + <xsl:template name="GtkWidget_breakevents2"> + <xsl:param name="string"/> + <xsl:choose> + <xsl:when test="contains($string, '|')"> + <xsl:value-of select="substring-before($string, '|')"/> + <xsl:text> | </xsl:text> + <xsl:call-template name="GtkWidget_breakevents2"> + <xsl:with-param name="string" select="substring-after($string, '|')"/> + </xsl:call-template> + </xsl:when> + <xsl:otherwise> + <xsl:value-of select="$string" /> + </xsl:otherwise> + </xsl:choose> + </xsl:template> + </export> + </glade-transform> + </object> + + <object type="Gtk.Container,gtk-sharp" wrapper="Stetic.Wrapper.Container" base-type="Gtk.Widget"> + <itemgroups> + <itemgroup name="Commands"> + <command name="IncreaseBorderWidth" label="Increase Border Width" icon="res:inc-border.png" /> + <command name="DecreaseBorderWidth" label="Decrease Border Width" icon="res:dec-border.png" /> + </itemgroup> + </itemgroups> + <signals> + <itemgroup label="Container Signals"> + <signal name="Added" /> + <signal name="FocusChildSet" /> + <signal name="Removed" /> + <signal name="ResizeChecked" /> + </itemgroup> + </signals> + </object> + + <object type="Gtk.Container+ContainerChild,gtk-sharp" wrapper="Stetic.Wrapper.Container+ContainerChild" /> + + <object type="Gtk.Window,gtk-sharp" base-type="Gtk.Container" wrapper="Stetic.Wrapper.Window" + label="Window" icon="window.png" palette-category="window" init-properties="Type"> + <itemgroups> + <itemgroup label="Window Properties"> + <property name="Title" init-with-name="true" translatable="true" /> + <property name="Icon" /> + <property name="Type" glade-override="true" internal="true" /> + <property name="TypeHint" glade-override="true" /> + <property name="WindowPosition" /> + <property name="Modal" glade-override="true" default="false" /> + <property name="BorderWidth" default="0"/> + </itemgroup> + <itemgroup label="Window Size Properties" name="Size"> + <property name="Resizable" default="true"/> + <property name="AllowGrow" default="true"/> + <property name="AllowShrink" default="false"/> + <property name="DefaultWidth" min="-1"/> + <property name="DefaultHeight" min="-1"/> + </itemgroup> + <itemgroup label="Miscellaneous Window Properties" name="Misc"> + <property name="AcceptFocus" default="true"/> + <property name="Decorated" default="true"/> + <property name="DestroyWithParent" default="false"/> + <property name="Gravity" default="NorthWest"/> + <property name="Role" /> + <property name="SkipPagerHint" default="false"/> + <property name="SkipTaskbarHint" default="false"/> + <property name="FocusOnMap" gtk-version="2.6"/> + </itemgroup> + </itemgroups> + <signals> + <itemgroup label="Window Signals"> + <signal name="DefaultActivated" /> + <signal name="FrameEvent" /> + <signal name="FocusActivated" /> + <signal name="KeysChanged" /> + <signal name="MoveFocus" /> + <signal name="SetFocus" /> + </itemgroup> + </signals> + </object> + + <object type="Gtk.Misc,gtk-sharp" wrapper="Stetic.Wrapper.Misc" base-type="Gtk.Widget"> + <itemgroups> + <itemgroup label="Miscellaneous Alignment Properties"> + <property name="Xpad" /> + <property name="Ypad" /> + <property name="Xalign" min="0.0" max="1.0" /> + <property name="Yalign" min="0.0" max="1.0" /> + <command name="AlignLeft" label="Align Left" icon="gtk-justify-left" /> + <command name="AlignCenter" label="Align Center" icon="gtk-justify-center" /> + <command name="AlignRight" label="Align Right" icon="gtk-justify-right" /> + </itemgroup> + </itemgroups> + </object> + + <object type="Gtk.Paned,gtk-sharp" wrapper="Stetic.Wrapper.Paned" base-type="Gtk.Container"> + <itemgroups> + <itemgroup label="Pane Properties"> + <property name="Position" /> + <property name="BorderWidth" /> + </itemgroup> + </itemgroups> + <signals> + <itemgroup label="Paned Signals"> + <signal name="CycleChildFocus" /> + <signal name="ToggleHandleFocus" /> + <signal name="AcceptPosition" /> + <signal name="CancelPosition" /> + <signal name="MoveHandle" /> + </itemgroup> + </signals> + </object> + <object type="Gtk.Paned+PanedChild,gtk-sharp"> + <itemgroups> + <itemgroup label="Pane Child Layout"> + <property name="Resize" /> + <property name="Shrink" /> + </itemgroup> + </itemgroups> + </object> + + <object type="Gtk.Range,gtk-sharp" wrapper="Stetic.Wrapper.Range" base-type="Gtk.Widget"> + <itemgroups> + <itemgroup label="Range Properties"> + <property name="UpdatePolicy" /> + <property name="Inverted" /> + <property name="Adjustment.Lower" /> + <property name="Adjustment.Upper" /> + <property name="Adjustment.PageIncrement" /> + <property name="Adjustment.PageSize" /> + <property name="Adjustment.StepIncrement" /> + <property name="Adjustment.Value" /> + </itemgroup> + </itemgroups> + <signals> + <itemgroup label="Range Signals"> + <signal name="AdjustBounds" /> + <signal name="ValueChanged" /> + <signal name="MoveSlider" /> + <signal name="ChangeValue" gtk-version="2.6"/> + </itemgroup> + </signals> + </object> + + <object type="Gtk.Scale,gtk-sharp" wrapper="Stetic.Wrapper.Scale" base-type="Gtk.Range"> + <itemgroups> + <itemgroup label="Scale Properties"> + <property name="DrawValue" ignore-default="true" /> + <property name="Digits"> + <disabled-if name="DrawValue" value="false" /> + </property> + <property name="ValuePos" ignore-default="true" > + <disabled-if name="DrawValue" value="false" /> + </property> + </itemgroup> + </itemgroups> + <signals> + <itemgroup label="Scale Signals"> + <signal name="FormatValue" /> + </itemgroup> + </signals> + </object> + + <object type="Gtk.Alignment,gtk-sharp" base-type="Gtk.Container" label="Alignment" icon="alignment.png" + init-properties="Xalign Yalign Xscale Yscale" palette-category="container"> + <itemgroups> + <itemgroup label="Alignment Properties"> + <property name="Xscale" /> + <property name="Yscale" /> + <property name="Xalign" /> + <property name="Yalign" /> + <property name="LeftPadding" /> + <property name="TopPadding" /> + <property name="RightPadding" /> + <property name="BottomPadding" /> + <property name="BorderWidth" /> + </itemgroup> + </itemgroups> + </object> + + <object type="Gtk.Arrow,gtk-sharp" base-type="Gtk.Misc" + label="Arrow" icon="arrow.png" palette-category="widget" init-properties="ArrowType ShadowType"> + <itemgroups> + <itemgroup label="Arrow Properties"> + <property name="ArrowType" /> + <property name="ShadowType" /> + </itemgroup> + </itemgroups> + </object> + + <object type="Gtk.Bin,gtk-sharp" base-type="Gtk.Container" wrapper="Stetic.Wrapper.Bin" + label="Bin" icon="custom.png"> + </object> + + <object type="Gtk.Box,gtk-sharp" wrapper="Stetic.Wrapper.Box" base-type="Gtk.Container"> + <itemgroups> + <itemgroup label="Box Properties"> + <property name="Homogeneous" /> + <property name="Spacing" /> + <property name="BorderWidth" /> + </itemgroup> + </itemgroups> + <contextmenu> + <command name="InsertBefore" label="Insert Before" + description="Insert an empty row/column before the selected one"> + <invisible-if check="ChildrenAllowed" /> + </command> + + <command name="InsertAfter" label="Insert After" + description="Insert an empty row/column after the selected one"> + <invisible-if check="ChildrenAllowed" /> + </command> + </contextmenu> + </object> + + <object type="Gtk.Box+BoxChild,gtk-sharp" wrapper="Stetic.Wrapper.Box+BoxChild"> + <itemgroups> + <itemgroup label="Box Child Layout"> + <property name="PackType" /> + <property name="Position" ignore-default="true"/> + <property name="AutoSize" label="Auto Size" + description="If set, the other packing properties for this cell will be automatically adjusted as other widgets are added to and removed from the container" /> + <property name="Expand"> + <disabled-if name="AutoSize" value="true" /> + </property> + <property name="Fill"> + <disabled-if name="AutoSize" value="true" /> + <disabled-if name="Expand" value="false" /> + </property> + <property name="Padding" /> + <command name="BoxExpand" label="Expand" icon="res:box-expand.png" /> + <command name="BoxFill" label="Fill" icon="res:box-fill.png" /> + </itemgroup> + </itemgroups> + </object> + + <object type="Gtk.ButtonBox,gtk-sharp" base-type="Gtk.Box" wrapper="Stetic.Wrapper.ButtonBox"> + <itemgroups> + <itemgroup label="Button Box Properties"> + <property name="Size" label="Size" + description="The number of buttons" + min="0" /> + <property name="LayoutStyle" /> + </itemgroup> + </itemgroups> + <contextmenu> + <command name="InsertBefore" label="Insert Button Before" + description="Insert a new button before the selected one" > + <invisible-if check="ChildrenAllowed" /> + </command> + <command name="InsertAfter" label="Insert Button After" + description="Insert a new button after the selected one"> + <invisible-if check="ChildrenAllowed" /> + </command> + </contextmenu> + </object> + <object type="Gtk.ButtonBox+ButtonBoxChild,gtk-sharp" wrapper="Stetic.Wrapper.ButtonBox+ButtonBoxChild"> + <itemgroups> + <itemgroup label="Button Box Child Layout"> + <property name="InDialog" internal="true" /> + <property name="Secondary"> + <invisible-if name="InDialog" value="true" /> + </property> + <property name="Position" /> + <property name="Expand" /> + <property name="Fill"> + <disabled-if name="Expand" value="false" /> + </property> + <property name="Padding" /> + </itemgroup> + </itemgroups> + </object> + + <object type="Gtk.Button,gtk-sharp" wrapper="Stetic.Wrapper.Button" base-type="Gtk.Container" + label="Button" icon="button.png" palette-category="widget"> + <itemgroups> + <itemgroup label="Button Properties"> + <property name="UseStock" internal="true" /> + <property name="Type" label="Button Type" + description="The type of button" /> + <property name="StockId" label="Stock Item" + description="The stock button ID" + editor="Stetic.Editor.StockItem"> + <invisible-if name="Type" value="TextOnly" /> + <invisible-if name="Type" value="TextAndIcon" /> + <invisible-if name="Type" value="Custom" /> + </property> + <property name="Icon" label="Icon" + description="The icon to display in the button" + editor="Stetic.Editor.ImageSelector"> + <invisible-if name="Type" value="StockItem" /> + <invisible-if name="Type" value="TextOnly" /> + <invisible-if name="Type" value="Custom" /> + </property> + <property name="Label" translatable="true"> + <invisible-if name="Type" value="StockItem" /> + <invisible-if name="Type" value="Custom" /> + </property> + <property name="UseUnderline"> + <invisible-if name="Type" value="StockItem" /> + <invisible-if name="Type" value="Custom" /> + </property> + <property name="IsDialogButton" internal="true" /> + <property name="ResponseId" label="Response Id" glade-name="response_id" + description="The response ID to emit when this button is clicked." + editor="Stetic.Editor.ResponseId"> + <invisible-if name="IsDialogButton" value="false" /> + </property> + </itemgroup> + <itemgroup label="Extra Button Properties" name="Extra"> + <property name="FocusOnClick" /> + <property name="Relief" /> + <property name="Xalign" /> + <property name="Yalign" /> + <property name="BorderWidth" /> + </itemgroup> + </itemgroups> + <signals> + <itemgroup label="Button Signals"> + <signal name="Activated" /> + <signal name="Clicked" /> + <signal name="Entered" /> + <signal name="Left" /> + <signal name="Pressed" /> + <signal name="Released" /> + </itemgroup> + </signals> + </object> + + <object type="Gtk.Calendar,gtk-sharp" base-type="Gtk.Widget" + label="Calendar" icon="calendar.png" palette-category="widget"> + <itemgroups> + <itemgroup label="Calendar Properties"> + <property name="DisplayOptions" glade-name="display_options" internal="true" /> + <property name="ShowHeading" /> + <property name="ShowDayNames" /> + <property name="ShowWeekNumbers" /> + <property name="NoMonthChange" /> + </itemgroup> + </itemgroups> + <signals> + <itemgroup label="Calendar Signals"> + <signal name="PrevMonth" /> + <signal name="DaySelected" /> + <signal name="NextMonth" /> + <signal name="MonthChanged" /> + <signal name="PrevYear" /> + <signal name="DaySelectedDoubleClick" /> + <signal name="NextYear" /> + </itemgroup> + </signals> + </object> + + <object type="Gtk.ToggleButton,gtk-sharp" base-type="Gtk.Button" + label="Toggle Button" icon="togglebutton.png" palette-category="widget"> + <itemgroups> + <itemgroup label="Toggle Button Properties"> + <property name="Active" /> + <property name="Inconsistent" /> + </itemgroup> + </itemgroups> + <signals> + <itemgroup label="Toggle Button Signals"> + <signal name="Toggled" /> + </itemgroup> + <itemgroup ref="Gtk.Button" /> + </signals> + </object> + + <object type="Gtk.CheckButton,gtk-sharp" wrapper="Stetic.Wrapper.CheckButton" + label="Check Box" icon="checkbutton.png" palette-category="widget" + hexpandable="true" base-type="Gtk.Container"> + <itemgroups> + <itemgroup label="Check Box Properties"> + <property name="Label" init-with-name="true" translatable="true" /> + <property name="Active" /> + <property name="Inconsistent" /> + <property name="DrawIndicator" ignore-default="true"/> + <property name="HasLabel" internal="true" /> + <property name="UseUnderline" /> + <command name="RestoreLabel" label="Restore Label" icon="res:add-check-label.png" + description="Restore the button's label"> + <disabled-if name="HasLabel" value="true" /> + </command> + <command name="RemoveLabel" label="Remove Label" icon="res:remove-check-label.png" + description="Remove the button's label"> + <disabled-if name="HasLabel" value="false" /> + </command> + </itemgroup> + <itemgroup ref="Gtk.Button.Extra" /> + </itemgroups> + <signals> + <itemgroup ref="Gtk.Button" /> + <itemgroup ref="Gtk.ToggleButton" /> + </signals> + <contextmenu> + <command ref="RemoveLabel" /> + <command ref="RestoreLabel" /> + </contextmenu> + </object> + + <object type="Gtk.MenuItem,gtk-sharp" wrapper="Stetic.Wrapper.MenuItem" + label="Menu Item"> + <itemgroups> + <itemgroup label="Menu Item Properties"> + <property name="Label" translatable="true" glade-name="label" label="Label" + description="The text of the menu item" /> + <property name="UseUnderline" glade-name="use_underline" label="Use Underline" + description="If set, an underline in the text indicates the next character should be used for the mnemonic accelerator key" /> + <property name="HasSubmenu" internal="true" /> + <property name="Accelerator" editor="Stetic.Editor.Accelerator"> + <disabled-if name="HasSubmenu" value="true" /> + </property> + </itemgroup> + <itemgroup ref="Gtk.Widget" /> + </itemgroups> + <signals> + <itemgroup label="Menu Item Signals"> + <signal name="Activated" /> + <signal name="ActivateItem" /> + <signal name="Deselected" /> + <signal name="Selected" /> + <signal name="Toggled" /> + <signal name="ToggleSizeAllocated" /> + <signal name="ToggleSizeRequested" /> + </itemgroup> + <itemgroup ref="Gtk.Widget" /> + <itemgroup ref="Gtk.Container" /> + </signals> + + <glade-transform> + <!-- A regular MenuItem with no label is really a SeparatorMenuItem --> + <import> + <xsl:template match="widget[@class='GtkMenuItem']"> + <xsl:choose> + <xsl:when test="not(property[@name='label']) and not(property[@name='stock_item'])"> + <widget class="GtkSeparatorMenuItem"> + <xsl:attribute name="id"><xsl:value-of select="@id" /></xsl:attribute> + <xsl:apply-templates select="node()" /> + </widget> + </xsl:when> + <xsl:otherwise> + <xsl:copy> + <xsl:apply-templates select="@*|node()" /> + </xsl:copy> + </xsl:otherwise> + </xsl:choose> + </xsl:template> + </import> + </glade-transform> + </object> + + <object type="Gtk.CheckMenuItem,gtk-sharp" label="Check Menu Item"> + <itemgroups> + <itemgroup label="Check Menu Item Properties"> + <property ref="Gtk.MenuItem.Label" /> + <property ref="Gtk.MenuItem.UseUnderline" /> + <property ref="Gtk.MenuItem.Accelerator" /> + <property name="Active" /> + <property name="Inconsistent" /> + </itemgroup> + <itemgroup ref="Gtk.Widget" /> + </itemgroups> + <signals> + <itemgroup label="Check Menu Item Signals"> + <signal name="Toggled" /> + </itemgroup> + <itemgroup ref="Gtk.Widget" /> + <itemgroup ref="Gtk.Container" /> + <itemgroup ref="Gtk.MenuItem" /> + </signals> + </object> + + <object type="Gtk.ColorButton,gtk-sharp" wrapper="Stetic.Wrapper.ColorButton" + label="Color Button" icon="colorbutton.png" palette-category="widget" base-type="Gtk.Container"> + <itemgroups> + <itemgroup label="Color Button Properties"> + <property name="Title" translatable="true" /> + <property name="UseAlpha" internal="true" /> + <property name="Alpha" min="-1" max="65535" /> + </itemgroup> + <itemgroup ref="Gtk.Button.Extra" /> + </itemgroups> + <signals> + <itemgroup label="Color Button Signals"> + <signal name="ColorSet" /> + </itemgroup> + <itemgroup ref="Gtk.Button" /> + </signals> + </object> + + <object type="Gtk.ComboBox,gtk-sharp" wrapper="Stetic.Wrapper.ComboBox" + label="Combo Box" icon="combo.png" palette-category="widget" base-type="Gtk.Container"> + <itemgroups> + <itemgroup label="Combo Box Properties"> + <property name="IsTextCombo" label="Text ComboBox" + description="Checked if the combo box displays a list of strings" /> + <property name="Items" translatable="true" label="Items" glade-name="items" + description="The items to display in the Combo Box, one per line" + editor="Stetic.Editor.StringArray"> + <disabled-if name="IsTextCombo" value="false" /> + </property> + <property name="Active" min="-1" default="-1"/> + <property name="HasFrame" gtk-version="2.6"/> + <property name="AddTearoffs" gtk-version="2.6"/> + <property name="FocusOnClick" gtk-version="2.6"/> + </itemgroup> + </itemgroups> + <signals> + <itemgroup label="ComboBox Signals"> + <signal name="Changed" /> + <signal name="EditingDone" gtk-version="2.6"/> + <signal name="WidgetRemoved" gtk-version="2.6"/> + </itemgroup> + </signals> + </object> + + <object type="Gtk.ComboBoxEntry,gtk-sharp" wrapper="Stetic.Wrapper.ComboBoxEntry" icon="comboentry.png" + label="Combo Box Entry" palette-category="widget" base-type="Gtk.ComboBox"> + </object> + + <object type="Gtk.Dialog,gtk-sharp" wrapper="Stetic.Wrapper.Dialog" + label="Dialog Box" icon="dialog.png" palette-category="window" base-type="Gtk.Window"> + <itemgroups> + <itemgroup label="Dialog Properties"> + <property name="Buttons" label="Number of Buttons" + description="The number of buttons" + min="1" /> + <property name="HelpButton" label="Help Button" + description="Whether or not to display a 'Help' button" /> + <property name="HasSeparator" default="true"/> + </itemgroup> + </itemgroups> + <signals> + <itemgroup label="Dialog Signals"> + <signal name="Close" /> + <signal name="Response" /> + </itemgroup> + </signals> + <internal-children> + <property name="VBox" glade-name="vbox" /> + <property name="ActionArea" glade-name="action_area" /> + </internal-children> + </object> + + <object type="Gtk.DrawingArea,gtk-sharp" base-type="Gtk.Widget" + label="Drawing Area" icon="drawingarea.png" palette-category="widget" + hexpandable="true" vexpandable="true"> + </object> + + <object type="Gtk.Entry,gtk-sharp" base-type="Gtk.Widget" + label="Entry" icon="entry.png" palette-category="widget" + hexpandable="true" wrapper="Stetic.Wrapper.Entry"> + <itemgroups> + <itemgroup label="Entry Properties"> + <property name="Text" translatable="true" /> + <property name="IsEditable" /> + <property name="WidthChars" min="-1"/> + <property name="MaxLength" /> + <property name="HasFrame" /> + <property name="ActivatesDefault" /> + <property name="Visibility" /> + </itemgroup> + <itemgroup label="Extra Entry Properties" name="Extra"> + <property name="InvisibleChar" /> + <property name="Xalign" /> + </itemgroup> + </itemgroups> + <signals> + <itemgroup label="Entry Signals"> + <signal name="InsertAtCursor" /> + <signal name="ToggleOverwrite" /> + <signal name="PopulatePopup" /> + <signal name="ClipboardCopied" /> + <signal name="ClipboardPasted" /> + <signal name="DeleteFromCursor" /> + <signal name="Activated" /> + <signal name="ClipboardCut" /> + <signal name="MoveCursor" /> + <signal name="Changed" /> + <signal name="TextDeleted" /> + <signal name="TextInserted" /> + <signal name="EditingDone" /> + <signal name="WidgetRemoved" /> + <signal name="Backspace" gtk-version="2.6"/> + </itemgroup> + </signals> + </object> + + <object type="Gtk.EventBox,gtk-sharp" base-type="Gtk.Container" + label="Event Box" icon="eventbox.png" palette-category="container"> + <itemgroups> + <itemgroup label="Event Box Properties"> + <property name="AboveChild" /> + <property name="VisibleWindow" /> + <property name="BorderWidth" /> + </itemgroup> + </itemgroups> + </object> + + <object type="Gtk.Expander,gtk-sharp" base-type="Gtk.Container" wrapper="Stetic.Wrapper.Expander" + label="Expander" icon="expander.png" palette-category="container"> + <itemgroups> + <itemgroup label="Expander Properties"> + <property name="Expanded" /> + <property name="Spacing" /> + <property name="BorderWidth" /> + </itemgroup> + </itemgroups> + <signals> + <itemgroup label="Expander Signals"> + <signal name="Activated" /> + </itemgroup> + </signals> + </object> + + <object type="Gtk.Fixed,gtk-sharp" wrapper="Stetic.Wrapper.Fixed" base-type="Gtk.Container" + label="Fixed" icon="fixed.png" palette-category="container"> + <itemgroups> + <itemgroup label="Fixed Properties"> + <property name="HasWindow" /> + </itemgroup> + </itemgroups> + </object> + + <object type="Gtk.Fixed+FixedChild,gtk-sharp" wrapper="Stetic.Wrapper.Fixed+FixedChild"> + <itemgroups> + <itemgroup label="Fixed Child Layout"> + <property name="X" /> + <property name="Y" /> + </itemgroup> + </itemgroups> + </object> + + <object type="Gtk.FontButton,gtk-sharp" wrapper="Stetic.Wrapper.FontButton" + label="Font Button" icon="fontbutton.png" palette-category="widget" base-type="Gtk.Container"> + <itemgroups> + <itemgroup label="Font Button Properties"> + <property name="Title" translatable="true" /> + <property name="FontName" /> + <property name="ShowSize" /> + <property name="ShowStyle" /> + <property name="UseFont" /> + <property name="UseSize"> + <disabled-if name="UseFont" value="false" /> + </property> + </itemgroup> + <itemgroup ref="Gtk.Button.Extra" /> + </itemgroups> + <signals> + <itemgroup label="Font Button Signals"> + <signal name="FontSet" /> + </itemgroup> + <itemgroup ref="Gtk.Button" /> + </signals> + </object> + + <object type="Gtk.Frame,gtk-sharp" wrapper="Stetic.Wrapper.Frame" base-type="Gtk.Container" + label="Frame" icon="frame.png" palette-category="container"> + <itemgroups> + <itemgroup label="Frame Properties"> + <property name="ShadowType" /> + <property name="LabelXalign" /> + <property name="LabelYalign" /> + <property name="BorderWidth" /> + </itemgroup> + </itemgroups> + </object> + + <object type="Gtk.HBox,gtk-sharp" base-type="Gtk.Box" + label="HBox" icon="hbox.png" palette-category="container"> + </object> + + <object type="Gtk.HButtonBox,gtk-sharp" base-type="Gtk.ButtonBox" + label="HButtonBox" icon="hbuttonbox.png" palette-category="container" + hexpandable="true"> + <glade-transform> + <!-- If a child has a "response_id" of -11 (GTK_RESPONSE_HELP), it should be packed with the "secondary" property --> + <import> + <xsl:template match="widget[@class='GtkHButtonBox']/child/widget[@class='GtkButton']"> + <xsl:copy> + <xsl:apply-templates select="@*|node()"/> + </xsl:copy> + <xsl:if test="number (property[@name='response_id']) = -11"> + <packing> + <property name="secondary">True</property> + </packing> + </xsl:if> + </xsl:template> + </import> + </glade-transform> + </object> + + <object type="Gtk.HPaned,gtk-sharp" base-type="Gtk.Paned" + label="HPaned" icon="hpaned.png" palette-category="container" + hexpandable="true"> + </object> + + <object type="Gtk.HScale,gtk-sharp" wrapper="Stetic.Wrapper.HScale" + label="Horizontal Scale" icon="hscale.png" palette-category="widget" + hexpandable="true" base-type="Gtk.Scale"> + </object> + + <object type="Gtk.HScrollbar,gtk-sharp" wrapper="Stetic.Wrapper.HScrollbar" + label="Horizontal Scrollbar" icon="hscrollbar.png" palette-category="widget" + hexpandable="true" base-type="Gtk.Range"> + </object> + + <object type="Gtk.HSeparator,gtk-sharp" base-type="Gtk.Widget" + label="Horizontal Separator" icon="hseparator.png" palette-category="widget" + hexpandable="true"> + </object> + + <object type="Gtk.Image,gtk-sharp" wrapper="Stetic.Wrapper.Image" + label="Image" icon="image.png" palette-category="widget" base-type="Gtk.Misc"> + <itemgroups> + <itemgroup label="Image Properties"> + <property name="Pixbuf" /> + </itemgroup> + </itemgroups> + </object> + + <object type="Gtk.ImageMenuItem,gtk-sharp" wrapper="Stetic.Wrapper.ImageMenuItem" + label="Image Menu Item"> + <itemgroups> + <itemgroup label="Image Menu Item Properties"> + <property name="Image" editor="Stetic.Editor.Image" /> + <property ref="Gtk.MenuItem.Label" /> + <property ref="Gtk.MenuItem.UseUnderline" /> + <property ref="Gtk.MenuItem.Accelerator" /> + </itemgroup> + <itemgroup ref="Gtk.Widget" /> + </itemgroups> + <signals> + <itemgroup ref="Gtk.Widget" /> + <itemgroup ref="Gtk.Container" /> + <itemgroup ref="Gtk.MenuItem" /> + </signals> + </object> + + <object type="Gtk.Label,gtk-sharp" wrapper="Stetic.Wrapper.Label" + label="Label" icon="label.png" palette-category="widget" base-type="Gtk.Misc"> + <itemgroups> + <itemgroup label="Label Properties"> + <property name="LabelProp" init-with-name="true" translatable="true" default=""/> + <property name="UseMarkup" /> + <property name="UseUnderline" /> + <property name="Wrap" /> + <property name="MnemonicWidget" glade-override="true" editor="Stetic.Editor.WidgetSelector" default=""/> + <property name="Justify" /> + <property name="Selectable" /> + <property name="Ellipsize" gtk-version="2.6"/> + <property name="WidthChars" min="-1" gtk-version="2.6" /> + <property name="MaxWidthChars" min="-1" gtk-version="2.6" /> + <property name="SingleLineMode" gtk-version="2.6" /> + <property name="Angle" gtk-version="2.6" /> + </itemgroup> + </itemgroups> + <signals> + <itemgroup label="Label Signals"> + <signal name="CopyClipboard" /> + <signal name="MoveCursor" /> + <signal name="PopulatePopup" /> + </itemgroup> + </signals> + </object> + + <object type="Gtk.MenuBar,gtk-sharp" wrapper="Stetic.Wrapper.MenuBar" + label="Menu Bar" icon="menubar.png" palette-category="widget" base-type="Gtk.Container"> + <itemgroups> + <itemgroup label="MenuBar Properties"> + <property name="PackDirection" gtk-version="2.8" /> + <property name="ChildPackDirection" gtk-version="2.8" /> + </itemgroup> + </itemgroups> + <signals> + <itemgroup label="Menu Bar Signals"> + <signal name="Deactivated" /> + <signal name="SelectionDone" /> + <signal name="MoveCurrent" /> + <signal name="ActivateCurrent" /> + <signal name="Canceled" /> + </itemgroup> + </signals> + </object> + + <object type="Gtk.Menu,gtk-sharp" label="Menu" icon="menu.png" base-type="Gtk.Container"> + <signals> + <itemgroup label="Menu Signals"> + <signal name="Deactivated" /> + <signal name="SelectionDone" /> + <signal name="MoveCurrent" /> + <signal name="ActivateCurrent" /> + <signal name="Canceled" /> + </itemgroup> + </signals> + </object> + <object type="Gtk.Menu+MenuChild,gtk-sharp" /> + +<!-- Code generation not implemented for MessageDialog + + <object type="Stetic.MessageDialog" cname="GtkMessageDialog" wrapper="Stetic.Wrapper.Window" + label="Message Dialog" icon="messagedialog.png" palette-category="window"> + <itemgroups> + <itemgroup label="Message Dialog Properties"> + <property ref="Gtk.Window.Title" /> + <property name="MessageType" label="Message Type" + description="The type of message dialog this is" /> + <property name="PrimaryText" translatable="true" label="Primary Text" + description="The primary message text" /> + <property name="SecondaryText" translatable="true" label="Secondary Text" + description="The secondary message text" /> + <property name="Buttons" label="Buttons" + description="The buttons to offer" /> + <property ref="Gtk.Window.Icon" /> + <property ref="Gtk.Window.WindowPosition" /> + <property ref="Gtk.Window.Modal" /> + <property name="BorderWidth" /> + </itemgroup> + <itemgroup ref="Gtk.Dialog.Misc" /> + <itemgroup ref="Gtk.Window.Size" /> + <itemgroup ref="Gtk.Widget" /> + <itemgroup ref="Gtk.Container.Commands" /> + </itemgroups> + <signals> + <itemgroup ref="Gtk.Widget" /> + <itemgroup ref="Gtk.Container" /> + <itemgroup ref="Gtk.Window" /> + <itemgroup ref="Gtk.Dialog" /> + </signals> + </object> +--> + + <object type="Gtk.Notebook,gtk-sharp" wrapper="Stetic.Wrapper.Notebook" base-type="Gtk.Container" + label="Notebook" icon="notebook.png" palette-category="container"> + <itemgroups> + <itemgroup label="Notebook Properties"> + <property name="CurrentPage" /> + <property name="EnablePopup" /> + <property name="TabPos" /> + <property name="ShowBorder" /> + <property name="ShowTabs" /> + <property name="Scrollable" /> + <property name="BorderWidth" /> + <command name="InsertBefore" label="Insert Page Before" + description="Insert a blank page before this one"> + <invisible-if check="ChildrenAllowed" /> + <disabled-if check="CheckInsertBefore" /> + </command> + <command name="InsertAfter" label="Insert Page After" + description="Insert a blank page after this one" > + <invisible-if check="ChildrenAllowed" /> + </command> + </itemgroup> + </itemgroups> + <signals> + <itemgroup label="Notebook Signals"> + <signal name="FocusTab" /> + <signal name="ChangeCurrentPage" /> + <signal name="MoveFocusOut" /> + <signal name="SwitchPage" /> + <signal name="SelectPage" /> + </itemgroup> + </signals> + <contextmenu> + <command name="PreviousPage" label="Go to Previous Page" + description="Show the previous page"> + <disabled-if check="CheckPreviousPage" /> + </command> + <command name="NextPage" label="Go to Next Page" + description="Show the next page"> + <disabled-if check="CheckNextPage" /> + </command> + <command name="DeletePage" label="Delete Page" + description="Delete the current page"> + <invisible-if check="ChildrenAllowed" /> + <disabled-if check="CheckDeletePage" /> + </command> + <command name="SwapPrevious" label="Swap with Previous Page" + description="Swap the contents of this page with the contents of the previous page"> + <invisible-if check="ChildrenAllowed" /> + <disabled-if check="CheckPreviousPage" /> + </command> + <command name="SwapNext" label="Swap with Next Page" + description="Swap the contents of this page with the contents of the next page"> + <invisible-if check="ChildrenAllowed" /> + <disabled-if check="CheckNextPage" /> + </command> + <command ref="InsertBefore" /> + <command ref="InsertAfter" /> + </contextmenu> + </object> + <object type="Gtk.Notebook+NotebookChild,gtk-sharp"> + <itemgroups> + <itemgroup label="Notebook Child Layout"> + <property name="Position" /> + <property name="TabPack" /> + <property name="TabExpand" /> + <property name="TabFill" /> + <property name="MenuLabel" translatable="true" /> + </itemgroup> + </itemgroups> + </object> + + <object type="Gtk.OptionMenu,gtk-sharp" wrapper="Stetic.Wrapper.OptionMenu" + label="Option Menu" icon="optionmenu.png" deprecated="true" base-type="Gtk.Container"> + <itemgroups> + <itemgroup label="Option Menu Properties"> + <property name="Active" glade-name="history" label="Active" + description="The active menu item" min="0" /> + </itemgroup> + </itemgroups> + <signals> + <itemgroup label="Option Menu Signals"> + <signal name="Changed" /> + </itemgroup> + <itemgroup ref="Gtk.Button" /> + </signals> + <internal-children> + <property name="Menu" glade-name="menu" /> + </internal-children> + </object> + + <object type="Gtk.ProgressBar,gtk-sharp" base-type="Gtk.Widget" + label="Progress Bar" icon="progressbar.png" palette-category="widget" + hexpandable="true"> + <itemgroups> + <itemgroup label="Progress Bar Properties"> + <property name="Orientation" /> + <property name="Text" translatable="true" /> + <property name="Fraction" /> + <property name="PulseStep" /> + <property name="Ellipsize" gtk-version="2.6"/> + </itemgroup> + </itemgroups> + </object> + + <object type="Gtk.RadioButton,gtk-sharp" wrapper="Stetic.Wrapper.RadioButton" + label="Radio Button" icon="radiobutton.png" palette-category="widget" + hexpandable="true" init-properties="Label" base-type="Gtk.CheckButton"> + <itemgroups> + <itemgroup label="Radio Button Properties"> + <property name="Group" label="Group" + description="The name of the radio button group that this button belongs to" + editor="Stetic.Editor.GroupPicker" /> + </itemgroup> + </itemgroups> + <signals> + <itemgroup label="Radio Button Signals"> + <signal name="GroupChanged" /> + </itemgroup> + </signals> + </object> +<!-- + <object type="Gtk.RadioMenuItem,gtk-sharp" wrapper="Stetic.Wrapper.RadioMenuItem" + label="Radio Menu Item"> + <itemgroups> + <itemgroup label="Radio Menu Item Properties"> + <property ref="Gtk.MenuItem.Label" /> + <property ref="Gtk.MenuItem.UseUnderline" /> + <property ref="Gtk.MenuItem.Accelerator" /> + <property name="Group" label="Group" + description="The name of the radio menu item group that this menu item belongs to" + editor="Stetic.Editor.GroupPicker" /> + <property name="Active" /> + <property name="Inconsistent" /> + </itemgroup> + <itemgroup ref="Gtk.Widget" /> + </itemgroups> + <signals> + <itemgroup label="Radio Menu Item Signals"> + <signal name="Toggled" /> + <signal name="GroupChanged" /> + </itemgroup> + <itemgroup ref="Gtk.Widget" /> + <itemgroup ref="Gtk.Container" /> + <itemgroup ref="Gtk.MenuItem" /> + </signals> + </object> + + <object type="Gtk.ToolItem,gtk-sharp" wrapper="Stetic.Wrapper.Widget"> + <signals> + <itemgroup label="Tool Item Signals"> + <signal name="ToolbarReconfigured" /> + <signal name="CreateMenuProxy" /> + <signal name="TooltipSet" /> + </itemgroup> + </signals> + </object> + + <object type="Gtk.ToolButton,gtk-sharp" wrapper="Stetic.Wrapper.ToolButton" + label="Toolbar Button" icon="button.png" palette-category="toolbaritem"> + <itemgroups> + <itemgroup label="Toolbar Button Properties"> + <property name="Type" label="Button Type" + description="The type of button" /> + <property name="StockId" label="Stock Item" + description="The stock button ID" + editor="Stetic.Editor.StockItem"> + <invisible-if name="Type" value="TextAndIcon" /> + </property> + <property name="Icon" label="Icon" + description="The icon to display in the button" + editor="Stetic.Editor.ImageSelector"> + <invisible-if name="Type" value="StockItem" /> + </property> + <property name="Label" translatable="true" /> + <property name="UseUnderline"> + <invisible-if name="Type" value="StockItem" /> + </property> + </itemgroup> + <itemgroup ref="Gtk.Widget" /> + </itemgroups> + <signals> + <itemgroup label="Tool Button Signals"> + <signal name="Clicked" /> + </itemgroup> + <itemgroup ref="Gtk.Widget" /> + <itemgroup ref="Gtk.Container" /> + <itemgroup ref="Gtk.ToolItem" /> + </signals> + </object> + + <object type="Gtk.RadioToolButton,gtk-sharp" wrapper="Stetic.Wrapper.RadioToolButton" + label="Toolbar Radio Button" icon="radiobutton.png" palette-category="toolbaritem"> + <itemgroups> + <itemgroup label="Toolbar Radio Button Properties"> + <property ref="Gtk.ToolButton.Icon" /> + <property ref="Gtk.ToolButton.Label" /> + <property ref="Gtk.ToolButton.UseUnderline" /> + <property name="Group" label="Group" + description="The name of the radio toolbar item group that this toolbar item belongs to" + editor="Stetic.Editor.GroupPicker" /> + <property name="Active" /> + </itemgroup> + <itemgroup ref="Gtk.Widget" /> + </itemgroups> + <signals> + <itemgroup label="Radio Tool Button Signals"> + <signal name="Toggled" /> + <signal name="Clicked" /> + </itemgroup> + <itemgroup ref="Gtk.Widget" /> + <itemgroup ref="Gtk.Container" /> + <itemgroup ref="Gtk.ToolItem" /> + </signals> + </object> +--> + + <object type="Gtk.ScrolledWindow,gtk-sharp" wrapper="Stetic.Wrapper.ScrolledWindow" + label="Scrolled Window" icon="scrolledwindow.png" palette-category="container" + hexpandable="true" vexpandable="true" base-type="Gtk.Container"> + <itemgroups> + <itemgroup label="Scrolled Window Properties"> + <property name="VscrollbarPolicy" default="Automatic" /> + <property name="HscrollbarPolicy" default="Automatic" /> + <property name="ShadowType" /> + <property name="WindowPlacement" /> + <property name="BorderWidth" /> + </itemgroup> + </itemgroups> + <signals> + <itemgroup label="Scrolled Window Signals"> + <signal name="MoveFocusOut" /> + <signal name="ScrollChild" /> + </itemgroup> + </signals> + </object> + + <object type="Gtk.SeparatorMenuItem,gtk-sharp" + label="Separator Menu Item" icon="hseparator.png"> + <itemgroups> + <itemgroup ref="Gtk.Widget" important="false" /> + </itemgroups> + <signals> + <itemgroup ref="Gtk.Widget" /> + <itemgroup ref="Gtk.Container" /> + <itemgroup ref="Gtk.MenuItem" /> + </signals> + </object> + +<!-- <object type="Gtk.SeparatorToolItem,gtk-sharp" + label="Toolbar Separator" icon="vseparator.png" palette-category="toolbaritem"> + <itemgroups> + <itemgroup label="Toolbar Separator Properties"> + <property name="Draw" /> + </itemgroup> + <itemgroup ref="Gtk.Widget" /> + </itemgroups> + <signals> + <itemgroup ref="Gtk.Widget" /> + <itemgroup ref="Gtk.Container" /> + <itemgroup ref="Gtk.ToolItem" /> + </signals> + </object> +--> + + <object type="Gtk.SpinButton,gtk-sharp" wrapper="Stetic.Wrapper.SpinButton" base-type="Gtk.Widget" + label="Spin Button" icon="spinbutton.png" palette-category="widget" init-properties="Lower Upper StepIncrement"> + <itemgroups> + <itemgroup label="Range Properties"> + <property name="Adjustment.Lower" /> + <property name="Adjustment.Upper" /> + <property name="Adjustment.PageIncrement" /> + <property name="Adjustment.PageSize" /> + <property name="Adjustment.StepIncrement" /> + </itemgroup> + <itemgroup label="Spin Button Properties" important="true"> + <property name="ClimbRate" /> + <property name="Digits" /> + <property name="Numeric" /> + <property name="SnapToTicks" /> + <property name="UpdatePolicy" /> + <property name="Value" /> + <property name="Wrap" /> + </itemgroup> + </itemgroups> + <signals> + <itemgroup label="Spin Button Signals"> + <signal name="ChangeValue" /> + <signal name="Input" /> + <signal name="ValueChanged" /> + <signal name="Output" /> + </itemgroup> + <itemgroup ref="Gtk.Entry" /> + </signals> + </object> + + <object type="Gtk.Statusbar,gtk-sharp" base-type="Gtk.HBox" + label="Statusbar" icon="statusbar.png" palette-category="widget" + hexpandable="true"> + <itemgroups> + <itemgroup label="Status Bar Properties"> + <property name="HasResizeGrip" /> + </itemgroup> + </itemgroups> + <signals> + <itemgroup label="Statusbar Signals"> + <signal name="TextPopped" /> + <signal name="TextPushed" /> + </itemgroup> + </signals> + </object> + + <object type="Gtk.Table,gtk-sharp" wrapper="Stetic.Wrapper.Table" base-type="Gtk.Container" + label="Table" icon="table.png" palette-category="container" init-properties="NRows NColumns Homogeneous"> + <itemgroups> + <itemgroup label="Table Properties"> + <property name="NRows" min="1"/> + <property name="NColumns" min="1"/> + <property name="Homogeneous" /> + <property name="RowSpacing" /> + <property name="ColumnSpacing" /> + <property name="BorderWidth" /> + </itemgroup> + </itemgroups> + <contextmenu> + <command name="InsertRowBefore" label="Insert Row Before" + description="Insert an empty row above the selected row"> + <invisible-if check="ChildrenAllowed" /> + </command> + <command name="InsertRowAfter" label="Insert Row After" + description="Insert an empty row below the selected row"> + <invisible-if check="ChildrenAllowed" /> + </command> + <command name="InsertColumnBefore" label="Insert Column Before" + description="Insert an empty column before the selected column"> + <invisible-if check="ChildrenAllowed" /> + </command> + <command name="InsertColumnAfter" label="Insert Column After" + description="Insert an empty column after the selected column"> + <invisible-if check="ChildrenAllowed" /> + </command> + <command name="DeleteRow" label="Delete Row" + description="Delete the selected row"> + <invisible-if check="ChildrenAllowed" /> + </command> + <command name="DeleteColumn" label="Delete Column" + description="Delete the selected column"> + <invisible-if check="ChildrenAllowed" /> + </command> + </contextmenu> + + <glade-transform> + <!-- Child packing options are non-standard ("expand" instead of "GTK_EXPAND") --> + <import> + <xsl:template match="widget[@class='GtkTable']/child/packing/property[@name='x_options' or @name='y_options']/text()"> + <xsl:call-template name="GtkTable_fixoptions2"> + <xsl:with-param name="string" select="." /> + </xsl:call-template> + </xsl:template> + <xsl:template name="GtkTable_fixoptions2"> + <xsl:param name="string"/> + <xsl:choose> + <xsl:when test="contains($string, '|')"> + <xsl:call-template name="GtkTable_fixoptions2"> + <xsl:with-param name="string" select="substring-before($string, '|')"/> + </xsl:call-template> + <xsl:text>|</xsl:text> + <xsl:call-template name="GtkTable_fixoptions2"> + <xsl:with-param name="string" select="substring-after($string, '|')"/> + </xsl:call-template> + </xsl:when> + <xsl:otherwise> + <xsl:text>GTK_</xsl:text> + <xsl:value-of select="translate($string,'abcdefghijklmnopqrstuvwxyz','ABCDEFGHIJKLMNOPQRSTUVWXYZ')"/> + </xsl:otherwise> + </xsl:choose> + </xsl:template> + </import> + <export> + <xsl:template match="widget[@class='GtkTable']/child/packing/property[@name='x_options' or @name='y_options']/text()"> + <xsl:call-template name="GtkTable_breakoptions2"> + <xsl:with-param name="options" select="." /> + </xsl:call-template> + </xsl:template> + <xsl:template name="GtkTable_breakoptions2"> + <xsl:param name="string"/> + <xsl:choose> + <xsl:when test="contains($string, '|')"> + <xsl:call-template name="GtkTable_breakoptions2"> + <xsl:with-param name="string" select="substring-before($string, '|')"/> + </xsl:call-template> + <xsl:text>|</xsl:text> + <xsl:call-template name="GtkTable_breakoptions2"> + <xsl:with-param name="string" select="substring-after($string, '|')"/> + </xsl:call-template> + </xsl:when> + <xsl:otherwise> + <xsl:value-of select="translate(substring-after($string, 'GTK_'),'ABCDEFGHIJKLMNOPQRSTUVWXYZ','abcdefghijklmnopqrstuvwxyz')"/> + </xsl:otherwise> + </xsl:choose> + </xsl:template> + </export> + </glade-transform> + </object> + <object type="Gtk.Table+TableChild,gtk-sharp" wrapper="Stetic.Wrapper.Table+TableChild"> + <itemgroups> + <itemgroup label="Table Child Layout"> + <property name="TopAttach" /> + <property name="BottomAttach" /> + <property name="LeftAttach" /> + <property name="RightAttach" /> + <property name="XPadding" /> + <property name="YPadding" /> + <property name="AutoSize" label="Auto Size" + description="If set, the other packing properties for this cell will be automatically adjusted as other widgets are added to and removed from the container" /> + <property name="XOptions" internal="true" /> + <property name="YOptions" internal="true" /> + <property name="XExpand" label="Expand Horizontally" + description="Whether or not the table cell should expand horizontally"> + <disabled-if name="AutoSize" value="true" /> + </property> + <property name="XFill" label="Fill Horizontally" + description="Whether or not the widget should expand to fill its cell horizontally"> + <disabled-if name="AutoSize" value="true" /> + <disabled-if name="XExpand" value="true" /> + </property> + <property name="XShrink" label="Shrink Horizontally" + description="Whether or not the table cell should shrink horizontally"> + <disabled-if name="AutoSize" value="true" /> + </property> + <property name="YExpand" label="Expand Vertically" + description="Whether or not the table cell should expand vertically"> + <disabled-if name="AutoSize" value="true" /> + </property> + <property name="YFill" label="Fill Vertically" + description="Whether or not the widget should expand to fill its cell vertically"> + <disabled-if name="AutoSize" value="true" /> + <disabled-if name="YExpand" value="true" /> + </property> + <property name="YShrink" label="Shrink Vertically" + description="Whether or not the table cell should shrink vertically"> + <disabled-if name="AutoSize" value="true" /> + </property> + <command name="CellXExpand" label="Expand Horizontally" icon="res:cell-expand-h.png" /> + <command name="CellXFill" label="Fill Horizontally" icon="res:cell-fill-h.png" /> + <command name="CellYExpand" label="Expand Vertically" icon="res:cell-expand-v.png" /> + <command name="CellYFill" label="Fill Vertically" icon="res:cell-fill-v.png" /> + </itemgroup> + </itemgroups> + </object> + + <object type="Gtk.TextView,gtk-sharp" wrapper="Stetic.Wrapper.TextView" + label="Text View" icon="textview.png" palette-category="widget" + hexpandable="true" vexpandable="true" base-type="Gtk.Container"> + <itemgroups> + <itemgroup label="Text View Properties"> + <property name="Editable" /> + <property name="CursorVisible" /> + <property name="Overwrite" /> + <property name="AcceptsTab" /> + <property name="Tabs" /> + <property name="Text" translatable="true" label="Text" glade-name="text" + description="The initial text to display in the Text View" + editor="Stetic.Editor.Text" /> + <property name="Justification" /> + <property name="WrapMode" /> + <property name="PixelsAboveLines" /> + <property name="PixelsBelowLines" /> + <property name="PixelsInsideWrap" /> + <property name="LeftMargin" /> + <property name="RightMargin" /> + <property name="Indent" /> + </itemgroup> + </itemgroups> + <signals> + <itemgroup label="Text View Signals"> + <signal name="PasteClipboard" /> + <signal name="InsertAtCursor" /> + <signal name="CutClipboard" /> + <signal name="ToggleOverwrite" /> + <signal name="PageHorizontally" /> + <signal name="MoveFocus" /> + <signal name="CopyClipboard" /> + <signal name="DeleteFromCursor" /> + <signal name="PopulatePopup" /> + <signal name="MoveCursor" /> + <signal name="SetAnchor" /> + <signal name="ScrollAdjustmentsSet" /> + <signal name="Backspace" gtk-version="2.6"/> + </itemgroup> + </signals> + </object> + +<!-- <object type="Gtk.ToggleToolButton,gtk-sharp" wrapper="Stetic.Wrapper.ToggleToolButton" + label="Toolbar Toggle Button" icon="checkbutton.png" palette-category="toolbaritem"> + <itemgroups> + <itemgroup label="Toolbar Toggle Button Properties"> + <property ref="Gtk.ToolButton.Icon" /> + <property ref="Gtk.ToolButton.Label" /> + <property ref="Gtk.ToolButton.UseUnderline" /> + <property name="Active" /> + </itemgroup> + <itemgroup ref="Gtk.Widget" /> + </itemgroups> + <signals> + <itemgroup label="Toggle Tool Button Signals"> + <signal name="Toggled" /> + <signal name="Clicked" /> + </itemgroup> + <itemgroup ref="Gtk.Widget" /> + <itemgroup ref="Gtk.Container" /> + <itemgroup ref="Gtk.ToolItem" /> + </signals> + </object> +--> + <object type="Gtk.Toolbar,gtk-sharp" wrapper="Stetic.Wrapper.ActionToolbarWrapper" + label="Toolbar" icon="toolbar.png" palette-category="widget" base-type="Gtk.Container"> + <itemgroups> + <itemgroup label="Tool Bar Properties"> + <property name="Orientation" /> + <property name="ShowArrow" /> + <property name="Tooltips" /> + <property name="ButtonStyle" label="Toolbar style"/> + <property name="ToolbarStyle" ignore-default="true" internal="true"/> + <property name="IconSize" /> + </itemgroup> + </itemgroups> + <signals> + <itemgroup label="Toolbar Signals"> + <signal name="OrientationChanged" /> + <signal name="PopupContextMenu" /> + <signal name="StyleChanged" /> + </itemgroup> + </signals> + </object> +<!-- + <object type="Gtk.Toolbar+ToolbarChild,gtk-sharp" wrapper="Stetic.Wrapper.Toolbar+ToolbarChild"> + <itemgroups> + <itemgroup label="Tool Bar Child Properties"> + <property name="Homogeneous" /> + <property name="Expand" /> + <property name="ToolItem" internal="true" /> + <property name="ToolItem.IsImportant" /> + <property name="ToolItem.VisibleHorizontal" /> + <property name="ToolItem.VisibleVertical" /> + </itemgroup> + </itemgroups> + </object> +--> + <object type="Gtk.TreeView,gtk-sharp" wrapper="Stetic.Wrapper.TreeView" + label="Tree View" icon="treeview.png" palette-category="widget" + hexpandable="true" vexpandable="true" base-type="Gtk.Container"> + <itemgroups> + <itemgroup label="Tree View Properties"> + <property name="EnableSearch" /> + <property name="FixedHeightMode" /> + <property name="HeadersVisible" /> + <property name="Reorderable" /> + <property name="RulesHint" /> + <property name="SearchColumn" min="-1"/> + <property name="Model" /> + <property name="HeadersClickable" gtk-version="2.6" default="true"/> + <property name="HoverSelection" gtk-version="2.6" /> + <property name="HoverExpand" gtk-version="2.6" /> + </itemgroup> + </itemgroups> + <signals> + <itemgroup label="Tree View Signals"> + <signal name="CursorChanged" /> + <signal name="TestCollapseRow" /> + <signal name="RowActivated" /> + <signal name="ExpandCollapseCursorRow" /> + <signal name="ColumnsChanged" /> + <signal name="UnselectAll" /> + <signal name="SelectCursorParent" /> + <signal name="RowCollapsed" /> + <signal name="SelectAll" /> + <signal name="SelectCursorRow" /> + <signal name="TestExpandRow" /> + <signal name="StartInteractiveSearch" /> + <signal name="MoveCursor" /> + <signal name="RowExpanded" /> + <signal name="ToggleCursorRow" /> + <signal name="ScrollAdjustmentsSet" /> + </itemgroup> + </signals> + </object> + + <object type="Gtk.NodeView,gtk-sharp" wrapper="Stetic.Wrapper.TreeView" + label="Node View" icon="treeview.png" palette-category="widget" + hexpandable="true" vexpandable="true" base-type="Gtk.TreeView"> + </object> + + <object type="Gtk.IconView,gtk-sharp" wrapper="Stetic.Wrapper.IconView" + label="Icon View" icon="iconview.png" palette-category="widget" + hexpandable="true" vexpandable="true" base-type="Gtk.Container" gtk-version="2.6"> + <itemgroups> + <itemgroup label="Icon View Properties"> + <property name="Columns" /> + <property name="ColumnSpacing" /> + <property name="ItemWidth" min="-1" /> + <property name="Margin" min="0" /> + <property name="Orientation" /> + <property name="Reorderable" gtk-version="2.8"/> + <property name="RowSpacing" /> + <property name="SelectionMode" /> + <property name="Spacing" /> + </itemgroup> + </itemgroups> + <signals> + <itemgroup label="Icon View Signals"> + <signal name="SelectionChanged" /> + <signal name="AllUnselected" /> + <signal name="ItemActivated" /> + <signal name="AllSelected" /> + <signal name="ToggleCursorItem" /> + <signal name="MoveCursor" /> + <signal name="ActivateCursorItem" /> + <signal name="SelectCursorItem" /> + </itemgroup> + </signals> + </object> + + <object type="Gtk.VBox,gtk-sharp" base-type="Gtk.Box" + label="VBox" icon="vbox.png" palette-category="container"> + </object> + + <object type="Gtk.VButtonBox,gtk-sharp" base-type="Gtk.ButtonBox" + label="VButtonBox" icon="vbuttonbox.png" palette-category="container" + vexpandable="true"> + </object> + + <object type="Gtk.Viewport,gtk-sharp" wrapper="Stetic.Wrapper.Viewport" + label="Viewport" icon="viewport.png" base-type="Gtk.Container"> + <itemgroups> + <itemgroup label="Viewport Properties"> + <property name="ShadowType" /> + </itemgroup> + </itemgroups> + <signals> + <itemgroup label="Viewport Signals"> + <signal name="ScrollAdjustmentsSet" /> + </itemgroup> + </signals> + </object> + + <object type="Gtk.VPaned,gtk-sharp" base-type="Gtk.Paned" + label="VPaned" icon="vpaned.png" palette-category="container" + vexpandable="true"> + </object> + + <object type="Gtk.VScale,gtk-sharp" wrapper="Stetic.Wrapper.VScale" + label="Vertical Scale" icon="vscale.png" palette-category="widget" + vexpandable="true" base-type="Gtk.Scale"> + </object> + + <object type="Gtk.VScrollbar,gtk-sharp" wrapper="Stetic.Wrapper.VScrollbar" + label="Vertical Scrollbar" icon="vscrollbar.png" palette-category="widget" + vexpandable="true" base-type="Gtk.Range"> + </object> + + <object type="Gtk.VSeparator,gtk-sharp" base-type="Gtk.Widget" + label="Vertical Separator" icon="vseparator.png" palette-category="widget" + vexpandable="true"> + </object> + + <object type="Stetic.Custom" cname="Custom" base-type="Gtk.Widget" + label="Custom Widget" icon="custom.png" palette-category="widget"> + <itemgroups> + <itemgroup label="Custom Widget Properties"> + <property name="CreationFunction" glade-name="creation_function" /> + <property name="LastModificationTime" glade-name="last_modification_time" internal="true" /> + <property name="String1" glade-name="string1" /> + <property name="String2" glade-name="string2" /> + <property name="Int1" glade-name="int1" /> + <property name="Int2" glade-name="int2" /> + </itemgroup> + </itemgroups> + </object> + +<!-- 2.6 + <object type="Gtk.AboutDialog,gtk-sharp" wrapper="Stetic.Wrapper.AboutDialog" + label="About Dialog" icon="aboutdialog.png" palette-category="window"> + <itemgroups> + <itemgroup label="About Dialog Properties"> + <property name="Name" translatable="true" /> + <property name="Version" translatable="true" /> + <property name="Logo" glade-override="true" + editor="Stetic.Editor.ImageFile" /> + <property name="Comments" translatable="true" /> + <property name="Copyright" translatable="true" /> + <property name="Website" translatable="true" /> + <property name="WebsiteLabel" translatable="true" /> + <property name="Authors" translatable="true" /> + <property name="Documenters" translatable="true" /> + <property name="Artists" translatable="true" /> + <property name="TranslatorCredits" translatable="true" /> + <property name="License" translatable="true" editor="Stetic.Editor.Text" /> + <property ref="Gtk.Window.Icon" /> + <property ref="Gtk.Window.WindowPosition" /> + <property ref="Gtk.Window.Modal" /> + </itemgroup> + <itemgroup ref="Gtk.Dialog.Misc" /> + <itemgroup ref="Gtk.Window.Size" /> + <itemgroup ref="Gtk.Widget" /> + </itemgroups> + </object> +--> + + <object type="Gtk.ColorSelection,gtk-sharp" wrapper="Stetic.Wrapper.Widget" + label="Color Selection" icon="colorselection.png" palette-category="widget" + hexpandable="true" vexpandable="true" base-type="Gtk.Widget"> + <itemgroups> + <itemgroup label="Color Selection Properties"> + <property name="HasPalette" /> + <property name="HasOpacityControl" /> + </itemgroup> + </itemgroups> + <signals> + <itemgroup label="Color Selection Signals"> + <signal name="ColorChanged" /> + </itemgroup> + </signals> + </object> + + <object type="Gtk.ColorSelectionDialog,gtk-sharp" base-type="Gtk.Dialog" wrapper="Stetic.Wrapper.Dialog" + label="Color Selection Dialog" icon="colorselectiondialog.png" palette-category="window"> + <internal-children> + <property name="ColorSelection" glade-name="color_selection" /> + <property name="OkButton" glade-name="ok_button" /> + <property name="CancelButton" glade-name="cancel_button" /> + <property name="HelpButton" glade-name="help_button" /> + <property name="VBox" glade-name="vbox" /> + <property name="ActionArea" glade-name="action_area" /> + </internal-children> + </object> + + <object type="Gtk.FileChooserWidget,gtk-sharp" wrapper="Stetic.Wrapper.Widget" + label="File Chooser Widget" icon="fileselection.png" palette-category="widget" + hexpandable="true" vexpandable="true" init-properties="Action" base-type="Gtk.Widget"> + <itemgroups> + <itemgroup label="File Chooser Widget Properties"> + <property name="Action" /> + <property name="LocalOnly" /> + <property name="SelectMultiple"> + <disabled-if name="Action" value="Save" /> + <disabled-if name="Action" value="CreateFolder" /> + </property> + <property name="ShowHidden" gtk-version="2.6"/> + <property name="DoOverwriteConfirmation" gtk-version="2.8" /> + </itemgroup> + </itemgroups> + <signals> + <itemgroup label="File Chooser Widget Signals"> + <signal name="SelectionChanged" /> + <signal name="FileActivated" /> + <signal name="UpdatePreview" /> + <signal name="CurrentFolderChanged" /> + <signal name="ConfirmOverwrite" gtk-version="2.8"/> + </itemgroup> + </signals> + </object> + + <object type="Gtk.FileChooserButton,gtk-sharp" wrapper="Stetic.Wrapper.Container" init-properties="Title Action" + label="File Chooser Button" icon="fileselection.png" palette-category="widget" + hexpandable="true" base-type="Gtk.Container" gtk-version="2.6"> + <itemgroups> + <itemgroup label="File Chooser Button Properties"> + <property name="Title" translatable="true" /> + <property name="Action" /> + <property name="LocalOnly" /> + <property name="SelectMultiple"> + <disabled-if name="Action" value="Save" /> + <disabled-if name="Action" value="CreateFolder" /> + </property> + <property name="WidthChars" min="-1"/> + <property name="ShowHidden" gtk-version="2.6"/> + <property name="DoOverwriteConfirmation" gtk-version="2.8" /> + </itemgroup> + </itemgroups> + <signals> + <itemgroup label="File Chooser Button Signals"> + <signal name="SelectionChanged" /> + <signal name="FileActivated" /> + <signal name="UpdatePreview" /> + <signal name="CurrentFolderChanged" /> + <signal name="ConfirmOverwrite" gtk-version="2.8"/> + </itemgroup> + </signals> + </object> + + <object type="Gtk.FileChooserDialog,gtk-sharp" base-type="Gtk.Dialog" + label="File Chooser Dialog" icon="fileselection.png" palette-category="window"> + <itemgroups> + <itemgroup label="File Chooser Dialog Properties"> + <property name="Action" /> + <property name="LocalOnly" /> + <property name="SelectMultiple"> + <disabled-if name="Action" value="Save" /> + <disabled-if name="Action" value="CreateFolder" /> + </property> + <property name="ShowHidden" gtk-version="2.6"/> + <property name="DoOverwriteConfirmation" gtk-version="2.8" /> + </itemgroup> + </itemgroups> + <signals> + <itemgroup label="File Chooser Dialog Signals"> + <signal name="SelectionChanged" /> + <signal name="FileActivated" /> + <signal name="UpdatePreview" /> + <signal name="CurrentFolderChanged" /> + <signal name="ConfirmOverwrite" gtk-version="2.8"/> + </itemgroup> + </signals> + <internal-children> + <property name="VBox" glade-name="vbox" /> + <property name="ActionArea" glade-name="action_area" /> + </internal-children> + </object> + + <object type="Gtk.FontSelection,gtk-sharp" wrapper="Stetic.Wrapper.Widget" + label="Font Selection" icon="fontselection.png" palette-category="widget" + hexpandable="true" vexpandable="true" base-type="Gtk.Widget"> + <itemgroups> + <itemgroup label="Font Selection Properties"> + <property name="FontName" /> + <property name="PreviewText" translatable="true" /> + </itemgroup> + </itemgroups> + </object> + + <object type="Gtk.FontSelectionDialog,gtk-sharp" base-type="Gtk.Dialog" wrapper="Stetic.Wrapper.FontSelectionDialog" + label="Font Selection Dialog" icon="fontselectiondialog.png" palette-category="window"> + <internal-children> + <property name="VBox" glade-name="vbox" /> + <property name="ActionArea" glade-name="action_area" /> + <property name="FontSelection" glade-name="font_selection" /> + <property name="OkButton" glade-name="ok_button" /> + <property name="CancelButton" glade-name="cancel_button" /> + <property name="ApplyButton" glade-name="help_button" /> + </internal-children> + </object> + + <object type="Stetic.ErrorWidget" wrapper="Stetic.ErrorWidgetWrapper"> + </object> + + <object type="Gtk.Action,gtk-sharp" label="Action" wrapper="Stetic.Wrapper.Action" + init-properties="Name Label Tooltip StockId" > + <itemgroups> + <itemgroup label="Action Properties"> + <property name="Name" editor="Stetic.Editor.Identifier" min="1"/> + <property name="Type" /> + <property name="Accelerator" editor="Stetic.Editor.Accelerator" /> + <property name="HideIfEmpty" /> + <property name="IsImportant" /> + <property name="Label" translatable="true"/> + <property name="Sensitive" /> + <property name="ShortLabel" default="" translatable="true"/> + <property name="StockId" editor="Stetic.Editor.StockItem"/> + <property name="Tooltip" translatable="true"/> + <property name="Visible" /> + <property name="VisibleHorizontal" /> + <property name="VisibleVertical" /> + <property name="VisibleOverflown" gtk-version="2.6"/> + <property name="DrawAsRadio" label="Draw as radio"> + <invisible-if name="Type" value="Action" /> + </property> + <property name="Active"> + <invisible-if name="Type" value="Action" /> + </property> + <property name="Value"> + <invisible-if name="Type" value="Action" /> + <invisible-if name="Type" value="Toggle" /> + </property> + <property name="Group" label="Group" + description="The name of the radio action group that this action belongs to" + editor="Stetic.Editor.GroupPicker"> + <invisible-if name="Type" value="Action" /> + <invisible-if name="Type" value="Toggle" /> + </property> + </itemgroup> + </itemgroups> + <signals> + <itemgroup label="Action Signals"> + <signal name="Activated" /> + <signal name="Changed" /> + <signal name="Toggled" /> + </itemgroup> + </signals> + </object> + + + + <enum type="Gdk.ExtensionMode,gdk-sharp"> + <value name="None" label="None" + description="No extension events are desired" /> + <value name="All" label="All" + description="All extension events are desired" /> + <value name="Cursor" label="Only if cursor displayed" + description="Extension events are desired only if a cursor will be displayed for the device" /> + </enum> + + <enum type="Gdk.EventMask,gdk-sharp"> + <value name="ExposureMask" label="Expose" + description="Receive expose events" /> + <value name="PointerMotionMask" label="All pointer motion" + description="Receive all pointer motion events" /> + <value name="PointerMotionHintMask" label="Requested pointer motion" + description="Receive pointer motion events when requested" /> + <value name="ButtonMotionMask" label="Pointer motion w/ any button" + description="Receive pointer motion events while any button is pressed" /> + <value name="Button1MotionMask" label="Pointer motion w/ button 1" + description="Receive pointer motion events while button 1 is pressed" /> + <value name="Button2MotionMask" label="Pointer motion w/ button 2" + description="Receive pointer motion events while button 2 is pressed" /> + <value name="Button3MotionMask" label="Pointer motion w/ button 3" + description="Receive pointer motion events while button 3 is pressed" /> + <value name="ButtonPressMask" label="Button press" + description="Receive button press events" /> + <value name="ButtonReleaseMask" label="Button release" + description="Receive button release events" /> + <value name="KeyPressMask" label="Key press" + description="Receive key press events" /> + <value name="KeyReleaseMask" label="Key release" + description="Receive key release events" /> + <value name="EnterNotifyMask" label="Window enter" + description="Receive window enter events" /> + <value name="LeaveNotifyMask" label="Window leave" + description="Receive window leave events" /> + <value name="FocusChangeMask" label="Focus change" + description="Receive focus change events" /> + <value name="StructureMask" label="Window structure change" + description="Receive events about window configuration change" /> + <value name="PropertyChangeMask" label="Property change" + description="Receive property change events" /> + <value name="VisibilityNotifyMask" label="Visibility change" + description="Receive visibility change events" /> + <value name="ProximityInMask" label="Proximity in" + description="Receive proximity in events" /> + <value name="ProximityOutMask" label="Proximity out" + description="Receive proximity out events" /> + <value name="SubstructureMask" label="Window substructure change" + description="Receive events about window configuration changes of child windows" /> + <value name="ScrollMask" label="Scroll" + description="Receive scroll events" /> + <value name="AllEventsMask" /> + </enum> + + <enum type="Gdk.Gravity,gdk-sharp"> + <value name="NorthWest" label="Northwest" + description="The reference point is at the top left corner" /> + <value name="North" label="North" + description="The reference point is at the middle of the top edge" /> + <value name="NorthEast" label="Northeast" + description="The reference point is at the top right corner" /> + <value name="West" label="West" + description="The reference point is at the middle of the left edge" /> + <value name="Center" label="Center" + description="The reference point is at the center of the window" /> + <value name="East" label="East" + description="The reference point is at the middle of the right edge" /> + <value name="SouthWest" label="Southwest" + description="The reference point is at the lower left corner" /> + <value name="South" label="South" + description="The reference point is at the middle of the lower edge" /> + <value name="SouthEast" label="Southeast" + description="The reference point is at the lower right corner" /> + <value name="Static" label="Static" + description="The reference point is at the top left corner of the window itself, ignoring window manager decorations" /> + </enum> + + <enum type="Gdk.WindowTypeHint,gdk-sharp"> + <value name="Normal" label="Normal" + description="Normal toplevel window" /> + <value name="Dialog" label="Dialog" + description="Dialog window" /> + <value name="Menu" label="Menu" + description="Window used to implement a menu" /> + <value name="Toolbar" label="Toolbar" + description="Window used to implement a toolbar" /> + <value name="Splashscreen" label="Splash screen" + description="Window used to display a splash screen" /> + <value name="Utility" label="Utility" + description="Utility windows which are not detached toolbars or dialogs" /> + <value name="Dock" label="Dock" + description="Used for creating dock or panel windows" /> + <value name="Desktop" label="Desktop" + description="Used for creating the desktop background window" /> + </enum> + + <enum type="Gtk.ArrowType,gtk-sharp"> + <value name="Up" label="Up" + description="Up" /> + <value name="Down" label="Down" + description="Down" /> + <value name="Left" label="Left" + description="Left" /> + <value name="Right" label="Right" + description="Right" /> + </enum> + + <enum type="Gtk.AttachOptions,gtk-sharp"> + <value name="Expand" label="Expand" + description="The widget should expand to take up any extra space in its container that has been allocated" /> + <value name="Shrink" label="Shrink" + description="The widget should shrink as and when possible" /> + <value name="Fill" label="Fill" + description="The widget should fill the space allocated to it" /> + </enum> + + <enum type="Gtk.ButtonBoxStyle,gtk-sharp"> + <value name="DefaultStyle" label="Default" + description="Default packing" /> + <value name="Spread" label="Spread" + description="Buttons are evenly spread across the ButtonBox" /> + <value name="Edge" label="Edge" + description="Buttons are placed at the edges of the ButtonBox" /> + <value name="Start" label="Start" + description="Buttons are grouped towards the start (left or top) of the box" /> + <value name="End" label="End" + description="Buttons are grouped toward the end (right or bottom) of the box" /> + </enum> + + <enum type="Gtk.ButtonsType,gtk-sharp"> + <value name="None" label="None" + description="No buttons at all" /> + <value name="Ok" label="OK" + description="an OK button" /> + <value name="Close" label="Close" + description="a Close button" /> + <value name="Cancel" label="Cancel" + description="a Cancel button" /> + <value name="YesNo" label="Yes / No" + description="Yes and No buttons" /> + <value name="OkCancel" label="OK / Cancel" + description="OK and Cancel buttons" /> + </enum> + + <enum type="Gtk.CornerType,gtk-sharp"> + <value name="TopLeft" label="Top Left" + description="Place the scrollbars on the right and bottom of the contents" /> + <value name="BottomLeft" label="Bottom Left" + description="Place the scrollbrs on the top and right of the contents" /> + <value name="TopRight" label="Top Right" + description="Place the scrollbrs on the left and bottom of the contents" /> + <value name="BottomRight" label="Bottom Right" + description="Place the scrollbrs on the top and left of the contents" /> + </enum> + + <enum type="Gtk.FileChooserAction,gtk-sharp"> + <value name="Open" label="Open" + description="Open mode. The file chooser will only let the user pick an existing file." /> + <value name="Save" label="Save" + description="Save mode. The file chooser will let the user pick an existing file, or type in a new filename." /> + <value name="SelectFolder" label="Select Folder" + description="Open mode for selecting folders. The file chooser will let the user pick an existing folder." /> + <value name="CreateFolder" label="Create Folder" + description="Mode for creating a new folder. The file chooser will let the user name an existing or new folder." /> + </enum> + + <enum type="Gtk.IconSize,gtk-sharp"> + <value name="Invalid" label="Invalid" + description="Invalid" /> + <value name="Menu" label="Menu" + description="The size of an icon an a menu item" /> + <value name="SmallToolbar" label="Small Toolbar" + description="The size of an icon in a small toolbar" /> + <value name="LargeToolbar" label="Large Toolbar" + description="The size of an icon in a large toolbar" /> + <value name="Button" label="Button" + description="The size of an icon in a button" /> + <value name="Dnd" label="Drag and Drop" + description="The size of an icon in a drag-and-drop operation" /> + <value name="Dialog" label="Dialog" + description="The size of an icon in a dialog box" /> + </enum> + + <enum type="Gtk.Justification,gtk-sharp"> + <value name="Left" label="Left" + description="The text is placed at the left edge of the label" /> + <value name="Right" label="Right" + description="The text is placed at the right edge of the label" /> + <value name="Center" label="Center" + description="The text is placed in the center of the label" /> + <value name="Fill" label="Fill" + description="The text is distributed across the label" /> + </enum> + + <enum type="Gtk.MessageType,gtk-sharp"> + <value name="Info" label="Info" + description="Informational message" /> + <value name="Warning" label="Warning" + description="Non-fatal warning message" /> + <value name="Question" label="Question" + description="Question requiring a choice" /> + <value name="Error" label="Error" + description="Fatal error message" /> + </enum> + + <enum type="Gtk.Orientation,gtk-sharp"> + <value name="Horizontal" label="Horizontal" + description="The widget is in horizontal orientation" /> + <value name="Vertical" label="Vertical" + description="The widget is in vertical orientation" /> + </enum> + + <enum type="Gtk.PackType,gtk-sharp"> + <value name="Start" label="Start" + description="The child is packed into the start (left or top) of the box" /> + <value name="End" label="End" + description="The child is packed into the end (right or bottom) of the box" /> + </enum> + + <enum type="Gtk.PolicyType,gtk-sharp"> + <value name="Always" label="Always" + description="The scrollbar is always visible" /> + <value name="Automatic" label="Automatic" + description="The scrollbar will appear and disappear as necessary" /> + <value name="Never" label="Never" + description="The scrollbar will never appear" /> + </enum> + + <enum type="Gtk.PositionType,gtk-sharp"> + <value name="Left" label="Left" + description="The feature is at the left edge" /> + <value name="Right" label="Right" + description="The feature is at the right edge" /> + <value name="Top" label="Top" + description="The feature is at the top edge" /> + <value name="Bottom" label="Bottom" + description="The feature is at the bottom edge" /> + </enum> + + <enum type="Gtk.ProgressBarOrientation,gtk-sharp"> + <value name="LeftToRight" label="Left to right" + description="A horizontal progress bar growing from left to right" /> + <value name="RightToLeft" label="Right to left" + description="A horizontal progress bar growing from right to left" /> + <value name="BottomToTop" label="Bottom to top" + description="A vertical progress bar growing from bottom to top" /> + <value name="TopToBottom" label="Top to bottom" + description="A vertical progress bar growing from top to bottom" /> + </enum> + + <enum type="Gtk.ReliefStyle,gtk-sharp"> + <value name="Normal" label="Normal" + description="Draw a normal relief around the button" /> + <value name="Half" label="Half" + description="Draw a half relief around the button" /> + <value name="None" label="None" + description="Draw no relief around the button" /> + </enum> + + <enum type="Gtk.ResponseType,gtk-sharp"> + <value name="None" label="None" + description="None" /> + <value name="Reject" label="Reject" + description="Reject" /> + <value name="Accept" label="Accept" + description="Accept" /> + <value name="DeleteEvent" /> + <value name="Ok" label="OK" + description="OK" /> + <value name="Cancel" label="Cancel" + description="Cancel" /> + <value name="Close" label="Close" + description="Close" /> + <value name="Yes" label="Yes" + description="Yes" /> + <value name="No" label="No" + description="No" /> + <value name="Apply" label="Apply" + description="Apply" /> + <value name="Help" label="Help" + description="Help" /> + </enum> + + <enum type="Gtk.ShadowType,gtk-sharp"> + <value name="None" label="None" + description="No outline" /> + <value name="In" label="In" + description="The outline is bevelled inwards" /> + <value name="Out" label="Out" + description="The outline is bevelled outwards, like a button" /> + <value name="EtchedIn" label="Etched in" + description="" /> + <value name="EtchedOut" label="Etched out" + description="" /> + </enum> + + <enum type="Gtk.SpinButtonUpdatePolicy,gtk-sharp"> + <value name="Always" label="Always" + description="When refreshing the SpinButton, the value is always displayed" /> + <value name="IfValid" label="If valid" + description="When refreshing the SpinButton, the value is only displayed if it is within the SpinButton's bounds" /> + </enum> + + <enum type="Stetic.Wrapper.ActionToolbarWrapper+ToolbarStyle"> + <value name="Default" label="System Default" + description="Use the system default style" /> + <value name="Icons" label="Icons" + description="Buttons display only icons in the toolbar" /> + <value name="Text" label="Text" + description="Buttons display only text labels in the toolbar" /> + <value name="Both" label="Both" + description="Buttons display text and icons in the toolbar" /> + <value name="BothHoriz" label="Both horizontally" + description="Buttons display icons and text alongside each other, rather than vertically stacked" /> + </enum> + + <enum type="Gtk.UpdateType,gtk-sharp"> + <value name="Continuous" label="Continuous" + description="The range value will change continuously as the slider is moved" /> + <value name="Discontinuous" label="Discontinuous" + description="The range value will change only after the user releases the mouse button" /> + <value name="Delayed" label="Delayed" + description="The range value will change if the user stops sliding the slider for a moment" /> + </enum> + + <enum type="Gtk.WindowPosition,gtk-sharp"> + <value name="None" label="Not specified" + description="The window can be placed wherever the window manager chooses" /> + <value name="Center" label="Centered" + description="The window should be placed in the center of the screen" /> + <value name="Mouse" label="At mouse position" + description="The window should be placed at the current mouse position" /> + <value name="CenterAlways" label="Always centered" + description="The window should be kept centered even if it changes size" /> + <value name="CenterOnParent" label="Centered on parent" + description="Center the window on the parent window that it is transient for" /> + </enum> + + <enum type="Gtk.WindowType,gtk-sharp"> + <value name="Toplevel" label="Toplevel" + description="A regular window or dialog" /> + <value name="Popup" label="Popup" + description="A special window such as a tooltip" /> + </enum> + + <enum type="Gtk.WrapMode,gtk-sharp"> + <value name="None" label="None" + description="Do not wrap lines; just make the text area wider" /> + <value name="Char" label="Character" + description="Wrap text, breaking lines between any characters" /> + <value name="Word" label="Word" + description="Wrap text, breaking lines between words" /> + <value name="WordChar" label="Word or Character" + description="Wrap text, preferably breaking lines between words, but also breaking between characters if needed" /> + </enum> + + <enum type="Stetic.Wrapper.Button+ButtonType"> + <value name="StockItem" label="Stock button" + description="Button displaying stock icon and text" /> + <value name="TextOnly" label="Text only" + description="Button displaying text only" /> + <value name="TextAndIcon" label="Text and Icon" + description="Button displaying an icon and application-provided text" /> + <value name="Custom" label="Custom" + description="Button with entirely custom contents" /> + </enum> + + <enum type="Stetic.Wrapper.ToolButton+ButtonType"> + <value name="StockItem" label="Stock button" + description="Button displaying stock icon and text" /> + <value name="TextAndIcon" label="Text and Icon" + description="Button displaying an icon and application-provided text" /> + </enum> + + <enum type="Stetic.Wrapper.Action+ActionType"> + <value name="Action" label="Action" + description="An normal action" /> + <value name="Toggle" label="Toggle Action" + description="The action can be toggled between two states" /> + <value name="Radio" label="Radio Action" + description="The action is controlled by a radio button" /> + </enum> + + <enum type="Pango.EllipsizeMode, pango-sharp"> + <value name="None" label="None" + description="No ellipsization" /> + <value name="Start" label="Start" + description="Omit characters at the start of the text" /> + <value name="Middle" label="Middle" + description="Omit characters in the middle of the text" /> + <value name="End" label="End" + description="Omit characters at the end of the text" /> + </enum> + + <enum type="Gtk.SelectionMode, gtk-sharp"> + <value name="None" label="None" + description="Nothing can be selected" /> + <value name="Single" label="Single" + description="Only one item can be selected at any given moment. Other items can have focus, but will not be marked as selected" /> + <value name="Browse" label="Browse" + description="Only one item can be selected at any given moment. Any item currently having focus will be marked as selected" /> + <value name="Multiple" label="Multiple" + description="Several items may be selected or unselected with a click or using the spacebar. The selection can be done using the Ctrl and Shift modifier keys in the usual way" /> + </enum> + + <enum type="Gtk.PackDirection, gtk-sharp"> + <value name="Ttb" label="Top to bottom" + description="Top to bottom" /> + <value name="Btt" label="Bottom to top" + description="Bottom to top" /> + <value name="Rtl" label="Right to left" + description="Right to left" /> + <value name="Ltr" label="Left to right" + description="Left to right" /> + </enum> + +</objects> diff --git a/main/src/addins/MonoDevelop.GtkCore2/libstetic/wrapper/pixmaps/COPIED b/main/src/addins/MonoDevelop.GtkCore2/libstetic/wrapper/pixmaps/COPIED new file mode 100644 index 0000000000..d693b81e9a --- /dev/null +++ b/main/src/addins/MonoDevelop.GtkCore2/libstetic/wrapper/pixmaps/COPIED @@ -0,0 +1 @@ +These were stolen from glade3 and are GPLed.
\ No newline at end of file diff --git a/main/src/addins/MonoDevelop.GtkCore2/libstetic/wrapper/pixmaps/accellabel.png b/main/src/addins/MonoDevelop.GtkCore2/libstetic/wrapper/pixmaps/accellabel.png Binary files differnew file mode 100644 index 0000000000..6ba42ba220 --- /dev/null +++ b/main/src/addins/MonoDevelop.GtkCore2/libstetic/wrapper/pixmaps/accellabel.png diff --git a/main/src/addins/MonoDevelop.GtkCore2/libstetic/wrapper/pixmaps/actiongroup.png b/main/src/addins/MonoDevelop.GtkCore2/libstetic/wrapper/pixmaps/actiongroup.png Binary files differnew file mode 100644 index 0000000000..de43e0a5c4 --- /dev/null +++ b/main/src/addins/MonoDevelop.GtkCore2/libstetic/wrapper/pixmaps/actiongroup.png diff --git a/main/src/addins/MonoDevelop.GtkCore2/libstetic/wrapper/pixmaps/add-check-label.png b/main/src/addins/MonoDevelop.GtkCore2/libstetic/wrapper/pixmaps/add-check-label.png Binary files differnew file mode 100644 index 0000000000..cf3ad0c7d9 --- /dev/null +++ b/main/src/addins/MonoDevelop.GtkCore2/libstetic/wrapper/pixmaps/add-check-label.png diff --git a/main/src/addins/MonoDevelop.GtkCore2/libstetic/wrapper/pixmaps/add-menu.png b/main/src/addins/MonoDevelop.GtkCore2/libstetic/wrapper/pixmaps/add-menu.png Binary files differnew file mode 100644 index 0000000000..19a98613c2 --- /dev/null +++ b/main/src/addins/MonoDevelop.GtkCore2/libstetic/wrapper/pixmaps/add-menu.png diff --git a/main/src/addins/MonoDevelop.GtkCore2/libstetic/wrapper/pixmaps/alignment.png b/main/src/addins/MonoDevelop.GtkCore2/libstetic/wrapper/pixmaps/alignment.png Binary files differnew file mode 100644 index 0000000000..5d7d311d96 --- /dev/null +++ b/main/src/addins/MonoDevelop.GtkCore2/libstetic/wrapper/pixmaps/alignment.png diff --git a/main/src/addins/MonoDevelop.GtkCore2/libstetic/wrapper/pixmaps/arrow.png b/main/src/addins/MonoDevelop.GtkCore2/libstetic/wrapper/pixmaps/arrow.png Binary files differnew file mode 100644 index 0000000000..c9153b6f67 --- /dev/null +++ b/main/src/addins/MonoDevelop.GtkCore2/libstetic/wrapper/pixmaps/arrow.png diff --git a/main/src/addins/MonoDevelop.GtkCore2/libstetic/wrapper/pixmaps/box-expand.png b/main/src/addins/MonoDevelop.GtkCore2/libstetic/wrapper/pixmaps/box-expand.png Binary files differnew file mode 100644 index 0000000000..956903992b --- /dev/null +++ b/main/src/addins/MonoDevelop.GtkCore2/libstetic/wrapper/pixmaps/box-expand.png diff --git a/main/src/addins/MonoDevelop.GtkCore2/libstetic/wrapper/pixmaps/box-fill.png b/main/src/addins/MonoDevelop.GtkCore2/libstetic/wrapper/pixmaps/box-fill.png Binary files differnew file mode 100644 index 0000000000..b0d67b54d7 --- /dev/null +++ b/main/src/addins/MonoDevelop.GtkCore2/libstetic/wrapper/pixmaps/box-fill.png diff --git a/main/src/addins/MonoDevelop.GtkCore2/libstetic/wrapper/pixmaps/button.png b/main/src/addins/MonoDevelop.GtkCore2/libstetic/wrapper/pixmaps/button.png Binary files differnew file mode 100644 index 0000000000..db816c21dc --- /dev/null +++ b/main/src/addins/MonoDevelop.GtkCore2/libstetic/wrapper/pixmaps/button.png diff --git a/main/src/addins/MonoDevelop.GtkCore2/libstetic/wrapper/pixmaps/calendar.png b/main/src/addins/MonoDevelop.GtkCore2/libstetic/wrapper/pixmaps/calendar.png Binary files differnew file mode 100644 index 0000000000..c3cdf73ce8 --- /dev/null +++ b/main/src/addins/MonoDevelop.GtkCore2/libstetic/wrapper/pixmaps/calendar.png diff --git a/main/src/addins/MonoDevelop.GtkCore2/libstetic/wrapper/pixmaps/cell-expand-h.png b/main/src/addins/MonoDevelop.GtkCore2/libstetic/wrapper/pixmaps/cell-expand-h.png Binary files differnew file mode 100644 index 0000000000..539a6f71b5 --- /dev/null +++ b/main/src/addins/MonoDevelop.GtkCore2/libstetic/wrapper/pixmaps/cell-expand-h.png diff --git a/main/src/addins/MonoDevelop.GtkCore2/libstetic/wrapper/pixmaps/cell-expand-v.png b/main/src/addins/MonoDevelop.GtkCore2/libstetic/wrapper/pixmaps/cell-expand-v.png Binary files differnew file mode 100644 index 0000000000..658e63d82c --- /dev/null +++ b/main/src/addins/MonoDevelop.GtkCore2/libstetic/wrapper/pixmaps/cell-expand-v.png diff --git a/main/src/addins/MonoDevelop.GtkCore2/libstetic/wrapper/pixmaps/cell-fill-h.png b/main/src/addins/MonoDevelop.GtkCore2/libstetic/wrapper/pixmaps/cell-fill-h.png Binary files differnew file mode 100644 index 0000000000..30162bf7ea --- /dev/null +++ b/main/src/addins/MonoDevelop.GtkCore2/libstetic/wrapper/pixmaps/cell-fill-h.png diff --git a/main/src/addins/MonoDevelop.GtkCore2/libstetic/wrapper/pixmaps/cell-fill-v.png b/main/src/addins/MonoDevelop.GtkCore2/libstetic/wrapper/pixmaps/cell-fill-v.png Binary files differnew file mode 100644 index 0000000000..95a9c1ab32 --- /dev/null +++ b/main/src/addins/MonoDevelop.GtkCore2/libstetic/wrapper/pixmaps/cell-fill-v.png diff --git a/main/src/addins/MonoDevelop.GtkCore2/libstetic/wrapper/pixmaps/checkbutton.png b/main/src/addins/MonoDevelop.GtkCore2/libstetic/wrapper/pixmaps/checkbutton.png Binary files differnew file mode 100644 index 0000000000..71565b0b1f --- /dev/null +++ b/main/src/addins/MonoDevelop.GtkCore2/libstetic/wrapper/pixmaps/checkbutton.png diff --git a/main/src/addins/MonoDevelop.GtkCore2/libstetic/wrapper/pixmaps/colorbutton.png b/main/src/addins/MonoDevelop.GtkCore2/libstetic/wrapper/pixmaps/colorbutton.png Binary files differnew file mode 100644 index 0000000000..281288d7cc --- /dev/null +++ b/main/src/addins/MonoDevelop.GtkCore2/libstetic/wrapper/pixmaps/colorbutton.png diff --git a/main/src/addins/MonoDevelop.GtkCore2/libstetic/wrapper/pixmaps/colorselection.png b/main/src/addins/MonoDevelop.GtkCore2/libstetic/wrapper/pixmaps/colorselection.png Binary files differnew file mode 100644 index 0000000000..281288d7cc --- /dev/null +++ b/main/src/addins/MonoDevelop.GtkCore2/libstetic/wrapper/pixmaps/colorselection.png diff --git a/main/src/addins/MonoDevelop.GtkCore2/libstetic/wrapper/pixmaps/colorselectiondialog.png b/main/src/addins/MonoDevelop.GtkCore2/libstetic/wrapper/pixmaps/colorselectiondialog.png Binary files differnew file mode 100644 index 0000000000..281288d7cc --- /dev/null +++ b/main/src/addins/MonoDevelop.GtkCore2/libstetic/wrapper/pixmaps/colorselectiondialog.png diff --git a/main/src/addins/MonoDevelop.GtkCore2/libstetic/wrapper/pixmaps/combo.png b/main/src/addins/MonoDevelop.GtkCore2/libstetic/wrapper/pixmaps/combo.png Binary files differnew file mode 100644 index 0000000000..dab25d3c02 --- /dev/null +++ b/main/src/addins/MonoDevelop.GtkCore2/libstetic/wrapper/pixmaps/combo.png diff --git a/main/src/addins/MonoDevelop.GtkCore2/libstetic/wrapper/pixmaps/comboentry.png b/main/src/addins/MonoDevelop.GtkCore2/libstetic/wrapper/pixmaps/comboentry.png Binary files differnew file mode 100644 index 0000000000..13e02c820b --- /dev/null +++ b/main/src/addins/MonoDevelop.GtkCore2/libstetic/wrapper/pixmaps/comboentry.png diff --git a/main/src/addins/MonoDevelop.GtkCore2/libstetic/wrapper/pixmaps/custom.png b/main/src/addins/MonoDevelop.GtkCore2/libstetic/wrapper/pixmaps/custom.png Binary files differnew file mode 100644 index 0000000000..df61924981 --- /dev/null +++ b/main/src/addins/MonoDevelop.GtkCore2/libstetic/wrapper/pixmaps/custom.png diff --git a/main/src/addins/MonoDevelop.GtkCore2/libstetic/wrapper/pixmaps/dec-border.png b/main/src/addins/MonoDevelop.GtkCore2/libstetic/wrapper/pixmaps/dec-border.png Binary files differnew file mode 100644 index 0000000000..c5e5ae5b9e --- /dev/null +++ b/main/src/addins/MonoDevelop.GtkCore2/libstetic/wrapper/pixmaps/dec-border.png diff --git a/main/src/addins/MonoDevelop.GtkCore2/libstetic/wrapper/pixmaps/dialog.png b/main/src/addins/MonoDevelop.GtkCore2/libstetic/wrapper/pixmaps/dialog.png Binary files differnew file mode 100644 index 0000000000..6e81b2fd60 --- /dev/null +++ b/main/src/addins/MonoDevelop.GtkCore2/libstetic/wrapper/pixmaps/dialog.png diff --git a/main/src/addins/MonoDevelop.GtkCore2/libstetic/wrapper/pixmaps/drawingarea.png b/main/src/addins/MonoDevelop.GtkCore2/libstetic/wrapper/pixmaps/drawingarea.png Binary files differnew file mode 100644 index 0000000000..ee65bba598 --- /dev/null +++ b/main/src/addins/MonoDevelop.GtkCore2/libstetic/wrapper/pixmaps/drawingarea.png diff --git a/main/src/addins/MonoDevelop.GtkCore2/libstetic/wrapper/pixmaps/entry.png b/main/src/addins/MonoDevelop.GtkCore2/libstetic/wrapper/pixmaps/entry.png Binary files differnew file mode 100644 index 0000000000..d97bb9f378 --- /dev/null +++ b/main/src/addins/MonoDevelop.GtkCore2/libstetic/wrapper/pixmaps/entry.png diff --git a/main/src/addins/MonoDevelop.GtkCore2/libstetic/wrapper/pixmaps/eventbox.png b/main/src/addins/MonoDevelop.GtkCore2/libstetic/wrapper/pixmaps/eventbox.png Binary files differnew file mode 100644 index 0000000000..c89d490375 --- /dev/null +++ b/main/src/addins/MonoDevelop.GtkCore2/libstetic/wrapper/pixmaps/eventbox.png diff --git a/main/src/addins/MonoDevelop.GtkCore2/libstetic/wrapper/pixmaps/expander.png b/main/src/addins/MonoDevelop.GtkCore2/libstetic/wrapper/pixmaps/expander.png Binary files differnew file mode 100644 index 0000000000..35d1c41d8b --- /dev/null +++ b/main/src/addins/MonoDevelop.GtkCore2/libstetic/wrapper/pixmaps/expander.png diff --git a/main/src/addins/MonoDevelop.GtkCore2/libstetic/wrapper/pixmaps/fileselection.png b/main/src/addins/MonoDevelop.GtkCore2/libstetic/wrapper/pixmaps/fileselection.png Binary files differnew file mode 100644 index 0000000000..03bda09484 --- /dev/null +++ b/main/src/addins/MonoDevelop.GtkCore2/libstetic/wrapper/pixmaps/fileselection.png diff --git a/main/src/addins/MonoDevelop.GtkCore2/libstetic/wrapper/pixmaps/fixed.png b/main/src/addins/MonoDevelop.GtkCore2/libstetic/wrapper/pixmaps/fixed.png Binary files differnew file mode 100644 index 0000000000..e6d5ece810 --- /dev/null +++ b/main/src/addins/MonoDevelop.GtkCore2/libstetic/wrapper/pixmaps/fixed.png diff --git a/main/src/addins/MonoDevelop.GtkCore2/libstetic/wrapper/pixmaps/fontbutton.png b/main/src/addins/MonoDevelop.GtkCore2/libstetic/wrapper/pixmaps/fontbutton.png Binary files differnew file mode 100644 index 0000000000..fe7a790ad4 --- /dev/null +++ b/main/src/addins/MonoDevelop.GtkCore2/libstetic/wrapper/pixmaps/fontbutton.png diff --git a/main/src/addins/MonoDevelop.GtkCore2/libstetic/wrapper/pixmaps/fontselection.png b/main/src/addins/MonoDevelop.GtkCore2/libstetic/wrapper/pixmaps/fontselection.png Binary files differnew file mode 100644 index 0000000000..fe7a790ad4 --- /dev/null +++ b/main/src/addins/MonoDevelop.GtkCore2/libstetic/wrapper/pixmaps/fontselection.png diff --git a/main/src/addins/MonoDevelop.GtkCore2/libstetic/wrapper/pixmaps/fontselectiondialog.png b/main/src/addins/MonoDevelop.GtkCore2/libstetic/wrapper/pixmaps/fontselectiondialog.png Binary files differnew file mode 100644 index 0000000000..6936c47c05 --- /dev/null +++ b/main/src/addins/MonoDevelop.GtkCore2/libstetic/wrapper/pixmaps/fontselectiondialog.png diff --git a/main/src/addins/MonoDevelop.GtkCore2/libstetic/wrapper/pixmaps/frame.png b/main/src/addins/MonoDevelop.GtkCore2/libstetic/wrapper/pixmaps/frame.png Binary files differnew file mode 100644 index 0000000000..8a4c1f3a0e --- /dev/null +++ b/main/src/addins/MonoDevelop.GtkCore2/libstetic/wrapper/pixmaps/frame.png diff --git a/main/src/addins/MonoDevelop.GtkCore2/libstetic/wrapper/pixmaps/globe-not.png b/main/src/addins/MonoDevelop.GtkCore2/libstetic/wrapper/pixmaps/globe-not.png Binary files differnew file mode 100644 index 0000000000..3b1e292737 --- /dev/null +++ b/main/src/addins/MonoDevelop.GtkCore2/libstetic/wrapper/pixmaps/globe-not.png diff --git a/main/src/addins/MonoDevelop.GtkCore2/libstetic/wrapper/pixmaps/globe.png b/main/src/addins/MonoDevelop.GtkCore2/libstetic/wrapper/pixmaps/globe.png Binary files differnew file mode 100644 index 0000000000..2f25501e49 --- /dev/null +++ b/main/src/addins/MonoDevelop.GtkCore2/libstetic/wrapper/pixmaps/globe.png diff --git a/main/src/addins/MonoDevelop.GtkCore2/libstetic/wrapper/pixmaps/handlebox.png b/main/src/addins/MonoDevelop.GtkCore2/libstetic/wrapper/pixmaps/handlebox.png Binary files differnew file mode 100644 index 0000000000..be064c6f51 --- /dev/null +++ b/main/src/addins/MonoDevelop.GtkCore2/libstetic/wrapper/pixmaps/handlebox.png diff --git a/main/src/addins/MonoDevelop.GtkCore2/libstetic/wrapper/pixmaps/hbox.png b/main/src/addins/MonoDevelop.GtkCore2/libstetic/wrapper/pixmaps/hbox.png Binary files differnew file mode 100644 index 0000000000..6971a3322b --- /dev/null +++ b/main/src/addins/MonoDevelop.GtkCore2/libstetic/wrapper/pixmaps/hbox.png diff --git a/main/src/addins/MonoDevelop.GtkCore2/libstetic/wrapper/pixmaps/hbuttonbox.png b/main/src/addins/MonoDevelop.GtkCore2/libstetic/wrapper/pixmaps/hbuttonbox.png Binary files differnew file mode 100644 index 0000000000..e38a4c5eed --- /dev/null +++ b/main/src/addins/MonoDevelop.GtkCore2/libstetic/wrapper/pixmaps/hbuttonbox.png diff --git a/main/src/addins/MonoDevelop.GtkCore2/libstetic/wrapper/pixmaps/hpaned.png b/main/src/addins/MonoDevelop.GtkCore2/libstetic/wrapper/pixmaps/hpaned.png Binary files differnew file mode 100644 index 0000000000..e2847abd09 --- /dev/null +++ b/main/src/addins/MonoDevelop.GtkCore2/libstetic/wrapper/pixmaps/hpaned.png diff --git a/main/src/addins/MonoDevelop.GtkCore2/libstetic/wrapper/pixmaps/hscale.png b/main/src/addins/MonoDevelop.GtkCore2/libstetic/wrapper/pixmaps/hscale.png Binary files differnew file mode 100644 index 0000000000..310e01cde2 --- /dev/null +++ b/main/src/addins/MonoDevelop.GtkCore2/libstetic/wrapper/pixmaps/hscale.png diff --git a/main/src/addins/MonoDevelop.GtkCore2/libstetic/wrapper/pixmaps/hscrollbar.png b/main/src/addins/MonoDevelop.GtkCore2/libstetic/wrapper/pixmaps/hscrollbar.png Binary files differnew file mode 100644 index 0000000000..717b656220 --- /dev/null +++ b/main/src/addins/MonoDevelop.GtkCore2/libstetic/wrapper/pixmaps/hscrollbar.png diff --git a/main/src/addins/MonoDevelop.GtkCore2/libstetic/wrapper/pixmaps/hseparator.png b/main/src/addins/MonoDevelop.GtkCore2/libstetic/wrapper/pixmaps/hseparator.png Binary files differnew file mode 100644 index 0000000000..b32843abec --- /dev/null +++ b/main/src/addins/MonoDevelop.GtkCore2/libstetic/wrapper/pixmaps/hseparator.png diff --git a/main/src/addins/MonoDevelop.GtkCore2/libstetic/wrapper/pixmaps/iconview.png b/main/src/addins/MonoDevelop.GtkCore2/libstetic/wrapper/pixmaps/iconview.png Binary files differnew file mode 100644 index 0000000000..b875d3741b --- /dev/null +++ b/main/src/addins/MonoDevelop.GtkCore2/libstetic/wrapper/pixmaps/iconview.png diff --git a/main/src/addins/MonoDevelop.GtkCore2/libstetic/wrapper/pixmaps/image.png b/main/src/addins/MonoDevelop.GtkCore2/libstetic/wrapper/pixmaps/image.png Binary files differnew file mode 100644 index 0000000000..7f790e56b3 --- /dev/null +++ b/main/src/addins/MonoDevelop.GtkCore2/libstetic/wrapper/pixmaps/image.png diff --git a/main/src/addins/MonoDevelop.GtkCore2/libstetic/wrapper/pixmaps/inc-border.png b/main/src/addins/MonoDevelop.GtkCore2/libstetic/wrapper/pixmaps/inc-border.png Binary files differnew file mode 100644 index 0000000000..7f457c3f03 --- /dev/null +++ b/main/src/addins/MonoDevelop.GtkCore2/libstetic/wrapper/pixmaps/inc-border.png diff --git a/main/src/addins/MonoDevelop.GtkCore2/libstetic/wrapper/pixmaps/label.png b/main/src/addins/MonoDevelop.GtkCore2/libstetic/wrapper/pixmaps/label.png Binary files differnew file mode 100644 index 0000000000..9299f0fe24 --- /dev/null +++ b/main/src/addins/MonoDevelop.GtkCore2/libstetic/wrapper/pixmaps/label.png diff --git a/main/src/addins/MonoDevelop.GtkCore2/libstetic/wrapper/pixmaps/menu.png b/main/src/addins/MonoDevelop.GtkCore2/libstetic/wrapper/pixmaps/menu.png Binary files differnew file mode 100644 index 0000000000..bcfdc9dd50 --- /dev/null +++ b/main/src/addins/MonoDevelop.GtkCore2/libstetic/wrapper/pixmaps/menu.png diff --git a/main/src/addins/MonoDevelop.GtkCore2/libstetic/wrapper/pixmaps/menubar.png b/main/src/addins/MonoDevelop.GtkCore2/libstetic/wrapper/pixmaps/menubar.png Binary files differnew file mode 100644 index 0000000000..14298a1b22 --- /dev/null +++ b/main/src/addins/MonoDevelop.GtkCore2/libstetic/wrapper/pixmaps/menubar.png diff --git a/main/src/addins/MonoDevelop.GtkCore2/libstetic/wrapper/pixmaps/messagedialog.png b/main/src/addins/MonoDevelop.GtkCore2/libstetic/wrapper/pixmaps/messagedialog.png Binary files differnew file mode 100644 index 0000000000..a5330e2918 --- /dev/null +++ b/main/src/addins/MonoDevelop.GtkCore2/libstetic/wrapper/pixmaps/messagedialog.png diff --git a/main/src/addins/MonoDevelop.GtkCore2/libstetic/wrapper/pixmaps/missing.png b/main/src/addins/MonoDevelop.GtkCore2/libstetic/wrapper/pixmaps/missing.png Binary files differnew file mode 100644 index 0000000000..589da692bb --- /dev/null +++ b/main/src/addins/MonoDevelop.GtkCore2/libstetic/wrapper/pixmaps/missing.png diff --git a/main/src/addins/MonoDevelop.GtkCore2/libstetic/wrapper/pixmaps/notebook.png b/main/src/addins/MonoDevelop.GtkCore2/libstetic/wrapper/pixmaps/notebook.png Binary files differnew file mode 100644 index 0000000000..7d8f7067f4 --- /dev/null +++ b/main/src/addins/MonoDevelop.GtkCore2/libstetic/wrapper/pixmaps/notebook.png diff --git a/main/src/addins/MonoDevelop.GtkCore2/libstetic/wrapper/pixmaps/optionmenu.png b/main/src/addins/MonoDevelop.GtkCore2/libstetic/wrapper/pixmaps/optionmenu.png Binary files differnew file mode 100644 index 0000000000..d682108ad8 --- /dev/null +++ b/main/src/addins/MonoDevelop.GtkCore2/libstetic/wrapper/pixmaps/optionmenu.png diff --git a/main/src/addins/MonoDevelop.GtkCore2/libstetic/wrapper/pixmaps/progressbar.png b/main/src/addins/MonoDevelop.GtkCore2/libstetic/wrapper/pixmaps/progressbar.png Binary files differnew file mode 100644 index 0000000000..f48b47c485 --- /dev/null +++ b/main/src/addins/MonoDevelop.GtkCore2/libstetic/wrapper/pixmaps/progressbar.png diff --git a/main/src/addins/MonoDevelop.GtkCore2/libstetic/wrapper/pixmaps/radiobutton.png b/main/src/addins/MonoDevelop.GtkCore2/libstetic/wrapper/pixmaps/radiobutton.png Binary files differnew file mode 100644 index 0000000000..c85d9492ad --- /dev/null +++ b/main/src/addins/MonoDevelop.GtkCore2/libstetic/wrapper/pixmaps/radiobutton.png diff --git a/main/src/addins/MonoDevelop.GtkCore2/libstetic/wrapper/pixmaps/remove-check-label.png b/main/src/addins/MonoDevelop.GtkCore2/libstetic/wrapper/pixmaps/remove-check-label.png Binary files differnew file mode 100644 index 0000000000..25136e6df9 --- /dev/null +++ b/main/src/addins/MonoDevelop.GtkCore2/libstetic/wrapper/pixmaps/remove-check-label.png diff --git a/main/src/addins/MonoDevelop.GtkCore2/libstetic/wrapper/pixmaps/remove-menu.png b/main/src/addins/MonoDevelop.GtkCore2/libstetic/wrapper/pixmaps/remove-menu.png Binary files differnew file mode 100644 index 0000000000..4777667d68 --- /dev/null +++ b/main/src/addins/MonoDevelop.GtkCore2/libstetic/wrapper/pixmaps/remove-menu.png diff --git a/main/src/addins/MonoDevelop.GtkCore2/libstetic/wrapper/pixmaps/scrolledwindow.png b/main/src/addins/MonoDevelop.GtkCore2/libstetic/wrapper/pixmaps/scrolledwindow.png Binary files differnew file mode 100644 index 0000000000..10323740f9 --- /dev/null +++ b/main/src/addins/MonoDevelop.GtkCore2/libstetic/wrapper/pixmaps/scrolledwindow.png diff --git a/main/src/addins/MonoDevelop.GtkCore2/libstetic/wrapper/pixmaps/spinbutton.png b/main/src/addins/MonoDevelop.GtkCore2/libstetic/wrapper/pixmaps/spinbutton.png Binary files differnew file mode 100644 index 0000000000..9e98bb0ca3 --- /dev/null +++ b/main/src/addins/MonoDevelop.GtkCore2/libstetic/wrapper/pixmaps/spinbutton.png diff --git a/main/src/addins/MonoDevelop.GtkCore2/libstetic/wrapper/pixmaps/statusbar.png b/main/src/addins/MonoDevelop.GtkCore2/libstetic/wrapper/pixmaps/statusbar.png Binary files differnew file mode 100644 index 0000000000..26d8c2f7f8 --- /dev/null +++ b/main/src/addins/MonoDevelop.GtkCore2/libstetic/wrapper/pixmaps/statusbar.png diff --git a/main/src/addins/MonoDevelop.GtkCore2/libstetic/wrapper/pixmaps/table.png b/main/src/addins/MonoDevelop.GtkCore2/libstetic/wrapper/pixmaps/table.png Binary files differnew file mode 100644 index 0000000000..dc5886c9ea --- /dev/null +++ b/main/src/addins/MonoDevelop.GtkCore2/libstetic/wrapper/pixmaps/table.png diff --git a/main/src/addins/MonoDevelop.GtkCore2/libstetic/wrapper/pixmaps/textview.png b/main/src/addins/MonoDevelop.GtkCore2/libstetic/wrapper/pixmaps/textview.png Binary files differnew file mode 100644 index 0000000000..642be08441 --- /dev/null +++ b/main/src/addins/MonoDevelop.GtkCore2/libstetic/wrapper/pixmaps/textview.png diff --git a/main/src/addins/MonoDevelop.GtkCore2/libstetic/wrapper/pixmaps/togglebutton.png b/main/src/addins/MonoDevelop.GtkCore2/libstetic/wrapper/pixmaps/togglebutton.png Binary files differnew file mode 100644 index 0000000000..62c13fad6e --- /dev/null +++ b/main/src/addins/MonoDevelop.GtkCore2/libstetic/wrapper/pixmaps/togglebutton.png diff --git a/main/src/addins/MonoDevelop.GtkCore2/libstetic/wrapper/pixmaps/toolbar.png b/main/src/addins/MonoDevelop.GtkCore2/libstetic/wrapper/pixmaps/toolbar.png Binary files differnew file mode 100644 index 0000000000..27b486a0fa --- /dev/null +++ b/main/src/addins/MonoDevelop.GtkCore2/libstetic/wrapper/pixmaps/toolbar.png diff --git a/main/src/addins/MonoDevelop.GtkCore2/libstetic/wrapper/pixmaps/treeview.png b/main/src/addins/MonoDevelop.GtkCore2/libstetic/wrapper/pixmaps/treeview.png Binary files differnew file mode 100644 index 0000000000..f6fd7d9d4e --- /dev/null +++ b/main/src/addins/MonoDevelop.GtkCore2/libstetic/wrapper/pixmaps/treeview.png diff --git a/main/src/addins/MonoDevelop.GtkCore2/libstetic/wrapper/pixmaps/vbox.png b/main/src/addins/MonoDevelop.GtkCore2/libstetic/wrapper/pixmaps/vbox.png Binary files differnew file mode 100644 index 0000000000..fce6eb11e1 --- /dev/null +++ b/main/src/addins/MonoDevelop.GtkCore2/libstetic/wrapper/pixmaps/vbox.png diff --git a/main/src/addins/MonoDevelop.GtkCore2/libstetic/wrapper/pixmaps/vbuttonbox.png b/main/src/addins/MonoDevelop.GtkCore2/libstetic/wrapper/pixmaps/vbuttonbox.png Binary files differnew file mode 100644 index 0000000000..68defd767e --- /dev/null +++ b/main/src/addins/MonoDevelop.GtkCore2/libstetic/wrapper/pixmaps/vbuttonbox.png diff --git a/main/src/addins/MonoDevelop.GtkCore2/libstetic/wrapper/pixmaps/viewport.png b/main/src/addins/MonoDevelop.GtkCore2/libstetic/wrapper/pixmaps/viewport.png Binary files differnew file mode 100644 index 0000000000..deccf531cb --- /dev/null +++ b/main/src/addins/MonoDevelop.GtkCore2/libstetic/wrapper/pixmaps/viewport.png diff --git a/main/src/addins/MonoDevelop.GtkCore2/libstetic/wrapper/pixmaps/vpaned.png b/main/src/addins/MonoDevelop.GtkCore2/libstetic/wrapper/pixmaps/vpaned.png Binary files differnew file mode 100644 index 0000000000..60628f46ef --- /dev/null +++ b/main/src/addins/MonoDevelop.GtkCore2/libstetic/wrapper/pixmaps/vpaned.png diff --git a/main/src/addins/MonoDevelop.GtkCore2/libstetic/wrapper/pixmaps/vscale.png b/main/src/addins/MonoDevelop.GtkCore2/libstetic/wrapper/pixmaps/vscale.png Binary files differnew file mode 100644 index 0000000000..dbdc71e8ab --- /dev/null +++ b/main/src/addins/MonoDevelop.GtkCore2/libstetic/wrapper/pixmaps/vscale.png diff --git a/main/src/addins/MonoDevelop.GtkCore2/libstetic/wrapper/pixmaps/vscrollbar.png b/main/src/addins/MonoDevelop.GtkCore2/libstetic/wrapper/pixmaps/vscrollbar.png Binary files differnew file mode 100644 index 0000000000..09f8008ab1 --- /dev/null +++ b/main/src/addins/MonoDevelop.GtkCore2/libstetic/wrapper/pixmaps/vscrollbar.png diff --git a/main/src/addins/MonoDevelop.GtkCore2/libstetic/wrapper/pixmaps/vseparator.png b/main/src/addins/MonoDevelop.GtkCore2/libstetic/wrapper/pixmaps/vseparator.png Binary files differnew file mode 100644 index 0000000000..6904fc2220 --- /dev/null +++ b/main/src/addins/MonoDevelop.GtkCore2/libstetic/wrapper/pixmaps/vseparator.png diff --git a/main/src/addins/MonoDevelop.GtkCore2/libstetic/wrapper/pixmaps/widget.png b/main/src/addins/MonoDevelop.GtkCore2/libstetic/wrapper/pixmaps/widget.png Binary files differnew file mode 100644 index 0000000000..7f5844bbfc --- /dev/null +++ b/main/src/addins/MonoDevelop.GtkCore2/libstetic/wrapper/pixmaps/widget.png diff --git a/main/src/addins/MonoDevelop.GtkCore2/libstetic/wrapper/pixmaps/window.png b/main/src/addins/MonoDevelop.GtkCore2/libstetic/wrapper/pixmaps/window.png Binary files differnew file mode 100644 index 0000000000..8f82250f04 --- /dev/null +++ b/main/src/addins/MonoDevelop.GtkCore2/libstetic/wrapper/pixmaps/window.png diff --git a/main/src/addins/MonoDevelop.GtkCore2/libsteticui/ActionComponent.cs b/main/src/addins/MonoDevelop.GtkCore2/libsteticui/ActionComponent.cs new file mode 100644 index 0000000000..d5db89c4af --- /dev/null +++ b/main/src/addins/MonoDevelop.GtkCore2/libsteticui/ActionComponent.cs @@ -0,0 +1,75 @@ + +using System; + +namespace Stetic +{ + public class ActionComponent: Component + { + Gdk.Pixbuf icon; + string label; + + internal static Gdk.Pixbuf DefaultActionIcon; + + static ActionComponent () + { + try { + DefaultActionIcon = Gdk.Pixbuf.LoadFromResource ("action.png"); + } catch (Exception e) { + Console.WriteLine ("Error while loading pixbuf 'action.png': " + e); + } + } + + public ActionComponent (Application owner, object backend, string name): base (owner, backend, name, owner.GetComponentType ("Gtk.Action")) + { + } + + public override string Name { + get { + if (name == null) + name = ((Wrapper.Action)backend).Name; + return name; + } + set { + name = value; + ((Wrapper.Action)backend).Name = value; + } + } + + public string Label { + get { + if (label == null) + label = ((Wrapper.Action)backend).Label; + return label; + } + set { + label = value; + ((Wrapper.Action)backend).Label = value; + } + } + + protected override void OnChanged () + { + name = null; + icon = null; + label = null; + base.OnChanged (); + } + + public Gdk.Pixbuf Icon { + get { + if (icon == null) { + byte[] data = app.Backend.GetActionIcon ((Wrapper.Action)backend); + if (data == null) + return DefaultActionIcon; + else + icon = new Gdk.Pixbuf (data); + } + return icon; + } + } + + public ActionGroupComponent ActionGroup { + get { return (ActionGroupComponent) app.GetComponent (((Wrapper.Action)backend).ActionGroup, null, null); } + } + } +} diff --git a/main/src/addins/MonoDevelop.GtkCore2/libsteticui/ActionGroupComponent.cs b/main/src/addins/MonoDevelop.GtkCore2/libsteticui/ActionGroupComponent.cs new file mode 100644 index 0000000000..1b2a871d26 --- /dev/null +++ b/main/src/addins/MonoDevelop.GtkCore2/libsteticui/ActionGroupComponent.cs @@ -0,0 +1,58 @@ + +using System; +using System.Collections; +using System.Collections.Specialized; + +namespace Stetic +{ + [Serializable] + public class ActionGroupComponent: Component + { + public ActionGroupComponent (Application app, object backend, string name): base (app, backend, name, app.GetComponentType ("Gtk.ActionGroup")) + { + } + + public override string Name { + get { + if (name == null) + name = ((Wrapper.ActionGroup)backend).Name; + return name; + } + set { + name = value; + ((Wrapper.ActionGroup)backend).Name = value; + } + } + + public override bool GeneratePublic { + get { return ((Wrapper.ActionGroup)backend).GeneratePublic; } + set { ((Wrapper.ActionGroup)backend).GeneratePublic = value; } + } + + protected override void OnChanged () + { + name = null; + base.OnChanged (); + } + + public ActionComponent[] GetActions () + { + Wrapper.ActionCollection acts = ((Wrapper.ActionGroup)backend).Actions; + + ArrayList comps = new ArrayList (acts.Count); + + for (int n=0; n<acts.Count; n++) { + ActionComponent ac = (ActionComponent) app.GetComponent (acts[n], null, null); + if (ac != null) + comps.Add (ac); + } + + return (ActionComponent[]) comps.ToArray (typeof(ActionComponent)); + } + + public override Component[] GetChildren () + { + return GetActions (); + } + } +} diff --git a/main/src/addins/MonoDevelop.GtkCore2/libsteticui/ActionGroupDesigner.cs b/main/src/addins/MonoDevelop.GtkCore2/libsteticui/ActionGroupDesigner.cs new file mode 100644 index 0000000000..473add6802 --- /dev/null +++ b/main/src/addins/MonoDevelop.GtkCore2/libsteticui/ActionGroupDesigner.cs @@ -0,0 +1,278 @@ + +using System; + +namespace Stetic +{ + public class ActionGroupDesigner: Designer + { + ActionGroupEditSession editSession; + ActionGroupDesignerFrontend frontend; + Project project; + string componentName; + string actionGroupName; + bool autoCommitChanges; + WidgetDesigner relatedWidgetDesigner; + + public event EventHandler BindField; + public event EventHandler ModifiedChanged; + public event EventHandler RootComponentChanged; + public event ComponentSignalEventHandler SignalAdded; + public event ComponentSignalEventHandler SignalChanged; + + internal ActionGroupDesigner (Project project, string componentName, string actionGroupName, WidgetDesigner relatedWidgetDesigner, bool autoCommitChanges): base (project.App) + { + this.componentName = componentName; + this.relatedWidgetDesigner = relatedWidgetDesigner; + + if (actionGroupName != null) + this.actionGroupName = actionGroupName; + this.autoCommitChanges = autoCommitChanges; + this.project = project; + + frontend = new ActionGroupDesignerFrontend (this); + + CreateSession (); + } + + internal override void SetActive () + { + app.ActiveProject = project; + } + + public override ProjectItemInfo ProjectItem { + get { return project.GetWidget (RootComponent.Name); } + } + + public Component RootComponent { + get { return app.GetComponent (editSession.EditedActionGroup, null, null); } + } + + public bool AllowActionBinding { + get { + return editSession != null && editSession.AllowActionBinding; + } + set { + if (editSession != null) + editSession.AllowActionBinding = value; + } + } + + public UndoQueue UndoQueue { + get { + if (relatedWidgetDesigner != null) + return relatedWidgetDesigner.UndoQueue; + else if (editSession != null) + return editSession.UndoQueue; + else + return UndoQueue.Empty; + } + } + + public ActionComponent SelectedAction { + get { + if (editSession == null) + return null; + Wrapper.Action act; + string an; + editSession.GetSelectedAction (out act, out an); + if (act != null) + return (ActionComponent) app.GetComponent (act, an, null); + else + return null; + } + set { + editSession.SetSelectedAction ((Wrapper.Action)value.Backend); + } + } + + public bool HasData { + get { return editSession != null && editSession.HasData; } + } + + public bool Modified { + get { return editSession != null && editSession.Modified; } + set { + if (editSession != null) + editSession.Modified = value; + } + } + + public string ActiveGroup { + get { + if (editSession == null) + return null; + return editSession.ActiveGroup; + } + set { + if (editSession != null) + editSession.ActiveGroup = value; + } + } + + public void Save () + { + if (editSession != null) { + editSession.Save (); + if (!autoCommitChanges && componentName != null) + componentName = editSession.ActiveGroup; + } + } + + public void CopySelection () + { + if (editSession != null) + editSession.CopySelection (); + } + + public void CutSelection () + { + if (editSession != null) + editSession.CutSelection (); + } + + public void PasteToSelection () + { + if (editSession != null) + editSession.PasteToSelection (); + } + + public void DeleteSelection () + { + if (editSession != null) + editSession.DeleteSelection (); + } + + protected override void OnCreatePlug (uint socketId) + { + editSession.CreateBackendWidgetPlug (socketId); + } + + protected override void OnDestroyPlug (uint socketId) + { + editSession.DestroyBackendWidgetPlug (); + } + + protected override Gtk.Widget OnCreateWidget () + { + return editSession.Backend; + } + + void CreateSession () + { + try { + if (actionGroupName != null) + editSession = project.ProjectBackend.CreateGlobalActionGroupDesignerSession (frontend, actionGroupName, autoCommitChanges); + else + editSession = project.ProjectBackend.CreateLocalActionGroupDesignerSession (frontend, componentName, autoCommitChanges); + ResetCustomWidget (); + } catch (Exception ex) { + editSession = null; + Console.WriteLine (ex); + AddCustomWidget (new Gtk.Label (ex.Message)); + } + } + + protected override void OnDestroyed () + { + frontend.disposed = true; + System.Runtime.Remoting.RemotingServices.Disconnect (frontend); + if (editSession != null) + editSession.Dispose (); + editSession = null; + base.OnDestroyed (); + } + + internal override void OnBackendChanged (ApplicationBackend oldBackend) + { + object[] sessionData = null; + + if (oldBackend != null) { + if (!autoCommitChanges) + sessionData = editSession.SaveState (); + if (editSession != null) + editSession.Dispose (); + } + + CreateSession (); + + if (sessionData != null && editSession != null) + editSession.RestoreState (sessionData); + + base.OnBackendChanged (oldBackend); + + if (RootComponentChanged != null) + RootComponentChanged (this, EventArgs.Empty); + } + + internal void NotifyBindField () + { + if (BindField != null) + BindField (this, EventArgs.Empty); + } + + internal void NotifyModified () + { + if (ModifiedChanged != null) + ModifiedChanged (this, EventArgs.Empty); + } + + internal void NotifySignalAdded (Wrapper.Action action, string name, Signal signal) + { + ActionComponent c = (ActionComponent) app.GetComponent (action, name, null); + if (c != null && SignalAdded != null) + SignalAdded (this, new ComponentSignalEventArgs (project, c, null, signal)); + } + + internal void NotifySignalChanged (Wrapper.Action action, string name, Signal oldSignal, Signal signal) + { + ActionComponent c = (ActionComponent) app.GetComponent (action, name, null); + if (c != null && SignalChanged != null) + SignalChanged (this, new ComponentSignalEventArgs (project, c, oldSignal, signal)); + } + } + + internal class ActionGroupDesignerFrontend: MarshalByRefObject + { + ActionGroupDesigner designer; + internal bool disposed; + + public ActionGroupDesignerFrontend (ActionGroupDesigner designer) + { + this.designer = designer; + } + + public void NotifyBindField () + { + Gtk.Application.Invoke ( + delegate { if (!disposed) designer.NotifyBindField (); } + ); + } + + public void NotifyModified () + { + Gtk.Application.Invoke ( + delegate { if (!disposed) designer.NotifyModified (); } + ); + } + + public void NotifySignalAdded (Wrapper.Action action, string name, Signal signal) + { + Gtk.Application.Invoke ( + delegate { if (!disposed) designer.NotifySignalAdded (action, name, signal); } + ); + } + + public void NotifySignalChanged (Wrapper.Action action, string name, Signal oldSignal, Signal signal) + { + Gtk.Application.Invoke ( + delegate { if (!disposed) designer.NotifySignalChanged (action, name, oldSignal, signal); } + ); + } + + public override object InitializeLifetimeService () + { + // Will be disconnected when calling Dispose + return null; + } + } +} diff --git a/main/src/addins/MonoDevelop.GtkCore2/libsteticui/ActionGroupDesignerBackend.cs b/main/src/addins/MonoDevelop.GtkCore2/libsteticui/ActionGroupDesignerBackend.cs new file mode 100644 index 0000000000..f5e562e12a --- /dev/null +++ b/main/src/addins/MonoDevelop.GtkCore2/libsteticui/ActionGroupDesignerBackend.cs @@ -0,0 +1,45 @@ + +using System; + +namespace Stetic +{ + internal class ActionGroupDesignerBackend: Gtk.VBox + { + Editor.ActionGroupEditor editor; + ActionGroupToolbar toolbar; + WidgetDesignerBackend groupDesign; + + internal ActionGroupDesignerBackend (WidgetDesignerBackend groupDesign, Editor.ActionGroupEditor editor, ActionGroupToolbar toolbar) + { + this.editor = editor; + this.toolbar = toolbar; + this.groupDesign = groupDesign; + + BorderWidth = 3; + PackStart (toolbar, false, false, 0); + PackStart (groupDesign, true, true, 3); + } + + public Editor.ActionGroupEditor Editor { + get { return editor; } + } + + public ActionGroupToolbar Toolbar { + get { return toolbar; } + } + + public void UpdateObjectViewers () + { + groupDesign.UpdateObjectViewers (); + } + + public override void Dispose () + { + this.editor = null; + this.toolbar = null; + this.groupDesign = null; + base.Dispose (); + } + + } +} diff --git a/main/src/addins/MonoDevelop.GtkCore2/libsteticui/ActionGroupEditSession.cs b/main/src/addins/MonoDevelop.GtkCore2/libsteticui/ActionGroupEditSession.cs new file mode 100644 index 0000000000..c7900efe5d --- /dev/null +++ b/main/src/addins/MonoDevelop.GtkCore2/libsteticui/ActionGroupEditSession.cs @@ -0,0 +1,355 @@ + +using System; +using System.Xml; +using System.Collections; + +namespace Stetic +{ + internal class ActionGroupEditSession: MarshalByRefObject, IDisposable + { + ActionGroupDesignerBackend designer; + Gtk.Plug plug; + ActionGroupDesignerFrontend frontend; + bool autoCommitChanges; + string groupToEdit; + string containerName; + ProjectBackend project; + bool modified; + bool allowActionBinding; + bool designerRequested; + ActionGroupToolbar groupToolbar; + + Stetic.Wrapper.ActionGroup groupCopy; + Stetic.Wrapper.ActionGroup group; + Hashtable actionCopyMap = new Hashtable (); + + UndoRedoManager undoManager; + UndoQueue undoQueue; + + public ActionGroupEditSession (ActionGroupDesignerFrontend frontend, ProjectBackend project, string containerName, string groupToEdit, bool autoCommitChanges) + { + this.groupToEdit = groupToEdit; + this.containerName = containerName; + this.frontend = frontend; + this.project = project; + this.autoCommitChanges = autoCommitChanges; + + if (groupToEdit != null) { + group = project.ActionGroups [groupToEdit]; + if (group == null) + throw new InvalidOperationException ("Unknown action group: " + groupToEdit); + Load (group); + undoManager = new UndoRedoManager (); + undoQueue = new UndoQueue (); + undoManager.UndoQueue = undoQueue; + undoManager.RootObject = groupCopy; + + groupToolbar = new ActionGroupToolbar (frontend, groupCopy); + } + else { + if (!autoCommitChanges) + throw new System.NotSupportedException (); + + Stetic.Wrapper.Container container = project.GetTopLevelWrapper (containerName, true); + groupToolbar = new ActionGroupToolbar (frontend, container.LocalActionGroups); + } + + // Don't delay the creation of the designer because when used in combination with the + // widget designer, change events are subscribed since the begining + + designer = UserInterface.CreateActionGroupDesigner (project, groupToolbar); + designer.Editor.GroupModified += OnModified; + designer.Toolbar.AllowActionBinding = allowActionBinding; + designer.Destroyed += delegate { designer = null; Dispose (); }; + } + + public Wrapper.ActionGroup EditedActionGroup { + get { return groupCopy; } + } + + void Load (Stetic.Wrapper.ActionGroup group) + { + if (autoCommitChanges) { + groupCopy = group; + } + else { + actionCopyMap.Clear (); + + groupCopy = new Stetic.Wrapper.ActionGroup (); + groupCopy.Name = group.Name; + + foreach (Stetic.Wrapper.Action action in group.Actions) { + Stetic.Wrapper.Action dupaction = action.Clone (); + groupCopy.Actions.Add (dupaction); + actionCopyMap [dupaction] = action; + } + groupCopy.SignalAdded += new Stetic.SignalEventHandler (OnSignalAdded); + groupCopy.SignalChanged += new Stetic.SignalChangedEventHandler (OnSignalChanged); + } + } + + public void Save () + { + if (autoCommitChanges) + return; + + if (group.Name != groupCopy.Name) + group.Name = groupCopy.Name; + + foreach (Stetic.Wrapper.Action actionCopy in groupCopy.Actions) { + Stetic.Wrapper.Action action = (Stetic.Wrapper.Action) actionCopyMap [actionCopy]; + if (action != null) + action.CopyFrom (actionCopy); + else { + action = actionCopy.Clone (); + actionCopyMap [actionCopy] = action; + group.Actions.Add (action); + } + } + + ArrayList todelete = new ArrayList (); + foreach (Stetic.Wrapper.Action actionCopy in actionCopyMap.Keys) { + if (!groupCopy.Actions.Contains (actionCopy)) + todelete.Add (actionCopy); + } + + foreach (Stetic.Wrapper.Action actionCopy in todelete) { + Stetic.Wrapper.Action action = (Stetic.Wrapper.Action) actionCopyMap [actionCopy]; + group.Actions.Remove (action); + actionCopyMap.Remove (actionCopy); + } + Modified = false; + } + + public UndoQueue UndoQueue { + get { + if (undoQueue != null) + return undoQueue; + else + return UndoQueue.Empty; + } + } + + public void CopySelection () + { + if (designer != null) + designer.Editor.Copy (); + } + + public void CutSelection () + { + if (designer != null) + designer.Editor.Cut (); + } + + public void PasteToSelection () + { + if (designer != null) + designer.Editor.Paste (); + } + + public void DeleteSelection () + { + if (designer != null) + designer.Editor.Delete (); + } + + void OnProjectReloaded (object s, EventArgs a) + { + // Called when the underlying project has changed. Object references need to be updated. + if (autoCommitChanges) { + if (designer != null) { + if (groupToEdit != null) { + groupToolbar.ActiveGroup = project.ActionGroups [groupToEdit]; + } else { + Stetic.Wrapper.Container container = project.GetTopLevelWrapper (containerName, true); + groupToolbar.ActionGroups = container.LocalActionGroups; + } + } + } else { + // We only need to remap the actions + group = project.ActionGroups [groupToEdit]; + actionCopyMap.Clear (); + foreach (Wrapper.Action dupac in groupCopy.Actions) { + Wrapper.Action ac = group.GetAction (dupac.Name); + if (ac != null) + actionCopyMap [dupac] = ac; + } + } + } + + void OnModified (object ob, EventArgs args) + { + modified = true; + frontend.NotifyModified (); + } + + public bool HasData { + get { + if (groupToEdit != null) + return true; + Stetic.Wrapper.Container container = project.GetTopLevelWrapper (containerName, true); + return container.LocalActionGroups.Count > 0; + } + } + + public bool Modified { + get { return modified; } + set { modified = value; frontend.NotifyModified (); } + } +// public bool Modified { +// get { return project.WasModified (); } +// } + + public string ActiveGroup { + get { + if (designer != null) { + Wrapper.ActionGroup grp = designer.Toolbar.ActiveGroup; + if (grp != null) + return grp.Name; + } + return null; + } + set { + if (value != null || designer != null) { + // No need to create the designer if the active group is being set to null. + Wrapper.ActionGroup grp = Backend.Toolbar.ActionGroups [value]; + Backend.Toolbar.ActiveGroup = grp; + } + } + } + + public void SetSelectedAction (Wrapper.Action action) + { + // No need to create the designer if the active action is being set to null. + if (action != null || designer != null) + Backend.Editor.SelectedAction = action; + } + + public void GetSelectedAction (out Wrapper.Action action, out string name) + { + if (designer != null) { + action = designer.Editor.SelectedAction; + if (action != null) + name = action.Name; + else + name = null; + } else { + action = null; + name = null; + } + } + + public ActionGroupDesignerBackend Backend { + get { + designerRequested = true; + return designer; + } + } + + [NoGuiDispatch] + public void CreateBackendWidgetPlug (uint socketId) + { + Gdk.Threads.Enter (); + plug = new Gtk.Plug (socketId); + plug.Add (Backend); + plug.Decorated = false; + plug.ShowAll (); + Gdk.Threads.Leave (); + } + + public void DestroyBackendWidgetPlug () + { + if (designer != null) { + Gtk.Plug plug = (Gtk.Plug) designer.Parent; + plug.Remove (designer); + plug.Destroy (); + } + } + + public bool AllowActionBinding { + get { + return allowActionBinding; + } + set { + allowActionBinding = value; + if (designer != null) + designer.Toolbar.AllowActionBinding = value; + } + } + + public void Dispose () + { + if (designer != null) { + designer.Editor.GroupModified -= OnModified; + if (!designerRequested) + designer.Destroy (); + } + + project.ProjectReloaded -= OnProjectReloaded; + + if (plug != null) { + plug.Destroy (); + plug = null; + } + + System.Runtime.Remoting.RemotingServices.Disconnect (this); + } + + public override object InitializeLifetimeService () + { + // Will be disconnected when calling Dispose + return null; + } + + public object[] SaveState () + { + if (autoCommitChanges) + return null; + + XmlDocument doc = new XmlDocument (); + doc.AppendChild (groupCopy.Write (new ObjectWriter (doc, FileFormat.Native))); + + Hashtable nameMap = new Hashtable (); + foreach (DictionaryEntry e in actionCopyMap) + nameMap [((Wrapper.Action)e.Key).Name] = ((Wrapper.Action)e.Value).Name; + + return new object[] { groupCopy.Name, nameMap, doc.OuterXml }; + } + + public void RestoreState (object[] data) + { + if (data == null) + return; + + groupCopy = new Stetic.Wrapper.ActionGroup (); + groupCopy.Name = (string) data [0]; + + XmlDocument doc = new XmlDocument (); + doc.LoadXml ((string) data [2]); + + // Create the map which links edited action with source actions + actionCopyMap.Clear (); + foreach (DictionaryEntry e in (Hashtable) data [1]) { + Wrapper.Action dupaction = groupCopy.GetAction ((string)e.Key); + Wrapper.Action action = group.GetAction ((string)e.Value); + actionCopyMap [dupaction] = action; + } + + groupCopy.SignalAdded += new Stetic.SignalEventHandler (OnSignalAdded); + groupCopy.SignalChanged += new Stetic.SignalChangedEventHandler (OnSignalChanged); + } + + void OnSignalAdded (object s, Stetic.SignalEventArgs a) + { + Wrapper.Action action = (Wrapper.Action) a.Wrapper; + frontend.NotifySignalAdded (action, action.Name, a.Signal); + } + + void OnSignalChanged (object s, Stetic.SignalChangedEventArgs a) + { + Wrapper.Action action = (Wrapper.Action) a.Wrapper; + frontend.NotifySignalChanged (action, action.Name, a.OldSignal, a.Signal); + } + } +} diff --git a/main/src/addins/MonoDevelop.GtkCore2/libsteticui/ActionGroupToolbar.cs b/main/src/addins/MonoDevelop.GtkCore2/libsteticui/ActionGroupToolbar.cs new file mode 100644 index 0000000000..c41601509c --- /dev/null +++ b/main/src/addins/MonoDevelop.GtkCore2/libsteticui/ActionGroupToolbar.cs @@ -0,0 +1,275 @@ + +using System; +using System.Collections; +using Stetic.Wrapper; +using Mono.Unix; + +namespace Stetic +{ + internal class ActionGroupToolbar: Gtk.Toolbar + { + Wrapper.ActionGroupCollection actionGroups; + Gtk.ComboBox combo; + bool updating; + ActionGroup currentGroup; + ArrayList internalButtons = new ArrayList (); + bool singleGroupMode; + bool allowBinding; + ActionGroupDesignerFrontend frontend; + Editor.ActionGroupEditor agroupEditor; + Gtk.ToolButton addButton; + Gtk.ToolButton removeButton; + + public event ActionGroupEventHandler ActiveGroupChanged; + public event ActionGroupEventHandler ActiveGroupCreated; + + public ActionGroupToolbar (ActionGroupDesignerFrontend frontend, bool singleGroupMode) + { + Initialize (frontend, null, singleGroupMode); + } + + public ActionGroupToolbar (ActionGroupDesignerFrontend frontend, Wrapper.ActionGroup actionGroup) + { + currentGroup = actionGroup; + Initialize (frontend, null, true); + } + + public ActionGroupToolbar (ActionGroupDesignerFrontend frontend, Wrapper.ActionGroupCollection actionGroups) + { + Initialize (frontend, actionGroups, false); + } + + public bool AllowActionBinding { + get { return allowBinding; } + set { allowBinding = value; } + } + + void Initialize (ActionGroupDesignerFrontend frontend, Wrapper.ActionGroupCollection actionGroups, bool singleGroupMode) + { + this.frontend = frontend; + this.singleGroupMode = singleGroupMode; + IconSize = Gtk.IconSize.SmallToolbar; + Orientation = Gtk.Orientation.Horizontal; + ToolbarStyle = Gtk.ToolbarStyle.BothHoriz; + + combo = Gtk.ComboBox.NewText (); + + if (!singleGroupMode) { + combo.Changed += OnActiveChanged; + + Gtk.ToolItem comboItem = new Gtk.ToolItem (); + Gtk.HBox cbox = new Gtk.HBox (); + cbox.PackStart (new Gtk.Label (Catalog.GetString ("Action Group:") + " "), false, false, 3); + cbox.PackStart (combo, true, true, 3); + comboItem.Add (cbox); + comboItem.ShowAll (); + Insert (comboItem, -1); + internalButtons.Add (comboItem); + + addButton = new Gtk.ToolButton (Gtk.Stock.Add); + addButton.Clicked += OnAddGroup; + Insert (addButton, -1); + internalButtons.Add (addButton); + + removeButton = new Gtk.ToolButton (Gtk.Stock.Remove); + removeButton.Clicked += OnRemoveGroup; + Insert (removeButton, -1); + internalButtons.Add (removeButton); + + ActionGroups = actionGroups; + + if (actionGroups != null && actionGroups.Count > 0) + combo.Active = 0; + } else { + UpdateActionCommands (null); + } + + ShowAll (); + } + + public override void Dispose () + { + if (combo == null) + return; + + combo.Changed -= OnActiveChanged; + combo = null; + if (addButton != null) { + addButton.Clicked -= OnAddGroup; + removeButton.Clicked -= OnRemoveGroup; + } + + if (agroupEditor != null) { + agroupEditor.SelectionChanged -= OnEditorSelectionChanged; + agroupEditor = null; + } + + if (!singleGroupMode) + ActionGroups = null; + base.Dispose (); + } + + public Wrapper.ActionGroupCollection ActionGroups { + get { return actionGroups; } + set { + if (singleGroupMode) + throw new InvalidOperationException ("ActionGroups can't be set in single group mode"); + + if (actionGroups != null) { + actionGroups.ActionGroupAdded -= OnCollectionChanged; + actionGroups.ActionGroupRemoved -= OnCollectionChanged; + actionGroups.ActionGroupChanged -= OnCollectionChanged; + } + + this.actionGroups = value; + + if (actionGroups != null) { + actionGroups.ActionGroupAdded += OnCollectionChanged; + actionGroups.ActionGroupRemoved += OnCollectionChanged; + actionGroups.ActionGroupChanged += OnCollectionChanged; + } + Refresh (); + } + } + + public void Bind (Editor.ActionGroupEditor agroupEditor) + { + this.agroupEditor = agroupEditor; + agroupEditor.SelectionChanged += OnEditorSelectionChanged; + agroupEditor.ActionGroup = ActiveGroup; + } + + public void OnEditorSelectionChanged (object s, EventArgs a) + { + UpdateActionCommands (agroupEditor.SelectedAction); + } + + public ActionGroup ActiveGroup { + get { + return currentGroup; + } + set { + if (singleGroupMode) { + currentGroup = value; + UpdateActionCommands (null); + NotifyActiveGroupChanged (); + } else { + int i = actionGroups.IndexOf (value); + if (i != -1) + combo.Active = i; + } + } + } + + void Refresh () + { + if (singleGroupMode || combo == null) + return; + + while (combo.Model.IterNChildren () > 0) + combo.RemoveText (0); + if (actionGroups != null) { + foreach (ActionGroup group in actionGroups) + combo.AppendText (group.Name); + } + } + + void OnCollectionChanged (object s, ActionGroupEventArgs args) + { + // Avoid firing the selection change event if the selected + // group is the same after the refresh + ActionGroup oldGroup = currentGroup; + updating = true; + + int i = combo.Active; + Refresh (); + if (actionGroups.Count == 0) { + combo.Sensitive = false; + currentGroup = null; + } + else { + combo.Sensitive = true; + if (i == -1) + i = 0; + if (i < actionGroups.Count) + combo.Active = i; + else + combo.Active = actionGroups.Count - 1; + currentGroup = (ActionGroup) actionGroups [combo.Active]; + } + updating = false; + if (currentGroup != oldGroup) + OnActiveChanged (null, null); + frontend.NotifyModified (); + } + + void OnAddGroup (object s, EventArgs args) + { + ActionGroup group = new ActionGroup (); + group.Name = Catalog.GetString ("New Action Group"); + actionGroups.Add (group); + combo.Active = actionGroups.Count - 1; + if (ActiveGroupCreated != null) + ActiveGroupCreated (this, new ActionGroupEventArgs (ActiveGroup)); + + if (agroupEditor != null) + agroupEditor.StartEditing (); + } + + void OnRemoveGroup (object s, EventArgs args) + { + if (combo.Active != -1) + actionGroups.RemoveAt (combo.Active); + } + + void OnActiveChanged (object s, EventArgs args) + { + if (!updating) { + UpdateActionCommands (null); + if (combo.Active != -1) + currentGroup = (ActionGroup) actionGroups [combo.Active]; + else + currentGroup = null; + NotifyActiveGroupChanged (); + } + } + + void NotifyActiveGroupChanged () + { + if (agroupEditor != null) + agroupEditor.ActionGroup = ActiveGroup; + if (ActiveGroupChanged != null) + ActiveGroupChanged (this, new ActionGroupEventArgs (ActiveGroup)); + } + + void UpdateActionCommands (Wrapper.Action action) + { + foreach (Gtk.Widget w in Children) { + if (!internalButtons.Contains (w)) { + Remove (w); + w.Destroy (); + } + } + AddActionCommands (action); + + if (internalButtons.Count > 0 && internalButtons.Count != Children.Length) { + Insert (new Gtk.SeparatorToolItem (), internalButtons.Count); + } + ShowAll (); + } + + protected virtual void AddActionCommands (Wrapper.Action action) + { + if (allowBinding) { + Gtk.ToolButton bindButton = new Gtk.ToolButton (null, Catalog.GetString ("Bind to Field")); + bindButton.IsImportant = true; + bindButton.Show (); + Insert (bindButton, -1); + if (action == null) + bindButton.Sensitive = false; + + bindButton.Clicked += delegate { frontend.NotifyBindField (); }; + } + } + } +} diff --git a/main/src/addins/MonoDevelop.GtkCore2/libsteticui/Application.cs b/main/src/addins/MonoDevelop.GtkCore2/libsteticui/Application.cs new file mode 100644 index 0000000000..afe4a3a00e --- /dev/null +++ b/main/src/addins/MonoDevelop.GtkCore2/libsteticui/Application.cs @@ -0,0 +1,584 @@ + +using System; +using System.Threading; +using System.Collections; +using System.CodeDom; +using System.CodeDom.Compiler; +using System.IO; +using System.Xml; +using System.Runtime.Serialization.Formatters.Binary; +using System.Runtime.Remoting; +using System.Runtime.Remoting.Channels; +using System.Runtime.Remoting.Channels.Tcp; +using System.Diagnostics; +using Mono.Remoting.Channels.Unix; +using Mono.Cecil; + +namespace Stetic +{ + public enum IsolationMode + { + None, + ProcessTcp, + ProcessUnix + } + + public delegate string AssemblyResolverCallback (string assemblyName); + + public static class ApplicationFactory { + + public static Application CreateApplication (IsolationMode mode) + { + switch (mode) { + case IsolationMode.None: + return new LocalApplication (); + case IsolationMode.ProcessTcp: + case IsolationMode.ProcessUnix: + return new IsolatedApplication (mode); + default: + throw new ArgumentException ("mode"); + } + } + } + + internal class IsolatedApplication : Application { + + string channelId; + ApplicationBackendController backendController; + + string RegisterRemotingChannel (IsolationMode mode) + { + string remotingChannel; + if (mode == IsolationMode.ProcessTcp) { + remotingChannel = "tcp"; + IChannel ch = ChannelServices.GetChannel ("tcp"); + if (ch == null) { + ChannelServices.RegisterChannel (new TcpChannel (0), false); + } + } else { + remotingChannel = "unix"; + IChannel ch = ChannelServices.GetChannel ("unix"); + if (ch == null) { + string unixRemotingFile = Path.GetTempFileName (); + ChannelServices.RegisterChannel (new UnixChannel (unixRemotingFile), false); + } + } + return remotingChannel; + } + + public IsolatedApplication (IsolationMode mode) + { + if (mode == IsolationMode.None) + throw new ArgumentException ("mode"); + channelId = RegisterRemotingChannel (mode); + backendController = new ApplicationBackendController (this, channelId); + backendController.StartBackend (); + OnBackendChanged (false); + } + + public override void Dispose () + { + base.Dispose (); + backendController.StopBackend (true); + } + + public event BackendChangingHandler BackendChanging; + public event BackendChangedHandler BackendChanged; + + void OnNewBackendStarted (object ob, EventArgs args) + { + OnBackendChanging (); + ApplicationBackendController oldBackend = backendController; + backendController = (ApplicationBackendController) ob; + OnBackendChanged (true); + oldBackend.StopBackend (false); + } + + void OnBackendStopped (object ob, EventArgs args) + { + // The backend process crashed, try to restart it + Backend = null; + backendController = new ApplicationBackendController (this, channelId); + backendController.StartBackend (); + OnBackendChanged (true); + } + + void OnBackendChanged (bool notify) + { + ApplicationBackend oldBackend = Backend; + + Backend = backendController.Backend; + backendController.Stopped += OnBackendStopped; + UpdateWidgetLibraries (false, false); + ClearCollections (); + if (notify && BackendChanged != null) + BackendChanged (oldBackend); + + Backend.ActiveProject = ActiveProject != null ? ActiveProject.ProjectBackend : null; + } + + void OnBackendChanging () + { + Backend.GlobalWidgetLibraries = widgetLibraries; + if (BackendChanging != null) + BackendChanging (); + } + + internal override void RestartBackend () + { + // The backend process needs to be restarted. + // This is done in background. + + ThreadPool.QueueUserWorkItem (delegate { + try { + // Start the new backend + ApplicationBackendController newController = new ApplicationBackendController (this, channelId); + newController.StartBackend (); + Gtk.Application.Invoke (newController, EventArgs.Empty, OnNewBackendStarted); + } catch { + // FIXME: show an error message + } + }); + } + + internal override ComponentType CreateComponentType (string typeName) + { + string desc = null, className = null, category = null, targetGtkVersion = null, library = null; + Gdk.Pixbuf px = null; + + byte[] icon; + + if (Backend.GetClassDescriptorInfo (typeName, out desc, out className, out category, out targetGtkVersion, out library, out icon) && icon != null) + px = new Gdk.Pixbuf (icon); + + if (px == null) + px = ComponentType.Unknown.Icon; + + if (desc == null) + desc = typeName; + + return new ComponentType (this, typeName, desc, className, category, targetGtkVersion, library, px); + } + } + + internal class LocalApplication : Application { + + public LocalApplication () + { + Backend = new ApplicationBackend (this); + } + + public override void Dispose () + { + base.Dispose (); + Backend.Dispose (); + } + + internal override ComponentType CreateComponentType (string typeName) + { + ClassDescriptor cls = Registry.LookupClassByName (typeName); + if (cls == null) + return null; + + return new ComponentType (this, typeName, cls.Label, cls.WrappedTypeName, cls.Category, cls.TargetGtkVersion, cls.Library.Name, cls.Icon); + } + } + + public abstract class Application : MarshalByRefObject, IDisposable { + + ApplicationBackend backend; + + Hashtable components = new Hashtable (); + Hashtable types = new Hashtable (); + internal ArrayList widgetLibraries = new ArrayList (); + ArrayList projects = new ArrayList (); + Project activeProject; + Designer activeDesigner; + + WidgetPropertyTree propertiesWidget; + Palette paletteWidget; + WidgetTree projectWidget; + SignalsEditor signalsWidget; + bool allowInProcLibraries = true; + bool disposed; + + public AssemblyResolverCallback WidgetLibraryResolver { + get { return Backend.WidgetLibraryResolver; } + set { Backend.WidgetLibraryResolver = value; } + } + + public MimeResolverDelegate MimeResolver { + set { Backend.MimeResolver = value; } + } + + public Editor.ShowUrlDelegate ShowUrl { + set { Backend.ShowUrl = value; } + } + + public bool ShowNonContainerWarning { + get { return Backend.ShowNonContainerWarning; } + set { Backend.ShowNonContainerWarning = value; } + } + + // Loads the libraries registered in the projects or in the application. + // It will reload the libraries if they have changed. Libraries won't be + // unloaded unless forceUnload is set to true + public void UpdateWidgetLibraries (bool forceUnload) + { + UpdateWidgetLibraries (true, forceUnload); + } + + internal virtual void RestartBackend () + { + } + + protected void ClearCollections () + { + lock (types) { + types.Clear (); + } + + Component[] comps; + lock (components) { + // All components should have been cleared by the backend, + // just make sure it did + comps = new Component [components.Count]; + components.Values.CopyTo (comps, 0); + components.Clear (); + } + + foreach (Component c in comps) { + c.Dispose (); + } + } + + internal void UpdateWidgetLibraries (bool allowBackendRestart, bool forceUnload) + { + // Collect libraries from the project and from the application + + ArrayList assemblies = new ArrayList (); + assemblies.AddRange (widgetLibraries); + + ArrayList projectBackends = new ArrayList (); + foreach (Project p in projects) + if (p.IsBackendLoaded) + projectBackends.Add (p.ProjectBackend); + + if (!Backend.UpdateLibraries (assemblies, projectBackends, allowBackendRestart, forceUnload)) + RestartBackend (); + } + + public virtual void Dispose () + { + if (disposed) + return; + + disposed = true; + ClearCollections (); + ArrayList copy = (ArrayList) projects.Clone (); + foreach (Project p in copy) + p.Dispose (); + if (propertiesWidget != null) + propertiesWidget.Destroy (); + if (paletteWidget != null) + paletteWidget.Destroy (); + if (projectWidget != null) + projectWidget.Destroy (); + if (signalsWidget != null) + signalsWidget.Destroy (); + widgetLibraries.Clear (); + System.Runtime.Remoting.RemotingServices.Disconnect (this); + } + + public override object InitializeLifetimeService () + { + // Will be disconnected when calling Dispose + return null; + } + + internal ApplicationBackend Backend { + get { return backend; } + set { backend = value; } + } + + void ProjectDisposed (object sender, EventArgs args) + { + projects.Remove (sender as Project); + if (!disposed) + UpdateWidgetLibraries (false, false); + } + +// public Project LoadProject (string path, IProjectDesignInfo info) +// { +// Project p = new Project (this, info); +// p.Load (path); +// projects.Add (p); +// p.Disposed += ProjectDisposed; +// return p; +// } + + public Project CreateProject (IProjectDesignInfo info) + { + Project p = new Project (this, info); + projects.Add (p); + p.Disposed += ProjectDisposed; + return p; + } + + public ComponentType[] GetComponentTypes (string fileName) + { + if (IsWidgetLibrary (fileName)) + return CecilWidgetLibrary.GetComponentTypes (this, fileName).ToArray (); + else + return new ComponentType [0]; + } + + public void AddWidgetLibrary (string assemblyPath) + { + if (!widgetLibraries.Contains (assemblyPath)) { + widgetLibraries.Add (assemblyPath); + Backend.GlobalWidgetLibraries = widgetLibraries; + UpdateWidgetLibraries (false, false); + } + } + + public void RemoveWidgetLibrary (string assemblyPath) + { + widgetLibraries.Remove (assemblyPath); + Backend.GlobalWidgetLibraries = widgetLibraries; + UpdateWidgetLibraries (false, false); + } + + public string[] GetWidgetLibraries () + { + return (string[]) widgetLibraries.ToArray (typeof(string)); + } + + public bool IsWidgetLibrary (string assemblyRef) + { + AssemblyResolver resolver = new AssemblyResolver (Backend); + return InternalIsWidgetLibrary (resolver, assemblyRef); + } + + internal static bool InternalIsWidgetLibrary (AssemblyResolver resolver, string assemblyRef) + { + string path; + + if (assemblyRef.EndsWith (".dll") || assemblyRef.EndsWith (".exe")) { + if (!File.Exists (assemblyRef)) + return false; + path = assemblyRef; + } + else { + path = resolver.Resolve (assemblyRef, null); + if (path == null) + return false; + } + + return CecilWidgetLibrary.IsWidgetLibrary (path); + } + + public CodeGenerationResult GenerateProjectCode (string file, string namespaceName, CodeDomProvider provider, GenerationOptions options, params Project[] projects) + { + ArrayList files = new ArrayList (); + CodeGenerationResult res = GenerateProjectCode (options, projects); + + string basePath = Path.GetDirectoryName (file); + string ext = Path.GetExtension (file); + + foreach (SteticCompilationUnit unit in res.Units) { + string fname; + if (unit.Name.Length == 0) + fname = file; + else + fname = Path.Combine (basePath, unit.Name) + ext; + files.Add (fname); + unit.Name = fname; + StreamWriter fileStream = new StreamWriter (fname); + try { + provider.GenerateCodeFromCompileUnit (unit, fileStream, new CodeGeneratorOptions ()); + } finally { + fileStream.Close (); + } + } + return res; + } + + public CodeGenerationResult GenerateProjectCode (GenerationOptions options, params Project[] projects) + { + ProjectBackend[] pbs = new ProjectBackend [projects.Length]; + for (int n=0; n<projects.Length; n++) + pbs [n] = projects [n].ProjectBackend; + + return Backend.GenerateProjectCode (options, pbs); + } + + public Designer ActiveDesigner { + get { + return activeDesigner; + } + set { + if (activeDesigner != value) { + activeDesigner = value; + if (activeDesigner != null) + activeDesigner.SetActive (); + else + ActiveProject = null; + } + } + } + + internal Project ActiveProject { + get { return activeProject; } + set { + activeProject = value; + Backend.ActiveProject = value != null ? value.ProjectBackend : null; + Backend.SetActiveDesignSession (null); + } + } + + internal void SetActiveDesignSession (Project p, WidgetEditSession session) + { + activeProject = p; + Backend.ActiveProject = p != null ? p.ProjectBackend : null; + Backend.SetActiveDesignSession (session); + } + + public WidgetPropertyTree PropertiesWidget { + get { + if (propertiesWidget == null) { + propertiesWidget = new WidgetPropertyTree (this); + propertiesWidget.Destroyed += delegate { propertiesWidget = null; }; + } + return propertiesWidget; + } + } + + public Palette PaletteWidget { + get { + if (paletteWidget == null) { + paletteWidget = new Palette (this); + paletteWidget.Destroyed += delegate { paletteWidget = null; }; + } + return paletteWidget; + } + } + + public WidgetTree WidgetTreeWidget { + get { + if (projectWidget == null) { + projectWidget = new WidgetTree (this); + projectWidget.Destroyed += delegate { projectWidget = null; }; + } + return projectWidget; + } + } + + public SignalsEditor SignalsWidget { + get { + if (signalsWidget == null) { + signalsWidget = new SignalsEditor (this); + signalsWidget.Destroyed += delegate { signalsWidget = null; }; + } + return signalsWidget; + } + } + + public bool AllowInProcLibraries { + get { return allowInProcLibraries; } + set { + allowInProcLibraries = value; + if (backend != null) + backend.AllowInProcLibraries = value; + } + } + + internal void NotifyLibraryUnloaded (string name) + { + // Remove cached types from the unloaded library + ArrayList toDelete = new ArrayList (); + lock (types) { + foreach (ComponentType ct in types.Values) { + if (ct.Library == name) + toDelete.Add (ct.Name); + } + foreach (string s in toDelete) + types.Remove (s); + } + } + + internal abstract ComponentType CreateComponentType (string typeName); + + internal ComponentType GetComponentType (string typeName) + { + lock (types) { + ComponentType t = (ComponentType) types [typeName]; + if (t != null) return t; + + if (typeName == "Gtk.Action" || typeName == "Gtk.ActionGroup") { + t = new ComponentType (this, typeName, "", typeName, "Actions", "2.4", null, ComponentType.Unknown.Icon); + types [typeName] = t; + return t; + } + + t = CreateComponentType (typeName); + types [typeName] = t; + return t; + } + } + + internal Component GetComponent (object cbackend, string name, string type) + { + try { + lock (components) { + if (cbackend == null) + return null; + + Component c = (Component) components [cbackend]; + if (c != null) + return c; + + // If the remote object is already disposed, don't try to create a + // local component. + if (cbackend is ObjectWrapper && ((ObjectWrapper)cbackend).IsDisposed) + return null; + + if (cbackend is Wrapper.Action) { + c = new ActionComponent (this, cbackend, name); + ((ObjectWrapper)cbackend).Frontend = c; + } else if (cbackend is Wrapper.ActionGroup) { + c = new ActionGroupComponent (this, cbackend, name); + ((Wrapper.ActionGroup)cbackend).Frontend = c; + } else if (cbackend is ObjectWrapper) { + c = new WidgetComponent (this, cbackend, name, type != null ? GetComponentType (type) : null); + ((ObjectWrapper)cbackend).Frontend = c; + } else if (cbackend == null) + throw new System.ArgumentNullException ("cbackend"); + else + throw new System.InvalidOperationException ("Invalid component type: " + cbackend.GetType ()); + + components [cbackend] = c; + return c; + } + } + catch (System.Runtime.Remoting.RemotingException) + { + // There may be a remoting exception if the remote wrapper + // has already been disconnected when trying to create the + // component frontend. This may happen since calls are + // dispatched in the GUI thread, so they may be delayed. + return null; + } + } + + internal void DisposeComponent (Component c) + { + lock (components) { + components.Remove (c.Backend); + } + } + } + + internal delegate void BackendChangingHandler (); + internal delegate void BackendChangedHandler (ApplicationBackend oldBackend); +} diff --git a/main/src/addins/MonoDevelop.GtkCore2/libsteticui/ApplicationBackend.cs b/main/src/addins/MonoDevelop.GtkCore2/libsteticui/ApplicationBackend.cs new file mode 100644 index 0000000000..eb738d5642 --- /dev/null +++ b/main/src/addins/MonoDevelop.GtkCore2/libsteticui/ApplicationBackend.cs @@ -0,0 +1,653 @@ + +using System; +using System.IO; +using System.Collections; +using System.Collections.Generic; +using System.CodeDom; +using System.Runtime.Serialization.Formatters.Binary; +using System.Runtime.Remoting; +using System.Runtime.Remoting.Channels; +using System.Runtime.Remoting.Channels.Tcp; +using Mono.Remoting.Channels.Unix; + +namespace Stetic +{ + internal class ApplicationBackend: MarshalByRefObject, IDisposable, IObjectViewer + { + PaletteBackend paletteWidget; + WidgetPropertyTreeBackend propertiesWidget; + SignalsEditorEditSession signalsWidget; + ProjectViewBackend projectWidget; + ArrayList globalWidgetLibraries = new ArrayList (); + AssemblyResolverCallback widgetLibraryResolver; + object targetViewerObject; + bool allowInProcLibraries = true; + Application appFrontend; + string coreLibrary; + + ProjectBackend activeProject; + WidgetEditSession activeDesignSession; + static ApplicationBackendController controller; + + public ApplicationBackend (Application app) + { + appFrontend = app; + coreLibrary = Path.GetFullPath (typeof(Registry).Assembly.Location); + Registry.Initialize (new AssemblyWidgetLibrary (coreLibrary, typeof(Registry).Assembly)); + + WidgetDesignerBackend.DefaultObjectViewer = this; + } + + public static void Main () + { + Gdk.Threads.Init (); + Gtk.Application.Init (); + + System.Threading.Thread.CurrentThread.Name = "gui-thread"; + + // Read the remoting channel to use + + string channel = Console.In.ReadLine (); + + IServerChannelSinkProvider formatterSink = new BinaryServerFormatterSinkProvider (); + formatterSink.Next = new GuiDispatchServerSinkProvider (); + + string unixPath = null; + if (channel == "unix") { + unixPath = System.IO.Path.GetTempFileName (); + Hashtable props = new Hashtable (); + props ["path"] = unixPath; + props ["name"] = "__internal_unix"; + ChannelServices.RegisterChannel (new UnixChannel (props, null, formatterSink), false); + } else { + Hashtable props = new Hashtable (); + props ["port"] = 0; + props ["name"] = "__internal_tcp"; + ChannelServices.RegisterChannel (new TcpChannel (props, null, formatterSink), false); + } + + // Read the reference to the application + + string sref = Console.In.ReadLine (); + byte[] data = Convert.FromBase64String (sref); + MemoryStream ms = new MemoryStream (data); + BinaryFormatter bf = new BinaryFormatter (); + + controller = (ApplicationBackendController) bf.Deserialize (ms); + ApplicationBackend backend = new ApplicationBackend (controller.Application); + + controller.Connect (backend); + + Gdk.Threads.Enter (); + Gtk.Application.Run (); + Gdk.Threads.Leave (); + + controller.Disconnect (backend); + } + + public virtual void Dispose () + { + if (controller != null) { + Gtk.Application.Quit (); + } + System.Runtime.Remoting.RemotingServices.Disconnect (this); + } + + public override object InitializeLifetimeService () + { + // Will be disconnected when calling Dispose + return null; + } + + public AssemblyResolverCallback WidgetLibraryResolver { + get { return widgetLibraryResolver; } + set { widgetLibraryResolver = value; } + } + + public MimeResolverDelegate MimeResolver { + set { ResourceInfo.MimeResolver = value; } + } + + public Editor.ShowUrlDelegate ShowUrl { + set { Editor.NonContainerWarningDialog.ShowUrl = value; } + } + + public bool ShowNonContainerWarning { + get { return Wrapper.Container.ShowNonContainerWarning; } + set { Wrapper.Container.ShowNonContainerWarning = value; } + } + + public ProjectBackend LoadProject (string path) + { + ProjectBackend p = new ProjectBackend (this); + + if (System.IO.Path.GetExtension (path) == ".glade") { + GladeFiles.Import (p, path); + } else { + p.Load (path); + } + return p; + } + + public CodeGenerationResult GenerateProjectCode (GenerationOptions options, ProjectBackend[] projects) + { + return CodeGenerator.GenerateProjectCode (options, projects); + } + + public ArrayList GlobalWidgetLibraries { + get { return globalWidgetLibraries; } + set { globalWidgetLibraries = value; } + } + + public bool AllowInProcLibraries { + get { return allowInProcLibraries; } + set { allowInProcLibraries = value; } + } + + public bool UpdateLibraries (ArrayList libraries, ArrayList projects, bool allowBackendRestart, bool forceUnload) + { + try { + Registry.BeginChangeSet (); + + libraries.Add (Registry.CoreWidgetLibrary.Name); +// libraries.Add (Registry.CoreWidgetLibrary2.Name); + + // Notify libraries that need to be unloaded and loaded again + foreach (WidgetLibrary lib in Registry.RegisteredWidgetLibraries) { + if (lib.NeedsReload) + appFrontend.NotifyLibraryUnloaded (lib.Name); + } + + if (!Registry.ReloadWidgetLibraries () && allowBackendRestart) + return false; + + // Store a list of registered libraries, used later to know which + // ones need to be unloaded + + ArrayList loaded = new ArrayList (); + foreach (WidgetLibrary alib in Registry.RegisteredWidgetLibraries) + loaded.Add (alib.Name); + + // Load required libraries + + Hashtable visited = new Hashtable (); + LoadLibraries (new AssemblyResolver (this), visited, libraries); + + foreach (ProjectBackend project in projects) + LoadLibraries (project.Resolver, visited, project.WidgetLibraries); + + // Unload libraries which are not required + + foreach (string name in loaded) { + if (!visited.Contains (name)) { + if (forceUnload && allowBackendRestart) + return false; + appFrontend.NotifyLibraryUnloaded (name); + Registry.UnregisterWidgetLibrary (Registry.GetWidgetLibrary (name)); + } + } + + return true; + } + finally { + Registry.EndChangeSet (); + } + } + + internal void LoadLibraries (AssemblyResolver resolver, IEnumerable libraries) + { + try { + Registry.BeginChangeSet (); + Hashtable visited = new Hashtable (); + LoadLibraries (resolver, visited, libraries); + } finally { + Registry.EndChangeSet (); + } + } + + void LoadLibraries (AssemblyResolver resolver, Hashtable visited, IEnumerable libraries) + { + // Convert all assembly names to assembly paths before registering the libraries. + // The registry and the library cache will only handle full paths. + foreach (string s in libraries) { + string sr = resolver.Resolve (s, null); + if (sr != null) + AddLibrary (resolver, visited, sr); + } + Registry.ReloadWidgetLibraries (); + } + + WidgetLibrary AddLibrary (AssemblyResolver resolver, Hashtable visited, string s) + { + if (Registry.IsRegistered (s)) { + WidgetLibrary lib = Registry.GetWidgetLibrary (s); + CheckDependencies (resolver, visited, lib); + return lib; + } + + // Avoid registering direct references of libstetic + if (Path.GetFileName (s) == "libstetic.dll" && s != coreLibrary) + return null; + + WidgetLibrary alib = CreateLibrary (resolver, s); + if (alib == null) + return null; + + RegisterLibrary (resolver, visited, alib); + return alib; + } + + void RegisterLibrary (AssemblyResolver resolver, Hashtable visited, WidgetLibrary lib) + { + if (lib == null || visited.Contains (lib.Name)) + return; + + visited [lib.Name] = lib; + + foreach (string s in lib.GetLibraryDependencies ()) { + if (!Application.InternalIsWidgetLibrary (resolver, s)) + continue; + AddLibrary (resolver, visited, s); + } + + try { + Registry.RegisterWidgetLibrary (lib); + } catch (Exception ex) { + // Catch errors when loading a library to avoid aborting + // the whole update method. After all, that's not a fatal + // error (some widgets just won't be shown). + // FIXME: return the error somewhere + Console.WriteLine (ex); + } + } + + WidgetLibrary CreateLibrary (AssemblyResolver resolver, string name) + { + try { + if (allowInProcLibraries) + return new AssemblyWidgetLibrary (resolver, name); + else + return new CecilWidgetLibrary (resolver, name); + } catch (Exception) { + // FIXME: handle the error, but keep loading. + return null; + } + } + + void CheckDependencies (AssemblyResolver resolver, Hashtable visited, WidgetLibrary lib) + { + if (visited.Contains (lib.Name)) + return; + + visited [lib.Name] = lib; + +// foreach (string dep in lib.GetLibraryDependencies ()) { +// WidgetLibrary depLib = Registry.GetWidgetLibrary (dep); +// if (depLib == null) +// AddLibrary (resolver, visited, dep); +// else +// CheckDependencies (resolver, visited, depLib); +// } + } + + public ProjectBackend ActiveProject { + get { return activeProject; } + set { + if (activeProject == value) + return; + activeProject = value; + if (paletteWidget != null) { + paletteWidget.ProjectBackend = activeProject; + paletteWidget.WidgetLibraries = GetActiveLibraries (); + } + if (propertiesWidget != null) + propertiesWidget.ProjectBackend = activeProject; + if (signalsWidget != null) + signalsWidget.ProjectBackend = activeProject; + } + } + + public void SetActiveDesignSession (WidgetEditSession session) + { + activeDesignSession = session; + if (projectWidget != null) + projectWidget.Bind (session); + } + + public WidgetLibrary[] GetActiveLibraries () + { + return GetProjectLibraries (activeProject); + } + + public WidgetLibrary[] GetProjectLibraries (ProjectBackend project) + { + ArrayList projectLibs = new ArrayList (); + if (project != null) + projectLibs.AddRange (project.WidgetLibraries); + + ArrayList list = new ArrayList (); + list.Add (Registry.CoreWidgetLibrary); + foreach (WidgetLibrary alib in Registry.RegisteredWidgetLibraries) { + if (project != null && !alib.SupportsGtkVersion (project.TargetGtkVersion)) + continue; + string aname = alib.Name; + if (projectLibs.Contains (aname) || globalWidgetLibraries.Contains (aname)) + list.Add (alib); + } + return (WidgetLibrary[]) list.ToArray (typeof(WidgetLibrary)); + } + + public ProjectBackend CreateProject () + { + return new ProjectBackend (this); + } + + object IObjectViewer.TargetObject { + get { return targetViewerObject; } + set { + targetViewerObject = value; + if (propertiesWidget != null) + propertiesWidget.TargetObject = targetViewerObject; + if (signalsWidget != null) + signalsWidget.Editor.TargetObject = targetViewerObject; + } + } + + public PaletteBackend GetPaletteWidget () + { + if (paletteWidget == null) { + paletteWidget = new PaletteBackend (this); + paletteWidget.ProjectBackend = activeProject; + paletteWidget.WidgetLibraries = GetActiveLibraries (); + } + return paletteWidget; + } + + public void CreatePaletteWidgetPlug (uint socketId) + { + Gtk.Plug plug = new Gtk.Plug (socketId); + plug.Decorated = false; +// Gtk.Window plug = new Gtk.Window (""); + plug.Add (GetPaletteWidget ()); + plug.Show (); + } + + public void DestroyPaletteWidgetPlug () + { + if (paletteWidget != null) { + Gtk.Plug plug = (Gtk.Plug)paletteWidget.Parent; + plug.Remove (paletteWidget); + plug.Destroy (); + } + } + + public WidgetPropertyTreeBackend GetPropertiesWidget () + { + if (propertiesWidget == null) { + propertiesWidget = new WidgetPropertyTreeBackend (); + propertiesWidget.ProjectBackend = activeProject; + propertiesWidget.TargetObject = targetViewerObject; + } + return propertiesWidget; + } + + public void CreatePropertiesWidgetPlug (uint socketId) + { + Gtk.Plug plug = new Gtk.Plug (socketId); + plug.Decorated = false; +// Gtk.Window plug = new Gtk.Window (""); + plug.Add (GetPropertiesWidget ()); + plug.Show (); + } + + public void DestroyPropertiesWidgetPlug () + { + if (propertiesWidget != null) { + Gtk.Plug plug = (Gtk.Plug) propertiesWidget.Parent; + plug.Remove (propertiesWidget); + plug.Destroy (); + } + } + + public SignalsEditorEditSession GetSignalsWidget (SignalsEditorFrontend frontend) + { + if (signalsWidget == null) { + signalsWidget = new SignalsEditorEditSession (frontend); + signalsWidget.ProjectBackend = activeProject; + signalsWidget.Editor.TargetObject = targetViewerObject; + } + return signalsWidget; + } + + public SignalsEditorEditSession CreateSignalsWidgetPlug (SignalsEditorFrontend frontend, uint socketId) + { + Gtk.Plug plug = new Gtk.Plug (socketId); + plug.Decorated = false; +// Gtk.Window plug = new Gtk.Window (""); + SignalsEditorEditSession session = GetSignalsWidget (frontend); + plug.Add (session.Editor); + plug.Show (); + return session; + } + + public void DestroySignalsWidgetPlug () + { + if (signalsWidget != null) { + Gtk.Plug plug = (Gtk.Plug) signalsWidget.Editor.Parent; + plug.Remove (signalsWidget.Editor); + plug.Destroy (); + } + } + + public ProjectViewBackend GetProjectWidget (ProjectViewFrontend frontend) + { + if (projectWidget == null) { + projectWidget = new ProjectViewBackend (frontend); + projectWidget.Bind (activeDesignSession); + } + return projectWidget; + } + + public void CreateProjectWidgetPlug (ProjectViewFrontend frontend, uint socketId) + { + Gtk.Plug plug = new Gtk.Plug (socketId); + plug.Decorated = false; +// Gtk.Window plug = new Gtk.Window (""); + plug.Add (GetProjectWidget (frontend)); + plug.Show (); + } + + public void DestroyProjectWidgetPlug () + { + if (projectWidget != null) { + Gtk.Plug plug = (Gtk.Plug)projectWidget.Parent; + plug.Remove (projectWidget); + plug.Destroy (); + } + } + + public ArrayList GetComponentTypes () + { + ArrayList list = new ArrayList (); + foreach (ClassDescriptor cd in Registry.AllClasses) + list.Add (cd.Name); + return list; + } + + public bool GetClassDescriptorInfo (string name, out string desc, out string className, out string category, out string targetGtkVersion, out string library, out byte[] icon) + { + ClassDescriptor cls = Registry.LookupClassByName (name); + if (cls == null) { + icon = null; + desc = null; + className = null; + category = null; + targetGtkVersion = null; + library = null; + return false; + } + desc = cls.Label; + className = cls.WrappedTypeName; + category = cls.Category; + targetGtkVersion = cls.TargetGtkVersion; + library = cls.Library.Name; + icon = cls.Icon != null ? cls.Icon.SaveToBuffer ("png") : null; + return true; + } + + public object[] GetClassDescriptorInitializationValues (string name) + { + ClassDescriptor cls = Registry.LookupClassByName (name); + ArrayList list = new ArrayList (); + + foreach (Stetic.PropertyDescriptor prop in cls.InitializationProperties) + { + if (prop.PropertyType.IsValueType) { + // Avoid sending to the main process types which should not be loaded there + if (prop.PropertyType.Assembly == typeof(object).Assembly || + prop.PropertyType.Assembly == typeof(Gtk.Widget).Assembly || + prop.PropertyType.Assembly == typeof(Gdk.Window).Assembly || + prop.PropertyType.Assembly == typeof(GLib.Object).Assembly) { + + list.Add (Activator.CreateInstance (prop.PropertyType)); + } else + return new object [0]; + } else + list.Add (null); + } + return list.ToArray (); + } + + public void ShowPaletteGroup (string name, string label) + { + GetPaletteWidget ().ShowGroup (name, label); + } + + public void HidePaletteGroup (string name) + { + GetPaletteWidget ().HideGroup (name); + } + + internal void GetClipboardOperations (object obj, out bool canCut, out bool canCopy, out bool canPaste) + { + Stetic.Wrapper.Widget wrapper = obj as Stetic.Wrapper.Widget; + if (wrapper != null) { + canCut = wrapper.InternalChildProperty == null && !wrapper.IsTopLevel; + canCopy = !wrapper.IsTopLevel; + canPaste = false; + } + else if (obj is Placeholder) { + // FIXME: make it work for placeholders + canCut = canCopy = false; + canPaste = true; + } + else { + canCut = canCopy = canPaste = false; + } + } + + internal void GetComponentInfo (object obj, out string name, out string type) + { + Stetic.Wrapper.Widget wrapper = obj as Stetic.Wrapper.Widget; + name = wrapper.Wrapped.Name; + type = wrapper.ClassDescriptor.Name; + } + + internal void RenameWidget (Wrapper.Widget w, string newName) + { + w.Wrapped.Name = newName; + } + + internal byte[] GetActionIcon (Wrapper.Action ac) + { + Gdk.Pixbuf pix = ac.RenderIcon (Gtk.IconSize.Menu); + if (pix == null) + return null; + return pix.SaveToBuffer ("png"); + } + + internal ArrayList GetWidgetChildren (Wrapper.Widget ww) + { + Stetic.Wrapper.Container cw = ww as Stetic.Wrapper.Container; + if (cw == null) + return null; + + ArrayList list = new ArrayList (); + foreach (object ob in cw.RealChildren) { + ObjectWrapper ow = ObjectWrapper.Lookup (ob); + if (ow != null) + list.Add (Component.GetSafeReference (ow)); + } + return list; + } + + internal void RemoveWidgetSignal (ObjectWrapper wrapper, Signal signal) + { + foreach (Signal s in wrapper.Signals) { + if (s.Handler == signal.Handler && s.SignalDescriptor.Name == signal.SignalDescriptor.Name) { + wrapper.Signals.Remove (s); + return; + } + } + } + + internal Wrapper.ActionGroup[] GetActionGroups (Wrapper.Widget widget) + { + return widget.LocalActionGroups.ToArray (); + } + + internal ObjectBindInfo[] GetBoundComponents (ObjectWrapper wrapper) + { + return CodeGenerator.GetFieldsToBind (wrapper).ToArray (); + } + + internal ObjectWrapper GetPropertyTreeTarget () + { + return targetViewerObject as ObjectWrapper; + } + + internal void BeginComponentDrag (ProjectBackend project, string desc, string className, ObjectWrapper wrapper, Gtk.Widget source, Gdk.DragContext ctx, ComponentDropCallback callback) + { + if (wrapper != null) { + Stetic.Wrapper.ActionPaletteItem it = new Stetic.Wrapper.ActionPaletteItem (Gtk.UIManagerItemType.Menuitem, null, (Wrapper.Action) wrapper); + DND.Drag (source, ctx, it); + } + else if (callback != null) { + DND.Drag (source, ctx, delegate () { + callback (); + + // If the class name has an assembly name, remove it now + int i = className.IndexOf (','); + if (i != -1) + className = className.Substring (0, i); + + ClassDescriptor cls = Registry.LookupClassByName (className); + if (cls != null) + return cls.NewInstance (project) as Gtk.Widget; + else { + // Class not found, show an error + string msg = string.Format ("The widget '{0}' could not be found.", className); + Gtk.MessageDialog dlg = new Gtk.MessageDialog (null, Gtk.DialogFlags.Modal, Gtk.MessageType.Error, Gtk.ButtonsType.Close, msg); + dlg.Run (); + dlg.Destroy (); + return null; + } + }, + (desc != null && desc.Length > 0) ? desc : className + ); + } + else { + ClassDescriptor cls = Registry.LookupClassByName (className); + DND.Drag (source, ctx, cls.NewInstance (project) as Gtk.Widget); + } + } + + public string ResolveAssembly (string assemblyName) + { + if (widgetLibraryResolver != null) + return widgetLibraryResolver (assemblyName); + else + return null; + } + } +} diff --git a/main/src/addins/MonoDevelop.GtkCore2/libsteticui/ApplicationBackendController.cs b/main/src/addins/MonoDevelop.GtkCore2/libsteticui/ApplicationBackendController.cs new file mode 100644 index 0000000000..5fdbbea4d5 --- /dev/null +++ b/main/src/addins/MonoDevelop.GtkCore2/libsteticui/ApplicationBackendController.cs @@ -0,0 +1,105 @@ + +using System; +using System.IO; +using System.Diagnostics; +using System.Threading; +using System.Runtime.Serialization.Formatters.Binary; +using System.Runtime.Remoting; +using System.Runtime.Remoting.Channels; +using System.Runtime.Remoting.Channels.Tcp; + +namespace Stetic +{ + internal class ApplicationBackendController: MarshalByRefObject + { + bool stopping; + ApplicationBackend backend; + string channelId; + IsolatedApplication app; + + ManualResetEvent runningEvent = new ManualResetEvent (false); + + public event EventHandler Stopped; + + public ApplicationBackendController (IsolatedApplication app, string channelId) + { + this.app = app; + this.channelId = channelId; + } + + public ApplicationBackend Backend { + get { return backend; } + } + + public Application Application { + get { return app; } + } + + public void StartBackend () + { + runningEvent.Reset (); + + string asm = GetType().Assembly.Location; + + BinaryFormatter bf = new BinaryFormatter (); + ObjRef oref = RemotingServices.Marshal (this); + MemoryStream ms = new MemoryStream (); + bf.Serialize (ms, oref); + string sref = Convert.ToBase64String (ms.ToArray ()); + + Process process = new Process (); + process.StartInfo = new ProcessStartInfo ("sh", "-c \"mono --debug " + asm + "\""); + process.StartInfo.WorkingDirectory = AppDomain.CurrentDomain.BaseDirectory; + process.StartInfo.UseShellExecute = false; + process.StartInfo.RedirectStandardInput = true; + process.EnableRaisingEvents = true; + process.Start (); + process.StandardInput.WriteLine (channelId); + process.StandardInput.WriteLine (sref); + process.StandardInput.Flush (); + process.Exited += OnExited; + + if (!runningEvent.WaitOne (10000, false)) + throw new ApplicationException ("Couldn't create a remote process."); + } + + public void StopBackend (bool waitUntilDone) + { + stopping = true; + runningEvent.Reset (); + backend.Dispose (); + if (waitUntilDone) + runningEvent.WaitOne (9000, false); + } + + void OnExited (object o, EventArgs args) + { + Gtk.Application.Invoke (OnExitedInGui); + } + + void OnExitedInGui (object o, EventArgs args) + { + if (!stopping && Stopped != null) + Stopped (this, EventArgs.Empty); + System.Runtime.Remoting.RemotingServices.Disconnect (this); + } + + internal void Connect (ApplicationBackend backend) + { + this.backend = backend; + runningEvent.Set (); + } + + internal void Disconnect (ApplicationBackend backend) + { + this.backend = null; + runningEvent.Set (); + } + + public override object InitializeLifetimeService () + { + // Will be disconnected when calling Dispose + return null; + } + } +} diff --git a/main/src/addins/MonoDevelop.GtkCore2/libsteticui/AssemblyResolver.cs b/main/src/addins/MonoDevelop.GtkCore2/libsteticui/AssemblyResolver.cs new file mode 100644 index 0000000000..afc8cd6dc6 --- /dev/null +++ b/main/src/addins/MonoDevelop.GtkCore2/libsteticui/AssemblyResolver.cs @@ -0,0 +1,242 @@ +// +// BaseAssemblyResolver.cs +// +// Author: +// Jb Evain (jbevain@gmail.com) +// +// (C) 2007 Novell, Inc. +// +// 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. +// + +// This code is a modified version of the assembly resolver implemented in Cecil. +// Keep in synch as much as possible. + +using System; +using System.Collections; +using System.Collections.Specialized; +using System.IO; +using System.Text; +using Mono.Cecil; + +namespace Stetic { + + internal class AssemblyResolver : BaseAssemblyResolver { + + Hashtable _assemblies; + ApplicationBackend app; + + public IDictionary AssemblyCache { + get { return _assemblies; } + } + + public AssemblyResolver (ApplicationBackend app) + { + this.app = app; + _assemblies = new Hashtable (); + } + + public StringCollection Directories = new StringCollection (); + + public override AssemblyDefinition Resolve (AssemblyNameReference name) + { + return Resolve (name, (string)null); + } + + public AssemblyDefinition Resolve (AssemblyNameReference name, string basePath) + { + AssemblyDefinition asm = (AssemblyDefinition) _assemblies [name.FullName]; + if (asm == null) { + if (app != null) { + string ares = app.ResolveAssembly (name.Name); + if (ares != null) { + asm = AssemblyFactory.GetAssembly (ares); + asm.Resolver = this; + _assemblies [name.FullName] = asm; + return asm; + } + } + string file = Resolve (name.FullName, basePath); + if (file != null) + asm = AssemblyFactory.GetAssembly (file); + else + asm = base.Resolve (name); + asm.Resolver = this; + _assemblies [name.FullName] = asm; + } + + return asm; + } + + public void ClearCache () + { + _assemblies.Clear (); + } + + public TypeDefinition Resolve (TypeReference type) + { + if (type is TypeDefinition) + return (TypeDefinition) type; + + AssemblyNameReference reference = type.Scope as AssemblyNameReference; + if (reference != null) { + AssemblyDefinition assembly = Resolve (reference); + return assembly.MainModule.Types [type.FullName]; + } + + ModuleDefinition module = type.Scope as ModuleDefinition; + if (module != null) + return module.Types [type.FullName]; + + throw new NotImplementedException (); + } + + public void CacheAssembly (AssemblyDefinition assembly) + { + _assemblies [assembly.Name.FullName] = assembly; + assembly.Resolver = this; + } + + public string Resolve (string assemblyName, string basePath) + { + if (Path.IsPathRooted (assemblyName) && (assemblyName.EndsWith (".dll") || assemblyName.EndsWith (".exe"))) + return Path.GetFullPath (assemblyName); + + if (app != null) { + string ares = app.ResolveAssembly (assemblyName); + if (ares != null) + return Path.GetFullPath (ares); + } + + StringCollection col = new StringCollection (); + col.Add (basePath); + foreach (string s in Directories) + col.Add (s); + + try { + return Resolve (AssemblyNameReference.Parse (assemblyName), col); + } catch { + } + return null; + } + + public string Resolve (AssemblyNameReference name, StringCollection basePaths) + { + string [] exts = new string [] { ".dll", ".exe" }; + + if (basePaths != null) { + foreach (string dir in basePaths) { + foreach (string ext in exts) { + string file = Path.Combine (dir, name.Name + ext); + if (File.Exists (file)) + return file; + } + } + } + + if (name.Name == "mscorlib") + return GetCorlib (name); + + string asm = GetAssemblyInGac (name); + if (asm != null) + return Path.GetFullPath (asm); + + throw new FileNotFoundException ("Could not resolve: " + name); + } + + string GetCorlib (AssemblyNameReference reference) + { + if (typeof (object).Assembly.GetName ().Version == reference.Version) + return typeof (object).Assembly.Location; + + string path = Directory.GetParent ( + Directory.GetParent ( + typeof (object).Module.FullyQualifiedName).FullName + ).FullName; + + if (OnMono ()) { + if (reference.Version.Major == 1) + path = Path.Combine (path, "1.0"); + else if (reference.Version.Major == 2) + path = Path.Combine (path, "2.0"); + else + throw new NotSupportedException ("Version not supported: " + reference.Version); + } else { + if (reference.Version.ToString () == "1.0.3300.0") + path = Path.Combine (path, "v1.0.3705"); + else if (reference.Version.ToString () == "1.0.5000.0") + path = Path.Combine (path, "v1.1.4322"); + else if (reference.Version.ToString () == "2.0.0.0") + path = Path.Combine (path, "v2.0.50727"); + else + throw new NotSupportedException ("Version not supported: " + reference.Version); + } + + return Path.GetFullPath (Path.Combine (path, "mscorlib.dll")); + } + + static string GetAssemblyInGac (AssemblyNameReference reference) + { + if (reference.PublicKeyToken == null || reference.PublicKeyToken.Length == 0) + return null; + + string currentGac = GetCurrentGacPath (); + if (OnMono ()) { + string s = GetAssemblyFile (reference, currentGac); + if (File.Exists (s)) + return s; + } else { + string [] gacs = new string [] {"GAC_MSIL", "GAC_32", "GAC"}; + for (int i = 0; i < gacs.Length; i++) { + string gac = Path.Combine (Directory.GetParent (currentGac).FullName, gacs [i]); + string asm = GetAssemblyFile (reference, gac); + if (Directory.Exists (gac) && File.Exists (asm)) + return asm; + } + } + + return null; + } + + static string GetAssemblyFile (AssemblyNameReference reference, string gac) + { + StringBuilder sb = new StringBuilder (); + sb.Append (reference.Version); + sb.Append ("__"); + for (int i = 0; i < reference.PublicKeyToken.Length; i++) + sb.Append (reference.PublicKeyToken [i].ToString ("x2")); + + return Path.Combine ( + Path.Combine ( + Path.Combine (gac, reference.Name), sb.ToString ()), + string.Concat (reference.Name, ".dll")); + } + + static string GetCurrentGacPath () + { + return Directory.GetParent ( + Directory.GetParent ( + Path.GetDirectoryName ( + typeof (Uri).Module.FullyQualifiedName) + ).FullName + ).FullName; + } + } +} diff --git a/main/src/addins/MonoDevelop.GtkCore2/libsteticui/AssemblyWidgetLibrary.cs b/main/src/addins/MonoDevelop.GtkCore2/libsteticui/AssemblyWidgetLibrary.cs new file mode 100644 index 0000000000..f57e43768e --- /dev/null +++ b/main/src/addins/MonoDevelop.GtkCore2/libsteticui/AssemblyWidgetLibrary.cs @@ -0,0 +1,141 @@ +using System; +using System.Collections; +using System.Reflection; +using System.Xml; +using System.IO; + +namespace Stetic +{ + internal class AssemblyWidgetLibrary: WidgetLibrary + { + static LibraryCache Cache = LibraryCache.Cache; + + Assembly assembly; + string name; + AssemblyResolver resolver; + LibraryCache.LibraryInfo cache_info; + + public AssemblyWidgetLibrary (string name, Assembly assembly) + { + this.name = name; + this.assembly = assembly; + UpdateCache (); + } + + public AssemblyWidgetLibrary (AssemblyResolver resolver, string assemblyPath) + { + this.name = assemblyPath; + + string ares = resolver.Resolve (assemblyPath, null); + if (ares != null) + assemblyPath = ares; + + this.resolver = resolver; + if (assemblyPath.EndsWith (".dll") || assemblyPath.EndsWith (".exe")) { + if (File.Exists (assemblyPath)) + assembly = Assembly.LoadFrom (assemblyPath); + } else + assembly = Assembly.Load (assemblyPath); + + if (assembly == null) + throw new InvalidOperationException ("Couldn't load assembly at " + assemblyPath); + + UpdateCache (); + } + + void UpdateCache () + { + Cache.Refresh (resolver, assembly.Location); + cache_info = Cache [assembly.Location]; + } + + public override string Name { + get { return name; } + } + + public override bool NeedsReload { + get { + return File.Exists (assembly.Location) && !Cache.IsCurrent (assembly.Location); + } + } + + public override bool CanReload { + get { return false; } + } + + public override void Load () + { + Load (cache_info.ObjectsDocument); + } + + 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 +/* + Disabled. The problem is that Assembly.Load tries to load the exact version + of the assembly, and loaded references may not have the same exact version. + + foreach (AssemblyName an in assembly.GetReferencedAssemblies ()) { + Assembly a = Assembly.Load (an); + t = a.GetType (typeName); + if (t != null) return t; + } +*/ + return null; + } + + public override System.IO.Stream GetResource (string name) + { + return assembly.GetManifestResourceStream (name); + } + + public override string[] GetLibraryDependencies () + { + if (!cache_info.HasWidgets) + return new string [0]; + + ArrayList list = new ArrayList (); + ScanLibraries (list, assembly); + return (string[]) list.ToArray (typeof(string)); + } + + void ScanLibraries (ArrayList list, Assembly asm) + { + foreach (AssemblyName aname in asm.GetReferencedAssemblies ()) { + Assembly depasm = null; + try { + depasm = Assembly.Load (aname); + } catch { + } + + if (depasm == null) { + string file = resolver.Resolve (aname.FullName, Path.GetDirectoryName (asm.Location)); + if (file != null) + depasm = Assembly.LoadFrom (file); + else + throw new InvalidOperationException ("Assembly not found: " + aname.FullName); + } + + ManifestResourceInfo res = depasm.GetManifestResourceInfo ("objects.xml"); + if (res != null) + list.Add (depasm.Location); + } + } + + public override void Flush () + { + base.Flush (); + if (resolver != null) + resolver.ClearCache (); + } + } + +} diff --git a/main/src/addins/MonoDevelop.GtkCore2/libsteticui/CecilClassDescriptor.cs b/main/src/addins/MonoDevelop.GtkCore2/libsteticui/CecilClassDescriptor.cs new file mode 100644 index 0000000000..08a3d8cc04 --- /dev/null +++ b/main/src/addins/MonoDevelop.GtkCore2/libsteticui/CecilClassDescriptor.cs @@ -0,0 +1,382 @@ +using System; +using System.Collections; +using System.IO; +using System.Xml; +using System.Reflection; +using Mono.Cecil; + +namespace Stetic +{ + internal class CecilClassDescriptor: Stetic.ClassDescriptor + { + string wrappedTypeName; + ClassDescriptor typeClassDescriptor; + ClassDescriptor wrapperClassDescriptor; + Gdk.Pixbuf icon; + TypeDefinition type; + XmlElement steticDefinition; + CecilWidgetLibrary cecilLib; + bool useCustomWidgetBox; + string widgetId; + bool canGenerateCode; + + public CecilClassDescriptor (CecilWidgetLibrary lib, XmlElement element, ClassDescriptor typeClassDescriptor, XmlElement steticDefinition, TypeDefinition cls) + { + this.cecilLib = lib; + this.steticDefinition = steticDefinition; + this.typeClassDescriptor = typeClassDescriptor; + wrappedTypeName = element.GetAttribute ("type"); + type = cls; + Load (element); + type = null; + canGenerateCode = true; + + string baseType = element.GetAttribute ("base-type"); + if (baseType.Length > 0) { + wrapperClassDescriptor = Registry.LookupClassByName (baseType); + if (wrapperClassDescriptor == null) + throw new InvalidOperationException ("Unknown base type: " + baseType); + } else { + wrapperClassDescriptor = typeClassDescriptor; + } + + if (steticDefinition == null && !AllowChildren && NeedsBlackBox (typeClassDescriptor.Name)) { + // It is not possible to create instances of that widget, instead we'll have + // to create the typical custom widget black box. + + if (!CanCreateWidgetInstance (wrapperClassDescriptor.Name)) + throw new InvalidOperationException ("Can't load widget type '" + Name + "'. Instances of that type can't be created because the type can't be loaded into the process."); + + useCustomWidgetBox = true; + } + + widgetId = Name.ToLower (); + int i = widgetId.LastIndexOf ('.'); + if (i != -1) { + if (i != widgetId.Length - 1) + widgetId = widgetId.Substring (i+1); + else + widgetId = widgetId.Replace (".", ""); + } + + string iconName = element.GetAttribute ("icon"); + icon = lib.GetEmbeddedIcon (iconName); + + // If the class is a custom widget created using stetic, it means that it has + // simple property and there is no custom logic, so it is safe to generate code + // for this class. + if (steticDefinition != null) + canGenerateCode = true; + + // If it has a custom wrapper, then it definitely has custom logic, so it can't generate code + if (element.HasAttribute ("wrapper")) + canGenerateCode = false; + } + + public override string WrappedTypeName { + get { return wrappedTypeName; } + } + + public override Gdk.Pixbuf Icon { + get { return icon; } + } + + public bool CanGenerateCode { + get { return canGenerateCode; } + } + + public override object CreateInstance (Stetic.IProject proj) + { + Gtk.Widget res; + + if (useCustomWidgetBox) { + res = CreateFakeWidget (wrapperClassDescriptor.Name); + res.ShowAll (); + } + else if (steticDefinition != null) { + Gtk.Container w = Stetic.WidgetUtils.ImportWidget (proj, steticDefinition) as Gtk.Container; + MakeChildrenUnselectable (w); + res = w; + } + else { + res = (Gtk.Widget) typeClassDescriptor.CreateInstance (proj); + + // If it is a custom widget and there is no stetic project for it, just + // show it as a regular custom widget. + Stetic.CustomWidget custom = res as Stetic.CustomWidget; + if (custom != null) { + Stetic.Custom c = new Stetic.Custom (); + // Give it some default size + c.WidthRequest = 20; + c.HeightRequest = 20; + custom.Add (c); + custom.ShowAll (); + res = custom; + } + } + + res.Name = widgetId; + return res; + } + + public override Stetic.ObjectWrapper CreateWrapper () + { + return wrapperClassDescriptor.CreateWrapper (); + } + + protected override Stetic.ItemDescriptor CreateItemDescriptor (XmlElement elem, Stetic.ItemGroup group) + { + string mname = elem.GetAttribute ("name"); + if (elem.Name == "property") { + if (type != null) { + PropertyDefinition propInfo = FindProperty (type, mname); + if (propInfo != null) + return new CecilPropertyDescriptor (cecilLib, elem, group, this, propInfo); + } + else + return new CecilPropertyDescriptor (cecilLib, elem, group, this, null); + } + else if (elem.Name == "signal") { + if (type != null) { + EventDefinition signalInfo = FindEvent (type, mname); + if (signalInfo != null) + return new CecilSignalDescriptor (cecilLib, elem, group, this, signalInfo); + } + else + return new CecilSignalDescriptor (cecilLib, elem, group, this, null); + } + else + return base.CreateItemDescriptor (elem, group); + + return null; + } + + PropertyDefinition FindProperty (TypeDefinition cls, string name) + { + foreach (PropertyDefinition propInfo in cls.Properties) + if (propInfo.Name == name) + return propInfo; + + if (cls.BaseType == null) + return null; + + string baseType = cls.BaseType.FullName; + Type t = Registry.GetType (baseType, false); + if (t != null) { + PropertyInfo prop = t.GetProperty (name); + if (prop != null) { + TypeReference tref = new TypeReference (prop.PropertyType.Name, prop.PropertyType.Namespace, null, prop.PropertyType.IsValueType); + PropertyDefinition pdef = new PropertyDefinition (name, tref, (Mono.Cecil.PropertyAttributes) 0); + PropertyDefinition.CreateGetMethod (pdef); + PropertyDefinition.CreateSetMethod (pdef); + return pdef; + } + } + + TypeDefinition bcls = cecilLib.FindTypeDefinition (baseType); + if (bcls != null) + return FindProperty (bcls, name); + else + return null; + } + + EventDefinition FindEvent (TypeDefinition cls, string name) + { + foreach (EventDefinition eventInfo in cls.Events) + if (eventInfo.Name == name) + return eventInfo; + + if (cls.BaseType == null) + return null; + + string baseType = cls.BaseType.FullName; + Type t = Registry.GetType (baseType, false); + if (t != null) { + EventInfo ev = t.GetEvent (name); + if (ev != null) { + TypeReference tref = new TypeReference (ev.EventHandlerType.Name, ev.EventHandlerType.Namespace, null, ev.EventHandlerType.IsValueType); + return new EventDefinition (name, tref, (Mono.Cecil.EventAttributes) 0); + } + } + + TypeDefinition bcls = cecilLib.FindTypeDefinition (baseType); + if (bcls != null) + return FindEvent (bcls, name); + else + return null; + } + + void MakeChildrenUnselectable (Gtk.Widget w) + { + // Remove the registered signals, since those signals are bound + // to the custom widget class, not the widget container class. + Stetic.Wrapper.Widget ww = Stetic.Wrapper.Widget.Lookup (w); + if (ww == null) + return; + ww.Signals.Clear (); + + foreach (Gtk.Widget child in (Gtk.Container)w) { + Stetic.Wrapper.Widget wrapper = Stetic.Wrapper.Widget.Lookup (child); + if (wrapper != null) { + wrapper.Signals.Clear (); + wrapper.Unselectable = true; + } + if (child is Gtk.Container) + MakeChildrenUnselectable (child); + } + } + + bool CanCreateWidgetInstance (string typeName) + { + switch (typeName) { + case "Gtk.Fixed": + return false; + } + return true; + } + + bool NeedsBlackBox (string typeName) + { + switch (typeName) { + case "Gtk.Widget": + case "Gtk.Container": + case "Gtk.Alignment": + case "Gtk.Fixed": + case "Gtk.Frame": + case "Gtk.HBox": + case "Gtk.VBox": + case "Gtk.Box": + case "Gtk.ButtonBox": + case "Gtk.Paned": + case "Gtk.VPaned": + case "Gtk.HPaned": + case "Gtk.Notebook": + case "Gtk.ScrolledWindow": + case "Gtk.Table": + case "Gtk.Bin": + return true; + } + return false; + } + + Gtk.Widget CreateFakeWidget (string typeName) + { + Stetic.Custom c = new Stetic.Custom (); + // Give it some default size + c.WidthRequest = 20; + c.HeightRequest = 20; + + Gtk.Container box = null; + + switch (typeClassDescriptor.Name) { + case "Gtk.Alignment": + box = new Gtk.Alignment (0.5f, 0.5f, 1f, 1f); + break; + case "Gtk.Fixed": + box = new Gtk.Alignment (0.5f, 0.5f, 1f, 1f); + break; + case "Gtk.Frame": + box = new Gtk.Frame (); + break; + case "Gtk.Box": + case "Gtk.HBox": { + Gtk.HBox cc = new Gtk.HBox (); + cc.PackStart (c, true, true, 0); + return cc; + } + case "Gtk.VBox": { + Gtk.VBox cc = new Gtk.VBox (); + cc.PackStart (c, true, true, 0); + return cc; + } + case "Gtk.Paned": + case "Gtk.VPaned": { + Gtk.VPaned cc = new Gtk.VPaned (); + cc.Add1 (c); + return cc; + } + case "Gtk.HPaned": { + Gtk.HPaned cc = new Gtk.HPaned (); + cc.Add1 (c); + return cc; + } + case "Gtk.Notebook": { + Gtk.Notebook nb = new Gtk.Notebook (); + nb.ShowTabs = false; + nb.AppendPage (c, null); + return nb; + } + case "Gtk.ScrolledWindow": { + Gtk.ScrolledWindow cc = new Gtk.ScrolledWindow (); + cc.VscrollbarPolicy = Gtk.PolicyType.Never; + cc.HscrollbarPolicy = Gtk.PolicyType.Never; + cc.AddWithViewport (c); + return cc; + } + case "Gtk.Table": { + Gtk.Table t = new Gtk.Table (1, 1, false); + t.Attach (c, 0, 1, 0, 1); + return t; + } + case "Gtk.ButtonBox": + return new Gtk.HButtonBox (); + } + if (box != null) { + box.Add (c); + return box; + } else { + Stetic.CustomWidget custom = new Stetic.CustomWidget (); + if (custom.Child != null) + custom.Remove (custom.Child); + custom.Add (c); + return custom; + } + } + } + + class CustomControlWrapper: Stetic.Wrapper.Container + { + protected override bool AllowPlaceholders { + get { + return false; + } + } + } + + class ClassDescriptorWrapper: Stetic.ClassDescriptor + { + ClassDescriptor wrapped; + + public ClassDescriptorWrapper (ClassDescriptor wrapped) + { + this.wrapped = wrapped; + label = wrapped.Label; + + } + + public override string WrappedTypeName { + get { return wrapped.WrappedTypeName; } + } + + public override Gdk.Pixbuf Icon { + get { return wrapped.Icon; } + } + + public override object CreateInstance (Stetic.IProject proj) + { + CustomWidget custom = new CustomWidget (); + Stetic.Custom c = new Stetic.Custom (); + // Give it some default size + c.WidthRequest = 20; + c.HeightRequest = 20; + custom.Add (c); + return c; + } + + public override Stetic.ObjectWrapper CreateWrapper () + { + return new Wrapper.Container (); + } + } +} + diff --git a/main/src/addins/MonoDevelop.GtkCore2/libsteticui/CecilPropertyDescriptor.cs b/main/src/addins/MonoDevelop.GtkCore2/libsteticui/CecilPropertyDescriptor.cs new file mode 100644 index 0000000000..292a99b740 --- /dev/null +++ b/main/src/addins/MonoDevelop.GtkCore2/libsteticui/CecilPropertyDescriptor.cs @@ -0,0 +1,127 @@ +using System; +using System.Collections; +using System.Xml; +using Mono.Cecil; + +namespace Stetic +{ + class CecilPropertyDescriptor: Stetic.PropertyDescriptor + { + string name; + Type type; + object initialValue; + bool canWrite; + + public CecilPropertyDescriptor (CecilWidgetLibrary lib, XmlElement elem, Stetic.ItemGroup group, Stetic.ClassDescriptor klass, PropertyDefinition pinfo): base (elem, group, klass) + { + string tname; + + if (pinfo != null) { + name = pinfo.Name; + tname = pinfo.PropertyType.FullName; + canWrite = pinfo.SetMethod != null; + } + else { + name = elem.GetAttribute ("name"); + tname = elem.GetAttribute ("type"); + canWrite = elem.Attributes ["canWrite"] == null; + } + + Load (elem); + + type = Stetic.Registry.GetType (tname, false); + + if (type == null) { + Console.WriteLine ("Could not find type: " + tname); + type = typeof(string); + } + if (type.IsValueType) + initialValue = Activator.CreateInstance (type); + + // Consider all properties runtime-properties, since they have been created + // from class properties. + isRuntimeProperty = true; + + if (pinfo != null) + SaveCecilXml (elem); + } + + public CecilPropertyDescriptor (XmlElement elem, Stetic.ItemGroup group, Stetic.ClassDescriptor klass, PropertyDescriptor prop): base (elem, group, klass) + { + this.name = prop.Name; + this.type = prop.PropertyType; + this.canWrite = prop.CanWrite; + if (type.IsValueType) + initialValue = Activator.CreateInstance (type); + this.label = prop.Label; + this.description = prop.Description; + this.maximum = prop.Maximum; + this.minimum = prop.Minimum; + this.initWithName = prop.InitWithName; + this.translatable = prop.Translatable; + } + + internal void SaveCecilXml (XmlElement elem) + { + elem.SetAttribute ("name", name); + elem.SetAttribute ("type", type.FullName); + if (!canWrite) + elem.SetAttribute ("canWrite", "false"); + } + + public override string Name { + get { return name; } + } + + // The property's type + public override Type PropertyType { + get { return type; } + } + + public override bool IsDefaultValue (object value) + { + return false; + } + + // Gets the value of the property on @obj + public override object GetValue (object obj) + { + Stetic.ObjectWrapper wrapper = (Stetic.ObjectWrapper) Stetic.ObjectWrapper.Lookup (obj); + Hashtable props = (Hashtable) wrapper.ExtendedData [typeof(CecilPropertyDescriptor)]; + object val = props != null ? props [name] : null; + if (val == null && initialValue != null) + return initialValue; + else + return val; + } + + // Whether or not the property is writable + public override bool CanWrite { + get { return canWrite; } + } + + // Sets the value of the property on @obj + public override void SetValue (object obj, object value) + { + Stetic.ObjectWrapper wrapper = (Stetic.ObjectWrapper) Stetic.ObjectWrapper.Lookup (obj); + Hashtable props = (Hashtable) wrapper.ExtendedData [typeof(CecilPropertyDescriptor)]; + if (props == null) { + props = new Hashtable (); + wrapper.ExtendedData [typeof(CecilPropertyDescriptor)] = props; + } + + props [name] = value; + } + + public override object GetRuntimeValue (object obj) + { + return null; + } + + public override void SetRuntimeValue (object obj, object value) + { + } + + } +} + diff --git a/main/src/addins/MonoDevelop.GtkCore2/libsteticui/CecilSignalDescriptor.cs b/main/src/addins/MonoDevelop.GtkCore2/libsteticui/CecilSignalDescriptor.cs new file mode 100644 index 0000000000..defc98e4b3 --- /dev/null +++ b/main/src/addins/MonoDevelop.GtkCore2/libsteticui/CecilSignalDescriptor.cs @@ -0,0 +1,88 @@ +using System; +using System.Collections; +using System.Xml; +using System.Reflection; +using Mono.Cecil; + +namespace Stetic +{ + class CecilSignalDescriptor: Stetic.SignalDescriptor + { + public CecilSignalDescriptor (CecilWidgetLibrary lib, XmlElement elem, Stetic.ItemGroup group, Stetic.ClassDescriptor klass, EventDefinition sinfo) : base (elem, group, klass) + { + if (sinfo != null) { + string handler = sinfo.EventType.FullName; + handlerTypeName = handler.Replace ('/','+'); + Type t = Registry.GetType (handler, false); + if (t != null) { + MethodInfo mi = t.GetMethod ("Invoke"); + handlerReturnTypeName = mi.ReturnType.FullName; + ParameterInfo[] pars = mi.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); + } else { + // If the type is generic, the type arguments must be ignored when looking for the type + string tn = handler; + int i = handler.IndexOf ('<'); + if (i != -1) { + tn = handler.Substring (0, i); + // Convert the type name to a type reference + handler = handler.Replace ('<', '['); + handler = handler.Replace ('>', ']'); + } + TypeDefinition td = lib.FindTypeDefinition (tn); + if (td != null) { + MethodDefinition mi = null; + foreach (MethodDefinition md in td.Methods) { + if (md.Name == "Invoke") { + mi = md; + break; + } + } + if (mi != null) { + handlerReturnTypeName = CecilWidgetLibrary.GetInstanceType (td, sinfo.EventType, mi.ReturnType.ReturnType); + handlerParameters = new ParameterDescriptor [mi.Parameters.Count]; + for (int n=0; n<handlerParameters.Length; n++) { + ParameterDefinition par = mi.Parameters [n]; + handlerParameters [n] = new ParameterDescriptor (par.Name, CecilWidgetLibrary.GetInstanceType (td, sinfo.EventType, par.ParameterType)); + } + } + } else { + handlerParameters = new ParameterDescriptor [0]; + } + } + SaveCecilXml (elem); + } + else { + handlerTypeName = elem.GetAttribute ("handlerTypeName"); + handlerReturnTypeName = elem.GetAttribute ("handlerReturnTypeName"); + + ArrayList list = new ArrayList (); + foreach (XmlNode npar in elem.ChildNodes) { + XmlElement epar = npar as XmlElement; + if (epar == null) continue; + list.Add (new ParameterDescriptor (epar.GetAttribute ("name"), epar.GetAttribute ("type"))); + } + + handlerParameters = (ParameterDescriptor[]) list.ToArray (typeof(ParameterDescriptor)); + } + + Load (elem); + } + + internal void SaveCecilXml (XmlElement elem) + { + elem.SetAttribute ("handlerTypeName", handlerTypeName); + elem.SetAttribute ("handlerReturnTypeName", handlerReturnTypeName); + if (handlerParameters != null) { + foreach (ParameterDescriptor par in handlerParameters) { + XmlElement epar = elem.OwnerDocument.CreateElement ("param"); + epar.SetAttribute ("name", par.Name); + epar.SetAttribute ("type", par.TypeName); + elem.AppendChild (epar); + } + } + } + } +} diff --git a/main/src/addins/MonoDevelop.GtkCore2/libsteticui/CecilWidgetLibrary.cs b/main/src/addins/MonoDevelop.GtkCore2/libsteticui/CecilWidgetLibrary.cs new file mode 100644 index 0000000000..0352d31fc5 --- /dev/null +++ b/main/src/addins/MonoDevelop.GtkCore2/libsteticui/CecilWidgetLibrary.cs @@ -0,0 +1,368 @@ +// CecilWidgetLibrary.cs +// +// Authors: +// Lluis Sanchez Gual <lluis@novell.com> +// Mike Kestner <mkestner@novell.com> +// +// Copyright (c) 2008 Novell, Inc +// +// Permission is hereby granted, free of charge, to any person obtaining +// a copy of this software and associated documentation files (the +// "Software"), to deal in the Software without restriction, including +// without limitation the rights to use, copy, modify, merge, publish, +// distribute, sublicense, and/or sell copies of the Software, and to +// permit persons to whom the Software is furnished to do so, subject to +// the following conditions: +// +// The above copyright notice and this permission notice shall be +// included in all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, +// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND +// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE +// LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION +// OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION +// WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + + +using System; +using System.IO; +using System.Collections; +using System.Collections.Generic; +using System.Collections.Specialized; +using System.Xml; +using Mono.Cecil; + +namespace Stetic +{ + internal class CecilWidgetLibrary: WidgetLibrary + { + static LibraryCache cache = LibraryCache.Cache; + + string name; + string filename; + string[] dependencies; + AssemblyResolver resolver; + bool canGenerateCode; + bool info_changed; + bool objects_dirty; + AssemblyDefinition assembly; + LibraryCache.LibraryInfo cache_info; + + public CecilWidgetLibrary (AssemblyResolver resolver, string path) + { + name = path; + this.resolver = resolver; + + if (System.IO.File.Exists (path)) + filename = path; + else if (resolver != null) + filename = resolver.Resolve (path, null); + + if (filename == null) + filename = path; + else + filename = System.IO.Path.GetFullPath (filename); + + RefreshFromCache (); + } + + public override string Name { + get { return name; } + } + + public override bool NeedsReload { + get { + cache.Refresh (resolver, filename); + return info_changed; + } + } + + public override bool CanReload { + get { return true; } + } + + public override bool CanGenerateCode { + get { return canGenerateCode; } + } + + public override void Load () + { + canGenerateCode = true; + + RefreshFromCache (); + if (cache_info == null || !File.Exists (filename)) + return; + + assembly = AssemblyFactory.GetAssembly (filename); + + objects_dirty = false; + Load (cache_info.ObjectsDocument); + if (objects_dirty) + cache_info.WriteObjectsFile (); + + foreach (string dep in GetLibraryDependencies ()) { + WidgetLibrary lib = Registry.GetWidgetLibrary (dep); + if (lib != null && !lib.CanGenerateCode) + canGenerateCode = false; + } + assembly = null; + info_changed = false; + } + + void RefreshFromCache () + { + LibraryCache.LibraryInfo newInfo = cache.Refresh (resolver, filename); + if (newInfo != cache_info) { + if (cache_info != null) + cache_info.Changed -= OnCacheInfoChanged; + cache_info = newInfo; + cache_info.Changed += OnCacheInfoChanged; + } + } + + void OnCacheInfoChanged (object o, EventArgs a) + { + info_changed = true; + } + + public override void Dispose () + { + base.Dispose (); + if (cache_info != null) { + cache_info.Changed -= OnCacheInfoChanged; + cache_info = null; + } + } + + + protected override ClassDescriptor LoadClassDescriptor (XmlElement element) + { + string name = element.GetAttribute ("type"); + + TypeDefinition cls = null; + Stetic.ClassDescriptor typeClassDescriptor = null; + string tname; + + if (element.HasAttribute ("baseClassType")) { + tname = element.GetAttribute ("baseClassType"); + typeClassDescriptor = Stetic.Registry.LookupClassByName (tname); + } else { + cls = assembly.MainModule.Types [name]; + if (cls != null) { + // Find the nearest type that can be loaded + typeClassDescriptor = FindType (assembly, cls); + tname = cls.Name; + if (typeClassDescriptor != null) { + element.SetAttribute ("baseClassType", typeClassDescriptor.Name); + objects_dirty = true; + } + } + } + + if (typeClassDescriptor == null) { + Console.WriteLine ("Descriptor not found: " + name); + return null; + } + + XmlElement steticDefinition = null; + + XmlDocument gui = cache [filename].GuiDocument; + if (gui != null) { + string wrappedTypeName = element.GetAttribute ("type"); + steticDefinition = (XmlElement) gui.DocumentElement.SelectSingleNode ("widget[@id='" + wrappedTypeName + "']"); + } + + CecilClassDescriptor cd = new CecilClassDescriptor (this, element, typeClassDescriptor, steticDefinition, cls); + + if (canGenerateCode && !cd.CanGenerateCode) + canGenerateCode = false; + return cd; + } + + Stetic.ClassDescriptor FindType (AssemblyDefinition asm, TypeDefinition cls) + { + if (cls.BaseType == null) + return null; + Stetic.ClassDescriptor klass = Stetic.Registry.LookupClassByName (cls.BaseType.FullName); + if (klass != null) return klass; + + TypeDefinition bcls = FindTypeDefinition (cls.BaseType.FullName); + if (bcls == null) + return null; + + return FindType (asm, bcls); + } + + AssemblyDefinition ResolveAssembly (AssemblyNameReference aref) + { + return resolver.Resolve (aref, Path.GetDirectoryName (filename)); + } + + internal TypeDefinition FindTypeDefinition (string fullName) + { + TypeDefinition t = FindTypeDefinition (new Hashtable (), assembly, fullName); + return t; + } + + TypeDefinition FindTypeDefinition (Hashtable visited, AssemblyDefinition asm, string fullName) + { + if (visited.Contains (asm)) + return null; + + visited [asm] = asm; + + TypeDefinition cls = asm.MainModule.Types [fullName]; + if (cls != null) + return cls; + + foreach (AssemblyNameReference aref in asm.MainModule.AssemblyReferences) { + AssemblyDefinition basm = ResolveAssembly (aref); + if (basm != null) { + cls = basm.MainModule.Types [fullName]; + if (cls != null) + return cls; +/* cls = FindTypeDefinition (visited, basm, fullName); + if (cls != null) + return cls; +*/ } + } + return null; + } + + public override string[] GetLibraryDependencies () + { + if (NeedsReload || dependencies == null) + LoadDependencies (); + return dependencies; + } + + void LoadDependencies () + { + RefreshFromCache (); + if (cache_info == null || cache_info.ObjectsDocument == null) { + dependencies = new string[0]; + return; + } + XmlElement elem = cache_info.ObjectsDocument.DocumentElement ["dependencies"]; + if (elem != null) { + ArrayList list = new ArrayList (); + foreach (XmlElement dep in elem.SelectNodes ("dependency")) + list.Add (dep.InnerText); + dependencies = (string[]) list.ToArray (typeof(string)); + } else + dependencies = new string[0]; + } + + public static bool IsWidgetLibrary (string path) + { + // Info can be null if the library could not be scanned for some reason + var info = cache [path]; + return info != null && info.HasWidgets; + } + + public static string GetInstanceType (TypeDefinition td, TypeReference sourceType, TypeReference tref) + { + string tn = null; + if (sourceType is GenericInstanceType) { + GenericInstanceType it = (GenericInstanceType) sourceType; + foreach (GenericParameter gc in td.GenericParameters) { + if (gc.Name == tref.FullName) { + tn = it.GenericArguments [gc.Position].FullName; + break; + } + } + } + if (tn == null) + tn = tref.FullName; + tn = tn.Replace ('<', '['); + tn = tn.Replace ('>', ']'); + return tn; + } + + public static List<ComponentType> GetComponentTypes (Application app, string filename) + { + List<ComponentType> list = new List<ComponentType> (); + + LibraryCache.LibraryInfo info = cache.Refresh (new AssemblyResolver (app.Backend), filename); + if (info.ObjectsDocument == null) + return list; + + string defTargetGtkVersion = info.ObjectsDocument.DocumentElement.GetAttribute ("gtk-version"); + if (defTargetGtkVersion.Length == 0) + defTargetGtkVersion = "2.4"; + + AssemblyDefinition adef = AssemblyFactory.GetAssembly (filename); + + foreach (XmlElement elem in info.ObjectsDocument.SelectNodes ("objects/object")) { + if (elem.GetAttribute ("internal") == "true" || elem.HasAttribute ("deprecated") || !elem.HasAttribute ("palette-category")) + continue; + + string iconname = elem.GetAttribute ("icon"); + Gdk.Pixbuf icon = GetEmbeddedIcon (adef, iconname); + + string targetGtkVersion = elem.GetAttribute ("gtk-version"); + if (targetGtkVersion.Length == 0) + targetGtkVersion = defTargetGtkVersion; + + ComponentType ct = new ComponentType (app, + elem.GetAttribute ("type"), + elem.GetAttribute ("label"), + elem.GetAttribute ("type"), + elem.GetAttribute ("palette-category"), + targetGtkVersion, + filename, + icon); + + list.Add (ct); + } + + return list; + } + + public Gdk.Pixbuf GetEmbeddedIcon (string iconname) + { + return GetEmbeddedIcon (assembly, iconname); + } + + static Gdk.Pixbuf GetEmbeddedIcon (AssemblyDefinition asm, string iconname) + { + Gdk.Pixbuf icon = null; + if (iconname != null && iconname.Length > 0) { + try { + // Using the pixbuf resource constructor generates a gdk warning. + EmbeddedResource res = GetResource (asm, iconname); + Gdk.PixbufLoader loader = new Gdk.PixbufLoader (res.Data); + icon = loader.Pixbuf; + } catch { + // Ignore + } + } + + if (icon == null) { + ClassDescriptor cc = Registry.LookupClassByName ("Gtk.Bin"); + icon = cc.Icon; + } + return icon; + } + + static EmbeddedResource GetResource (AssemblyDefinition asm, string name) + { + foreach (Resource res in asm.MainModule.Resources) { + EmbeddedResource eres = res as EmbeddedResource; + if (eres != null && eres.Name == name) + return eres; + } + return null; + } + + public override void Flush () + { + base.Flush (); + if (resolver != null) + resolver.ClearCache (); + } + + } +} diff --git a/main/src/addins/MonoDevelop.GtkCore2/libsteticui/ChangeLog b/main/src/addins/MonoDevelop.GtkCore2/libsteticui/ChangeLog new file mode 100644 index 0000000000..8d924e5e94 --- /dev/null +++ b/main/src/addins/MonoDevelop.GtkCore2/libsteticui/ChangeLog @@ -0,0 +1,431 @@ +2010-10-28 Krzysztof Marecki <marecki.krzysztof@gmail.com> + + * ApplicationBackend.cs: + +2010-10-04 Krzysztof Marecki <marecki.krzysztof@gmail.com> + + * Makefile.am: + * libsteticui2.csproj: + * ApplicationBackend.cs: + +2010-09-30 Krzysztof Marecki <marecki.krzysztof@gmail.com> + + * ApplicationBackend.cs: + +2010-09-30 Krzysztof Marecki <marecki.krzysztof@gmail.com> + + * Makefile.am: + * libsteticui2.csproj: + * ApplicationBackend.cs: + +2010-09-22 Krzysztof Marecki <marecki.krzysztof@gmail.com> + + * Project.cs: Add ReloadComponent method + * ProjectBackend.cs: + +2010-09-21 Krzysztof Marecki <marecki.krzysztof@gmail.com> + + * Project.cs: Code cleanup + * ProjectBackend.cs: + +2010-09-20 Krzysztof Marecki <marecki.krzysztof@gmail.com> + + * ProjectBackend.cs: + +2010-09-17 Krzysztof Marecki <marecki.krzysztof@gmail.com> + + * libsteticui2.csproj: + +2010-09-17 Krzysztof Marecki <marecki.krzysztof@gmail.com> + + * libsteticui2.csproj: + +2010-09-15 Krzysztof Marecki <marecki.krzysztof@gmail.com> + + * libsteticui2.csproj: + +2010-09-08 Krzysztof Marecki <freefirma@gmail.com> + + * SignalsEditorBackend.cs: + +2010-08-17 Krzysztof Marecki <freefirma@gmail.com> + + * Application.cs: + * ProjectBackend.cs: + +2010-08-16 Krzysztof Marecki <freefirma@gmail.com> + + * ProjectBackend.cs: + * WidgetEditSession.cs: + * IProjectDesignInfo.cs: + +2010-08-15 Krzysztof Marecki <freefirma@gmail.com> + + * CodeGenerator.cs: + * ProjectBackend.cs: + * WidgetEditSession.cs: + * CodeGeneratorPartialClass.cs: + +2010-08-13 Krzysztof Marecki <freefirma@gmail.com> + + * Project.cs: + * Makefile.am: + * CodeGenerator.cs: + * libsteticui2.csproj: + * ActionGroupEditSession.cs: + * CodeGeneratorPartialClass.cs: + * CodeGeneratorInternalClass.cs: Remove class + +2010-08-09 Krzysztof Marecki <freefirma@gmail.com> + + * Project.cs: Add ComponentNeedsCodeGeneration method + * ProjectBackend.cs: + * IProjectDesignInfo.cs: + * CodeGeneratorPartialClass.cs: Only generate code for components that + have been changed + +2010-08-07 Krzysztof Marecki <marecki.krzysztof@gmail.com> + + * Project.cs: Remove Modifies property + * ProjectBackend.cs: Add modifiedTopLevel list, handled on project loading, saving. + * libsteticui2.csproj: + * WidgetEditSession.cs: Use ProjectBackend.WasModified to determine if it was modified + +2010-08-05 Krzysztof Marecki <freefirma@gmail.com> + + * WidgetDesigner.cs: + * ProjectBackend.cs: + +2010-08-05 Krzysztof Marecki <marecki.krzysztof@gmail.com> + Remove ModifiedChanged event, + change Changed event to ProjectChangedEventHandler (pass name of changed widget) + * Project.cs: + * WidgetDesigner.cs: + * ProjectBackend.cs: + * WidgetEditSession.cs: + +2010-08-04 Krzysztof Marecki <freefirma@gmail.com> + + * Project.cs: Pass root widget name in NotifyChanged + * Makefile.am: + * ProjectBackend.cs: + * libsteticui2.csproj: + +2010-08-03 Krzysztof Marecki <marecki.krzysztof@gmail.com> + + * Glade.cs: + * Makefile.am: + * ProjectBackend.cs: + +2010-08-03 Krzysztof Marecki <marecki.krzysztof@gmail.com> + + * Makefile.am: + * ProjectBackend.cs: Return empty string when GtktargetVersion + is not initialized + +2010-07-27 Krzysztof Marecki <marecki.krzysztof@gmail.com> + + * Project.cs: Remove autoCommit argument + * Makefile.am: + * WidgetDesigner.cs: Remove temporary project + * ProjectBackend.cs: Do not clear libraries on Close + * WidgetEditSession.cs: Remove temporary project + +2010-07-27 Krzysztof Marecki <marecki.krzysztof@gmail.com> + + * Project.cs: + * WidgetDesigner.cs: + * ProjectBackend.cs: + +2010-07-06 Krzysztof Marecki <marecki.krzysztof@gmail.com> + + * Project.cs: Add parameter to Convert method for passing + a new gtk gui folder name. + * ProjectBackend.cs: + +2010-07-05 Krzysztof Marecki <marecki.krzysztof@gmail.com> + + * Glade.cs: + * Project.cs: AddComponent method + * Makefile.am: + * ProjectBackend.cs: + * libsteticui2.csproj: + +2010-06-28 Krzysztof Marecki <marecki.krzysztof@gmail.com> + + * Project.cs: Find class name for given .gtkx file + * Makefile.am: + * ProjectBackend.cs: + * IProjectDesignInfo.cs: + +2010-06-28 Krzysztof Marecki <marecki.krzysztof@gmail.com> + + * Makefile.am: + * ProjectBackend.cs: + * libsteticui2.csproj: + +2010-06-23 Krzysztof Marecki <marecki.krzysztof@gmail.com> + + * Makefile.am: + * libsteticui2.csproj: + +2010-06-23 Krzysztof Marecki <marecki.krzysztof@gmail.com> + + * Makefile.am: + * libsteticui2.csproj: + +2010-06-22 Krzysztof Marecki <marecki.krzysztof@gmail.com> + + * Makefile.am: + +2010-06-16 Krzysztof Marecki <marecki.krzysztof@gmail.com> + + * Makefile.am: + +2010-06-15 Krzysztof Marecki <marecki.krzysztof@gmail.com> + + * Project.cs: Create backend for Convert + +2010-06-09 Krzysztof Marecki <marecki.krzysztof@gmail.com> + + * Makefile.am: + * libsteticui2.csproj: + +2010-06-07 Krzysztof Marecki <marecki.krzysztof@gmail.com> + + * Project.cs: Transition from project file name to project folder. + * Makefile.am: + * Application.cs: + * ProjectBackend.cs: + * WidgetEditSession.cs: + +2010-06-07 Krzysztof Marecki <marecki.krzysztof@gmail.com> + + * Project.cs: + * Makefile.am: + * ProjectBackend.cs: + * IProjectDesignInfo.cs: + +2010-06-02 Krzysztof Marecki <marecki.krzysztof@gmail.com> + + * Makefile.am: + * libsteticui2.csproj: + +2010-04-16 Lluis Sanchez Gual <lluis@novell.com> + + * CecilSignalDescriptor.cs: Cecil uses '/' as separator for + inner classes. Convert to the standard '+' separator. + +2010-01-18 Lluis Sanchez Gual <lluis@novell.com> + + * Makefile.am: + * CodeGenerator.cs: + * libsteticui.csproj: + * CodeGeneratorPartialClass.cs: + * CodeGeneratorInternalClass.cs: Use global:: for type + references in generated code. + +2010-01-15 Mike Krüger <mkrueger@novell.com> + + * libsteticui.csproj: upgraded to v3.5 framework. + +2009-12-18 Michael Hutchinson <mhutchinson@novell.com> + + * WidgetDesignerBackend.cs: Disable checkerboard background + because redraw is super-inefficient and makes resizing + unbearably slow. It needs to do more selective invalidation + in resizes (like GTK viewport), and take the exposed area + into account in expose events. + +2009-11-12 Lluis Sanchez Gual <lluis@novell.com> + + * WidgetDesignerBackend.cs: Don't try to realize the child if + the widget is not anchored. Fixes bug #553475 - + "Gtk-Critical: gtk_widget_realize: assertion" when running a + gtk# app inside MD. + +2009-11-05 Mike Kestner <mkestner@novell.com> + + * Application.cs: + * ApplicationBackend.cs: + * CodeGenerator.cs: some warning cleanup. + +2009-10-21 Lluis Sanchez Gual <lluis@novell.com> + + * libsteticui.csproj: Flush. + +2009-10-16 Mike Krüger <mkrueger@novell.com> + + * ActionComponent.cs: Handled icon loading failures. + +2009-10-08 Ankit Jain <jankit@novell.com> + + * libsteticui.csproj: Mark Mono.Cecil project referece + as private. + +2009-09-10 Christian Hergert <chris@dronelabs.com> + + * libsteticui/libsteticui.dll.config: Use quartz on osx. + +2009-09-04 Michael Hutchinson <mhutchinson@novell.com> + + * Metacity/Preview.cs: Use Assembly.LoadWithPartialName. It's + obsolete, but at least it works. + +2009-08-27 Mike Krüger <mkrueger@novell.com> + + * Metacity/Preview.cs: + * WidgetDesignerBackend.cs: Worked on designer decoration. + +2009-08-27 Mike Krüger <mkrueger@novell.com> + + * Grid.cs: + * LibraryCache.cs: + * Windows/Preview.cs: + * WidgetActionBar.cs: + * ApplicationBackend.cs: Fixed some warnings. + +2009-08-26 Lluis Sanchez Gual <lluis@novell.com> + + * libsteticui.csproj: Updated dependencies. We now depend on + gtk# 2.12.8, Mono 2.4, and Mono.Addins 0.4. + +2009-08-24 Lluis Sanchez Gual <lluis@novell.com> + + * Project.cs: + * UndoQueue.cs: + * WidgetDesigner.cs: + * ProjectBackend.cs: + * WidgetEditSession.cs: Added support for saving and restoring + the status of the designer, including the undo queue. This + allows implenting ISupportsProjectReload. + +2009-07-31 Lluis Sanchez Gual <lluis@novell.com> + + * Metacity/Preview.cs: Remove debug code. + +2009-07-31 Lluis Sanchez Gual <lluis@novell.com> + + * Windows/Preview.cs: Dont try to create a Win32 preview + window when not running on Windows. + +2009-07-01 Lluis Sanchez Gual <lluis@novell.com> + + * WidgetDesigner.cs: + * ActionGroupDesigner.cs: + * WidgetDesignerBackend.cs: + * ActionGroupEditSession.cs: No more missing IntPtr + constructor exceptions. + +2009-06-25 Lluis Sanchez Gual <lluis@novell.com> + + * WidgetDesignerBackend.cs: Fix rendering of the window + decoration. + +2009-06-25 Lluis Sanchez Gual <lluis@novell.com> + + * WidgetDesigner.cs: + * WidgetDesignerBackend.cs: Dispose is not guaranteed to be + called when destroying a widget. Use OnDestroyed instead. + +2009-06-25 Mike Krüger <mkrueger@novell.com> + + * WidgetDesignerBackend.cs: Draw dialog background. + +2009-06-25 Mike Krüger <mkrueger@novell.com> + + * WidgetDesignerBackend.cs: Draw checkboard background in the + gui designer instead of monochrome dialog background. + +2009-06-04 Lluis Sanchez Gual <lluis@novell.com> + + * PluggableWidget.cs: When replacing the child widget (because + of reloading of the project for example), make sure the old + one is destroyed. + +2009-05-07 Lluis Sanchez Gual <lluis@novell.com> + + * Makefile.am: + * libsteticui.csproj: Updated. + + * Metacity/Theme.cs: + * Metacity/FrameType.cs: + * Metacity/FrameFlags.cs: + * Metacity/ButtonLayout.cs: + * Metacity/ObjectManager.cs: + * Metacity/ButtonFunction.cs: Use a better namespace. + + * Metacity/Preview.cs: Use the new TopLevelWindow class. Track + changes in the title of the window. + + * Windows: + * Windows/Preview.cs: + * Windows/WindowsTheme.cs: + * WidgetDesignerBackend.cs: Added support for win32 window + decorations. + + * EmbedWindow.cs: + * UserInterface.cs: EmbedWindow is not required anymore. + +2009-05-04 Lluis Sanchez Gual <lluis@novell.com> + + * libsteticui.csproj: Copy the config file to the output dir. + Set project type to library. + + * Metacity/Preview.cs: + * WidgetDesignerBackend.cs: Avoid exception in the + MetacityPreview class constructor, since it crashes MD under + ms.net. + +2009-04-29 Lluis Sanchez Gual <lluis@novell.com> + + * libsteticui.csproj: Don't require a specific gtk# version. + +2009-03-03 Lluis Sanchez Gual <lluis@novell.com> + + * LibraryCache.cs: Avoid recursive loading of + AssemblyDefinition. Rely on cache info to check if a + referenced library contains widget definitions. + + * AssemblyResolver.cs: Make sure the resolver returns full + paths. + + * CecilWidgetLibrary.cs: Use the full path to query info from + the cache. Properly unsubscribe the Changed event from the + cache. Resolve assemblies using the provided assembly + resolver. + + * ApplicationBackend.cs: + * AssemblyWidgetLibrary.cs: From now on the registry and the + library cache only handle libraries with full paths. + + * Project.cs: Make sure unused project backends are properly + disposed. + +2009-02-26 Lluis Sanchez Gual <lluis@novell.com> + + * libsteticui.csproj: Flush. + +2009-02-12 Michael Hutchinson <mhutchinson@novell.com> + + * PropertyTree.cs: + * WidgetDesignerBackend.cs: Dispose Gdk cursors, else + finalisers destroy them outside of the GUI thread and often + crash MD due to X asserts resulting in _XCBUnlockDisplay + errors. + +2009-02-10 Michael Hutchinson <mhutchinson@novell.com> + + * libsteticui.csproj: Don't build with make, since MD can + build these just fine. + +2009-02-07 Michael Hutchinson <mhutchinson@novell.com> + + * libsteticui.csproj: Allow unsafe code, since Shadow.cs has + unsafe code. + +2009-02-06 Lluis Sanchez Gual <lluis@novell.com> + + * libsteticui.mdp: + * libsteticui.csproj: Migrated to MSBuild file format. + diff --git a/main/src/addins/MonoDevelop.GtkCore2/libsteticui/CodeGenerationResult.cs b/main/src/addins/MonoDevelop.GtkCore2/libsteticui/CodeGenerationResult.cs new file mode 100644 index 0000000000..3e2dedcd84 --- /dev/null +++ b/main/src/addins/MonoDevelop.GtkCore2/libsteticui/CodeGenerationResult.cs @@ -0,0 +1,26 @@ + +using System; + +namespace Stetic +{ + [Serializable] + public class CodeGenerationResult + { + SteticCompilationUnit[] units; + string[] warnings; + + internal CodeGenerationResult (SteticCompilationUnit[] units, string[] warnings) + { + this.units = units; + this.warnings = warnings; + } + + public SteticCompilationUnit[] Units { + get { return units; } + } + + public string[] Warnings { + get { return warnings; } + } + } +} diff --git a/main/src/addins/MonoDevelop.GtkCore2/libsteticui/CodeGenerator.cs b/main/src/addins/MonoDevelop.GtkCore2/libsteticui/CodeGenerator.cs new file mode 100644 index 0000000000..7ea4b3d4df --- /dev/null +++ b/main/src/addins/MonoDevelop.GtkCore2/libsteticui/CodeGenerator.cs @@ -0,0 +1,432 @@ +using System; +using System.Reflection; +using System.CodeDom; +using System.CodeDom.Compiler; +using System.Collections.Generic; +using System.IO; +using System.Collections; + +namespace Stetic +{ + internal static class CodeGenerator + { +// public static void GenerateProjectCode (string file, CodeDomProvider provider, GenerationOptions options, ProjectBackend[] projects) +// { +// CodeGenerationResult res = GenerateProjectCode (options, projects); +// +// string basePath = Path.GetDirectoryName (file); +// +// foreach (SteticCompilationUnit unit in res.Units) { +// string fname; +// if (unit.Name.Length == 0) +// fname = file; +// else +// fname = Path.Combine (basePath, unit.Name); +// StreamWriter fileStream = new StreamWriter (fname); +// try { +// provider.GenerateCodeFromCompileUnit (unit, fileStream, new CodeGeneratorOptions ()); +// } finally { +// fileStream.Close (); +// } +// } +// } + + public static CodeGenerationResult GenerateProjectCode (GenerationOptions options, ProjectBackend[] projects) + { + ArrayList warningList = new ArrayList (); + + List<SteticCompilationUnit> units = new List<SteticCompilationUnit> (); +// SteticCompilationUnit globalUnit = new SteticCompilationUnit (""); +// units.Add (globalUnit); + + if (options == null) + options = new GenerationOptions (); + CodeNamespace globalNs = new CodeNamespace (options.GlobalNamespace); +// globalUnit.Namespaces.Add (globalNs); + + // Global class + + CodeTypeDeclaration globalType = new CodeTypeDeclaration ("Gui"); + globalType.Attributes = MemberAttributes.Private; + globalType.TypeAttributes = TypeAttributes.NestedAssembly; + globalNs.Types.Add (globalType); + + // Create the project initialization method + // This method will only be added at the end if there + // is actually something to initialize + + CodeMemberMethod initMethod = new CodeMemberMethod (); + initMethod.Name = "Initialize"; + initMethod.ReturnType = new CodeTypeReference (typeof(void)); + initMethod.Attributes = MemberAttributes.Assembly | MemberAttributes.Static; + initMethod.Parameters.Add (new CodeParameterDeclarationExpression (typeof(Gtk.Widget), "iconRenderer")); + + GeneratorContext initContext = new ProjectGeneratorContext (globalNs, globalType, initMethod.Statements, options); + initContext.RootObject = new CodeArgumentReferenceExpression ("iconRenderer"); + + // Generate icon factory creation + + foreach (ProjectBackend gp in projects) { + if (gp.IconFactory.Icons.Count > 0) + gp.IconFactory.GenerateBuildCode (initContext); + } + warningList.AddRange (initContext.Warnings); + + // Generate the code + CodeGeneratorPartialClass.GenerateProjectGuiCode (globalNs, globalType, options, units, projects, warningList); + + GenerateProjectActionsCode (globalNs, options, projects); + + // Final step. If there is some initialization code, add all needed infrastructure + + globalType.Members.Add (initMethod); + + CodeMemberField initField = new CodeMemberField (typeof(bool), "initialized"); + initField.Attributes = MemberAttributes.Private | MemberAttributes.Static; + globalType.Members.Add (initField); + + CodeFieldReferenceExpression initVar = new CodeFieldReferenceExpression ( + new CodeTypeReferenceExpression (globalNs.Name + ".Gui"), + "initialized" + ); + + CodeConditionStatement initCondition = new CodeConditionStatement (); + initCondition.Condition = new CodeBinaryOperatorExpression ( + initVar, + CodeBinaryOperatorType.IdentityEquality, + new CodePrimitiveExpression (false) + ); + initCondition.TrueStatements.Add (new CodeAssignStatement ( + initVar, + new CodePrimitiveExpression (true) + )); + initCondition.TrueStatements.AddRange (initMethod.Statements); + initMethod.Statements.Clear (); + initMethod.Statements.Add (initCondition); + + //create separate compilation unit for each type in the global namespace + //and insert them at the begining of the units list. + int index = 0; + foreach (CodeTypeDeclaration type in globalNs.Types) + { + SteticCompilationUnit unit = new SteticCompilationUnit (type.Name); + CodeNamespace ns = new CodeNamespace (globalNs.Name); + + ns.Types.Add (type); + unit.Namespaces.Add (ns); + units.Insert (index++, unit); + } + + return new CodeGenerationResult (units.ToArray (), (string[]) warningList.ToArray (typeof(string))); + } + + internal static void BindSignalHandlers (CodeExpression targetObjectVar, ObjectWrapper wrapper, Stetic.WidgetMap map, CodeStatementCollection statements, GenerationOptions options) + { + foreach (Signal signal in wrapper.Signals) { + SignalDescriptor descriptor = signal.SignalDescriptor; + + CodeExpression createDelegate = new CodeDelegateCreateExpression ( + new CodeTypeReference (descriptor.HandlerTypeName, CodeTypeReferenceOptions.GlobalReference), + new CodeThisReferenceExpression (), + signal.Handler); + + CodeAttachEventStatement cevent = new CodeAttachEventStatement ( + new CodeEventReferenceExpression ( + map.GetWidgetExp (wrapper), + descriptor.Name), + createDelegate); + + statements.Add (cevent); + } + + Wrapper.Widget widget = wrapper as Wrapper.Widget; + if (widget != null && widget.IsTopLevel) { + // Bind local action signals + foreach (Wrapper.ActionGroup grp in widget.LocalActionGroups) { + foreach (Wrapper.Action ac in grp.Actions) + BindSignalHandlers (targetObjectVar, ac, map, statements, options); + } + } + + Gtk.Container cont = wrapper.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 (targetObjectVar, ww, map, statements, options); + } + } + + } + + static void GenerateProjectActionsCode (CodeNamespace cns, GenerationOptions options, params ProjectBackend[] projects) + { + bool multiProject = projects.Length > 1; + + CodeTypeDeclaration type = new CodeTypeDeclaration ("ActionGroups"); + type.Attributes = MemberAttributes.Private; + type.TypeAttributes = TypeAttributes.NestedAssembly; + cns.Types.Add (type); + + // Generate the global action group getter + + CodeMemberMethod met = new CodeMemberMethod (); + met.Name = "GetActionGroup"; + type.Members.Add (met); + met.Parameters.Add (new CodeParameterDeclarationExpression (typeof(Type), "type")); + if (multiProject) + met.Parameters.Add (new CodeParameterDeclarationExpression (typeof(string), "file")); + met.ReturnType = new CodeTypeReference (typeof(Gtk.ActionGroup)); + met.Attributes = MemberAttributes.Public | MemberAttributes.Static; + + CodeMethodInvokeExpression call = new CodeMethodInvokeExpression ( + new CodeMethodReferenceExpression ( + new CodeTypeReferenceExpression (new CodeTypeReference (cns.Name + ".ActionGroups")), + "GetActionGroup" + ), + new CodePropertyReferenceExpression ( + new CodeArgumentReferenceExpression ("type"), + "FullName" + ) + ); + if (multiProject) + call.Parameters.Add (new CodeArgumentReferenceExpression ("file")); + + met.Statements.Add (new CodeMethodReturnStatement (call)); + + // Generate the global action group getter (overload) + + met = new CodeMemberMethod (); + met.Name = "GetActionGroup"; + type.Members.Add (met); + met.Parameters.Add (new CodeParameterDeclarationExpression (typeof(string), "name")); + if (multiProject) + met.Parameters.Add (new CodeParameterDeclarationExpression (typeof(string), "file")); + met.ReturnType = new CodeTypeReference (typeof(Gtk.ActionGroup)); + met.Attributes = MemberAttributes.Public | MemberAttributes.Static; + + CodeArgumentReferenceExpression cfile = new CodeArgumentReferenceExpression ("file"); + CodeArgumentReferenceExpression cid = new CodeArgumentReferenceExpression ("name"); + + CodeStatementCollection projectCol = met.Statements; + int n=1; + + foreach (ProjectBackend 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 (Wrapper.ActionGroup grp in gp.ActionGroups) { + string fname = "group" + (n++); + CodeMemberField grpField = new CodeMemberField (new CodeTypeReference (typeof(Gtk.ActionGroup), CodeTypeReferenceOptions.GlobalReference), fname); + grpField.Attributes |= MemberAttributes.Static; + type.Members.Add (grpField); + CodeFieldReferenceExpression grpVar = new CodeFieldReferenceExpression ( + new CodeTypeReferenceExpression (new CodeTypeReference (cns.Name + ".ActionGroups", CodeTypeReferenceOptions.GlobalReference)), + fname + ); + + CodeConditionStatement pcond = new CodeConditionStatement (); + pcond.Condition = new CodeBinaryOperatorExpression ( + cid, + CodeBinaryOperatorType.IdentityEquality, + new CodePrimitiveExpression (grp.Name) + ); + widgetCol.Add (pcond); + + // If the group has not yet been created, create it + CodeConditionStatement pcondGrp = new CodeConditionStatement (); + pcondGrp.Condition = new CodeBinaryOperatorExpression ( + grpVar, + CodeBinaryOperatorType.IdentityEquality, + new CodePrimitiveExpression (null) + ); + + pcondGrp.TrueStatements.Add ( + new CodeAssignStatement ( + grpVar, + new CodeObjectCreateExpression (grp.Name) + ) + ); + + pcond.TrueStatements.Add (pcondGrp); + pcond.TrueStatements.Add (new CodeMethodReturnStatement (grpVar)); + + widgetCol = pcond.FalseStatements; + } + widgetCol.Add (new CodeMethodReturnStatement (new CodePrimitiveExpression (null))); + } + if (met.Statements.Count == 0) + met.Statements.Add (new CodeMethodReturnStatement (new CodePrimitiveExpression (null))); + } + + internal static List<ObjectBindInfo> GetFieldsToBind (ObjectWrapper wrapper) + { + List<ObjectBindInfo> tobind = new List<ObjectBindInfo> (); + GetFieldsToBind (tobind, wrapper); + return tobind; + } + + static void GetFieldsToBind (List<ObjectBindInfo> tobind, ObjectWrapper wrapper) + { + string memberName = null; + + if (wrapper is Wrapper.Widget) { + Wrapper.Widget ww = wrapper as Wrapper.Widget; + if (!String.IsNullOrEmpty (ww.UIManagerName)) + tobind.Add (new ObjectBindInfo ("Gtk.UIManager", ww.UIManagerName)); + + if (!ww.IsTopLevel && ww.InternalChildProperty == null && !ww.Unselectable) + memberName = ((Wrapper.Widget) wrapper).Wrapped.Name; + } + else if (wrapper is Wrapper.Action) + memberName = ((Wrapper.Action) wrapper).Name; + + if (memberName != null) { + ObjectBindInfo binfo = new ObjectBindInfo (wrapper.WrappedTypeName, memberName); + tobind.Add (binfo); + } + + Wrapper.ActionGroup agroup = wrapper as Wrapper.ActionGroup; + if (agroup != null) { + foreach (Wrapper.Action ac in agroup.Actions) + GetFieldsToBind (tobind, ac); + } + + Wrapper.Widget widget = wrapper as Wrapper.Widget; + if (widget != null && widget.IsTopLevel) { + // Generate fields for local actions + foreach (Wrapper.ActionGroup grp in widget.LocalActionGroups) { + GetFieldsToBind (tobind, grp); + } + } + + Gtk.Container cont = wrapper.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) + GetFieldsToBind (tobind, ww); + } + } + } + + public static WidgetMap GenerateCreationCode (CodeNamespace cns, CodeTypeDeclaration type, Gtk.Widget w, CodeExpression widgetVarExp, CodeStatementCollection statements, GenerationOptions options, ArrayList warnings) + { + statements.Add (new CodeCommentStatement ("Widget " + w.Name)); + GeneratorContext ctx = new ProjectGeneratorContext (cns, type, statements, options); + Stetic.Wrapper.Widget ww = Stetic.Wrapper.Widget.Lookup (w); + ctx.GenerateCreationCode (ww, widgetVarExp); + ctx.EndGeneration (); + warnings.AddRange (ctx.Warnings); + return ctx.WidgetMap; + } + + public static WidgetMap GenerateCreationCode (CodeNamespace cns, CodeTypeDeclaration type, Wrapper.ActionGroup grp, CodeExpression groupVarExp, CodeStatementCollection statements, GenerationOptions options, ArrayList warnings) + { + statements.Add (new CodeCommentStatement ("Action group " + grp.Name)); + GeneratorContext ctx = new ProjectGeneratorContext (cns, type, statements, options); + ctx.GenerateCreationCode (grp, groupVarExp); + ctx.EndGeneration (); + warnings.AddRange (ctx.Warnings); + return ctx.WidgetMap; + } + } + + class ProjectGeneratorContext: GeneratorContext + { + CodeTypeDeclaration type; + + public ProjectGeneratorContext (CodeNamespace cns, CodeTypeDeclaration type, CodeStatementCollection statements, GenerationOptions options): base (cns, "w", statements, options) + { + this.type = type; + } + + public override CodeExpression GenerateInstanceExpression (ObjectWrapper wrapper, CodeExpression newObject) + { + string typeName = wrapper.WrappedTypeName; + string memberName = null; + if (wrapper is Wrapper.Widget) + memberName = ((Wrapper.Widget) wrapper).Wrapped.Name; + else if (wrapper is Wrapper.Action) + memberName = ((Wrapper.Action) wrapper).Name; + + if (memberName == null) + return base.GenerateInstanceExpression (wrapper, newObject); + +// if (Options.UsePartialClasses) { + // Don't generate fields for top level widgets and for widgets accessible + // through other widget's properties + Wrapper.Widget ww = wrapper as Wrapper.Widget; + if (ww == null || (!ww.IsTopLevel && ww.InternalChildProperty == null && !ww.Unselectable)) { + type.Members.Add ( + new CodeMemberField ( + new CodeTypeReference (typeName, CodeTypeReferenceOptions.GlobalReference), + memberName + ) + ); + CodeExpression var = new CodeFieldReferenceExpression ( + new CodeThisReferenceExpression (), + memberName + ); + + Statements.Add ( + new CodeAssignStatement ( + var, + newObject + ) + ); + return var; + } else + return base.GenerateInstanceExpression (wrapper, newObject); +// } else { +// CodeExpression var = base.GenerateInstanceExpression (wrapper, newObject); +// Statements.Add ( +// new CodeAssignStatement ( +// new CodeIndexerExpression ( +// new CodeVariableReferenceExpression ("bindings"), +// new CodePrimitiveExpression (memberName) +// ), +// var +// ) +// ); +// return var; +// } + } + } + + [Serializable] + public class SteticCompilationUnit: CodeCompileUnit + { + string name; + + public SteticCompilationUnit (string name) + { + this.name = name; + } + + public string Name { + get { return name; } + internal set { name = value; } + } + + public CodeNamespace Namespace + { + get { return (Namespaces.Count > 0) ? Namespaces [0] : null; } + } + } +} diff --git a/main/src/addins/MonoDevelop.GtkCore2/libsteticui/CodeGeneratorPartialClass.cs b/main/src/addins/MonoDevelop.GtkCore2/libsteticui/CodeGeneratorPartialClass.cs new file mode 100644 index 0000000000..7371b4892c --- /dev/null +++ b/main/src/addins/MonoDevelop.GtkCore2/libsteticui/CodeGeneratorPartialClass.cs @@ -0,0 +1,143 @@ + +using System; +using System.Reflection; +using System.CodeDom; +using System.CodeDom.Compiler; +using System.Collections.Generic; +using System.Collections; +using System.IO; + +namespace Stetic +{ + internal static class CodeGeneratorPartialClass + { + public static void GenerateProjectGuiCode (CodeNamespace globalNs, CodeTypeDeclaration globalType, GenerationOptions options, List<SteticCompilationUnit> units, ProjectBackend[] projects, ArrayList warnings) + { + // Generate code for each project + foreach (ProjectBackend gp in projects) { + + // Generate top levels + foreach (Gtk.Widget w in gp.Toplevels) { + Stetic.Wrapper.Widget wwidget = Stetic.Wrapper.Widget.Lookup (w); + string topLevelName = wwidget.Name; + if (gp.ComponentNeedsCodeGeneration (topLevelName)) { + //designer file for widget could be changed beyond stetic process + //and we nead update wrapper before code generation + //during reloading wrappered widget w could be changed; + Gtk.Widget currentw = w; + if (gp.ReloadTopLevel (topLevelName)) { + currentw = gp.GetWidget (topLevelName); + } + GenerateWidgetCode (globalNs, options, units, currentw, warnings); + } + } + + // Generate global action groups + foreach (Wrapper.ActionGroup agroup in gp.ActionGroups) { + string groupName = agroup.Name; + if (gp.ComponentNeedsCodeGeneration (groupName)) { + //designer file for action group could be changed beyond stetic process + //and we nead update wrapper + gp.ReloadActionGroup (groupName); + GenerateGlobalActionGroupCode (globalNs, options, units, agroup, warnings); + } + } + } + } + + static CodeTypeDeclaration CreatePartialClass (List<SteticCompilationUnit> units, GenerationOptions options, string name) + { + SteticCompilationUnit unit; + + unit = new SteticCompilationUnit (name); + units.Add (unit); + + string ns = ""; + int i = name.LastIndexOf ('.'); + if (i != -1) { + ns = name.Substring (0, i); + name = name.Substring (i+1); + } + + CodeTypeDeclaration type = new CodeTypeDeclaration (name); + type.IsPartial = true; + type.Attributes = MemberAttributes.Public; + type.TypeAttributes = TypeAttributes.Public; + + CodeNamespace cns = new CodeNamespace (ns); + cns.Types.Add (type); + unit.Namespaces.Add (cns); + return type; + } + + + static void GenerateWidgetCode (CodeNamespace globalNs, GenerationOptions options, List<SteticCompilationUnit> units, Gtk.Widget w, ArrayList warnings) + { + // Generate the build method + + CodeTypeDeclaration type = CreatePartialClass (units, options, w.Name); + CodeMemberMethod met = new CodeMemberMethod (); + met.Name = "Build"; + type.Members.Add (met); + met.ReturnType = new CodeTypeReference (typeof(void)); + met.Attributes = MemberAttributes.Family; + + Stetic.Wrapper.Widget wwidget = Stetic.Wrapper.Widget.Lookup (w); + + if (options.GenerateEmptyBuildMethod) { + GenerateWrapperFields (type, wwidget); + return; + } + + met.Statements.Add ( + new CodeMethodInvokeExpression ( + new CodeTypeReferenceExpression (new CodeTypeReference (globalNs.Name + ".Gui", CodeTypeReferenceOptions.GlobalReference)), + "Initialize", + new CodeThisReferenceExpression () + ) + ); + + if (wwidget.GeneratePublic) + type.TypeAttributes = TypeAttributes.Public; + else + type.TypeAttributes = TypeAttributes.NotPublic; + + if (!String.IsNullOrEmpty (wwidget.UIManagerName)) + type.Members.Add (new CodeMemberField (new CodeTypeReference ("Gtk.UIManager", CodeTypeReferenceOptions.GlobalReference), wwidget.UIManagerName)); + + Stetic.WidgetMap map = Stetic.CodeGenerator.GenerateCreationCode (globalNs, type, w, new CodeThisReferenceExpression (), met.Statements, options, warnings); + CodeGenerator.BindSignalHandlers (new CodeThisReferenceExpression (), wwidget, map, met.Statements, options); + } + + static void GenerateWrapperFields (CodeTypeDeclaration type, ObjectWrapper wrapper) + { + foreach (ObjectBindInfo binfo in CodeGenerator.GetFieldsToBind (wrapper)) { + type.Members.Add ( + new CodeMemberField ( + new CodeTypeReference (binfo.TypeName, CodeTypeReferenceOptions.GlobalReference), + binfo.Name + ) + ); + } + } + + + static void GenerateGlobalActionGroupCode (CodeNamespace globalNs, GenerationOptions options, List<SteticCompilationUnit> units, Wrapper.ActionGroup agroup, ArrayList warnings) + { + CodeTypeDeclaration type = CreatePartialClass (units, options, agroup.Name); + + // Generate the build method + + CodeMemberMethod met = new CodeMemberMethod (); + met.Name = "Build"; + type.Members.Add (met); + met.ReturnType = new CodeTypeReference (typeof(void)); + met.Attributes = MemberAttributes.Public; + + Stetic.WidgetMap map = Stetic.CodeGenerator.GenerateCreationCode (globalNs, type, agroup, new CodeThisReferenceExpression (), met.Statements, options, warnings); + + foreach (Wrapper.Action ac in agroup.Actions) + CodeGenerator.BindSignalHandlers (new CodeThisReferenceExpression (), ac, map, met.Statements, options); + } + } +} diff --git a/main/src/addins/MonoDevelop.GtkCore2/libsteticui/Component.cs b/main/src/addins/MonoDevelop.GtkCore2/libsteticui/Component.cs new file mode 100644 index 0000000000..1a1d495ccf --- /dev/null +++ b/main/src/addins/MonoDevelop.GtkCore2/libsteticui/Component.cs @@ -0,0 +1,112 @@ + +using System; +using System.Collections; + +namespace Stetic +{ + public class Component: MarshalByRefObject, IObjectFrontend + { + protected string name; + protected ComponentType type; + protected string typeName; + protected object backend; + protected Application app; + + public event EventHandler Changed; + + internal Component (Application app, object backend, string name, ComponentType type) + { + this.app = app; + this.backend = backend; + this.name = name; + this.type = type; + } + + public virtual void Dispose () + { + System.Runtime.Remoting.RemotingServices.Disconnect (this); + if (app != null) + app.DisposeComponent (this); + } + + public SignalCollection GetSignals () + { + if (backend is ObjectWrapper) + return ((ObjectWrapper)backend).Signals; + else + return new SignalCollection (); + } + + public void RemoveSignal (Signal signal) + { + if (backend is ObjectWrapper && app != null) + app.Backend.RemoveWidgetSignal ((ObjectWrapper) backend, signal); + } + + public virtual Component[] GetChildren () + { + return new Component [0]; + } + + void IObjectFrontend.NotifyChanged () + { + OnChanged (); + } + + protected virtual void OnChanged () + { + if (Changed != null) + Changed (this, EventArgs.Empty); + } + + public virtual string Name { + get { return name; } + set { name = value; } + } + + public virtual ComponentType Type { + get { + return type; + } + } + + public virtual bool GeneratePublic { + get { return true; } + set {} + } + + internal object Backend { + get { return backend; } + } + + internal static MarshalByRefObject GetSafeReference (MarshalByRefObject ob) + { + // Make sure we don't leak the wrapper type to the frontend process + + if (ob is Wrapper.Window) { + System.Runtime.Remoting.RemotingServices.Marshal (ob, null, typeof(Wrapper.Window)); + } else if (ob is Wrapper.Container) { + System.Runtime.Remoting.RemotingServices.Marshal (ob, null, typeof(Wrapper.Container)); + } else if (ob is Wrapper.Widget) { + System.Runtime.Remoting.RemotingServices.Marshal (ob, null, typeof(Wrapper.Widget)); + } else if (ob is ObjectWrapper) { + System.Runtime.Remoting.RemotingServices.Marshal (ob, null, typeof(ObjectWrapper)); + } + return ob; + } + + public override string ToString () + { + return base.ToString() + " " + backend; + } + + public ObjectBindInfo[] GetObjectBindInfo () + { + ObjectWrapper ww = backend as ObjectWrapper; + if (ww != null) + return app.Backend.GetBoundComponents (ww); + else + return new ObjectBindInfo [0]; + } + } +} diff --git a/main/src/addins/MonoDevelop.GtkCore2/libsteticui/ComponentEventHandler.cs b/main/src/addins/MonoDevelop.GtkCore2/libsteticui/ComponentEventHandler.cs new file mode 100644 index 0000000000..d4226f0da7 --- /dev/null +++ b/main/src/addins/MonoDevelop.GtkCore2/libsteticui/ComponentEventHandler.cs @@ -0,0 +1,67 @@ + +using System; + +namespace Stetic +{ + public delegate void ComponentEventHandler (object sender, ComponentEventArgs args); + public delegate void ComponentNameEventHandler (object sender, ComponentNameEventArgs args); + public delegate void ComponentRemovedEventHandler (object sender, ComponentRemovedEventArgs args); + + public class ComponentEventArgs: EventArgs + { + Project project; + Component component; + + internal ComponentEventArgs (Project p, Component c) + { + project = p; + component = c; + } + + public Project Project { + get { return project; } + } + + public Component Component { + get { return component; } + } + } + + public class ComponentNameEventArgs: ComponentEventArgs + { + string oldName; + + internal ComponentNameEventArgs (Project p, Component c, string oldName): base (p, c) + { + this.oldName = oldName; + } + + public string OldName { + get { return oldName; } + } + + public string NewName { + get { return Component.Name; } + } + } + + public class ComponentRemovedEventArgs: EventArgs + { + Project project; + string componentName; + + internal ComponentRemovedEventArgs (Project p, string name) + { + project = p; + componentName = name; + } + + public Project Project { + get { return project; } + } + + public string ComponentName { + get { return componentName; } + } + } +} diff --git a/main/src/addins/MonoDevelop.GtkCore2/libsteticui/ComponentSignalEventHandler.cs b/main/src/addins/MonoDevelop.GtkCore2/libsteticui/ComponentSignalEventHandler.cs new file mode 100644 index 0000000000..07c6263a71 --- /dev/null +++ b/main/src/addins/MonoDevelop.GtkCore2/libsteticui/ComponentSignalEventHandler.cs @@ -0,0 +1,27 @@ + +using System; + +namespace Stetic +{ + public delegate void ComponentSignalEventHandler (object sender, ComponentSignalEventArgs args); + + public class ComponentSignalEventArgs: ComponentEventArgs + { + public Signal oldSignal; + public Signal signal; + + public ComponentSignalEventArgs (Project p, Component c, Signal oldSignal, Signal signal): base (p, c) + { + this.oldSignal = oldSignal; + this.signal = signal; + } + + public Signal Signal { + get { return signal; } + } + + public Signal OldSignal { + get { return oldSignal; } + } + } +} diff --git a/main/src/addins/MonoDevelop.GtkCore2/libsteticui/ComponentType.cs b/main/src/addins/MonoDevelop.GtkCore2/libsteticui/ComponentType.cs new file mode 100644 index 0000000000..47ed725282 --- /dev/null +++ b/main/src/addins/MonoDevelop.GtkCore2/libsteticui/ComponentType.cs @@ -0,0 +1,94 @@ + +using System; + +namespace Stetic +{ + public class ComponentType + { + Application app; + string name; + string description; + string className; + string category; + Gdk.Pixbuf icon; + ActionComponent action; + string targetGtkVersion; + string library; + static ComponentType unknown; + + internal ComponentType (Application app, string name, string desc, string className, string category, string targetGtkVersion, string library, Gdk.Pixbuf icon) + { + this.app = app; + this.name = name; + this.description = desc; + this.icon = icon; + this.className = className; + this.category = category; + this.targetGtkVersion = targetGtkVersion; + this.library = library; + } + + internal ComponentType (Application app, ActionComponent action) + { + this.action = action; + this.app = app; + this.name = action.Name; + this.description = action.Label != null ? action.Label.Replace ("_", "") : action.Name; + this.icon = action.Icon; + this.className = "Gtk.Action"; + this.category = "Actions / " + action.ActionGroup.Name; + this.targetGtkVersion = "2.4"; // Not version-specific + } + + public string Name { + get { return name; } + } + + public string ClassName { + get { return className; } + } + + public string Category { + get { return category; } + } + + public string Description { + get { return description; } + } + + public string Library { + get { return library; } + } + + public Gdk.Pixbuf Icon { + get { return icon; } + } + + internal ActionComponent Action { + get { return action; } + } + + internal static ComponentType Unknown { + get { + if (unknown == null) { + unknown = new ComponentType (null, "Unknown", "Unknown", "", "", "2.4", null, WidgetUtils.MissingIcon); + } + return unknown; + } + } + + public object[] InitializationValues { + get { + if (app == null) + return new object [0]; + return app.Backend.GetClassDescriptorInitializationValues (name); + } + } + + public string TargetGtkVersion { + get { + return targetGtkVersion; + } + } + } +} diff --git a/main/src/addins/MonoDevelop.GtkCore2/libsteticui/ContainerUndoRedoManager.cs b/main/src/addins/MonoDevelop.GtkCore2/libsteticui/ContainerUndoRedoManager.cs new file mode 100644 index 0000000000..ddfe62d2e7 --- /dev/null +++ b/main/src/addins/MonoDevelop.GtkCore2/libsteticui/ContainerUndoRedoManager.cs @@ -0,0 +1,18 @@ + +using System; +using System.Xml; +using System.Collections; + +namespace Stetic +{ + class ContainerUndoRedoManager: UndoRedoManager + { + protected override object GetDiff (ObjectWrapper w) + { + // Only track changes in widgets. + Wrapper.Widget widget = w as Wrapper.Widget; + if (widget != null) return w.GetUndoDiff (); + else return null; + } + } +} diff --git a/main/src/addins/MonoDevelop.GtkCore2/libsteticui/ContextMenu.cs b/main/src/addins/MonoDevelop.GtkCore2/libsteticui/ContextMenu.cs new file mode 100644 index 0000000000..3b64a286f5 --- /dev/null +++ b/main/src/addins/MonoDevelop.GtkCore2/libsteticui/ContextMenu.cs @@ -0,0 +1,174 @@ +using Gtk; +using System; +using System.Collections; +using System.Reflection; +using Mono.Unix; + +namespace Stetic { + + class ContextMenu : Gtk.Menu { + + Gtk.Widget widget; + IEditableObject editable; + + public ContextMenu (Placeholder ph) + { + MenuItem item; + + editable = ph; + this.widget = ph; + + item = LabelItem (ph); + item.Sensitive = false; + Add (item); + + item = new MenuItem (Catalog.GetString ("_Select")); + item.Sensitive = false; + Add (item); + + BuildContextMenu (Stetic.Wrapper.Container.LookupParent (ph), true, ph); + } + + public ContextMenu (Stetic.Wrapper.Widget wrapper) : this (wrapper, wrapper.Wrapped) {} + + public ContextMenu (Stetic.Wrapper.Widget wrapper, Gtk.Widget context) + { + MenuItem item; + + editable = wrapper; + widget = wrapper.Wrapped; + + if (widget == context) { + item = LabelItem (widget); + item.Sensitive = false; + Add (item); + } + + item = new MenuItem (Catalog.GetString ("_Select")); + item.Activated += DoSelect; + Add (item); + + ClassDescriptor klass = wrapper.ClassDescriptor; + if (klass != null) { + foreach (ItemDescriptor id in klass.ContextMenu) { + CommandDescriptor cmd = (CommandDescriptor)id; + if (!cmd.VisibleFor (widget)) + continue; + item = new MenuItem (cmd.Label); + if (cmd.Enabled (widget, context)) { + Gtk.Widget wdup = widget, cdup = context; // FIXME bxc 75689 + item.Activated += delegate (object o, EventArgs args) { + cmd.Run (wdup, cdup); + }; + } else + item.Sensitive = false; + Add (item); + } + } + + BuildContextMenu (wrapper.ParentWrapper, widget == context, context); + } + + void BuildContextMenu (Stetic.Wrapper.Widget parentWrapper, bool top, Widget context) + { + MenuItem item; + + item = new ImageMenuItem (Gtk.Stock.Cut, null); + if (editable.CanCut) + item.Activated += DoCut; + else + item.Sensitive = false; + Add (item); + + item = new ImageMenuItem (Gtk.Stock.Copy, null); + if (editable.CanCopy) + item.Activated += DoCopy; + else + item.Sensitive = false; + Add (item); + + item = new ImageMenuItem (Gtk.Stock.Paste, null); + if (editable.CanPaste) + item.Activated += DoPaste; + else + item.Sensitive = false; + Add (item); + + if (editable.CanDelete) { + item = new ImageMenuItem (Gtk.Stock.Delete, null); + item.Activated += DoDelete; + Add (item); + } + + if (top) { + for (; parentWrapper != null; parentWrapper = parentWrapper.ParentWrapper) { + Add (new SeparatorMenuItem ()); + + item = LabelItem (parentWrapper.Wrapped); + item.Submenu = new ContextMenu (parentWrapper, context); + Add (item); + } + } + + ShowAll (); + } + + protected override void OnSelectionDone () + { + Destroy (); + } + + void DoSelect (object obj, EventArgs args) + { + Stetic.Wrapper.Widget wrapper = Stetic.Wrapper.Widget.Lookup (widget); + if (wrapper != null) + wrapper.Select (); + } + + void DoCut (object obj, EventArgs args) + { + editable.Cut (); + } + + void DoCopy (object obj, EventArgs args) + { + editable.Copy (); + } + + void DoPaste (object obj, EventArgs args) + { + editable.Paste (); + } + + void DoDelete (object obj, EventArgs args) + { + editable.Delete (); + } + + static MenuItem LabelItem (Gtk.Widget widget) + { + ImageMenuItem item; + Label label; + + label = new Label (widget is Placeholder ? Catalog.GetString ("Placeholder") : widget.Name); + label.UseUnderline = false; + label.SetAlignment (0.0f, 0.5f); + item = new ImageMenuItem (); + item.Add (label); + + 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; + } + } +} diff --git a/main/src/addins/MonoDevelop.GtkCore2/libsteticui/Designer.cs b/main/src/addins/MonoDevelop.GtkCore2/libsteticui/Designer.cs new file mode 100644 index 0000000000..21aaf500c7 --- /dev/null +++ b/main/src/addins/MonoDevelop.GtkCore2/libsteticui/Designer.cs @@ -0,0 +1,44 @@ +// Designer.cs +// +// Author: +// Lluis Sanchez Gual +// +// Copyright (c) 2007 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; + +namespace Stetic +{ + public abstract class Designer: PluggableWidget + { + protected Designer (Application app): base (app) + { + } + + internal virtual void SetActive () + { + } + + public abstract ProjectItemInfo ProjectItem { get; } + } +} diff --git a/main/src/addins/MonoDevelop.GtkCore2/libsteticui/Glade.cs b/main/src/addins/MonoDevelop.GtkCore2/libsteticui/Glade.cs new file mode 100644 index 0000000000..4fcd4ff76a --- /dev/null +++ b/main/src/addins/MonoDevelop.GtkCore2/libsteticui/Glade.cs @@ -0,0 +1,63 @@ +using System; +using System.Xml; +using System.Collections; +using System.Reflection; +using System.Runtime.InteropServices; +using Mono.Unix; + +using Gtk; + +namespace Stetic { + + internal static class GladeFiles { + + public static void Import (ProjectBackend project, string filename) + { + XmlDocument doc = new XmlDocument (); + doc.PreserveWhitespace = true; + doc.XmlResolver = null; + 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 (Catalog.GetString ("Not a glade file according to node name.")); + + ObjectReader reader = new ObjectReader (project, FileFormat.Glade); + foreach (XmlElement toplevel in node.SelectNodes ("widget")) { + Wrapper.Container wrapper = Stetic.ObjectWrapper.ReadObject (reader, toplevel, null) as Wrapper.Container; + if (wrapper != null) + project.AddWidget ((Gtk.Widget)wrapper.Wrapped); + } + } + + public static void Export (ProjectBackend project, string filename) + { + XmlDocument doc = new XmlDocument (); + doc.PreserveWhitespace = true; + + XmlElement toplevel = doc.CreateElement ("glade-interface"); + doc.AppendChild (toplevel); + + ObjectWriter owriter = new ObjectWriter (doc, FileFormat.Glade); + foreach (Widget w in project.Toplevels) { + Stetic.Wrapper.Container wrapper = Stetic.Wrapper.Container.Lookup (w); + if (wrapper == null) + continue; + + XmlElement elem = wrapper.Write (owriter); + if (elem != null) + toplevel.AppendChild (elem); + } + + doc = GladeUtils.XslExportTransform (doc); + + // FIXME; if you use UTF8, it starts with a BOM??? + XmlTextWriter writer = new XmlTextWriter (filename, System.Text.Encoding.ASCII); + writer.Formatting = Formatting.Indented; + doc.Save (writer); + writer.Close (); + } + } +} diff --git a/main/src/addins/MonoDevelop.GtkCore2/libsteticui/Grid.cs b/main/src/addins/MonoDevelop.GtkCore2/libsteticui/Grid.cs new file mode 100644 index 0000000000..5f82fd0253 --- /dev/null +++ b/main/src/addins/MonoDevelop.GtkCore2/libsteticui/Grid.cs @@ -0,0 +1,347 @@ +using Gtk; +using System; +using System.Collections; + +namespace Stetic { + + internal class Grid : Gtk.Container { + + public Grid () : base () + { + BorderWidth = 2; + WidgetFlags |= WidgetFlags.NoWindow; + lines = new ArrayList (); + group = null; + } + + // Padding constants + const int groupPad = 6; + const int hPad = 6; + const int linePad = 3; + + // Theme-based sizes; computed at first SizeRequest + static int indent = -1; + static int lineHeight = -1; + + Grid[] group; + public static void Connect (params Grid[] grids) + { + for (int i = 0; i < grids.Length; i++) { + grids[i].group = new Grid[grids.Length - 1]; + Array.Copy (grids, 0, grids[i].group, 0, i); + Array.Copy (grids, i + 1, grids[i].group, i, grids.Length - i - 1); + } + } + + class Pair { + Gtk.Widget label; + Gtk.Widget editor; + + public Pair (Grid grid, string name, Widget editor) : this (grid, name, editor, null) {} + + public Pair (Grid grid, string name, Widget editor, string description) + { + Gtk.Label l = new Label (name); + l.UseMarkup = true; + l.Justify = Justification.Left; + l.Xalign = 0; + l.Show (); + + if (description == null) + label = l; + else { + Gtk.EventBox ebox = new Gtk.EventBox (); + ebox.Add (l); + ebox.Show (); + ebox.TooltipText = description; + label = ebox; + } + label.Parent = grid; + + this.editor = editor; + editor.Parent = grid; + editor.Show (); + } + + public Widget Label { + get { + return label; + } + } + + public Widget Editor { + get { + return editor; + } + } + } + + // list of widgets and Stetic.Grid.Pairs + ArrayList lines; + + public void Append (Widget w) + { + w.Parent = this; + w.Show (); + + lines.Add (w); + QueueDraw (); + } + + public void Append (Widget w, string description) + { + if ((w.WidgetFlags & WidgetFlags.NoWindow) != 0) { + Gtk.EventBox ebox = new Gtk.EventBox (); + ebox.Add (w); + ebox.Show (); + w = ebox; + } + w.Parent = this; + w.Show (); + w.TooltipText = description; + lines.Add (w); + QueueDraw (); + } + + public void AppendLabel (string text) + { + Gtk.Label label = new Label (text); + label.UseMarkup = true; + label.Justify = Justification.Left; + label.Xalign = 0; + Append (label); + } + + public void AppendGroup (string name, bool expanded) + { + Gtk.Expander exp = new Expander ("<b>" + name + "</b>"); + exp.UseMarkup = true; + exp.Expanded = expanded; + exp.AddNotification ("expanded", ExpansionChanged); + Append (exp); + } + + public void AppendPair (string label, Widget editor, string description) + { + Stetic.Grid.Pair pair = new Pair (this, label, editor, description); + lines.Add (pair); + QueueDraw (); + } + + protected override void OnRemoved (Widget w) + { + w.Unparent (); + } + + void ExpansionChanged (object obj, GLib.NotifyArgs args) + { + Gtk.Expander exp = obj as Gtk.Expander; + + int ind = lines.IndexOf (exp); + if (ind == -1) + return; + + ind++; + while (ind < lines.Count && !(lines[ind] is Gtk.Expander)) { + if (lines[ind] is Widget) { + Widget w = (Widget)lines[ind]; + if (exp.Expanded) + w.Show (); + else + w.Hide (); + } else if (lines[ind] is Pair) { + Pair p = (Pair)lines[ind]; + if (exp.Expanded) { + p.Label.Show (); + p.Editor.Show (); + } else { + p.Label.Hide (); + p.Editor.Hide (); + } + } + ind++; + } + + QueueDraw (); + } + + protected void Clear () + { + foreach (object obj in lines) { + if (obj is Widget) + ((Widget)obj).Destroy (); + else if (obj is Pair) { + Pair p = (Pair)obj; + p.Label.Destroy (); + p.Editor.Destroy (); + } + } + + lines.Clear (); + } + + protected override void ForAll (bool include_internals, Gtk.Callback callback) + { + if (!include_internals) + return; + + foreach (object obj in lines) { + if (obj is Widget) + callback ((Widget)obj); + else if (obj is Pair) { + Pair p = (Pair)obj; + callback (p.Label); + callback (p.Editor); + } + } + } + + // These are figured out at requisition time and used again at + // allocation time. + int lwidth, ewidth; + + void SizeRequestGrid (Grid grid, ref Gtk.Requisition req) + { + bool visible = true; + + req.Width = req.Height = 0; + foreach (object obj in grid.lines) { + if (obj is Expander) { + Gtk.Widget w = (Gtk.Widget)obj; + Gtk.Requisition childreq; + + childreq = w.SizeRequest (); + if (req.Width < childreq.Width) + req.Width = childreq.Width; + req.Height += groupPad + childreq.Height; + + visible = ((Gtk.Expander)obj).Expanded; + + if (indent == -1) { + // Seems like there should be an easier way... + int focusWidth = (int)w.StyleGetProperty ("focus-line-width"); + int focusPad = (int)w.StyleGetProperty ("focus-padding"); + int expanderSize = (int)w.StyleGetProperty ("expander-size"); + int expanderSpacing = (int)w.StyleGetProperty ("expander-spacing"); + indent = focusWidth + focusPad + expanderSize + 2 * expanderSpacing; + } + } else if (obj is Widget) { + Gtk.Widget w = (Gtk.Widget)obj; + Gtk.Requisition childreq; + + childreq = w.SizeRequest (); + if (lwidth < childreq.Width) + lwidth = childreq.Width; + if (visible) + req.Height += linePad + childreq.Height; + } else if (obj is Pair) { + Pair p = (Pair)obj; + Gtk.Requisition lreq, ereq; + + lreq = p.Label.SizeRequest (); + ereq = p.Editor.SizeRequest (); + + if (lineHeight == -1) + lineHeight = (int)(1.5 * lreq.Height); + + if (lreq.Width > lwidth) + lwidth = lreq.Width; + if (ereq.Width > ewidth) + ewidth = ereq.Width; + + if (visible) + req.Height += Math.Max (lineHeight, ereq.Height) + linePad; + } + } + + req.Width = Math.Max (req.Width, indent + lwidth + hPad + ewidth); + req.Height += 2 * (int)BorderWidth; + req.Width += 2 * (int)BorderWidth; + } + + protected override void OnSizeRequested (ref Gtk.Requisition req) + { + lwidth = ewidth = 0; + + if (group != null) { + foreach (Grid grid in group) + SizeRequestGrid (grid, ref req); + } + + SizeRequestGrid (this, ref req); + } + + protected override void OnSizeAllocated (Gdk.Rectangle alloc) + { + int xbase = alloc.X + (int)BorderWidth; + int ybase = alloc.Y + (int)BorderWidth; + + base.OnSizeAllocated (alloc); + + int y = ybase; + bool visible = true; + + foreach (object obj in lines) { + if (!visible && !(obj is Expander)) + continue; + + if (obj is Widget) { + Gtk.Widget w = (Gtk.Widget)obj; + if (!w.Visible) + continue; + + Gdk.Rectangle childalloc; + Gtk.Requisition childreq; + + childreq = w.ChildRequisition; + + if (obj is Expander) { + childalloc.X = xbase; + childalloc.Width = alloc.Width - 2 * (int)BorderWidth; + visible = ((Gtk.Expander)obj).Expanded; + y += groupPad; + } else { + childalloc.X = xbase + indent; + childalloc.Width = lwidth; + y += linePad; + } + childalloc.Y = y; + childalloc.Height = childreq.Height; + w.SizeAllocate (childalloc); + + y += childalloc.Height; + } else if (obj is Pair) { + Pair p = (Pair)obj; + if (!p.Editor.Visible) { + p.Label.Hide (); + continue; + } else if (!p.Label.Visible) + p.Label.Show (); + + Gtk.Requisition lreq, ereq; + Gdk.Rectangle lalloc, ealloc; + + lreq = p.Label.ChildRequisition; + ereq = p.Editor.ChildRequisition; + + lalloc.X = xbase + indent; + if (ereq.Height < lineHeight * 2) + lalloc.Y = y + (ereq.Height - lreq.Height) / 2; + else + lalloc.Y = y + (lineHeight - lreq.Height) / 2; + lalloc.Width = lwidth; + lalloc.Height = lreq.Height; + p.Label.SizeAllocate (lalloc); + + ealloc.X = lalloc.X + lwidth + hPad; + ealloc.Y = y + Math.Max (0, (lineHeight - ereq.Height) / 2); + ealloc.Width = Math.Max (ewidth, alloc.Width - 2 * (int)BorderWidth - ealloc.X); + ealloc.Height = ereq.Height; + p.Editor.SizeAllocate (ealloc); + + y += Math.Max (ereq.Height, lineHeight) + linePad; + } + } + } + } +} diff --git a/main/src/addins/MonoDevelop.GtkCore2/libsteticui/GuiDispatchServerSink.cs b/main/src/addins/MonoDevelop.GtkCore2/libsteticui/GuiDispatchServerSink.cs new file mode 100644 index 0000000000..e1262948e4 --- /dev/null +++ b/main/src/addins/MonoDevelop.GtkCore2/libsteticui/GuiDispatchServerSink.cs @@ -0,0 +1,142 @@ + +using System; +using System.Threading; +using System.IO; +using System.Runtime.Remoting; +using System.Runtime.Remoting.Channels; +using System.Runtime.Remoting.Messaging; +using System.Collections; + +namespace Stetic +{ + public class GuiDispatchServerSink: IServerChannelSink, IChannelSinkBase + { + IServerChannelSink nextSink;
+
+ public GuiDispatchServerSink (IServerChannelSink nextSink, IChannelReceiver receiver)
+ {
+ this.nextSink = nextSink;
+ }
+
+ public IServerChannelSink NextChannelSink {
+ get { return nextSink; }
+ }
+
+ public IDictionary Properties {
+ get { return null; }
+ }
+
+ public void AsyncProcessResponse (IServerResponseChannelSinkStack sinkStack, object state,
+ IMessage msg, ITransportHeaders headers, Stream stream)
+
+ { + sinkStack.AsyncProcessResponse (msg, headers, stream);
+ }
+
+ public Stream GetResponseStream (IServerResponseChannelSinkStack sinkStack, object state,
+ IMessage msg, ITransportHeaders headers)
+ {
+ // this method shouldn't be called
+ throw new NotSupportedException ();
+ }
+
+ public ServerProcessing ProcessMessage (IServerChannelSinkStack sinkStack,
+ IMessage requestMsg, ITransportHeaders requestHeaders, Stream requestStream,
+ out IMessage responseMsg, out ITransportHeaders responseHeaders, out Stream responseStream)
+ { + IMethodCallMessage msg = (IMethodCallMessage) requestMsg; +// Console.WriteLine ("MESSAGE: " + msg.TypeName + " - " + msg.MethodName); + + sinkStack.Push (this, null); +
+ if (Attribute.IsDefined (msg.MethodBase, typeof(NoGuiDispatchAttribute))) { + ServerProcessing ret; + try { + ret = nextSink.ProcessMessage (sinkStack,
+ requestMsg,
+ requestHeaders,
+ requestStream,
+ out responseMsg,
+ out responseHeaders,
+ out responseStream); + } finally { + sinkStack.Pop (this); + } + return ret; + } + else + { + Dispatcher d = new Dispatcher (); + d.nextSink = nextSink; + d.sinkStack = sinkStack; + d.requestMsg = requestMsg; + d.requestHeaders = requestHeaders; + d.requestStream = requestStream; + + Gtk.Application.Invoke (d.Dispatch); + responseMsg = null; + responseHeaders = null; + responseStream = null; + + return ServerProcessing.Async; + }
+ } +
+ class Dispatcher + { + public IServerChannelSink nextSink; + + public IServerChannelSinkStack sinkStack; + public IMessage requestMsg; + public ITransportHeaders requestHeaders; + public Stream requestStream; +
+ public void Dispatch (object o, EventArgs a) + { + IMessage responseMsg; + ITransportHeaders responseHeaders = null; + Stream responseStream = null; + + try { + nextSink.ProcessMessage (sinkStack,
+ requestMsg,
+ requestHeaders,
+ requestStream,
+ out responseMsg,
+ out responseHeaders,
+ out responseStream); + } + catch (Exception ex) { + responseMsg = new ReturnMessage (ex, (IMethodCallMessage)requestMsg); + } + + sinkStack.AsyncProcessResponse (responseMsg, responseHeaders, responseStream); + } + } + } + + class GuiDispatch + { + public static void InvokeSync (EventHandler h) + { + if (GLib.MainContext.Depth > 0) + h (null, null); + else { + object wo = new object (); + lock (wo) { + Gtk.Application.Invoke (delegate { + try { + h (null, null); + } finally { + lock (wo) { + System.Threading.Monitor.PulseAll (wo); + } + } + }); + System.Threading.Monitor.Wait (wo); + } + } + } + } + +} diff --git a/main/src/addins/MonoDevelop.GtkCore2/libsteticui/GuiDispatchServerSinkProvider.cs b/main/src/addins/MonoDevelop.GtkCore2/libsteticui/GuiDispatchServerSinkProvider.cs new file mode 100644 index 0000000000..d35c2b3950 --- /dev/null +++ b/main/src/addins/MonoDevelop.GtkCore2/libsteticui/GuiDispatchServerSinkProvider.cs @@ -0,0 +1,30 @@ + +using System; +using System.Runtime.Remoting; +using System.Runtime.Remoting.Channels; + +namespace Stetic +{ + public class GuiDispatchServerSinkProvider: IServerFormatterSinkProvider, IServerChannelSinkProvider + { + private IServerChannelSinkProvider next; + + public IServerChannelSinkProvider Next {
+ get { return next; }
+ set { next = value; }
+ }
+
+ public IServerChannelSink CreateSink (IChannelReceiver channel)
+ {
+ IServerChannelSink chain = next.CreateSink (channel);
+ GuiDispatchServerSink sink = new GuiDispatchServerSink (chain, channel);
+ return sink;
+ }
+
+ public void GetChannelData (IChannelDataStore channelData)
+ {
+ if(next != null)
+ next.GetChannelData(channelData);
+ }
+ } +} diff --git a/main/src/addins/MonoDevelop.GtkCore2/libsteticui/IProjectDesignInfo.cs b/main/src/addins/MonoDevelop.GtkCore2/libsteticui/IProjectDesignInfo.cs new file mode 100644 index 0000000000..903850429a --- /dev/null +++ b/main/src/addins/MonoDevelop.GtkCore2/libsteticui/IProjectDesignInfo.cs @@ -0,0 +1,22 @@ +using System; + +namespace Stetic +{ + //Provides access to informations managed by ide + public interface IProjectDesignInfo + { + //Returns component source file for given component + string GetComponentFile (string componentName); + bool HasComponentFile (string componentFile); + + //Returns gtkx file name for given component file + string GetDesignerFileFromComponent (string componentFile); + + //Search for all components source file folders + string[] GetComponentFolders (); + + // Checks if code generation for a component is needed + bool ComponentNeedsCodeGeneration (string componentName); + } +} + diff --git a/main/src/addins/MonoDevelop.GtkCore2/libsteticui/LibraryCache.cs b/main/src/addins/MonoDevelop.GtkCore2/libsteticui/LibraryCache.cs new file mode 100644 index 0000000000..93301495a3 --- /dev/null +++ b/main/src/addins/MonoDevelop.GtkCore2/libsteticui/LibraryCache.cs @@ -0,0 +1,793 @@ +// LibraryCache.cs : Assembly file caching class +// +// Author: Mike Kestner <mkestner@novell.com> +// +// Copyright (c) 2008 Novell, Inc +// +// Permission is hereby granted, free of charge, to any person obtaining +// a copy of this software and associated documentation files (the +// "Software"), to deal in the Software without restriction, including +// without limitation the rights to use, copy, modify, merge, publish, +// distribute, sublicense, and/or sell copies of the Software, and to +// permit persons to whom the Software is furnished to do so, subject to +// the following conditions: +// +// The above copyright notice and this permission notice shall be +// included in all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, +// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND +// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE +// LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION +// OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION +// WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + + +using System; +using System.Collections; +using System.Collections.Generic; +using System.Collections.Specialized; +using System.IO; +using System.Xml; +using System.Xml.Serialization; +using ENV = System.Environment; +using Mono.Cecil; + +namespace Stetic { + + public class LibraryCache { + + public class LibraryInfo { + + public LibraryInfo () {} + + string file; + Guid guid; + DateTime timestamp; + XmlDocument gui; + XmlDocument objects; + + string CacheDirectory { + get { return Path.Combine (dir, Guid.ToString ()); } + } + + [XmlAttribute] + public string File { + get { return file; } + set { file = value; } + } + + [XmlAttribute] + public Guid Guid { + get { return guid; } + set { + string path = Path.Combine (dir, guid.ToString ()); + if (Directory.Exists (path)) + Directory.Delete (path, true); + guid = value; + } + } + + public bool IsCurrent { + get { + return Timestamp == System.IO.File.GetLastWriteTime (file).ToUniversalTime (); + } + } + + [XmlIgnore] + public XmlDocument GuiDocument { + get { + if (gui == null) { + if (System.IO.File.Exists (GuiPath)) { + try { + gui = new XmlDocument (); + using (Stream stream = System.IO.File.Open (GuiPath, FileMode.Open)) + gui.Load (stream); + } catch (Exception) { + gui = null; + } + } + } + return gui; + } + set { + gui = value; + WriteGuiFile (); + } + } + + string GuiPath { + get { return Path.Combine (CacheDirectory, "steticGui"); } + } + + public bool HasWidgets { + get { return System.IO.File.Exists (ObjectsPath); } + } + + [XmlIgnore] + public XmlDocument ObjectsDocument { + get { + if (objects == null) { + if (System.IO.File.Exists (ObjectsPath)) { + try { + objects = new XmlDocument (); + using (Stream stream = System.IO.File.Open (ObjectsPath, FileMode.Open)) + objects.Load (stream); + } catch (Exception) { + objects = null; + } + } + } + return objects; + } + set { + objects = value; + WriteObjectsFile (); + if (objects == null && gui != null) + GuiDocument = null; + } + } + + internal ToolboxItemInfo GetToolboxItem (string name, string asmName) + { + XmlDocument doc = ObjectsDocument; + if (doc != null) { + XmlElement elem = (XmlElement) doc.SelectSingleNode ("/objects/object[@type='" + name + "']"); + if (elem == null) + elem = (XmlElement) doc.SelectSingleNode ("/objects/object[@type='" + name + "," + asmName + "']"); + if (elem != null) { + ToolboxItemInfo info = new ToolboxItemInfo (elem.GetAttribute ("base-type")); + info.PaletteCategory = elem.GetAttribute ("palette-category"); + return info; + } + + } + return null; + } + + string ObjectsPath { + get { return Path.Combine (CacheDirectory, "objects"); } + } + + [XmlAttribute] + public DateTime Timestamp { + get { return timestamp; } + set { timestamp = value; } + } + + void WriteGuiFile () + { + if (gui == null) { + if (System.IO.File.Exists (GuiPath)) + System.IO.File.Delete (GuiPath); + return; + } + if (!Directory.Exists (CacheDirectory)) + Directory.CreateDirectory (CacheDirectory); + + using (Stream stream = System.IO.File.Create (GuiPath)) + gui.Save (stream); + } + + public void WriteObjectsFile () + { + if (objects == null) { + if (System.IO.File.Exists (ObjectsPath)) + System.IO.File.Delete (ObjectsPath); + return; + } + + if (!Directory.Exists (CacheDirectory)) + Directory.CreateDirectory (CacheDirectory); + + using (Stream stream = System.IO.File.Create (ObjectsPath)) + objects.Save (stream); + } + + public event EventHandler Changed; + + public void OnChanged () + { + if (Changed != null) + Changed (this, EventArgs.Empty); + } + } + + static string dir = Path.Combine (Path.Combine (ENV.GetFolderPath (ENV.SpecialFolder.ApplicationData), "stetic"), "library-cache"); + + public class LibraryInfoCollection : IEnumerable { + + Dictionary<string, LibraryInfo> libs = new Dictionary<string, LibraryInfo> (); + + public LibraryInfo this [string path] { + get { + path = Path.GetFullPath (path); + if (libs.ContainsKey (path)) + return libs [path]; + return null; + } + } + + public void Add (object obj) + { + Add (obj as LibraryInfo); + } + + public void Add (LibraryInfo info) + { + libs [info.File] = info; + } + + public IEnumerator GetEnumerator () + { + return libs.Values.GetEnumerator (); + } + + public void Remove (string file) + { + file = Path.GetFullPath (file); + libs.Remove (file); + } + } + + public static LibraryCache Cache = Load (); + + [XmlArray] + [XmlArrayItem (ElementName="LibraryInfo", Type=typeof(LibraryInfo))] + public LibraryInfoCollection Members = new LibraryInfoCollection (); + + public LibraryCache () {} + + public LibraryInfo this [string file] { + get { + file = Path.GetFullPath (file); + if (IsCurrent (file)) + return Members [file]; + + Refresh (null, file); + return Members [file]; + } + } + + public bool IsCurrent (string file) + { + file = Path.GetFullPath (file); + LibraryInfo info = Members [file]; + return info != null && info.Timestamp == File.GetLastWriteTime (file).ToUniversalTime (); + } + + EmbeddedResource GetResource (AssemblyDefinition asm, string name) + { + foreach (Resource res in asm.MainModule.Resources) { + EmbeddedResource eres = res as EmbeddedResource; + if (eres != null && eres.Name == name) + return eres; + } + return null; + } + + void AddDependencies (XmlElement elem, AssemblyResolver resolver, string filename, AssemblyDefinition asm) + { + string dir = Path.GetDirectoryName (filename); + foreach (AssemblyNameReference aref in asm.MainModule.AssemblyReferences) { + LibraryInfo info = GetInfo (resolver, aref.FullName, dir); + if (info != null && info.HasWidgets) { + XmlElement edep = elem.OwnerDocument.CreateElement ("dependency"); + edep.InnerText = info.File; + elem.AppendChild (edep); + } + } + } + + XmlDocument GetGuiDoc (AssemblyDefinition adef) + { + XmlDocument doc = null; + try { + EmbeddedResource res = GetResource (adef, "gui.stetic"); + if (res != null) { + MemoryStream stream = new MemoryStream (res.Data); + doc = new XmlDocument (); + using (stream) + doc.Load (stream); + } + } catch { + doc = null; + } + + return doc; + } + + bool ReferenceChainContainsGtk (AssemblyResolver resolver, AssemblyNameReference aref, Hashtable visited) + { + if (aref.Name == "gtk-sharp") + return true; + else if (visited.Contains (aref.Name)) + return false; + + visited [aref.Name] = aref; + + AssemblyDefinition adef = resolver.Resolve (aref); + if (adef == null) + return false; + + foreach (AssemblyNameReference child in adef.MainModule.AssemblyReferences) + if (ReferenceChainContainsGtk (resolver, child, visited)) + return true; + + return false; + } + + internal class ToolboxItemInfo { + + public ToolboxItemInfo (string base_type) + { + BaseType = base_type; + } + + public string BaseType; + public string PaletteCategory; + } + + ToolboxItemInfo GetToolboxItemInfo (AssemblyResolver resolver, string baseDirectory, AssemblyDefinition asm, TypeDefinition tdef, bool checkBaseType) + { + if (tdef == null) + return null; + + ToolboxItemInfo info = null; + string category = "General"; + + foreach (CustomAttribute attr in tdef.CustomAttributes) { + switch (attr.Constructor.DeclaringType.FullName) { + case "System.ComponentModel.ToolboxItemAttribute": + try { + attr.Resolve (); + } catch { + // Ignore + return null; + } + if (attr.ConstructorParameters.Count > 0) { + object param = attr.ConstructorParameters [0]; + if (param == null) + return null; + else if (param.GetType () == typeof (bool)) { + if ((bool) param) + info = new ToolboxItemInfo ("Gtk.Widget"); + else + return null; + } else if (param.GetType () == typeof (System.Type)) + info = new ToolboxItemInfo ("Gtk.Widget"); + else + return null; + } + break; + case "System.ComponentModel.CategoryAttribute": + try { + attr.Resolve (); + } catch { + // Ignore + return null; + } + if (attr.ConstructorParameters.Count > 0) { + object param = attr.ConstructorParameters [0]; + if (param.GetType () == typeof (string)) + category = (string) param; + } + break; + default: + continue; + } + } + + if (info == null && checkBaseType && tdef.BaseType != null) { + string baseName = tdef.BaseType.FullName; + + foreach (AssemblyNameReference aref in asm.MainModule.AssemblyReferences) { + LibraryInfo libInfo = GetInfo (resolver, aref.FullName, baseDirectory); + if (libInfo != null && libInfo.HasWidgets) { + ToolboxItemInfo binfo = libInfo.GetToolboxItem (baseName, aref.Name); + if (binfo != null) { + info = new ToolboxItemInfo (baseName); + category = binfo.PaletteCategory; + break; + } + } + } + } + + if (info != null) + info.PaletteCategory = category; + + return info; + } + + XmlElement GetItemGroup (XmlElement groups, string cat, string default_label) + { + XmlElement group; + + if (String.IsNullOrEmpty (cat)) + group = (XmlElement) groups.SelectSingleNode ("itemgroup[(not(@name) or @name='') and not(@ref)]"); + else + group = (XmlElement) groups.SelectSingleNode ("itemgroup[@name='" + cat + "']"); + + if (group == null) { + group = groups.OwnerDocument.CreateElement ("itemgroup"); + if (String.IsNullOrEmpty (cat)) + group.SetAttribute ("label", default_label); + else { + group.SetAttribute ("name", cat); + group.SetAttribute ("label", cat); + } + groups.AppendChild (group); + } + return group; + } + + void AddProperty (PropertyDefinition prop, string cat, XmlElement obj) + { + XmlElement groups = obj ["itemgroups"]; + if (groups == null) { + groups = obj.OwnerDocument.CreateElement ("itemgroups"); + obj.AppendChild (groups); + } + + XmlElement group = GetItemGroup (groups, cat, prop.DeclaringType.Name + " Properties"); + XmlElement elem = group.OwnerDocument.CreateElement ("property"); + elem.SetAttribute ("name", prop.Name); + group.AppendChild (elem); + } + + static string[] supported_types = new string[] { + "System.Boolean", + "System.Char", + "System.SByte", + "System.Byte", + "System.Int16", + "System.UInt16", + "System.Int32", + "System.UInt32", + "System.Int64", + "System.UInt64", + "System.Decimal", + "System.Single", + "System.Double", + "System.DateTime", + "System.String", + "System.TimeSpan", + "Gtk.Adjustment", + }; + + void AddProperties (TypeDefinition tdef, XmlElement obj) + { + foreach (PropertyDefinition prop in tdef.Properties) { + if (prop.GetMethod == null || !prop.GetMethod.IsPublic || prop.SetMethod == null || !prop.SetMethod.IsPublic) + continue; + else if (Array.IndexOf (supported_types, prop.PropertyType.FullName) < 0) + continue; + bool browsable = true; + string category = String.Empty; + foreach (CustomAttribute attr in prop.CustomAttributes) { + switch (attr.Constructor.DeclaringType.FullName) { + case "System.ComponentModel.BrowsableAttribute": + attr.Resolve (); + if (attr.ConstructorParameters.Count > 0) { + object param = attr.ConstructorParameters [0]; + if (param.GetType () == typeof (bool)) + browsable = (bool) param; + } + break; + case "System.ComponentModel.CategoryAttribute": + attr.Resolve (); + if (attr.ConstructorParameters.Count > 0) { + object param = attr.ConstructorParameters [0]; + if (param.GetType () == typeof (string)) + category = (string) param; + } + break; + default: + continue; + } + if (!browsable) + break; + } + if (browsable) + AddProperty (prop, category, obj); + } + } + + void AddEvent (EventDefinition ev, string cat, XmlElement obj) + { + XmlElement groups = obj ["signals"]; + if (groups == null) { + groups = obj.OwnerDocument.CreateElement ("signals"); + obj.AppendChild (groups); + } + + XmlElement group = GetItemGroup (groups, cat, ev.DeclaringType.Name + " Signals"); + XmlElement elem = group.OwnerDocument.CreateElement ("signal"); + elem.SetAttribute ("name", ev.Name); + group.AppendChild (elem); + } + + void AddEvents (TypeDefinition tdef, XmlElement obj) + { + + foreach (EventDefinition ev in tdef.Events) { + if (ev.AddMethod == null || !ev.AddMethod.IsPublic) + continue; + bool browsable = true; + string category = String.Empty; + foreach (CustomAttribute attr in ev.CustomAttributes) { + switch (attr.Constructor.DeclaringType.FullName) { + case "System.ComponentModel.BrowsableAttribute": + attr.Resolve (); + if (attr.ConstructorParameters.Count > 0) { + object param = attr.ConstructorParameters [0]; + if (param.GetType () == typeof (bool)) + browsable = (bool) param; + } + break; + case "System.ComponentModel.CategoryAttribute": + attr.Resolve (); + if (attr.ConstructorParameters.Count > 0) { + object param = attr.ConstructorParameters [0]; + if (param.GetType () == typeof (string)) + category = (string) param; + } + break; + default: + continue; + } + if (!browsable) + break; + } + if (browsable) + AddEvent (ev, category, obj); + } + } + + void AddObjects (XmlDocument doc, AssemblyResolver resolver, string basePath, AssemblyDefinition adef) + { + Dictionary<TypeDefinition,ToolboxItemInfo> localObjects = new Dictionary<TypeDefinition, ToolboxItemInfo> (); + + foreach (TypeDefinition tdef in adef.MainModule.Types) { + if (tdef.IsAbstract || !tdef.IsClass) + continue; + + ToolboxItemInfo tbinfo = GetToolboxItemInfo (resolver, basePath, adef, tdef, true); + if (tbinfo == null) + continue; + + localObjects [tdef] = tbinfo; + } + + foreach (KeyValuePair<TypeDefinition,ToolboxItemInfo> item in localObjects) { + TypeDefinition tdef = item.Key; + ToolboxItemInfo tbinfo = item.Value; + XmlElement elem = doc.CreateElement ("object"); + elem.SetAttribute ("type", tdef.FullName); + elem.SetAttribute ("allow-children", "false"); + elem.SetAttribute ("palette-category", tbinfo.PaletteCategory); + if (tdef.IsNotPublic) + elem.SetAttribute ("internal", "true"); + doc.DocumentElement.AppendChild (elem); + + TypeDefinition curDef = tdef; + while (curDef != null && curDef.FullName != tbinfo.BaseType) { + if (curDef != tdef && localObjects.ContainsKey (curDef)) { + tbinfo.BaseType = curDef.FullName; + break; + } + else if (curDef.Module.Assembly.Name.Name == "gtk-sharp") { + tbinfo.BaseType = curDef.FullName; + break; + } + else if (curDef != tdef && GetToolboxItemInfo (resolver, basePath, curDef.Module.Assembly, curDef, false) != null) { + tbinfo.BaseType = curDef.FullName; + break; + } + if (curDef.Module.Assembly != adef) { + + LibraryInfo li = Refresh (resolver, curDef.Module.Image.FileInformation.FullName, basePath); + if (li.HasWidgets && li.GetToolboxItem (curDef.FullName, curDef.Module.Assembly.Name.Name) != null) { + tbinfo.BaseType = curDef.FullName; + break; + } + } + AddProperties (curDef, elem); + AddEvents (curDef, elem); + if (curDef.BaseType != null && curDef.BaseType.FullName != tbinfo.BaseType) + curDef = FindTypeDefinition (resolver, adef, basePath, curDef.BaseType.FullName); + else + curDef = null; + } + + elem.SetAttribute ("base-type", tbinfo.BaseType); + } + } + + XmlDocument GetObjectsDoc (AssemblyResolver resolver, AssemblyDefinition adef, string path, string baseDirectory) + { + XmlDocument doc = null; + bool isMainLib = Path.GetFileName (path) == "libstetic.dll"; + + try { + EmbeddedResource res = GetResource (adef, "objects.xml"); + if (res != null) { + MemoryStream stream = new MemoryStream (res.Data); + doc = new XmlDocument (); + using (stream) + doc.Load (stream); + } + + if (resolver == null) + resolver = new AssemblyResolver (null); + + baseDirectory = baseDirectory ?? Path.GetDirectoryName (path); + + if (!isMainLib) { + // Make sure all referenced assemblies are up to date. + foreach (AssemblyNameReference aref in adef.MainModule.AssemblyReferences) { + Refresh (resolver, aref.FullName, baseDirectory); + } + } + + if (doc == null) { +// Hashtable visited = new Hashtable (); + foreach (AssemblyNameReference aref in adef.MainModule.AssemblyReferences) { + if (aref.Name != "gtk-sharp") { + LibraryInfo info = GetInfo (resolver, aref.FullName, baseDirectory); + if (info == null || !info.HasWidgets) + continue; + } + + if (doc == null) { + doc = new XmlDocument (); + doc.AppendChild (doc.CreateElement ("objects")); + } + AddObjects (doc, resolver, baseDirectory, adef); + break; + } + } + + if (doc != null && !isMainLib) { + XmlElement elem = doc.CreateElement ("dependencies"); + doc.DocumentElement.AppendChild (elem); + AddDependencies (elem, resolver, path, adef); + } + } catch (Exception e) { + Console.WriteLine ("Got exception loading objects: " + e); + doc = null; + } + + return doc; + } + + LibraryInfo GetInfo (AssemblyResolver resolver, string assembly, string baseDirectory) + { + string file = assembly; + if (File.Exists (assembly)) + file = assembly; + else { + if (resolver == null) + resolver = new AssemblyResolver (null); + try { + string path = resolver.Resolve (assembly, baseDirectory); + if (path != null) + file = path; + else + return null; + } catch (Exception) { + return null; + } + } + + file = Path.GetFullPath (file); + + LibraryInfo info = Members [file]; + if (info == null) { + info = new LibraryInfo (); + info.File = file ?? assembly; + Members.Add (info); + } + return info; + } + + internal LibraryInfo Refresh (AssemblyResolver resolver, string assembly) + { + return Refresh (resolver, assembly, null); + } + + LibraryInfo Refresh (AssemblyResolver resolver, string assembly, string baseDirectory) + { + LibraryInfo info = GetInfo (resolver, assembly, baseDirectory); + + if (info == null || info.IsCurrent || !File.Exists (info.File)) + return info; + + info.Timestamp = File.GetLastWriteTime (info.File).ToUniversalTime (); + info.Guid = Guid.NewGuid (); + Save (); + AssemblyDefinition adef = AssemblyFactory.GetAssembly (info.File); + XmlDocument objects = GetObjectsDoc (resolver, adef, info.File, baseDirectory); + if (objects != null) { + info.ObjectsDocument = objects; + XmlDocument gui = GetGuiDoc (adef); + if (gui != null) + info.GuiDocument = gui; + } + info.OnChanged (); + return info; + } + + void Save () + { + if (!Directory.Exists (dir)) + Directory.CreateDirectory (dir); + + // remove any dead assemblies from the cache + StringCollection zombies = new StringCollection (); + foreach (LibraryInfo info in Members) { + if (File.Exists (info.File)) + continue; + zombies.Add (info.File); + string zombie_dir = Path.Combine (dir, info.Guid.ToString ()); + if (Directory.Exists (zombie_dir)) + Directory.Delete (Path.Combine (dir, info.Guid.ToString ()), true); + } + + foreach (string file in zombies) + Members.Remove (file); + + XmlSerializer serializer = new XmlSerializer (typeof (LibraryCache)); + using (FileStream fs = File.Create (Path.Combine (dir, "index.xml"))) + serializer.Serialize (fs, this); + } + + static LibraryCache Load () + { + string index_path = Path.Combine (dir, "index.xml"); + if (File.Exists (index_path)) { + try { + LibraryCache result; + XmlSerializer serializer = new XmlSerializer (typeof (LibraryCache)); + using (XmlTextReader rdr = new XmlTextReader (index_path)) + result = (LibraryCache) serializer.Deserialize (rdr); + return result; + } catch (Exception e) { + Console.WriteLine ("Cache index serialization failed " + e); + } + } + + return new LibraryCache (); + } + + internal TypeDefinition FindTypeDefinition (AssemblyResolver resolver, AssemblyDefinition assembly, string basePath, string fullName) + { + TypeDefinition t = FindTypeDefinition (new Hashtable (), resolver, basePath, assembly, fullName); + return t; + } + + TypeDefinition FindTypeDefinition (Hashtable visited, AssemblyResolver resolver, string basePath, AssemblyDefinition asm, string fullName) + { + if (visited.Contains (asm)) + return null; + + visited [asm] = asm; + + TypeDefinition cls = asm.MainModule.Types [fullName]; + if (cls != null) + return cls; + + foreach (AssemblyNameReference aref in asm.MainModule.AssemblyReferences) { + AssemblyDefinition basm = resolver.Resolve (aref, basePath); + if (basm != null) { + cls = basm.MainModule.Types [fullName]; + if (cls != null) + return cls; + } + } + return null; + } + } +} diff --git a/main/src/addins/MonoDevelop.GtkCore2/libsteticui/Makefile.am b/main/src/addins/MonoDevelop.GtkCore2/libsteticui/Makefile.am new file mode 100644 index 0000000000..5128750332 --- /dev/null +++ b/main/src/addins/MonoDevelop.GtkCore2/libsteticui/Makefile.am @@ -0,0 +1,107 @@ +ADDIN_BUILD = $(top_builddir)/build/AddIns/MonoDevelop.GtkCore +ASSEMBLY = $(ADDIN_BUILD)/libsteticui.dll +assemblydir = $(MD_ADDIN_DIR)/MonoDevelop.GtkCore +assembly_DATA = $(ASSEMBLY) $(ASSEMBLY).mdb $(build_dll_config) + +FILES = \ + ActionComponent.cs \ + ActionGroupComponent.cs \ + ActionGroupDesigner.cs \ + ActionGroupDesignerBackend.cs \ + ActionGroupEditSession.cs \ + ActionGroupToolbar.cs \ + Application.cs \ + ApplicationBackend.cs \ + ApplicationBackendController.cs \ + AssemblyResolver.cs \ + AssemblyWidgetLibrary.cs \ + CecilClassDescriptor.cs \ + CecilPropertyDescriptor.cs \ + CecilSignalDescriptor.cs \ + CecilWidgetLibrary.cs \ + CodeGenerationResult.cs \ + CodeGenerator.cs \ + CodeGeneratorPartialClass.cs \ + Component.cs \ + ComponentEventHandler.cs \ + ComponentSignalEventHandler.cs \ + ComponentType.cs \ + ContainerUndoRedoManager.cs \ + ContextMenu.cs \ + Designer.cs \ + Glade.cs \ + Grid.cs \ + GuiDispatchServerSink.cs \ + GuiDispatchServerSinkProvider.cs \ + IProjectDesignInfo.cs \ + LibraryCache.cs \ + Metacity/ButtonFunction.cs \ + Metacity/ButtonLayout.cs \ + Metacity/FrameFlags.cs \ + Metacity/FrameType.cs \ + Metacity/ObjectManager.cs \ + Metacity/Preview.cs \ + Metacity/Theme.cs \ + Palette.cs \ + PaletteBackend.cs \ + PluggableWidget.cs \ + Project.cs \ + ProjectBackend.cs \ + ProjectViewBackend.cs \ + PropertyEditor.cs \ + PropertyGrid.cs \ + PropertyTree.cs \ + Shadow.cs \ + SignalsEditor.cs \ + SignalsEditorBackend.cs \ + UndoQueue.cs \ + UserInterface.cs \ + WidgetActionBar.cs \ + WidgetComponent.cs \ + WidgetDesigner.cs \ + WidgetDesignerBackend.cs \ + WidgetEditSession.cs \ + WidgetFactory.cs \ + WidgetInfoEventHandler.cs \ + WidgetPropertyTree.cs \ + WidgetPropertyTreeBackend.cs \ + WidgetTree.cs \ + WidgetTreeCombo.cs \ + Windows/Preview.cs \ + Windows/WindowsTheme.cs + +RES = \ + action.png \ + missing.png + +DEPS = ../../../../build/AddIns/MonoDevelop.GtkCore2/libstetic2.dll + +REFS = \ + $(GLADE_SHARP_LIBS) \ + $(GLIB_SHARP_LIBS) \ + $(GTK_SHARP_LIBS) \ + -pkg:monodevelop \ + -r:Mono.Posix \ + -r:System \ + -r:System.Core \ + -r:System.Runtime.Remoting \ + -r:System.Xml + +$(ASSEMBLY): $(build_sources) $(build_resources) $(DEPS) + mkdir -p $(ADDIN_BUILD) + $(CSC) $(CSC_FLAGS) -debug -unsafe -main:Stetic.ApplicationBackend -out:$@ \ + $(build_resources:%=/resource:%) $(build_sources) $(REFS) $(build_deps) + +dll_config = libsteticui.dll.config +build_dll_config = $(ADDIN_BUILD)/$(dll_config) + +$(build_dll_config): $(srcdir)/$(dll_config) + mkdir -p $(ADDIN_BUILD) + cp $(srcdir)/$(dll_config) $@ + +EXTRA_DIST = $(FILES) $(RES) $(dll_config) + +CLEANFILES = $(ASSEMBLY) $(ASSEMBLY).mdb + +include $(top_srcdir)/Makefile.include + diff --git a/main/src/addins/MonoDevelop.GtkCore2/libsteticui/Metacity/ButtonFunction.cs b/main/src/addins/MonoDevelop.GtkCore2/libsteticui/Metacity/ButtonFunction.cs new file mode 100644 index 0000000000..9fa8ef4907 --- /dev/null +++ b/main/src/addins/MonoDevelop.GtkCore2/libsteticui/Metacity/ButtonFunction.cs @@ -0,0 +1,20 @@ +// This file was generated by the Gtk# code generator. +// Any changes made will be lost if regenerated. + +namespace Stetic.Metacity +{ + + using System; + using System.Runtime.InteropServices; + +#region Autogenerated code + internal enum ButtonFunction { + + Menu, + Minimize, + Maximize, + Close, + Last, + } +#endregion +} diff --git a/main/src/addins/MonoDevelop.GtkCore2/libsteticui/Metacity/ButtonLayout.cs b/main/src/addins/MonoDevelop.GtkCore2/libsteticui/Metacity/ButtonLayout.cs new file mode 100644 index 0000000000..e954c20a3e --- /dev/null +++ b/main/src/addins/MonoDevelop.GtkCore2/libsteticui/Metacity/ButtonLayout.cs @@ -0,0 +1,36 @@ +// This file was generated by the Gtk# code generator. +// Any changes made will be lost if regenerated. + +namespace Stetic.Metacity +{ + + using System; + using System.Collections; + using System.Runtime.InteropServices; + +#region Autogenerated code + [StructLayout(LayoutKind.Sequential)] + internal 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; + } + + internal static GLib.GType GType { + get { return GLib.GType.Pointer; } + } +#endregion + } +} diff --git a/main/src/addins/MonoDevelop.GtkCore2/libsteticui/Metacity/FrameFlags.cs b/main/src/addins/MonoDevelop.GtkCore2/libsteticui/Metacity/FrameFlags.cs new file mode 100644 index 0000000000..bc6172fbe8 --- /dev/null +++ b/main/src/addins/MonoDevelop.GtkCore2/libsteticui/Metacity/FrameFlags.cs @@ -0,0 +1,30 @@ +// This file was generated by the Gtk# code generator. +// Any changes made will be lost if regenerated. + +namespace Stetic.Metacity +{ + + using System; + using System.Runtime.InteropServices; + +#region Autogenerated code + [Flags] + internal 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 +} diff --git a/main/src/addins/MonoDevelop.GtkCore2/libsteticui/Metacity/FrameType.cs b/main/src/addins/MonoDevelop.GtkCore2/libsteticui/Metacity/FrameType.cs new file mode 100644 index 0000000000..7ecc08d277 --- /dev/null +++ b/main/src/addins/MonoDevelop.GtkCore2/libsteticui/Metacity/FrameType.cs @@ -0,0 +1,22 @@ +// This file was generated by the Gtk# code generator. +// Any changes made will be lost if regenerated. + +namespace Stetic.Metacity +{ + + using System; + using System.Runtime.InteropServices; + +#region Autogenerated code + internal enum FrameType { + + Normal, + Dialog, + ModalDialog, + Utility, + Menu, + Border, + Last, + } +#endregion +} diff --git a/main/src/addins/MonoDevelop.GtkCore2/libsteticui/Metacity/ObjectManager.cs b/main/src/addins/MonoDevelop.GtkCore2/libsteticui/Metacity/ObjectManager.cs new file mode 100644 index 0000000000..201c52370e --- /dev/null +++ b/main/src/addins/MonoDevelop.GtkCore2/libsteticui/Metacity/ObjectManager.cs @@ -0,0 +1,19 @@ +// This file was generated by the Gtk# code generator. +// Any changes made will be lost if regenerated. + +namespace GtkSharp.MetacitySharp { + + 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 (Stetic.Metacity.Preview.GType, typeof (Stetic.Metacity.Preview)); + } + } +} diff --git a/main/src/addins/MonoDevelop.GtkCore2/libsteticui/Metacity/Preview.cs b/main/src/addins/MonoDevelop.GtkCore2/libsteticui/Metacity/Preview.cs new file mode 100644 index 0000000000..509beac264 --- /dev/null +++ b/main/src/addins/MonoDevelop.GtkCore2/libsteticui/Metacity/Preview.cs @@ -0,0 +1,227 @@ +// This file was generated by the Gtk# code generator. +// Any changes made will be lost if regenerated. + +namespace Stetic.Metacity { + + using System; + using System.Reflection; + using System.Collections; + using System.Runtime.InteropServices; + + internal class Preview : Gtk.Bin + { + static Theme theme; + public static bool ThemeError = false; + + public static Metacity.Preview Create (TopLevelWindow window) + { + Metacity.Preview metacityPreview; + + try { + Metacity.Preview.Init (); + metacityPreview = new Metacity.Preview (); + } + catch { + return null; + } + + 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.AddWindow (window); + + metacityPreview.Theme = GetTheme (); + + return metacityPreview; + } + + public void AddWindow (TopLevelWindow window) + { + base.Add (window); + + Title = window.Title ?? string.Empty; + window.PropertyChanged += OnWindowPropChange; + Destroyed += delegate { + window.PropertyChanged -= OnWindowPropChange; + }; + } + + void OnWindowPropChange (object ob, EventArgs e) + { + Title = ((TopLevelWindow)ob).Title ?? string.Empty; + } + + static Theme GetTheme () + { + if (theme == null) { + try { + Assembly assm = Assembly.LoadWithPartialName ("gconf-sharp"); + Type client_type = assm.GetType ("GConf.Client"); + MethodInfo method = client_type.GetMethod ("Get", BindingFlags.Instance | BindingFlags.Public); + object client = Activator.CreateInstance (client_type, new object[] { + + }); + string themeName = (string)method.Invoke (client, new object[] { "/apps/metacity/general/theme" }); + theme = Metacity.Theme.Load (themeName); + } catch { + // Set theme error flag - in case of a theme error a solid background needs to be drawn. + ThemeError = true; + // Don't crash if metacity is not available + return null; + } + } + 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; + } + } + */ + + ~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 Stetic.Metacity.ButtonLayout button_layout); + + public Stetic.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 Stetic.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 Stetic.Metacity.FrameFlags FrameFlags + { + set { + meta_preview_set_frame_flags(Handle, (int) value); + } + } + + + public static void Init() + { + GtkSharp.MetacitySharp.ObjectManager.Initialize (); + } + } +} diff --git a/main/src/addins/MonoDevelop.GtkCore2/libsteticui/Metacity/Theme.cs b/main/src/addins/MonoDevelop.GtkCore2/libsteticui/Metacity/Theme.cs new file mode 100644 index 0000000000..b9254d710d --- /dev/null +++ b/main/src/addins/MonoDevelop.GtkCore2/libsteticui/Metacity/Theme.cs @@ -0,0 +1,41 @@ + +namespace Stetic.Metacity +{ + using System; + using System.Runtime.InteropServices; + + internal 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); + } + } +} diff --git a/main/src/addins/MonoDevelop.GtkCore2/libsteticui/Palette.cs b/main/src/addins/MonoDevelop.GtkCore2/libsteticui/Palette.cs new file mode 100644 index 0000000000..3f747df6cf --- /dev/null +++ b/main/src/addins/MonoDevelop.GtkCore2/libsteticui/Palette.cs @@ -0,0 +1,46 @@ + +using System; +using Gtk; + +namespace Stetic +{ + public class Palette: PluggableWidget + { + bool showWindowCategory = true; + + internal Palette (Application app): base (app) + { + } + + protected override void OnCreatePlug (uint socketId) + { + app.Backend.CreatePaletteWidgetPlug (socketId); + Update (); + } + + protected override void OnDestroyPlug (uint socketId) + { + app.Backend.DestroyPaletteWidgetPlug (); + } + + protected override Gtk.Widget OnCreateWidget () + { + Update (); + return app.Backend.GetPaletteWidget (); + } + + public bool ShowWindowCategory { + get { return showWindowCategory; } + set { + showWindowCategory = value; + Update (); + } + } + + void Update () + { + if (!showWindowCategory) + app.Backend.HidePaletteGroup ("window"); + } + } +} diff --git a/main/src/addins/MonoDevelop.GtkCore2/libsteticui/PaletteBackend.cs b/main/src/addins/MonoDevelop.GtkCore2/libsteticui/PaletteBackend.cs new file mode 100644 index 0000000000..40d6e8050d --- /dev/null +++ b/main/src/addins/MonoDevelop.GtkCore2/libsteticui/PaletteBackend.cs @@ -0,0 +1,409 @@ +using Gtk; +using Gdk; +using System; +using System.Collections; +using System.Reflection; +using Mono.Unix; + +namespace Stetic { + + internal class PaletteBackend : Gtk.ScrolledWindow, IComparer { + + Hashtable groups; + ProjectBackend project; + WidgetLibrary[] libraries; + ArrayList visibleGroups = new ArrayList (); + Wrapper.Widget selection; + ActionGroupBox localActionsBox; + ActionGroupBox globalActionsBox; + Gtk.VBox box; + ApplicationBackend app; + + public PaletteBackend (ApplicationBackend app) + { + this.app = app; + box = new Gtk.VBox (false, 0); + AddWithViewport (box); + groups = new Hashtable (); + Registry.RegistryChanged += OnRegistryChanged; + + ShowGroup ("window", Catalog.GetString ("Windows")); + ShowGroup ("widget", Catalog.GetString ("Widgets")); + ShowGroup ("container", Catalog.GetString ("Containers")); +// ShowGroup ("toolbaritem", "Toolbar Items"); + ShowGroup ("actions", Catalog.GetString ("Actions")); + } + + public override void Dispose () + { + Registry.RegistryChanged -= OnRegistryChanged; + + foreach (PaletteGroup grp in groups.Values) + grp.Destroy (); + + if (localActionsBox != null) { + localActionsBox.Destroy (); + localActionsBox = null; + } + if (globalActionsBox != null) { + globalActionsBox.Destroy (); + globalActionsBox = null; + } + + project = null; + selection = null; + base.Dispose (); + } + + public PaletteBackend (ApplicationBackend app, ProjectBackend project): this (app) + { + this.ProjectBackend = project; + } + + public ProjectBackend ProjectBackend { + get { return project; } + set { + if (project != null) { + project.SelectionChanged -= OnSelectionChanged; + project.ProjectReloaded -= OnProjectReloaded; + } + project = value; + if (project != null) { + UpdateSelection (Wrapper.Widget.Lookup (project.Selection)); + project.SelectionChanged += OnSelectionChanged; + project.ProjectReloaded += OnProjectReloaded; + } else + UpdateSelection (null); + LoadWidgets (project); + } + } + + public WidgetLibrary[] WidgetLibraries { + get { return libraries; } + set { + libraries = value; + LoadWidgets (project); + } + } + + void OnProjectReloaded (object s, EventArgs args) + { + LoadWidgets (project); + } + + void OnSelectionChanged (object ob, Stetic.Wrapper.WidgetEventArgs args) + { + UpdateSelection (args.WidgetWrapper); + } + + void UpdateSelection (Wrapper.Widget sel) + { + selection = sel; + if (localActionsBox != null) + localActionsBox.SetActionGroups (selection != null ? selection.LocalActionGroups : null); + ShowAll (); + } + + public void ShowGroup (string name, string label) + { + visibleGroups.Add (new string[] { name, label }); + if (project != null) + LoadWidgets (project); + } + + public void HideGroup (string name) + { + for (int n=0; n < visibleGroups.Count; n++) { + if (((string[])visibleGroups[n])[0] == name) { + visibleGroups.RemoveAt (n); + if (project != null) + LoadWidgets (project); + return; + } + } + } + + void OnRegistryChanged (object o, EventArgs args) + { + WidgetLibraries = app.GetActiveLibraries (); + } + + public void LoadWidgets (ProjectBackend project) + { + if (project == null) { + box.Hide (); + return; + } + + box.Show (); + + foreach (PaletteGroup g in groups.Values) { + box.Remove (g); + g.Destroy (); + } + + groups.Clear (); + + foreach (string[] grp in visibleGroups) + AddOrGetGroup (grp[0], grp[1]); + + ArrayList classes = new ArrayList (); + if (libraries == null) { + foreach (ClassDescriptor klass in Registry.AllClasses) + if (klass.SupportsGtkVersion (project.TargetGtkVersion)) + classes.Add (klass); + } else if (project != null) { + foreach (WidgetLibrary lib in libraries) { + bool isInternalLib = project.IsInternalLibrary (lib.Name); + foreach (ClassDescriptor cd in lib.AllClasses) { + if (!cd.Deprecated && cd.Category.Length > 0 && (isInternalLib || !cd.IsInternal) && cd.SupportsGtkVersion (project.TargetGtkVersion)) + classes.Add (cd); + } + } + } + + classes.Sort (this); + + foreach (ClassDescriptor klass in classes) { + + if (!groups.Contains (klass.Category)) + continue; + + WidgetFactory factory; + if (klass.Category == "window") + factory = new WindowFactory (project, klass); + else + factory = new WidgetFactory (project, klass); + + AddOrGetGroup(klass.Category).Append (factory); + } + + if (localActionsBox != null) + localActionsBox.Destroy (); + if (globalActionsBox != null) + globalActionsBox.Destroy (); + + PaletteGroup widgetGroup = AddOrGetGroup ("actions", Catalog.GetString ("Actions")); + localActionsBox = new ActionGroupBox (); + globalActionsBox = new ActionGroupBox (); + widgetGroup.Append (localActionsBox); + widgetGroup.Append (globalActionsBox); + + if (project != null) { + widgetGroup.Sensitive = true; + localActionsBox.SetActionGroups (selection != null ? selection.LocalActionGroups : null); + globalActionsBox.SetActionGroups (project.ActionGroups); + } else { + widgetGroup.Sensitive = false; + localActionsBox.SetActionGroups (null); + globalActionsBox.SetActionGroups (null); + } + + // This is a workaround. In looks like the palette is not correctly + // redrawn if it is rebuilt while it is not visible (the dock is hidden in MD). + GLib.Idle.Add (delegate { + ShowAll (); + return false; + }); + } + + int IComparer.Compare (object x, object y) + { + return string.Compare (((ClassDescriptor)x).Label, + ((ClassDescriptor)y).Label); + } + + private PaletteGroup AddOrGetGroup (string id, string name) + { + PaletteGroup group = (PaletteGroup) groups[id]; + + if (group == null) { + group = new PaletteGroup (name); + box.PackStart (group, false, false, 0); + groups.Add (id, group); + } + + return group; + } + + private PaletteGroup AddOrGetGroup (string name) + { + return AddOrGetGroup (name, name); + } + } + + class PaletteGroup : Gtk.Expander + { + private Gtk.Alignment align; + private Gtk.VBox vbox; + Gtk.Label emptyLabel; + bool isEmpty = true; + + public PaletteGroup (string name) : base ("<b>" + name + "</b>") + { + vbox = new VBox (false, 0); + emptyLabel = new Gtk.Label (); + emptyLabel.Markup = "<small><i><span foreground='darkgrey'> " + Catalog.GetString ("Empty") + "</span></i></small>"; + vbox.PackStart (emptyLabel, false, false, 0); + + align = new Gtk.Alignment (0, 0, 0, 0); + align.SetPadding (0, 0, 20, 0); + align.Child = vbox; + + UseMarkup = true; + Expanded = true; + Child = align; + } + + public void SetName (string name) + { + Label = "<b>" + name + "</b>"; + } + + public void Append (Widget w) + { + if (isEmpty) { + vbox.Remove (emptyLabel); + isEmpty = false; + } + vbox.PackStart (w, false, false, 0); + } + + public void Clear () + { + foreach (Gtk.Widget w in vbox.Children) { + vbox.Remove (w); + w.Destroy (); + } + + isEmpty = true; + vbox.PackStart (emptyLabel, false, false, 0); + } + } + + class ActionPaletteGroup : PaletteGroup + { + Wrapper.ActionGroup group; + + public ActionPaletteGroup (string name, Wrapper.ActionGroup group): base (name) + { + DND.DestSet (this, true); + this.group = group; + group.ActionAdded += OnActionGroupChanged; + group.ActionRemoved += OnActionGroupChanged; + group.ActionChanged += OnActionGroupChanged; + group.ObjectChanged += OnActionGroupChanged; + Fill (); + } + + public Wrapper.ActionGroup Group { + get { return group; } + } + + public override void Dispose () + { + group.ActionAdded -= OnActionGroupChanged; + group.ActionRemoved -= OnActionGroupChanged; + group.ActionChanged -= OnActionGroupChanged; + group.ObjectChanged -= OnActionGroupChanged; + base.Dispose (); + } + + public void Fill () + { + foreach (Stetic.Wrapper.Action action in group.Actions) { + Gdk.Pixbuf icon = action.RenderIcon (Gtk.IconSize.Menu); + if (icon == null) icon = ActionComponent.DefaultActionIcon; + Stetic.Wrapper.ActionPaletteItem it = new Stetic.Wrapper.ActionPaletteItem (Gtk.UIManagerItemType.Menuitem, null, action); + Append (new InstanceWidgetFactory (action.MenuLabel, icon, it)); + } + } + + void OnActionGroupChanged (object s, EventArgs args) + { + SetName (((Stetic.Wrapper.ActionGroup)s).Name); + } + + void OnActionGroupChanged (object s, Stetic.Wrapper.ActionEventArgs args) + { + Clear (); + Fill (); + ShowAll (); + } + + protected override bool OnDragDrop (Gdk.DragContext context, int x, int y, uint time) + { + Wrapper.ActionPaletteItem dropped = DND.Drop (context, null, time) as Wrapper.ActionPaletteItem; + if (dropped == null) + return false; + + if (dropped.Node.Action.ActionGroup != group) { + using (dropped.Node.Action.UndoManager.AtomicChange) { + dropped.Node.Action.ActionGroup.Actions.Remove (dropped.Node.Action); + group.Actions.Add (dropped.Node.Action); + } + } + + return base.OnDragDrop (context, x, y, time); + } + } + + class ActionGroupBox: Gtk.VBox + { + Stetic.Wrapper.ActionGroupCollection groups; + + public void SetActionGroups (Stetic.Wrapper.ActionGroupCollection groups) + { + if (this.groups != null) { + this.groups.ActionGroupAdded -= OnGroupAdded; + this.groups.ActionGroupRemoved -= OnGroupRemoved; + } + this.groups = groups; + if (this.groups != null) { + this.groups.ActionGroupAdded += OnGroupAdded; + this.groups.ActionGroupRemoved += OnGroupRemoved; + } + Update (); + } + + public override void Dispose () + { + foreach (ActionPaletteGroup grp in Children) + grp.Destroy (); + base.Dispose (); + } + + public void Update () + { + foreach (ActionPaletteGroup grp in Children) { + Remove (grp); + grp.Destroy (); + } + + if (groups != null) { + foreach (Stetic.Wrapper.ActionGroup group in groups) { + ActionPaletteGroup pg = new ActionPaletteGroup (group.Name, group); + PackStart (pg, false, false, 0); + } + } + ShowAll (); + } + + void OnGroupAdded (object s, Stetic.Wrapper.ActionGroupEventArgs args) + { + ActionPaletteGroup pg = new ActionPaletteGroup (args.ActionGroup.Name, args.ActionGroup); + pg.ShowAll (); + PackStart (pg, false, false, 0); + } + + void OnGroupRemoved (object s, Stetic.Wrapper.ActionGroupEventArgs args) + { + foreach (ActionPaletteGroup grp in Children) { + if (grp.Group == args.ActionGroup) { + Remove (grp); + grp.Destroy (); + } + } + } + } +} diff --git a/main/src/addins/MonoDevelop.GtkCore2/libsteticui/PluggableWidget.cs b/main/src/addins/MonoDevelop.GtkCore2/libsteticui/PluggableWidget.cs new file mode 100644 index 0000000000..be70fee7a2 --- /dev/null +++ b/main/src/addins/MonoDevelop.GtkCore2/libsteticui/PluggableWidget.cs @@ -0,0 +1,154 @@ + +using System; + +namespace Stetic +{ + public abstract class PluggableWidget: Gtk.EventBox + { + internal Application app; + bool initialized; + Gtk.Socket socket; + bool customWidget; + Gtk.Notebook book; + + public PluggableWidget (Application app) + { + book = new Gtk.Notebook (); + book.ShowTabs = false; + book.ShowBorder = false; + book.Show (); + Add (book); + + this.app = app; + if (app is IsolatedApplication) { + (app as IsolatedApplication).BackendChanged += OnBackendChanged; + (app as IsolatedApplication).BackendChanging += OnBackendChanging; + } + } + + protected void AddCustomWidget (Gtk.Widget w) + { + w.ShowAll (); + book.AppendPage (w, null); + book.Page = book.NPages - 1; + + if (initialized) { + Gtk.Widget cw = book.GetNthPage (0); + book.RemovePage (0); + cw.Destroy (); + } + else + initialized = true; + customWidget = true; + } + + protected void ResetCustomWidget () + { + customWidget = false; + } + + protected override void OnRealized () + { + base.OnRealized (); + if (!initialized) { + initialized = true; + if (app is IsolatedApplication) + ConnectPlug (); + else { + Gtk.Widget w = OnCreateWidget (); + w.Show (); + book.AppendPage (w, null); + } + } + } + + protected override void OnUnrealized () + { + if (app is IsolatedApplication && initialized) { + OnDestroyPlug (socket.Id); + initialized = false; + } + base.OnUnrealized (); + } + + protected void PrepareUpdateWidget () + { + // This method is called when the child widget is going to be changed. + // It takes a 'screenshot' of the widget. This image will be shown until + // UpdateWidget is called. + + if (book.NPages == 1) { + Gtk.Widget w = book.GetNthPage (0); + Gdk.Window win = w.GdkWindow; + if (win != null && win.IsViewable) { + Gdk.Pixbuf img = Gdk.Pixbuf.FromDrawable (win, win.Colormap, w.Allocation.X, w.Allocation.Y, 0, 0, w.Allocation.Width, w.Allocation.Height); + Gtk.Image oldImage = new Gtk.Image (img); + oldImage.Show (); + book.AppendPage (oldImage, null); + book.Page = 1; + book.RemovePage (0); + } + } + } + + protected void UpdateWidget () + { + if (!initialized) + return; + + if (app is LocalApplication) { + Gtk.Widget w = OnCreateWidget (); + if (w.Parent != book) { + book.AppendPage (w, null); + w.Show (); + } + book.Page = book.NPages - 1; + if (book.NPages > 1) { + Gtk.Widget cw = book.GetNthPage (0); + book.Remove (cw); + OnDestroyWidget (cw); + } + } + } + + protected abstract void OnCreatePlug (uint socketId); + protected abstract void OnDestroyPlug (uint socketId); + + protected abstract Gtk.Widget OnCreateWidget (); + protected virtual void OnDestroyWidget (Gtk.Widget w) { w.Destroy (); } + + public override void Dispose () + { + if (app is IsolatedApplication) { + IsolatedApplication iapp = app as IsolatedApplication; + iapp.BackendChanged -= OnBackendChanged; + iapp.BackendChanging -= OnBackendChanging; + } + base.Dispose (); + } + + internal virtual void OnBackendChanged (ApplicationBackend oldBackend) + { + if (!initialized) + return; + + Gtk.Widget w = book.GetNthPage (0); + book.RemovePage (0); + w.Destroy (); + socket.Dispose (); + ConnectPlug (); + } + + internal virtual void OnBackendChanging () + { + } + + void ConnectPlug () + { + socket = new Gtk.Socket (); + socket.Show (); + book.AppendPage (socket, null); + OnCreatePlug (socket.Id); + } + } +} diff --git a/main/src/addins/MonoDevelop.GtkCore2/libsteticui/Project.cs b/main/src/addins/MonoDevelop.GtkCore2/libsteticui/Project.cs new file mode 100644 index 0000000000..a784aea82d --- /dev/null +++ b/main/src/addins/MonoDevelop.GtkCore2/libsteticui/Project.cs @@ -0,0 +1,870 @@ + +using System; +using System.Xml; +using System.IO; +using System.Collections; +using System.Collections.Generic; +using System.Collections.Specialized; + +namespace Stetic +{ + public class Project: MarshalByRefObject + { + Application app; + ProjectBackend backend; + //string fileName; + string folderName; + IResourceProvider resourceProvider; + Component selection; + string tmpProjectFile; + bool reloadRequested; + List<WidgetInfo> widgets = new List<WidgetInfo> (); + List<ActionGroupInfo> groups = new List<ActionGroupInfo> (); + ImportFileDelegate importFileDelegate; + + public event WidgetInfoEventHandler WidgetAdded; + public event WidgetInfoEventHandler WidgetRemoved; + public event ComponentNameEventHandler ComponentNameChanged; + public event EventHandler ComponentTypesChanged; + + public event EventHandler ActionGroupsChanged; + public event EventHandler ModifiedChanged; + public event EventHandler Changed; + + + // Internal events + internal event BackendChangingHandler BackendChanging; + internal event BackendChangedHandler BackendChanged; + internal event ComponentSignalEventHandler SignalAdded; + internal event ComponentSignalEventHandler SignalRemoved; + internal event ComponentSignalEventHandler SignalChanged; + + public event EventHandler ProjectReloading; + public event EventHandler ProjectReloaded; + + internal Project (Application app, IProjectDesignInfo info): this (app, null, info) + { + } + + internal Project (Application app, ProjectBackend backend, IProjectDesignInfo info) + { + this.app = app; + if (backend != null) { + this.backend = backend; + backend.SetFrontend (this); + } + + if (app is IsolatedApplication) { + IsolatedApplication iapp = app as IsolatedApplication; + iapp.BackendChanging += OnBackendChanging; + iapp.BackendChanged += OnBackendChanged; + } + + DesignInfo = info; + } + + internal IProjectDesignInfo DesignInfo { get; private set; } + + internal ProjectBackend ProjectBackend { + get { + if (backend == null) { + backend = app.Backend.CreateProject (); + backend.SetFrontend (this); + if (resourceProvider != null) + backend.ResourceProvider = resourceProvider; + if (folderName != null) + backend.Load (folderName); + } + return backend; + } + } + + internal bool IsBackendLoaded { + get { return backend != null; } + } + + internal Application App { + get { return app; } + } + + internal event EventHandler Disposed; + + public void Dispose () + { + if (app is IsolatedApplication) { + IsolatedApplication iapp = app as IsolatedApplication; + iapp.BackendChanging -= OnBackendChanging; + iapp.BackendChanged -= OnBackendChanged; + } + + if (tmpProjectFile != null && File.Exists (tmpProjectFile)) { + File.Delete (tmpProjectFile); + tmpProjectFile = null; + } + if (backend != null) + backend.Dispose (); + if (Disposed != null) + Disposed (this, EventArgs.Empty); + System.Runtime.Remoting.RemotingServices.Disconnect (this); + } + + public override object InitializeLifetimeService () + { + // Will be disconnected when calling Dispose + return null; + } + +// public string FileName { +// get { return fileName; } +// } + + public IResourceProvider ResourceProvider { + get { return resourceProvider; } + set { + resourceProvider = value; + if (backend != null) + backend.ResourceProvider = value; + } + } + + public Stetic.ProjectIconFactory IconFactory { + get { return ProjectBackend.IconFactory; } + set { backend.IconFactory = value; } + } + + public ImportFileDelegate ImportFileCallback { + get { return importFileDelegate; } + set { importFileDelegate = value; } + } + + public bool CanGenerateCode { + get { return ProjectBackend.CanGenerateCode; } + } + + public Component Selection { + get { return selection; } + } + + public string ImagesRootPath { + get { return ProjectBackend.ImagesRootPath; } + set { ProjectBackend.ImagesRootPath = value; } + } + + public string TargetGtkVersion { + get { return ProjectBackend.TargetGtkVersion; } + set { ProjectBackend.TargetGtkVersion = value; } + } + + public void Close () + { + if (backend != null) + backend.Close (); + } + + public void Load (string folderName) + { + this.folderName = folderName; + if (backend != null) + backend.Load (folderName); + + foreach (string basePath in DesignInfo.GetComponentFolders ()) { + if (!Directory.Exists (basePath)) + continue; + + DirectoryInfo dir = new DirectoryInfo (basePath); + + foreach (FileInfo file in dir.GetFiles ()) { + if (file.Extension == ".gtkx") { + + using (StreamReader sr = new StreamReader (file.FullName)) { + XmlTextReader reader = new XmlTextReader (sr); + + reader.MoveToContent (); + if (reader.IsEmptyElement) + return; + + reader.ReadStartElement ("stetic-interface"); + if (reader.IsEmptyElement) + return; + while (reader.NodeType != XmlNodeType.EndElement) { + if (reader.NodeType == XmlNodeType.Element) { + if (reader.LocalName == "widget") + ReadWidget (reader); + else if (reader.LocalName == "action-group") + ReadActionGroup (reader); + else + reader.Skip (); + } + else { + reader.Skip (); + } + reader.MoveToContent (); + } + } + } + } + } + } + + public void ReloadComponent (string componentName) + { + if (backend != null) + backend.ReloadComponent (componentName); + } + + void ReadWidget (XmlTextReader reader) + { + WidgetInfo w = new WidgetInfo (this, reader.GetAttribute ("id"), reader.GetAttribute ("class")); + widgets.Add (w); + if (reader.IsEmptyElement) { + reader.Skip (); + return; + } + reader.ReadStartElement (); + reader.MoveToContent (); + while (reader.NodeType != XmlNodeType.EndElement) { + if (reader.NodeType == XmlNodeType.Element && reader.LocalName == "action-group") { + w.AddGroup (reader.GetAttribute ("name")); + } + reader.Skip (); + reader.MoveToContent (); + } + reader.ReadEndElement (); + } + + void ReadActionGroup (XmlTextReader reader) + { + groups.Add (new ActionGroupInfo (this, reader.GetAttribute ("name"))); + reader.Skip (); + } + + public void ConvertProject (string oldSteticFileName, string newGuiFolderName) + { + //ProjectBackend property when created invokes Load method which is not valid + //for old file layout + + ProjectBackend backend = app.Backend.CreateProject (); + backend.SetFrontend (this); + backend.ConvertProject (oldSteticFileName, newGuiFolderName); + } + + public void Save (string folderName) + { + this.folderName = folderName; + if (backend != null) + backend.Save (folderName); + } + + public void ImportGlade (string fileName) + { + ProjectBackend.ImportGlade (fileName); + } + + public void ExportGlade (string fileName) + { + ProjectBackend.ExportGlade (fileName); + } + + public IEnumerable<WidgetInfo> Widgets { + get { return widgets; } + } + + public IEnumerable<ActionGroupInfo> ActionGroups { + get { return groups; } + } + + public WidgetInfo GetWidget (string name) + { + foreach (WidgetInfo w in widgets) + if (w.Name == name) + return w; + return null; + } + + public ActionGroupInfo GetActionGroup (string name) + { + foreach (ActionGroupInfo w in groups) + if (w.Name == name) + return w; + return null; + } + +// public WidgetDesigner CreateWidgetDesigner (WidgetInfo widgetInfo, bool autoCommitChanges) +// { +// return new WidgetDesigner (this, widgetInfo.Name, autoCommitChanges); +// } + + public WidgetDesigner CreateWidgetDesigner (WidgetInfo widgetInfo) + { + return new WidgetDesigner (this, widgetInfo.Name); + } + + public ActionGroupDesigner CreateActionGroupDesigner (ActionGroupInfo actionGroup, bool autoCommitChanges) + { + return new ActionGroupDesigner (this, null, actionGroup.Name, null, autoCommitChanges); + } + + public WidgetInfo AddNewComponent (ComponentType type, string name) + { + object ob = ProjectBackend.AddNewWidget (type.Name, name); + WidgetComponent wc = (WidgetComponent) App.GetComponent (ob, null, null); + WidgetInfo wi = GetWidget (wc.Name); + if (wi == null) { + wi = new WidgetInfo (this, wc); + widgets.Add (wi); + } + return wi; + } + + public WidgetInfo AddNewComponent (XmlElement template) + { + object ob = ProjectBackend.AddNewWidgetFromTemplate (template.OuterXml); + WidgetComponent wc = (WidgetComponent) App.GetComponent (ob, null, null); + WidgetInfo wi = GetWidget (wc.Name); + if (wi == null) { + wi = new WidgetInfo (this, wc); + widgets.Add (wi); + } + return wi; + } + + public object AddNewComponent (string fileName) + { + object ob = ProjectBackend.AddNewComponent (fileName); + object component = App.GetComponent (ob, null, null); + + if (component is WidgetComponent) { + var wc = (WidgetComponent) component; + WidgetInfo wi = GetWidget (wc.Name); + if (wi == null) { + wi = new WidgetInfo (this, wc); + widgets.Add (wi); + } + return wi; + } + + if (component is ActionGroupComponent) { + var ac = (ActionGroupComponent) component; + // Don't wait for the group added event to come to update the groups list since + // it may be too late. + ActionGroupInfo gi = GetActionGroup (ac.Name); + if (gi == null) { + gi = new ActionGroupInfo (this, ac.Name); + groups.Add (gi); + } + return gi; + } + + return null; + } + + public ComponentType[] GetComponentTypes () + { + ArrayList types = new ArrayList (); + + ArrayList typeNames = ProjectBackend.GetComponentTypes (); + for (int n=0; n<typeNames.Count; n++) + types.Add (app.GetComponentType ((string) typeNames [n])); + + // Global action groups + foreach (ActionGroupComponent grp in GetActionGroups ()) { + foreach (ActionComponent ac in grp.GetActions ()) + types.Add (new ComponentType (app, ac)); + } + + return (ComponentType[]) types.ToArray (typeof(ComponentType)); + } + + // Returns a list of all support widget types (including base classes) + public string[] GetWidgetTypes () + { + return ProjectBackend.GetWidgetTypes (); + } + + public void RemoveComponent (WidgetInfo component) + { + ProjectBackend.RemoveWidget (component.Name); + } + + public WidgetComponent GetComponent (string name) + { + object ob = ProjectBackend.GetTopLevelWrapper (name, false); + if (ob != null) + return (WidgetComponent) App.GetComponent (ob, name, null); + else + return null; + } + + public ActionGroupComponent AddNewActionGroup (string id) + { + object ob = ProjectBackend.AddNewActionGroup (id); + ActionGroupComponent ac = (ActionGroupComponent) App.GetComponent (ob, id, null); + + // Don't wait for the group added event to come to update the groups list since + // it may be too late. + ActionGroupInfo gi = GetActionGroup (ac.Name); + if (gi == null) { + gi = new ActionGroupInfo (this, ac.Name); + groups.Add (gi); + } + return ac; + } + + public ActionGroupComponent AddNewActionGroup (XmlElement template) + { + object ob = ProjectBackend.AddNewActionGroupFromTemplate (template.OuterXml); + ActionGroupComponent ac = (ActionGroupComponent) App.GetComponent (ob, null, null); + + // Don't wait for the group added event to come to update the groups list since + // it may be too late. + ActionGroupInfo gi = GetActionGroup (ac.Name); + if (gi == null) { + gi = new ActionGroupInfo (this, ac.Name); + groups.Add (gi); + } + return ac; + } + + public void RemoveActionGroup (ActionGroupInfo group) + { + ActionGroupComponent ac = (ActionGroupComponent) group.Component; + ProjectBackend.RemoveActionGroup ((Stetic.Wrapper.ActionGroup) ac.Backend); + } + + internal ActionGroupComponent[] GetActionGroups () + { + Wrapper.ActionGroup[] acs = ProjectBackend.GetActionGroups (); + + ArrayList comps = new ArrayList (acs.Length); + for (int n=0; n<acs.Length; n++) { + ActionGroupComponent ag = (ActionGroupComponent) App.GetComponent (acs[n], null, null); + if (ag != null) + comps.Add (ag); + } + + return (ActionGroupComponent[]) comps.ToArray (typeof(ActionGroupComponent)); + } + + public void AddWidgetLibrary (string assemblyPath) + { + AddWidgetLibrary (assemblyPath, false); + } + + public void AddWidgetLibrary (string assemblyPath, bool isInternal) + { + reloadRequested = false; + ProjectBackend.AddWidgetLibrary (assemblyPath, isInternal); + app.UpdateWidgetLibraries (false, false); + if (!reloadRequested) + ProjectBackend.Reload (); + } + + public void RemoveWidgetLibrary (string assemblyPath) + { + reloadRequested = false; + ProjectBackend.RemoveWidgetLibrary (assemblyPath); + app.UpdateWidgetLibraries (false, false); + if (!reloadRequested) + ProjectBackend.Reload (); + } + + public string[] WidgetLibraries { + get { + return (string[]) ProjectBackend.WidgetLibraries.ToArray (typeof(string)); + } + } + + public void SetWidgetLibraries (string[] libraries, string[] internalLibraries) + { + reloadRequested = false; + + ArrayList libs = new ArrayList (); + libs.AddRange (libraries); + libs.AddRange (internalLibraries); + ProjectBackend.WidgetLibraries = libs; + + libs = new ArrayList (); + libs.AddRange (internalLibraries); + ProjectBackend.InternalWidgetLibraries = libs; + + app.UpdateWidgetLibraries (false, false); + if (!reloadRequested) + ProjectBackend.Reload (); + } + +/* public bool CanCopySelection { + get { return Selection != null ? Selection.CanCopy : false; } + } + + public bool CanCutSelection { + get { return Selection != null ? Selection.CanCut : false; } + } + + public bool CanPasteToSelection { + get { return Selection != null ? Selection.CanPaste : false; } + } + + public void CopySelection () + { + if (Selection != null) + backend.ClipboardCopySelection (); + } + + public void CutSelection () + { + if (Selection != null) + backend.ClipboardCutSelection (); + } + + public void PasteToSelection () + { + if (Selection != null) + backend.ClipboardPaste (); + } + + public void DeleteSelection () + { + backend.DeleteSelection (); + } +*/ + + public void EditIcons () + { + ProjectBackend.EditIcons (); + } + + internal void NotifyWidgetAdded (object obj, string name, string typeName) + { + GuiDispatch.InvokeSync ( + delegate { + Component c = App.GetComponent (obj, name, typeName); + if (c != null) { + WidgetInfo wi = GetWidget (c.Name); + if (wi == null) { + wi = new WidgetInfo (this, c); + widgets.Add (wi); + } + if (WidgetAdded != null) + WidgetAdded (this, new WidgetInfoEventArgs (this, wi)); + } + } + ); + } + + internal void NotifyWidgetRemoved (string name) + { + GuiDispatch.InvokeSync ( + delegate { + WidgetInfo wi = GetWidget (name); + if (wi != null) { + widgets.Remove (wi); + if (WidgetRemoved != null) + WidgetRemoved (this, new WidgetInfoEventArgs (this, wi)); + } + } + ); + } + + internal void NotifyModifiedChanged () + { + GuiDispatch.InvokeSync ( + delegate { + if (ModifiedChanged != null) + ModifiedChanged (this, EventArgs.Empty); + } + ); + } + + internal void NotifyChanged (string rootWidgetName) + { + GuiDispatch.InvokeSync ( + delegate { + if (Changed != null) + Changed (this, EventArgs.Empty); + + // TODO: Optimize + foreach (ProjectItemInfo it in widgets) { + if (it.Name == rootWidgetName) + it.NotifyChanged (); + } + foreach (ProjectItemInfo it in groups) { + if (it.Name == rootWidgetName) + it.NotifyChanged (); + } + } + ); + } + + internal void NotifyWidgetNameChanged (object obj, string oldName, string newName, bool isRoot) + { + WidgetComponent c = obj != null ? (WidgetComponent) App.GetComponent (obj, null, null) : null; + if (c != null) + c.UpdateName (newName); + + if (isRoot) { + WidgetInfo wi = GetWidget (oldName); + if (wi != null) + wi.NotifyNameChanged (newName); + } + + GuiDispatch.InvokeSync ( + delegate { + if (c != null) { + if (ComponentNameChanged != null) + ComponentNameChanged (this, new ComponentNameEventArgs (this, c, oldName)); + } + } + ); + } + + internal void NotifyActionGroupAdded (string group) + { + GuiDispatch.InvokeSync (delegate { + ActionGroupInfo gi = GetActionGroup (group); + if (gi == null) { + gi = new ActionGroupInfo (this, group); + groups.Add (gi); + } + if (ActionGroupsChanged != null) + ActionGroupsChanged (this, EventArgs.Empty); + }); + } + + internal void NotifyActionGroupRemoved (string group) + { + GuiDispatch.InvokeSync (delegate { + ActionGroupInfo gi = GetActionGroup (group); + if (gi != null) { + groups.Remove (gi); + if (ActionGroupsChanged != null) + ActionGroupsChanged (this, EventArgs.Empty); + } + }); + } + + internal void NotifySignalAdded (object obj, string name, Signal signal) + { + GuiDispatch.InvokeSync (delegate { + if (SignalAdded != null) { + Component c = App.GetComponent (obj, name, null); + if (c != null) + SignalAdded (this, new ComponentSignalEventArgs (this, c, null, signal)); + } + }); + } + + internal void NotifySignalRemoved (object obj, string name, Signal signal) + { + GuiDispatch.InvokeSync (delegate { + if (SignalRemoved != null) { + Component c = App.GetComponent (obj, name, null); + if (c != null) + SignalRemoved (this, new ComponentSignalEventArgs (this, c, null, signal)); + } + }); + } + + internal void NotifySignalChanged (object obj, string name, Signal oldSignal, Signal signal) + { + GuiDispatch.InvokeSync (delegate { + if (SignalChanged != null) { + Component c = App.GetComponent (obj, name, null); + if (c != null) + SignalChanged (this, new ComponentSignalEventArgs (this, c, oldSignal, signal)); + } + }); + } + + internal void NotifyProjectReloaded () + { + GuiDispatch.InvokeSync (delegate { + if (ProjectReloaded != null) + ProjectReloaded (this, EventArgs.Empty); + }); + } + + internal void NotifyProjectReloading () + { + GuiDispatch.InvokeSync (delegate { + if (ProjectReloading != null) + ProjectReloading (this, EventArgs.Empty); + }); + } + + internal void NotifyComponentTypesChanged () + { + GuiDispatch.InvokeSync (delegate { + if (ComponentTypesChanged != null) + ComponentTypesChanged (this, EventArgs.Empty); + }); + } + + internal string ImportFile (string filePath) + { + if (importFileDelegate != null) { + string res = null; + GuiDispatch.InvokeSync (delegate { + res = importFileDelegate (filePath); + }); + return res; + } + else + return filePath; + } + + internal void NotifyUpdateLibraries () + { + app.UpdateWidgetLibraries (false, false); + } + + void OnBackendChanging () + { + selection = null; + + if (BackendChanging != null) + BackendChanging (); + } + + void OnBackendChanged (ApplicationBackend oldBackend) + { + if (oldBackend != null) { + tmpProjectFile = Path.GetTempFileName (); + backend.Save (tmpProjectFile); + backend.Dispose (); + } + + backend = app.Backend.CreateProject (); + backend.SetFrontend (this); + + if (tmpProjectFile != null && File.Exists (tmpProjectFile)) { +// backend.Load (tmpProjectFile, fileName); + throw new NotImplementedException ("OnBackendChanged"); + File.Delete (tmpProjectFile); + tmpProjectFile = null; + } else if (folderName != null) { + backend.Load (folderName); + } + + if (resourceProvider != null) + backend.ResourceProvider = resourceProvider; + + if (BackendChanged != null) + BackendChanged (oldBackend); + + if (ProjectReloaded != null) + ProjectReloaded (this, EventArgs.Empty); + } + } + + public abstract class ProjectItemInfo + { + string name; + protected Project project; + + public event EventHandler Changed; + + internal ProjectItemInfo (Project project, string name) + { + this.name = name; + this.project = project; + } + + public string Name { + get { return name; } + set { Component.Name = value; name = value; } + } + + internal void NotifyNameChanged (string name) + { + this.name = name; + NotifyChanged (); + } + + internal void NotifyChanged () + { + if (Changed != null) + Changed (this, EventArgs.Empty); + } + + public abstract Component Component { get; } + } + + public class WidgetInfo: ProjectItemInfo + { + string type; + List<ActionGroupInfo> groups; + + internal WidgetInfo (Project project, string name, string type): base (project, name) + { + this.type = type; + } + + internal WidgetInfo (Project project, Component c): base (project, c.Name) + { + type = c.Type.Name; + } + + public IEnumerable<ActionGroupInfo> ActionGroups { + get { + if (groups != null) + return groups; + else + return new ActionGroupInfo [0]; + } + } + + public string Type { + get { return type; } + } + + public bool IsWindow { + get { return type == "Gtk.Dialog" || type == "Gtk.Window"; } + } + + public override Component Component { + get { return project.GetComponent (Name); } + } + + internal void AddGroup (string group) + { + if (groups == null) + groups = new List<ActionGroupInfo> (); + groups.Add (new ActionGroupInfo (project, group, Name)); + } + } + + public class ActionGroupInfo: ProjectItemInfo + { + string widgetName; + + internal ActionGroupInfo (Project project, string name): base (project, name) + { + } + + internal ActionGroupInfo (Project project, string name, string widgetName): base (project, name) + { + this.widgetName = widgetName; + } + + public override Component Component { + get { + ActionGroupComponent[] ags; + if (widgetName != null) { + WidgetComponent c = project.GetComponent (widgetName) as WidgetComponent; + if (c == null) + return null; + ags = c.GetActionGroups (); + } + else { + ags = project.GetActionGroups (); + } + foreach (ActionGroupComponent ag in ags) + if (ag.Name == Name) + return ag; + return null; + } + } + } + + public delegate string ImportFileDelegate (string fileName); +} diff --git a/main/src/addins/MonoDevelop.GtkCore2/libsteticui/ProjectBackend.cs b/main/src/addins/MonoDevelop.GtkCore2/libsteticui/ProjectBackend.cs new file mode 100644 index 0000000000..677c0a4af6 --- /dev/null +++ b/main/src/addins/MonoDevelop.GtkCore2/libsteticui/ProjectBackend.cs @@ -0,0 +1,1237 @@ +using Gtk; +using System; +using System.IO; +using System.Xml; +using System.Collections; +using System.Collections.Generic; +using System.Collections.Specialized; +using System.CodeDom; +using Mono.Unix; + +namespace Stetic { + + internal class ProjectBackend : MarshalByRefObject, IProject, IDisposable + { + List<WidgetData> topLevels; + bool modified; + Gtk.Widget selection; + string id; + string folderName; + XmlDocument tempDoc; + bool loading; + IResourceProvider resourceProvider; + + // Global action groups of the project + Stetic.Wrapper.ActionGroupCollection actionGroups; + bool ownedGlobalActionGroups = true; // It may be false when reusing groups from another project + + Stetic.ProjectIconFactory iconFactory; + Project frontend; + ArrayList widgetLibraries; + ArrayList internalLibs; + ApplicationBackend app; + AssemblyResolver resolver; + string imagesRootPath; + string targetGtkVersion; + List<string> modifiedTopLevels; + //During project conversion flag is set + bool converting; + + // The action collection of the last selected widget + Stetic.Wrapper.ActionGroupCollection oldTopActionCollection; + + public event Wrapper.WidgetNameChangedHandler WidgetNameChanged; + public event Wrapper.WidgetEventHandler WidgetAdded; + public event Wrapper.WidgetEventHandler WidgetContentsChanged; + public event ObjectWrapperEventHandler ObjectChanged; + public event EventHandler ComponentTypesChanged; + + public event SignalEventHandler SignalAdded; + public event SignalEventHandler SignalRemoved; + public event SignalChangedEventHandler SignalChanged; + + public event Wrapper.WidgetEventHandler SelectionChanged; + public event ProjectChangedEventHandler Changed; + + // Fired when the project has been reloaded, due for example to + // a change in the registry + public event EventHandler ProjectReloading; + public event EventHandler ProjectReloaded; + + public ProjectBackend (ApplicationBackend app) + { + this.app = app; + topLevels = new List<WidgetData> (); + + ActionGroups = new Stetic.Wrapper.ActionGroupCollection (); + + Registry.RegistryChanging += OnRegistryChanging; + Registry.RegistryChanged += OnRegistryChanged; + + iconFactory = new ProjectIconFactory (); + widgetLibraries = new ArrayList (); + internalLibs = new ArrayList (); + modifiedTopLevels = new List<string> (); + } + + public void Dispose () + { + // First of all, disconnect from the frontend, + // to avoid sending notifications while disposing + frontend = null; + + if (oldTopActionCollection != null) + oldTopActionCollection.ActionGroupChanged -= OnComponentTypesChanged; + + Registry.RegistryChanging -= OnRegistryChanging; + Registry.RegistryChanged -= OnRegistryChanged; + Close (); + iconFactory = null; + ActionGroups = null; + System.Runtime.Remoting.RemotingServices.Disconnect (this); + } + + public override object InitializeLifetimeService () + { + // Will be disconnected when calling Dispose + return null; + } + + + public string FileName { + get { throw new Exception("FileName is obsolete"); } + set { throw new Exception("FileName is obsolete"); } + } + + public string FolderName { + get { return folderName; } + set { + this.folderName = value; + if (folderName != null ) + Id = System.IO.Path.GetFullPath (folderName); + else + Id = null; + } + } + + internal ArrayList WidgetLibraries { + get { return widgetLibraries; } + set { widgetLibraries = value; } + } + + internal ArrayList InternalWidgetLibraries { + get { return internalLibs; } + set { internalLibs = value; } + } + + public bool IsInternalLibrary (string lib) + { + return internalLibs.Contains (lib); + } + + public bool CanGenerateCode { + get { + // It can generate code if all libraries on which depend can generate code + foreach (string s in widgetLibraries) { + WidgetLibrary lib = Registry.GetWidgetLibrary (s); + if (lib != null && !lib.CanGenerateCode) + return false; + } + return true; + } + } + + public string TargetGtkVersion { + get { return targetGtkVersion ?? string.Empty; } + set { + if (TargetGtkVersion == value) + return; + targetGtkVersion = value; + +// Update the project + OnRegistryChanging (null, null); + OnRegistryChanged (null, null); + } + } + + public string ImagesRootPath { + get { + if (string.IsNullOrEmpty (imagesRootPath)) { + if (string.IsNullOrEmpty (folderName)) + return "."; + else + return Path.GetFullPath (folderName); + } + else { + if (Path.IsPathRooted (imagesRootPath)) + return imagesRootPath; + else if (!string.IsNullOrEmpty (folderName)) + return Path.GetFullPath (Path.Combine (folderName, imagesRootPath)); + else + return imagesRootPath; + } + } + set { imagesRootPath = value; } + } + + + public void AddWidgetLibrary (string lib) + { + AddWidgetLibrary (lib, false); + } + + public void AddWidgetLibrary (string lib, bool isInternal) + { + if (!widgetLibraries.Contains (lib)) + widgetLibraries.Add (lib); + if (isInternal) { + if (!internalLibs.Contains (lib)) + internalLibs.Add (lib); + } + else { + internalLibs.Remove (lib); + } + } + + public void RemoveWidgetLibrary (string lib) + { + widgetLibraries.Remove (lib); + internalLibs.Remove (lib); + } + + public ArrayList GetComponentTypes () + { + ArrayList list = new ArrayList (); + foreach (WidgetLibrary lib in app.GetProjectLibraries (this)) { + // Don't include in the list widgets which are internal (when the library is + // not internal to the project), widgets not assigned to any category, and deprecated ones. + bool isInternalLib = IsInternalLibrary (lib.Name); + if (lib.NeedsReload) + lib.Reload (); + foreach (ClassDescriptor cd in lib.AllClasses) { + if (!cd.Deprecated && cd.Category.Length > 0 && (isInternalLib || !cd.IsInternal) && cd.SupportsGtkVersion (TargetGtkVersion)) + list.Add (cd.Name); + } + } + return list; + } + + public string[] GetWidgetTypes () + { + List<string> list = new List<string> (); + foreach (WidgetLibrary lib in app.GetProjectLibraries (this)) { + // Don't include in the list widgets which are internal (when the library is + // not internal to the project) and deprecated ones. + bool isInternalLib = IsInternalLibrary (lib.Name); + foreach (ClassDescriptor cd in lib.AllClasses) { + if (!cd.Deprecated && (isInternalLib || !cd.IsInternal)) + list.Add (cd.Name); + } + } + return list.ToArray (); + } + + public IResourceProvider ResourceProvider { + get { return resourceProvider; } + set { resourceProvider = value; } + } + + public Stetic.Wrapper.ActionGroupCollection ActionGroups { + get { return actionGroups; } + set { + if (actionGroups != null) { + actionGroups.ActionGroupAdded -= OnGroupAdded; + actionGroups.ActionGroupRemoved -= OnGroupRemoved; + actionGroups.ActionGroupChanged -= OnComponentTypesChanged; + } + actionGroups = value; + if (actionGroups != null) { + actionGroups.ActionGroupAdded += OnGroupAdded; + actionGroups.ActionGroupRemoved += OnGroupRemoved; + actionGroups.ActionGroupChanged += OnComponentTypesChanged; + } + ownedGlobalActionGroups = true; + } + } + + public void AttachActionGroups (Stetic.Wrapper.ActionGroupCollection groups) + { + ActionGroups = groups; + ownedGlobalActionGroups = false; + } + + public Stetic.ProjectIconFactory IconFactory { + get { return iconFactory; } + set { iconFactory = value; } + } + + internal void SetFrontend (Project project) + { + frontend = project; + } + + public void Close () + { + if (actionGroups != null && ownedGlobalActionGroups) { + foreach (Stetic.Wrapper.ActionGroup ag in actionGroups) + ag.Dispose (); + actionGroups.Clear (); + } + + foreach (WidgetData wd in topLevels) { + if (wd.Widget != null) + wd.Widget.Destroy (); + } + + selection = null; + topLevels.Clear (); + //widgetLibraries.Clear (); + + + iconFactory = new ProjectIconFactory (); + } + + public void Load (string folderName) + { + this.folderName = folderName; + XmlDocument doc = new XmlDocument (); + doc.PreserveWhitespace = true; + XmlElement toplevel = doc.CreateElement ("stetic-interface"); + doc.AppendChild (toplevel); + modifiedTopLevels.Clear (); + + ReadIconFactory (doc); + ReadActionGroups (doc); + ReadTopLevels (doc); + Read (doc); + + Id = System.IO.Path.GetFullPath (folderName); + } + + public void LoadOldVersion (string fileName) + { + if (!File.Exists (fileName)) + return; + + XmlDocument doc = new XmlDocument (); + doc.PreserveWhitespace = true; + doc.Load (fileName); + + Read (doc); + + Id = System.IO.Path.GetFileName (fileName); + } + + void ReadIconFactory (XmlDocument doc) + { + XmlNode node = doc.SelectSingleNode ("/stetic-interface"); + if (node == null) + return; + + string basePath = folderName; + string xmlfile = Path.Combine(basePath, "IconFactory.gtkx"); + + if (File.Exists (xmlfile)) { + + XmlDocument doc2 = new XmlDocument (); + doc2.PreserveWhitespace = true; + doc2.Load (xmlfile); + + XmlNode ifnode2 = doc2.SelectSingleNode ("/stetic-interface/icon-factory"); + + if (ifnode2 != null) { + XmlNode ifnode = doc.ImportNode (ifnode2, true); + node.AppendChild (ifnode); + } + } + } + + void ReadActionGroups (XmlDocument doc) + { + ReadSplitFiles (doc, "action-group", "name"); + } + + void ReadTopLevels (XmlDocument doc) + { + ReadSplitFiles (doc, "widget", "id"); + } + + void ReadSplitFiles (XmlDocument doc, string splitElement, string idAttribute) + { + XmlNode node = doc.SelectSingleNode ("/stetic-interface"); + if (node == null) + return; + + foreach (string basePath in frontend.DesignInfo.GetComponentFolders ()) { + DirectoryInfo dir = new DirectoryInfo (basePath); + + foreach (FileInfo file in dir.GetFiles ()) { + if (file.Extension == ".gtkx") { + + XmlDocument wdoc = new XmlDocument (); + wdoc.PreserveWhitespace = true; + wdoc.Load (file.FullName); + + XmlNode wnode = wdoc.SelectSingleNode ("/stetic-interface"); + + foreach (XmlElement toplevel in wnode.SelectNodes (splitElement)) { + string id = toplevel.GetAttribute (idAttribute); + + if (frontend.DesignInfo.HasComponentFile (id)) { + XmlNode imported = doc.ImportNode (toplevel, true); + node.AppendChild (imported); + } + } + } + } + } + } + + void AddActionGroup (XmlElement groupElem) + { + ObjectReader reader = new ObjectReader (this, FileFormat.Native); + + Wrapper.ActionGroup actionGroup = new Wrapper.ActionGroup (); + actionGroup.Read (reader, groupElem); + actionGroups.Add (actionGroup); + } + + void AddWidget (XmlElement toplevel) + { + topLevels.Add (new WidgetData (toplevel.GetAttribute ("id"), toplevel, null)); + } + + void Read (XmlDocument doc) + { + loading = true; + + try { + Close (); + + XmlNode node = doc.SelectSingleNode ("/stetic-interface"); + if (node == null) + throw new ApplicationException (Catalog.GetString ("Not a Stetic file according to node name.")); + + // Load the assembly directories + resolver = new AssemblyResolver (app); + app.LoadLibraries (resolver, widgetLibraries); + + if (ownedGlobalActionGroups) { + foreach (XmlElement groupElem in node.SelectNodes ("action-group")) + AddActionGroup (groupElem); + } + + XmlElement iconsElem = node.SelectSingleNode ("icon-factory") as XmlElement; + if (iconsElem != null) + iconFactory.Read (this, iconsElem); + + foreach (XmlElement toplevel in node.SelectNodes ("widget")) + AddWidget (toplevel); + + } finally { + loading = false; + } + } + + public Gtk.Widget GetWidget (WidgetData data) + { + if (data.Widget == null) { + try { + loading = true; + ObjectReader reader = new ObjectReader (this, FileFormat.Native); + Wrapper.Container wrapper = Stetic.ObjectWrapper.ReadObject (reader, data.XmlData, null) as Wrapper.Container; + data.Widget = wrapper.Wrapped; + data.Widget.Destroyed += (s,e) => data.Widget = null; + } finally { + loading = false; + } + } + + return data.Widget; + } + + public bool ReloadTopLevel (string topLevelName) + { + XmlElement topLevelElem = ReadDesignerFile (topLevelName, "widget"); + if (topLevelName != null) { + WidgetData data = GetWidgetData (topLevelName); + + if (data != null) { + //Stetic.Wrapper.Widget ww = Stetic.Wrapper.Widget.Lookup (data.Widget); + data.SetXmlData (topLevelName, topLevelElem); + GetWidget (data); + return true; + } + } + return false; + } + + public void ReloadComponent (string componentName) + { + ReloadTopLevel (componentName); + //TODO: Make reloading works for action groups + } + + + public void ReloadActionGroup (string groupName) + { + //TODO : Implement method ReloadActionGroup + } + + XmlElement ReadDesignerFile (string componentName, string elementName) + { + string gtkxFile = GetDesignerFileName (componentName); + if (gtkxFile != null) { + XmlDocument wdoc = new XmlDocument (); + wdoc.PreserveWhitespace = true; + wdoc.Load (gtkxFile); + + XmlNode wnode = wdoc.SelectSingleNode ("/stetic-interface"); + foreach (XmlElement toplevel in wnode.SelectNodes (elementName)) { + return toplevel; + } + + string msg = string.Format (@"Cannot find /stetic-interface/{0} element in {1} file.", + elementName, gtkxFile); + throw new InvalidOperationException (msg); + } + + return null; + } + + public void ConvertProject (string oldSteticFileName, string newGuiFolderName) + { + converting = true; + try { + LoadOldVersion (oldSteticFileName); + Save (newGuiFolderName); + } finally { + converting = false; + } + } + + public void Save (string folderName) + { + this.folderName = folderName; + XmlDocument doc = Write (false); + + XmlTextWriter writer = null; + try { + WriteIconFactory (doc); + WriteActionGroups (doc); + WriteTopLevels (doc); + + } finally { + if (writer != null) + writer.Close (); + } + } + + private void WriteIconFactory (XmlDocument doc) + { + XmlNode node = doc.SelectSingleNode ("/stetic-interface"); + if (node == null) + return; + + XmlNode ifnode = node.SelectSingleNode ("icon-factory"); + if (ifnode == null) + return; + + XmlDocument doc2 = new XmlDocument (); + doc2.PreserveWhitespace = true; + + XmlElement node2 = doc2.CreateElement ("stetic-interface"); + doc2.AppendChild (node2); + + XmlNode ifnode2 = doc2.ImportNode (ifnode, true); + node2.AppendChild (ifnode2); + + string basePath = this.folderName; + string xmlFile = Path.Combine (basePath, "IconFactory.gtkx"); + WriteXmlFile (xmlFile, doc2); + + node.RemoveChild (ifnode); + } + + void WriteActionGroups (XmlDocument doc) + { + WriteSplitFiles (doc, "action-group", "name"); + } + + void WriteTopLevels (XmlDocument doc) + { + WriteSplitFiles (doc, "widget", "id"); + } + + void WriteSplitFiles (XmlDocument doc, string splitElement, string idAttribute) + { + XmlNode node = doc.SelectSingleNode ("/stetic-interface"); + if (node == null) + return; + + foreach (XmlElement toplevel in node.SelectNodes (splitElement)) { + + string id = toplevel.GetAttribute (idAttribute); + if (modifiedTopLevels.Contains (id) || converting) { + string xmlFile = GetDesignerFileName (id); + if (xmlFile != null) { + XmlDocument doc2 = new XmlDocument (); + doc2.PreserveWhitespace = true; + + XmlElement node2 = doc2.CreateElement ("stetic-interface"); + doc2.AppendChild (node2); + + XmlNode wnode2 = doc2.ImportNode (toplevel, true); + node2.AppendChild (wnode2); + + WriteXmlFile (xmlFile, doc2); + if (modifiedTopLevels.Contains (id)) + modifiedTopLevels.Remove (id); + } + } + } + } + + private string GetDesignerFileName (string componentName) + { + string componentFile = frontend.DesignInfo.GetComponentFile (componentName); + return frontend.DesignInfo.GetDesignerFileFromComponent (componentFile); + } + + void WriteXmlFile (string xmlFile, XmlDocument doc) + { + XmlTextWriter writer = null; + try { + writer = new XmlTextWriter (xmlFile + "~", System.Text.Encoding.UTF8); + writer.Formatting = Formatting.Indented; + + doc.Save (writer); + writer.Close (); + + File.Copy (xmlFile + "~", xmlFile, true); + File.Delete (xmlFile + "~"); + } finally { + if (writer != null) + writer.Close (); + } + } + + XmlDocument Write (bool includeUndoInfo) + { + XmlDocument doc = new XmlDocument (); + doc.PreserveWhitespace = true; + + XmlElement toplevel = doc.CreateElement ("stetic-interface"); + doc.AppendChild (toplevel); + + ObjectWriter writer = new ObjectWriter (doc, FileFormat.Native); + writer.CreateUndoInfo = includeUndoInfo; + if (ownedGlobalActionGroups) { + foreach (Wrapper.ActionGroup agroup in actionGroups) { + XmlElement elem = agroup.Write (writer); + toplevel.AppendChild (elem); + } + } + + if (iconFactory.Icons.Count > 0) + toplevel.AppendChild (iconFactory.Write (doc)); + + foreach (WidgetData data in topLevels) { + if (data.Widget != null) { + Stetic.Wrapper.Container wrapper = Stetic.Wrapper.Container.Lookup (data.Widget); + if (wrapper == null) + continue; + + XmlElement elem = wrapper.Write (writer); + if (elem != null) + toplevel.AppendChild (elem); + } else { + toplevel.AppendChild (doc.ImportNode (data.XmlData, true)); + } + } + + // Remove undo annotations from the xml document + if (!includeUndoInfo) + CleanUndoData (doc.DocumentElement); + + return doc; + } + + public void ImportGlade (string fileName) + { + GladeFiles.Import (this, fileName); + } + + public void ExportGlade (string fileName) + { + GladeFiles.Export (this, fileName); + } + + public void EditIcons () + { + using (Stetic.Editor.EditIconFactoryDialog dlg = new Stetic.Editor.EditIconFactoryDialog (null, this, this.IconFactory)) { + dlg.Run (); + } + } + +// internal WidgetEditSession CreateWidgetDesignerSession (WidgetDesignerFrontend frontend, string windowName, Stetic.ProjectBackend editingBackend, bool autoCommitChanges) +// { +// return new WidgetEditSession (this, frontend, windowName, editingBackend, autoCommitChanges); +// } + + internal WidgetEditSession CreateWidgetDesignerSession (WidgetDesignerFrontend frontend, string windowName) + { + return new WidgetEditSession (this, frontend, windowName); + } + + internal ActionGroupEditSession CreateGlobalActionGroupDesignerSession (ActionGroupDesignerFrontend frontend, string groupName, bool autoCommitChanges) + { + return new ActionGroupEditSession (frontend, this, null, groupName, autoCommitChanges); + } + + internal ActionGroupEditSession CreateLocalActionGroupDesignerSession (ActionGroupDesignerFrontend frontend, string windowName, bool autoCommitChanges) + { + return new ActionGroupEditSession (frontend, this, windowName, null, autoCommitChanges); + } + + public Wrapper.Container GetTopLevelWrapper (string name, bool throwIfNotFound) + { + Gtk.Widget w = GetWidget (name); + if (w != null) { + Wrapper.Container ww = Wrapper.Container.Lookup (w); + if (ww != null) + return (Wrapper.Container) Component.GetSafeReference (ww); + } + if (throwIfNotFound) + throw new InvalidOperationException ("Component not found: " + name); + return null; + } + + public object AddNewComponent (string fileName) + { + XmlDocument doc = new XmlDocument(); + doc.PreserveWhitespace = true; + doc.Load (fileName); + + XmlElement toplevel = (XmlElement)doc.SelectSingleNode ("/stetic-interface/widget"); + if (toplevel != null) + return AddNewWidgetFromTemplate (toplevel.OuterXml); + + XmlElement groupElem = (XmlElement)doc.SelectSingleNode ("/stetic-interface/action-group"); + if (groupElem != null) + return AddNewActionGroupFromTemplate (groupElem.OuterXml); + + return null; + } + + public object AddNewWidget (string type, string name) + { + ClassDescriptor cls = Registry.LookupClassByName (type); + Gtk.Widget w = (Gtk.Widget) cls.NewInstance (this); + w.Name = name; + this.AddWidget (w); + return Component.GetSafeReference (ObjectWrapper.Lookup (w)); + } + + public object AddNewWidgetFromTemplate (string template) + { + XmlDocument doc = new XmlDocument (); + doc.LoadXml (template); + Gtk.Widget widget = Stetic.WidgetUtils.ImportWidget (this, doc.DocumentElement); + AddWidget (widget); + + string name = widget.Name; + return Component.GetSafeReference (ObjectWrapper.Lookup (widget)); + } + + public void RemoveWidget (string name) + { + WidgetData data = GetWidgetData (name); + if (data == null) + return; + + if (frontend != null) + frontend.NotifyWidgetRemoved (data.Name); + + if (modifiedTopLevels.Contains (name)) + modifiedTopLevels.Remove (name); + } + + public Stetic.Wrapper.ActionGroup AddNewActionGroup (string name) + { + Stetic.Wrapper.ActionGroup group = new Stetic.Wrapper.ActionGroup (); + group.Name = name; + ActionGroups.Add (group); + this.modifiedTopLevels.Add (name); + return group; + } + + public Stetic.Wrapper.ActionGroup AddNewActionGroupFromTemplate (string template) + { + XmlDocument doc = new XmlDocument (); + doc.LoadXml (template); + ObjectReader or = new ObjectReader (this, FileFormat.Native); + Stetic.Wrapper.ActionGroup group = new Stetic.Wrapper.ActionGroup (); + group.Read (or, doc.DocumentElement); + ActionGroups.Add (group); + this.modifiedTopLevels.Add (group.Name); + return group; + } + + public void RemoveActionGroup (Stetic.Wrapper.ActionGroup group) + { + ActionGroups.Remove (group); + string name = group.Name; + if (modifiedTopLevels.Contains (name)) + modifiedTopLevels.Remove (name); + } + + public Wrapper.ActionGroup[] GetActionGroups () + { + // Needed since ActionGroupCollection can't be made serializable + return ActionGroups.ToArray (); + } + + void CleanUndoData (XmlElement elem) + { + elem.RemoveAttribute ("undoId"); + foreach (XmlNode cn in elem.ChildNodes) { + XmlElement ce = cn as XmlElement; + if (ce != null) + CleanUndoData (ce); + } + } + + void OnRegistryChanging (object o, EventArgs args) + { + if (loading) return; + + // Store a copy of the current tree. The tree will + // be recreated once the registry change is completed. + + tempDoc = Write (true); + Selection = null; + } + + void OnRegistryChanged (object o, EventArgs args) + { + if (loading) return; + + if (tempDoc != null) + LoadStatus (tempDoc); + } + + public object SaveStatus () + { + return Write (true); + } + + public void LoadStatus (object ob) + { + if (frontend != null) + frontend.NotifyProjectReloading (); + if (ProjectReloading != null) + ProjectReloading (this, EventArgs.Empty); + + ProjectIconFactory icf = iconFactory; + + Read ((XmlDocument)ob); + + // Reuse the same icon factory, since a registry change has no effect to it + // and it may be inherited from another project + iconFactory = icf; + + if (frontend != null) + frontend.NotifyProjectReloaded (); + if (ProjectReloaded != null) + ProjectReloaded (this, EventArgs.Empty); + NotifyComponentTypesChanged (); + } + + bool preserveWidgetLibraries; + + public void Reload () + { + try { + preserveWidgetLibraries = true; + OnRegistryChanging (null, null); + OnRegistryChanged (null, null); + } + finally + { + preserveWidgetLibraries = false; + } + } + + public string Id { + get { return id; } + set { id = value; } + } + + public bool WasModified (string topLevel) + { + return modifiedTopLevels.Contains (topLevel); + } + + public bool ComponentNeedsCodeGeneration (string topLevel) + { + return frontend.DesignInfo.ComponentNeedsCodeGeneration (topLevel); + } + + public AssemblyResolver Resolver { + get { return resolver; } + } + + public string ImportFile (string filePath) + { + return frontend.ImportFile (filePath); + } + + public void AddWindow (Gtk.Window window) + { + AddWindow (window, false); + } + + public void AddWindow (Gtk.Window window, bool select) + { + AddWidget (window); + if (select) + Selection = window; + } + + public void AddWidget (Gtk.Widget widget) + { + if (!typeof(Gtk.Container).IsInstanceOfType (widget)) + throw new System.ArgumentException ("widget", "Only containers can be top level widgets"); + topLevels.Add (new WidgetData (null, null, widget)); + + if (!loading) { + Stetic.Wrapper.Widget ww = Stetic.Wrapper.Widget.Lookup (widget); + + if (ww == null) + throw new InvalidOperationException ("Widget not wrapped"); + if (frontend != null) + frontend.NotifyWidgetAdded (Component.GetSafeReference (ww), widget.Name, ww.ClassDescriptor.Name); + OnWidgetAdded (new Stetic.Wrapper.WidgetEventArgs (ww)); + } + } + + void IProject.NotifyObjectChanged (ObjectWrapperEventArgs args) + { + if (loading) + return; + NotifyChanged (args.Wrapper.RootWrapperName); + if (ObjectChanged != null) + ObjectChanged (this, args); + } + + void IProject.NotifyNameChanged (Stetic.Wrapper.WidgetNameChangedArgs args) + { + if (loading) + return; + NotifyChanged (args.WidgetWrapper.RootWrapperName); + OnWidgetNameChanged (args, args.WidgetWrapper.IsTopLevel); + } + + void IProject.NotifySignalAdded (SignalEventArgs args) + { + if (loading) + return; + if (frontend != null) + frontend.NotifySignalAdded (Component.GetSafeReference (args.Wrapper), null, args.Signal); + OnSignalAdded (args); + } + + void IProject.NotifySignalRemoved (SignalEventArgs args) + { + if (loading) + return; + if (frontend != null) + frontend.NotifySignalRemoved (Component.GetSafeReference (args.Wrapper), null, args.Signal); + OnSignalRemoved (args); + } + + void IProject.NotifySignalChanged (SignalChangedEventArgs args) + { + if (loading) + return; + OnSignalChanged (args); + } + + void IProject.NotifyWidgetContentsChanged (Wrapper.Widget w) + { + if (loading) + return; + if (WidgetContentsChanged != null) + WidgetContentsChanged (this, new Wrapper.WidgetEventArgs (w)); + } + + void OnWidgetNameChanged (Stetic.Wrapper.WidgetNameChangedArgs args, bool isTopLevel) + { + if (frontend != null) + frontend.NotifyWidgetNameChanged (Component.GetSafeReference (args.WidgetWrapper), args.OldName, args.NewName, isTopLevel); + if (args.WidgetWrapper != null && WidgetNameChanged != null) + WidgetNameChanged (this, args); + + if (modifiedTopLevels.Contains (args.OldName)) + modifiedTopLevels.Remove (args.OldName); + + if (!modifiedTopLevels.Contains (args.NewName)) + modifiedTopLevels.Add (args.NewName); + } + + void OnSignalAdded (object sender, SignalEventArgs args) + { + if (frontend != null) + frontend.NotifySignalAdded (Component.GetSafeReference (args.Wrapper), null, args.Signal); + OnSignalAdded (args); + } + + protected virtual void OnSignalAdded (SignalEventArgs args) + { + if (SignalAdded != null) + SignalAdded (this, args); + } + + void OnSignalRemoved (object sender, SignalEventArgs args) + { + if (frontend != null) + frontend.NotifySignalRemoved (Component.GetSafeReference (args.Wrapper), null, args.Signal); + OnSignalRemoved (args); + } + + protected virtual void OnSignalRemoved (SignalEventArgs args) + { + if (SignalRemoved != null) + SignalRemoved (this, args); + } + + void OnSignalChanged (object sender, SignalChangedEventArgs args) + { + OnSignalChanged (args); + } + + protected virtual void OnSignalChanged (SignalChangedEventArgs args) + { + if (frontend != null) + frontend.NotifySignalChanged (Component.GetSafeReference (args.Wrapper), null, args.OldSignal, args.Signal); + if (SignalChanged != null) + SignalChanged (this, args); + } + + public Gtk.Widget[] Toplevels { + get { + List<Gtk.Widget> list = new List<Gtk.Widget> (); + foreach (WidgetData w in topLevels) + list.Add (GetWidget (w)); + return list.ToArray (); + } + } + + public Gtk.Widget GetWidget (string name) + { + WidgetData w = GetWidgetData (name); + if (w != null) + return GetWidget (w); + else + return null; + } + + public WidgetData GetWidgetData (string name) + { + foreach (WidgetData w in topLevels) { + if (w.Name == name) + return w; + } + return null; + } + + // IProject + + public Gtk.Widget Selection { + get { + return selection; + } + set { + if (selection == value) + return; + + Wrapper.ActionGroupCollection newCollection = null; + + // FIXME: should there be an IsDestroyed property? + if (selection != null && selection.Handle != IntPtr.Zero) { + Stetic.Wrapper.Container parent = Stetic.Wrapper.Container.LookupParent (selection); + if (parent == null) + parent = Stetic.Wrapper.Container.Lookup (selection); + if (parent != null) + parent.UnSelect (selection); + } + + selection = value; + + if (selection != null && selection.Handle != IntPtr.Zero) { + Stetic.Wrapper.Container parent = Stetic.Wrapper.Container.LookupParent (selection); + if (parent == null) + parent = Stetic.Wrapper.Container.Lookup (selection); + if (parent != null) + parent.Select (selection); + Wrapper.Widget w = Wrapper.Widget.Lookup (selection); + if (w != null) + newCollection = w.LocalActionGroups; + } + + if (SelectionChanged != null) + SelectionChanged (this, new Wrapper.WidgetEventArgs (Wrapper.Widget.Lookup (selection))); + + if (oldTopActionCollection != newCollection) { + if (oldTopActionCollection != null) + oldTopActionCollection.ActionGroupChanged -= OnComponentTypesChanged; + if (newCollection != null) + newCollection.ActionGroupChanged += OnComponentTypesChanged; + oldTopActionCollection = newCollection; + OnComponentTypesChanged (null, null); + } + } + } + + public void PopupContextMenu (Stetic.Wrapper.Widget wrapper) + { + Gtk.Menu m = new ContextMenu (wrapper); + m.Popup (); + } + + public void PopupContextMenu (Placeholder ph) + { + Gtk.Menu m = new ContextMenu (ph); + m.Popup (); + } + + internal static string AbsoluteToRelativePath (string baseDirectoryPath, string absPath) + { + if (!Path.IsPathRooted (absPath)) + return absPath; + + absPath = Path.GetFullPath (absPath); + baseDirectoryPath = Path.GetFullPath (baseDirectoryPath); + char[] separators = { Path.DirectorySeparatorChar, Path.VolumeSeparatorChar, Path.AltDirectorySeparatorChar }; + + string[] bPath = baseDirectoryPath.Split (separators); + string[] aPath = absPath.Split (separators); + int indx = 0; + for(; indx < Math.Min(bPath.Length, aPath.Length); ++indx) { + if(!bPath[indx].Equals(aPath[indx])) + break; + } + + if (indx == 0) { + return absPath; + } + + string erg = ""; + + if(indx == bPath.Length) { + erg += "." + Path.DirectorySeparatorChar; + } else { + for (int i = indx; i < bPath.Length; ++i) { + erg += ".." + Path.DirectorySeparatorChar; + } + } + erg += String.Join(Path.DirectorySeparatorChar.ToString(), aPath, indx, aPath.Length-indx); + + return erg; + } + + void OnComponentTypesChanged (object s, EventArgs a) + { + if (!loading) + NotifyComponentTypesChanged (); + } + + public void NotifyComponentTypesChanged () + { + if (frontend != null) + frontend.NotifyComponentTypesChanged (); + if (ComponentTypesChanged != null) + ComponentTypesChanged (this, EventArgs.Empty); + } + + void OnGroupAdded (object s, Stetic.Wrapper.ActionGroupEventArgs args) + { + args.ActionGroup.SignalAdded += OnSignalAdded; + args.ActionGroup.SignalRemoved += OnSignalRemoved; + args.ActionGroup.SignalChanged += OnSignalChanged; + if (frontend != null) + frontend.NotifyActionGroupAdded (args.ActionGroup.Name); + OnComponentTypesChanged (null, null); + } + + void OnGroupRemoved (object s, Stetic.Wrapper.ActionGroupEventArgs args) + { + args.ActionGroup.SignalAdded -= OnSignalAdded; + args.ActionGroup.SignalRemoved -= OnSignalRemoved; + args.ActionGroup.SignalChanged -= OnSignalChanged; + if (frontend != null) + frontend.NotifyActionGroupRemoved (args.ActionGroup.Name); + OnComponentTypesChanged (null, null); + } + + void NotifyChanged (string rootWidgetName) + { + if (!modifiedTopLevels.Contains (rootWidgetName)) + modifiedTopLevels.Add (rootWidgetName); + if (frontend != null) + frontend.NotifyChanged (rootWidgetName); + if (Changed != null) + Changed (this, new ProjectChangedEventArgs (rootWidgetName)); + } + + protected virtual void OnWidgetAdded (Stetic.Wrapper.WidgetEventArgs args) + { + NotifyChanged (args.WidgetWrapper.RootWrapperName); + if (WidgetAdded != null) + WidgetAdded (this, args); + } + } + + class WidgetData + { + string name; + + public WidgetData (string name, XmlElement data, Gtk.Widget widget) + { + SetXmlData (name, data); + Widget = widget; + } + + public void SetXmlData (string name, XmlElement data) + { + this.name = name; + XmlData = data; + Widget = null; + } + + public XmlElement XmlData; + public Gtk.Widget Widget; + + public string Name { + get { + if (Widget != null) + return Widget.Name; + else + return name; + } + } + } + + public class ProjectChangedEventArgs : EventArgs + { + public string ChangedTopLevelName { get; private set; } + + public ProjectChangedEventArgs (string changedTopLevel) + { + ChangedTopLevelName = changedTopLevel; + } + } + + public delegate void ProjectChangedEventHandler (object sender, ProjectChangedEventArgs args); +} diff --git a/main/src/addins/MonoDevelop.GtkCore2/libsteticui/ProjectViewBackend.cs b/main/src/addins/MonoDevelop.GtkCore2/libsteticui/ProjectViewBackend.cs new file mode 100644 index 0000000000..3d93a71e7c --- /dev/null +++ b/main/src/addins/MonoDevelop.GtkCore2/libsteticui/ProjectViewBackend.cs @@ -0,0 +1,345 @@ +using Gtk; +using System; +using Mono.Unix; +using System.Collections.Generic; + +namespace Stetic { + + internal class ProjectViewBackend : ScrolledWindow + { + ProjectViewBackendNodeView nodeView; + + public ProjectViewBackend (ProjectViewFrontend frontend) + { + ShadowType = Gtk.ShadowType.In; + nodeView = new ProjectViewBackendNodeView (frontend); + Add (nodeView); + ShowAll (); + } + + public event Wrapper.WidgetEventHandler WidgetActivated { + add { nodeView.WidgetActivated += value; } + remove { nodeView.WidgetActivated -= value; } + } + + public void Bind (WidgetEditSession newSession) + { + nodeView.Bind (newSession); + } + } + + internal class ProjectViewBackendNodeView : TreeView + { + ProjectViewFrontend frontend; + TreeStore store; + WidgetEditSession editSession; + + const int ColIcon = 0; + const int ColName = 1; + const int ColWrapper = 2; + const int ColFilled = 3; + + public event Wrapper.WidgetEventHandler WidgetActivated; + + public ProjectViewBackendNodeView (ProjectViewFrontend frontend) + { + this.frontend = frontend; + HeadersVisible = false; + + store = new TreeStore (typeof(Gdk.Pixbuf), typeof(string), typeof(ObjectWrapper), typeof(bool)); + Model = store; + + TreeViewColumn col; + CellRenderer renderer; + + col = new TreeViewColumn (); + + renderer = new CellRendererPixbuf (); + col.PackStart (renderer, false); + col.AddAttribute (renderer, "pixbuf", 0); + + renderer = new CellRendererText (); + col.PackStart (renderer, true); + col.AddAttribute (renderer, "text", 1); + + AppendColumn (col); + + Selection.Mode = SelectionMode.Single; + Selection.Changed += RowSelected; + TestExpandRow += OnTestExpandRow; + ShowAll (); + } + + public void Bind (WidgetEditSession newSession) + { + if (editSession != null) { + editSession.SelectionChanged -= WidgetSelected; + editSession.EditingBackend.ProjectReloaded -= OnProjectReloaded; + editSession.EditingBackend.WidgetNameChanged -= OnWidgetNameChanged; + editSession.EditingBackend.WidgetContentsChanged -= OnContentsChanged; + } + editSession = newSession; + if (editSession != null) { + editSession.SelectionChanged += WidgetSelected; + editSession.EditingBackend.ProjectReloaded += OnProjectReloaded; + editSession.EditingBackend.WidgetNameChanged += OnWidgetNameChanged; + editSession.EditingBackend.WidgetContentsChanged += OnContentsChanged; + } + LoadProject (); + } + + public override void Dispose () + { + if (editSession != null) { + editSession.SelectionChanged -= WidgetSelected; + editSession.EditingBackend.ProjectReloaded -= OnProjectReloaded; + editSession.EditingBackend.WidgetNameChanged -= OnWidgetNameChanged; + editSession.EditingBackend.WidgetContentsChanged -= OnContentsChanged; + } + base.Dispose (); + } + + public void LoadProject () + { + Clear (); + if (editSession == null || editSession.RootWidget == null) + return; + + AddNode (TreeIter.Zero, editSession.RootWidget.Wrapped); + } + + public void AddNode (TreeIter iter, Gtk.Widget widget) + { + Stetic.Wrapper.Widget wrapper = GetVisibleWrapper (widget); + if (wrapper == null) + return; + + Gdk.Pixbuf icon = wrapper.ClassDescriptor.Icon.ScaleSimple (16, 16, Gdk.InterpType.Bilinear); + string txt = widget.Name; + + if (!iter.Equals (TreeIter.Zero)) + iter = store.AppendValues (iter, icon, txt, wrapper, true); + else + iter = store.AppendValues (icon, txt, wrapper, true); + + FillChildren (iter, wrapper); + } + + void FillChildren (TreeIter it, Wrapper.Widget wrapper) + { + Stetic.Wrapper.Container container = wrapper as Wrapper.Container; + if (container != null) { + foreach (Gtk.Widget w in container.RealChildren) { + Stetic.Wrapper.Widget ww = GetVisibleWrapper (w); + if (ww != null) { + // Add a dummy node to allow lazy loading + store.SetValue (it, ColFilled, false); + store.AppendValues (it, null, "", null, false); + return; + } + } + } + store.SetValue (it, ColFilled, true); + } + + Wrapper.Widget GetVisibleWrapper (Gtk.Widget w) + { + Stetic.Wrapper.Widget wrapper = Stetic.Wrapper.Widget.Lookup (w); + if (wrapper == null || wrapper.Unselectable) + return null; + else + return wrapper; + } + + void EnsureFilled (TreeIter it) + { + bool filled = (bool) store.GetValue (it, ColFilled); + if (filled) + return; + + // Remove the dummy node + TreeIter cit; + store.IterChildren (out cit, it); + store.Remove (ref cit); + + // Add the real children + Stetic.Wrapper.Container container = store.GetValue (it, ColWrapper) as Wrapper.Container; + if (container != null) { + foreach (Gtk.Widget w in container.RealChildren) + AddNode (it, w); + } + + store.SetValue (it, ColFilled, true); + } + + void OnTestExpandRow (object s, Gtk.TestExpandRowArgs args) + { + EnsureFilled (args.Iter); + args.RetVal = false; + } + + public void Clear () + { + TreeIter it; + while (store.GetIterFirst (out it)) { + store.Remove (ref it); + } + } + + void RefreshNode (TreeIter it) + { + Wrapper.Widget wrapper = (Wrapper.Widget) store.GetValue (it, ColWrapper); + store.SetValue (it, ColName, wrapper.Wrapped.Name); + TreeIter cit; + while (store.IterChildren (out cit, it)) { + store.Remove (ref cit); + } + FillChildren (it, wrapper); + } + + void OnWidgetNameChanged (object s, Wrapper.WidgetNameChangedArgs args) + { + TreeIter? node = FindNode (args.WidgetWrapper, false); + if (node == null) + return; + store.SetValue (node.Value, ColName, args.NewName); + } + + void OnContentsChanged (object s, Wrapper.WidgetEventArgs args) + { + TreeIter? node = FindNode (args.WidgetWrapper, false); + if (node != null) + RefreshNode (node.Value); + } + + void OnProjectReloaded (object o, EventArgs a) + { + LoadProject (); + } + + Stetic.Wrapper.Widget SelectedWrapper { + get { + TreeIter iter; + if (!Selection.GetSelected (out iter)) + return null; + Wrapper.Widget w = (Wrapper.Widget) store.GetValue (iter, ColWrapper); + return w; + } + } + + bool syncing = false; + + void RowSelected (object obj, EventArgs args) + { + if (!syncing) { + syncing = true; + Stetic.Wrapper.Widget selection = SelectedWrapper; + if (selection != null) + selection.Select (); + syncing = false; + NotifySelectionChanged (selection); + } + } + + void WidgetSelected (object s, Wrapper.WidgetEventArgs args) + { + if (!syncing) { + syncing = true; + if (args.Widget != null) { + Wrapper.Widget w = Wrapper.Widget.Lookup (args.Widget); + if (w != null) { + TreeIter? it = FindNode (w, true); + if (it != null) { + ExpandToPath (store.GetPath (it.Value)); + Selection.SelectIter (it.Value); + ScrollToCell (store.GetPath (it.Value), Columns[0], false, 0, 0); + NotifySelectionChanged (w); + } + } + } + else { + Selection.UnselectAll (); + NotifySelectionChanged (null); + } + syncing = false; + } + } + + TreeIter? FindNode (Wrapper.Widget w, bool loadBranches) + { + Wrapper.Widget parent = w.ParentWrapper; + TreeIter it; + + if (parent == null) { + if (!store.GetIterFirst (out it)) + return null; + } else { + TreeIter? pi = FindNode (parent, loadBranches); + if (pi == null) + return null; + if (loadBranches) + EnsureFilled (pi.Value); + if (!store.IterChildren (out it, pi.Value)) + return null; + } + + do { + Wrapper.Widget cw = (Wrapper.Widget) store.GetValue (it, ColWrapper); + if (cw == w) + return it; + } while (store.IterNext (ref it)); + + return null; + } + + void NotifySelectionChanged (Stetic.Wrapper.Widget w) + { + if (frontend == null) + return; + if (w != null) + frontend.NotifySelectionChanged (Component.GetSafeReference (w), w.Wrapped.Name, w.ClassDescriptor.Name); + else + frontend.NotifySelectionChanged (null, null, null); + } + + protected override bool OnButtonPressEvent (Gdk.EventButton evt) + { + if (evt.Button == 3 && evt.Type == Gdk.EventType.ButtonPress) + return OnPopupMenu (); + return base.OnButtonPressEvent (evt); + } + + protected override bool OnPopupMenu () + { + Stetic.Wrapper.Widget selection = SelectedWrapper; + + if (selection != null) { + Menu m = new ContextMenu (selection); + if (selection.IsTopLevel) { + // Allow deleting top levels from the project view + ImageMenuItem item = new ImageMenuItem (Gtk.Stock.Delete, null); + item.Activated += delegate (object obj, EventArgs args) { + selection.Delete (); + }; + item.Show (); + m.Add (item); + } + m.Popup (); + return true; + } else + return base.OnPopupMenu (); + } + + protected override void OnRowActivated (TreePath path, TreeViewColumn col) + { + base.OnRowActivated (path, col); + Stetic.Wrapper.Widget w = SelectedWrapper; + if (w != null) { + if (frontend != null) + frontend.NotifyWidgetActivated (Component.GetSafeReference (w), w.Wrapped.Name, w.ClassDescriptor.Name); + if (WidgetActivated != null) + WidgetActivated (this, new Wrapper.WidgetEventArgs (w)); + } + } + } +} diff --git a/main/src/addins/MonoDevelop.GtkCore2/libsteticui/PropertyEditor.cs b/main/src/addins/MonoDevelop.GtkCore2/libsteticui/PropertyEditor.cs new file mode 100644 index 0000000000..27656da718 --- /dev/null +++ b/main/src/addins/MonoDevelop.GtkCore2/libsteticui/PropertyEditor.cs @@ -0,0 +1,64 @@ +using Gtk; +using System; +using System.Collections; +using System.Reflection; + +namespace Stetic { + + class PropertyEditor : VBox + { + IPropertyEditor propEditor; + EditSession session; + + public PropertyEditor (PropertyDescriptor prop) : base (false, 0) + { + propEditor = CreateEditor (prop); + Add ((Gtk.Widget) propEditor); + } + + public void AttachObject (object ob) + { + if (session != null) + session.AttachObject (ob); + } + + public IPropertyEditor CreateEditor (PropertyDescriptor prop) + { + PropertyEditorCell cell = PropertyEditorCell.GetPropertyCell (prop); + cell.Initialize (this, prop, null); + + session = cell.StartEditing (new Gdk.Rectangle (), StateType.Normal); + if (session == null) + return new DummyEditor (); + + Gtk.Widget w = (Gtk.Widget) session.Editor as Gtk.Widget; + w.ShowAll (); + return session.Editor; + } + + public void Update () + { + if (session != null) + session.UpdateEditor (); + } + } + + class DummyEditor: Gtk.Label, IPropertyEditor + { + public void Initialize (PropertyDescriptor prop) + { + Text = "(" + prop.PropertyType.Name + ")"; + } + + public void AttachObject (object obj) + { + } + + public object Value { + get { return null; } + set { } + } + + public event EventHandler ValueChanged { add {} remove {} } + } +} diff --git a/main/src/addins/MonoDevelop.GtkCore2/libsteticui/PropertyGrid.cs b/main/src/addins/MonoDevelop.GtkCore2/libsteticui/PropertyGrid.cs new file mode 100644 index 0000000000..fe8ca717bd --- /dev/null +++ b/main/src/addins/MonoDevelop.GtkCore2/libsteticui/PropertyGrid.cs @@ -0,0 +1,275 @@ +using Gtk; +using GLib; +using System; +using System.Collections; +using System.Reflection; + +namespace Stetic { + + internal class PropertyGrid : Gtk.VBox { + + Hashtable cachedGroups = new Hashtable (); + + Stetic.Wrapper.Widget selection; + Stetic.Wrapper.Widget newSelection; + Stetic.Wrapper.Container.ContainerChild packingSelection; + + PropertyGridHeader header; + Gtk.Widget noSelection; + + ProjectBackend project; + + public PropertyGrid () + { + header = new PropertyGridHeader (); + header.Show (); + PackStart (header, false, false, 0); + + Label lab = new Label (); + lab.Markup = "<i>No selection</i>"; + PackStart (lab, false, false, 0); + noSelection = lab; + + Stetic.Registry.RegistryChanging += new EventHandler (OnRegistryChanging); + } + + public PropertyGrid (ProjectBackend project): this () + { + this.ProjectBackend = 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 ProjectBackend ProjectBackend { + get { return project; } + set { + if (project != null) + project.SelectionChanged -= Selected; + + project = value; + project.SelectionChanged += Selected; + Selected (null, null); + } + } + + void Clear () + { + if (selection != null) { + selection.Notify -= Notified; + selection = null; + } + foreach (Gtk.Widget w in Children) + w.Hide (); + } + + void Notified (object wrapper, string propertyName) + { + foreach (object ob in Children) { + PropertyGridGroup grid = ob as PropertyGridGroup; + if (grid != null) + grid.Notified (propertyName); + } + } + + void Selected (object s, Wrapper.WidgetEventArgs args) + { + newSelection = args != null ? args.WidgetWrapper : null; + GLib.Timeout.Add (50, new GLib.TimeoutHandler (SelectedHandler)); + } + + bool SelectedHandler () + { + ClassDescriptor klass; + + Clear (); + + selection = newSelection; + + if (selection == null || selection.Wrapped is ErrorWidget) { + noSelection.Show (); + return false; + } + + header.Show (); + + selection.Notify += Notified; + + klass = selection.ClassDescriptor; + + header.AttachObject (selection.Wrapped); + AppendItemGroups (klass, selection.Wrapped); + + packingSelection = Stetic.Wrapper.Container.ChildWrapper (selection); + if (packingSelection != null) { + klass = packingSelection.ClassDescriptor; + if (klass.ItemGroups.Count > 0) { + AppendItemGroups (klass, packingSelection.Wrapped); + packingSelection.Notify += Notified; + } + } + return false; + } + + void AppendItemGroups (ClassDescriptor klass, object obj) + { + int n = 1; + foreach (ItemGroup igroup in klass.ItemGroups) { + PropertyGridGroup grid = (PropertyGridGroup) cachedGroups [igroup]; + if (grid == null) { + grid = new PropertyGridGroup (); + grid.AddGroup (igroup); + cachedGroups [igroup] = grid; + PackStart (grid, false, false, 0); + } + ReorderChild (grid, n++); + grid.ShowAll (); + grid.AttachObject (obj); + } + } + } + + class PropertyGridGroup: Stetic.Grid + { + Hashtable editors; + Hashtable sensitives, invisibles; + object obj; + + public PropertyGridGroup () + { + editors = new Hashtable (); + sensitives = new Hashtable (); + invisibles = new Hashtable (); + } + + public void AddGroup (ItemGroup igroup) + { + AppendGroup (igroup.Label, true); + foreach (ItemDescriptor item in igroup) { + if (item.IsInternal) + continue; + if (item is PropertyDescriptor) + AppendProperty ((PropertyDescriptor)item); + else if (item is CommandDescriptor) + AppendCommand ((CommandDescriptor)item); + } + } + + public virtual void AttachObject (object ob) + { + this.obj = ob; + + foreach (object ed in editors.Values) { + PropertyEditor pe = ed as PropertyEditor; + if (pe != null) + pe.AttachObject (ob); + } + UpdateSensitivity (); + } + + protected void AppendProperty (PropertyDescriptor prop) + { + PropertyEditor rep = new PropertyEditor (prop); + + // FIXME: Make sure all notify events are based on prop names, not propspec + editors[prop.Name] = rep; + + AppendPair (prop.Label, rep, prop.Description); + rep.ShowAll (); + + if (prop.HasDependencies) + sensitives[prop] = prop; + if (prop.HasVisibility) + invisibles[prop] = prop; + } + + void AppendCommand (CommandDescriptor cmd) + { + Gtk.Button button = new Gtk.Button (cmd.Label); + button.Clicked += delegate (object o, EventArgs args) { + cmd.Run (this.obj); + }; + button.Show (); + Append (button, cmd.Description); + + if (cmd.HasDependencies) { + editors[cmd.Name] = button; + sensitives[cmd] = cmd; + } + if (cmd.HasVisibility) { + editors[cmd.Name] = button; + invisibles[cmd] = cmd; + } + } + + void UpdateSensitivity () + { + foreach (ItemDescriptor item in sensitives.Keys) { + Widget w = editors[item.Name] as Widget; + if (w != null) { + object ob = sensitives.Contains (item) ? obj : null; + w.Sensitive = item.EnabledFor (ob); + } + } + foreach (ItemDescriptor item in invisibles.Keys) { + Widget w = editors[item.Name] as Widget; + if (w != null) { + object ob = invisibles.Contains (item) ? obj : null; + if (!item.VisibleFor (ob)) + w.Hide (); + else + w.Show (); + } + } + } + + public void Notified (string propertyName) + { + PropertyEditor ed = editors [propertyName] as PropertyEditor; + if (ed != null) + ed.Update (); + UpdateSensitivity (); + } + } + + class PropertyGridHeader: PropertyGridGroup + { + PropertyDescriptor name; + Gtk.Image image; + Gtk.Label label; + + public PropertyGridHeader () + { + name = (PropertyDescriptor)Registry.LookupClassByName ("Gtk.Widget") ["Name"]; + AppendProperty (name); + + Gtk.HBox box = new Gtk.HBox (false, 6); + image = new Gtk.Image (); + box.PackStart (image, false, false, 0); + label = new Gtk.Label (); + box.PackStart (label, false, false, 0); + box.ShowAll (); + AppendPair ("Widget Class", box, null); + } + + public override void AttachObject (object ob) + { + base.AttachObject (ob); + Gtk.Widget w = (Gtk.Widget) ob; + ObjectWrapper wrapper = ObjectWrapper.Lookup (w); + image.Pixbuf = wrapper.ClassDescriptor.Icon; + label.Text = wrapper.WrappedTypeName; + } + } +} diff --git a/main/src/addins/MonoDevelop.GtkCore2/libsteticui/PropertyTree.cs b/main/src/addins/MonoDevelop.GtkCore2/libsteticui/PropertyTree.cs new file mode 100644 index 0000000000..c846444392 --- /dev/null +++ b/main/src/addins/MonoDevelop.GtkCore2/libsteticui/PropertyTree.cs @@ -0,0 +1,565 @@ + +using System; +using System.Collections; +using Gtk; +using Gdk; +using Mono.Unix; + +namespace Stetic +{ + public class PropertyTree: Gtk.ScrolledWindow + { + Gtk.TreeStore store; + InternalTree tree; + TreeViewColumn editorColumn; + Hashtable propertyRows; + Hashtable sensitives, invisibles; + ArrayList expandStatus = new ArrayList (); + + public PropertyTree () + { + propertyRows = new Hashtable (); + sensitives = new Hashtable (); + invisibles = new Hashtable (); + + store = new TreeStore (typeof (string), typeof(PropertyDescriptor), typeof(bool), typeof(InstanceData)); + + tree = new InternalTree (this, store); + + CellRendererText crt; + + TreeViewColumn col; + + col = new TreeViewColumn (); + col.Title = Catalog.GetString ("Property"); + crt = new CellRendererPropertyGroup (tree); + col.PackStart (crt, true); + col.SetCellDataFunc (crt, new TreeCellDataFunc (GroupData)); + col.Resizable = true; + col.Expand = false; + col.Sizing = TreeViewColumnSizing.Fixed; + col.FixedWidth = 150; + tree.AppendColumn (col); + + editorColumn = new TreeViewColumn (); + editorColumn.Title = Catalog.GetString ("Value"); + + CellRendererProperty crp = new CellRendererProperty (tree); + + editorColumn.PackStart (crp, true); + editorColumn.SetCellDataFunc (crp, new TreeCellDataFunc (PropertyData)); + editorColumn.Sizing = TreeViewColumnSizing.Fixed; + editorColumn.Resizable = false; + editorColumn.Expand = true; + tree.AppendColumn (editorColumn); + + tree.HeadersVisible = false; + this.ShadowType = Gtk.ShadowType.In; + this.HscrollbarPolicy = Gtk.PolicyType.Never; + + Add (tree); + ShowAll (); + + tree.Selection.Changed += OnSelectionChanged; + } + + public void AddProperties (ItemGroupCollection itemGroups, object instance, string targetGtkVersion) + { + foreach (ItemGroup igroup in itemGroups) + AddGroup (igroup, instance, targetGtkVersion); + } + + public void SaveStatus () + { + expandStatus.Clear (); + + TreeIter iter; + if (!tree.Model.GetIterFirst (out iter)) + return; + + do { + if (tree.GetRowExpanded (tree.Model.GetPath (iter))) { + expandStatus.Add (tree.Model.GetValue (iter, 0)); + } + } while (tree.Model.IterNext (ref iter)); + } + + public void RestoreStatus () + { + TreeIter iter; + if (!tree.Model.GetIterFirst (out iter)) + return; + + // If the tree only has one group, show it always expanded + TreeIter iter2 = iter; + if (!tree.Model.IterNext (ref iter2)) { + tree.ExpandRow (tree.Model.GetPath (iter), true); + return; + } + + do { + object grp = tree.Model.GetValue (iter, 0); + if (expandStatus.Contains (grp)) + tree.ExpandRow (tree.Model.GetPath (iter), true); + } while (tree.Model.IterNext (ref iter)); + } + + public virtual void Clear () + { + store.Clear (); + propertyRows.Clear (); + sensitives.Clear (); + invisibles.Clear (); + } + + public virtual void Update () + { + // Just repaint the cells + QueueDraw (); + } + + public void AddGroup (ItemGroup igroup, object instance, string targetGtkVersion) + { + ArrayList props = new ArrayList (); + foreach (ItemDescriptor item in igroup) { + if (item.IsInternal) + continue; + if (item is PropertyDescriptor && item.SupportsGtkVersion (targetGtkVersion)) + props.Add (item); + } + + if (props.Count == 0) + return; + + InstanceData idata = new InstanceData (instance); + TreeIter iter = store.AppendValues (igroup.Label, null, true, idata); + foreach (PropertyDescriptor item in props) + AppendProperty (iter, (PropertyDescriptor)item, idata); + } + + protected void AppendProperty (PropertyDescriptor prop, object instance) + { + AppendProperty (TreeIter.Zero, prop, new InstanceData (instance)); + } + + protected void AppendProperty (TreeIter piter, PropertyDescriptor prop, object instance) + { + AppendProperty (piter, prop, new InstanceData (instance)); + } + + void AppendProperty (TreeIter piter, PropertyDescriptor prop, InstanceData idata) + { + TreeIter iter; + if (piter.Equals (TreeIter.Zero)) + iter = store.AppendValues (prop.Label, prop, false, idata); + else + iter = store.AppendValues (piter, prop.Label, prop, false, idata); + if (prop.HasDependencies) + sensitives[prop] = prop; + if (prop.HasVisibility) + invisibles[prop] = prop; + propertyRows [prop] = store.GetStringFromIter (iter); + } + + protected virtual void OnObjectChanged () + { + } + + void OnSelectionChanged (object s, EventArgs a) + { + TreePath[] rows = tree.Selection.GetSelectedRows (); + if (!tree.dragging && rows != null && rows.Length > 0) { + tree.SetCursor (rows[0], editorColumn, true); + } + } + + internal void NotifyChanged () + { + OnObjectChanged (); + } + + void PropertyData (Gtk.TreeViewColumn tree_column, Gtk.CellRenderer cell, Gtk.TreeModel model, Gtk.TreeIter iter) + { + CellRendererProperty rc = (CellRendererProperty) cell; + bool group = (bool) model.GetValue (iter, 2); + if (group) { + rc.SetData (null, null, null); + } else { + PropertyDescriptor prop = (PropertyDescriptor) model.GetValue (iter, 1); + PropertyEditorCell propCell = PropertyEditorCell.GetPropertyCell (prop); + InstanceData idata = (InstanceData) model.GetValue (iter, 3); + propCell.Initialize (tree, prop, idata.Instance); + rc.SetData (idata.Instance, prop, propCell); + } + } + + void GroupData (Gtk.TreeViewColumn tree_column, Gtk.CellRenderer cell, Gtk.TreeModel model, Gtk.TreeIter iter) + { + CellRendererPropertyGroup rc = (CellRendererPropertyGroup) cell; + rc.IsGroup = (bool) model.GetValue (iter, 2); + rc.Text = (string) model.GetValue (iter, 0); + + PropertyDescriptor prop = (PropertyDescriptor) model.GetValue (iter, 1); + if (prop != null) { + InstanceData idata = (InstanceData) model.GetValue (iter, 3); + rc.SensitiveProperty = prop.EnabledFor (idata.Instance) && prop.VisibleFor (idata.Instance); + } else + rc.SensitiveProperty = true; + } + } + + class InternalTree: TreeView + { + internal ArrayList Groups = new ArrayList (); + Pango.Layout layout; + bool editing; + PropertyTree tree; + internal bool dragging; + int dragPos; + Gdk.Cursor resizeCursor = new Gdk.Cursor (CursorType.SbHDoubleArrow); + + public InternalTree (PropertyTree tree, TreeModel model): base (model) + { + this.tree = tree; + layout = new Pango.Layout (this.PangoContext); + layout.Wrap = Pango.WrapMode.Char; + Pango.FontDescription des = this.Style.FontDescription.Copy(); + layout.FontDescription = des; + } + + public bool Editing { + get { return editing; } + set { editing = value; Update (); tree.NotifyChanged (); } + } + + protected override bool OnExposeEvent (Gdk.EventExpose e) + { + Groups.Clear (); + + bool res = base.OnExposeEvent (e); + + foreach (TreeGroup grp in Groups) { + layout.SetMarkup ("<b>" + GLib.Markup.EscapeText (grp.Group) + "</b>"); + e.Window.DrawLayout (this.Style.TextGC (grp.State), grp.X, grp.Y, layout); + } + + return res; + } + + protected override bool OnMotionNotifyEvent (EventMotion evnt) + { + if (dragging) { + int nw = (int)(evnt.X) + dragPos; + if (nw <= 40) nw = 40; + GLib.Idle.Add (delegate { + Columns[0].FixedWidth = nw; + return false; + }); + } else { + int w = Columns[0].Width; + if (Math.Abs (w - evnt.X) < 5) + this.GdkWindow.Cursor = resizeCursor; + else + this.GdkWindow.Cursor = null; + } + return base.OnMotionNotifyEvent (evnt); + } + + protected override bool OnButtonPressEvent (EventButton evnt) + { + int w = Columns[0].Width; + if (Math.Abs (w - evnt.X) < 5) { + TreePath[] rows = Selection.GetSelectedRows (); + if (rows != null && rows.Length > 0) + SetCursor (rows[0], Columns[0], false); + dragging = true; + dragPos = w - (int) evnt.X; + this.GdkWindow.Cursor = resizeCursor; + } + return base.OnButtonPressEvent (evnt); + } + + protected override bool OnButtonReleaseEvent (EventButton evnt) + { + if (dragging) { + this.GdkWindow.Cursor = null; + dragging = false; + } + return base.OnButtonReleaseEvent (evnt); + } + + public virtual void Update () + { + } + + protected override void OnDestroyed () + { + base.OnDestroyed (); + if (resizeCursor != null) { + resizeCursor.Dispose (); + resizeCursor = null; + } + } + + } + + class TreeGroup + { + public string Group; + public int X; + public int Y; + public StateType State; + } + + class CellRendererProperty: CellRenderer + { + PropertyDescriptor property; + object instance; + int rowHeight; + PropertyEditorCell editorCell; + bool sensitive; + bool visible; + TreeView tree; + + public CellRendererProperty (TreeView tree) + { + this.tree = tree; + Xalign = 0; + Xpad = 3; + + Mode |= Gtk.CellRendererMode.Editable; + Entry dummyEntry = new Gtk.Entry (); + dummyEntry.HasFrame = false; + rowHeight = dummyEntry.SizeRequest ().Height; + } + + public void SetData (object instance, PropertyDescriptor property, PropertyEditorCell editor) + { + this.instance = instance; + this.property = property; + if (property == null) + this.CellBackgroundGdk = tree.Style.MidColors [(int)Gtk.StateType.Normal]; + else + this.CellBackground = null; + + visible = property != null ? property.VisibleFor (instance): true; + sensitive = property != null ? property.EnabledFor (instance) && property.VisibleFor (instance): true; + editorCell = editor; + } + + public override void GetSize (Widget widget, ref Rectangle cell_area, out int x_offset, out int y_offset, out int width, out int height) + { + if (editorCell != null) + editorCell.GetSize ((int)(cell_area.Width - this.Xpad * 2), out width, out height); + else { + width = height = 0; + } + + width += (int) this.Xpad * 2; + height += (int) this.Ypad * 2; + + x_offset = 0; + y_offset = 0; + + if (height < rowHeight) + height = rowHeight; + } + + protected override void Render (Drawable window, Widget widget, Rectangle background_area, Rectangle cell_area, Rectangle expose_area, CellRendererState flags) + { + if (instance == null || !visible) + return; + int width = 0, height = 0; + int iwidth = cell_area.Width - (int) this.Xpad * 2; + + if (editorCell != null) + editorCell.GetSize ((int)(cell_area.Width - this.Xpad * 2), out width, out height); + + Rectangle bounds = new Rectangle (); + bounds.Width = width > iwidth ? iwidth : width; + bounds.Height = height; + bounds.X = (int) (cell_area.X + this.Xpad); + bounds.Y = cell_area.Y + (cell_area.Height - height) / 2; + + StateType state = GetState (flags); + + if (editorCell != null) + editorCell.Render (window, bounds, state); + } + + public override CellEditable StartEditing (Gdk.Event ev, Widget widget, string path, Gdk.Rectangle background_area, Gdk.Rectangle cell_area, CellRendererState flags) + { + if (property == null || editorCell == null || !sensitive) + return null; + + StateType state = GetState (flags); + EditSession session = editorCell.StartEditing (cell_area, state); + if (session == null) + return null; + Gtk.Widget propEditor = (Gtk.Widget) session.Editor; + propEditor.Show (); + HackEntry e = new HackEntry (propEditor, session); + e.Show (); + return e; + } + + StateType GetState (CellRendererState flags) + { + if (!sensitive) + return StateType.Insensitive; + else if ((flags & CellRendererState.Selected) != 0) + return StateType.Selected; + else + return StateType.Normal; + } + } + + class CellRendererPropertyGroup: CellRendererText + { + TreeView tree; + Pango.Layout layout; + bool isGroup; + bool sensitive; + + public bool IsGroup { + get { return isGroup; } + set { + isGroup = value; + if (value) + this.CellBackgroundGdk = tree.Style.MidColors [(int)Gtk.StateType.Normal]; + else + this.CellBackground = null; + } + } + + public bool SensitiveProperty { + get { return sensitive; } + set { sensitive = value; } + } + + public CellRendererPropertyGroup (TreeView tree) + { + this.tree = tree; + layout = new Pango.Layout (tree.PangoContext); + layout.Wrap = Pango.WrapMode.Char; + + Pango.FontDescription des = tree.Style.FontDescription.Copy(); + layout.FontDescription = des; + } + + protected void GetCellSize (Widget widget, int availableWidth, out int width, out int height) + { + layout.SetMarkup (Text); + layout.Width = -1; + layout.GetPixelSize (out width, out height); + } + + public override void GetSize (Widget widget, ref Rectangle cell_area, out int x_offset, out int y_offset, out int width, out int height) + { + GetCellSize (widget, (int)(cell_area.Width - this.Xpad * 2), out width, out height); + width += (int) this.Xpad * 2; + height += (int) this.Ypad * 2; + + x_offset = y_offset = 0; + + if (IsGroup) + width = 0; + } + + protected override void Render (Drawable window, Widget widget, Rectangle background_area, Rectangle cell_area, Rectangle expose_area, CellRendererState flags) + { + int width, height; + GetCellSize (widget, (int)(cell_area.Width - this.Xpad * 2), out width, out height); + + int x = (int) (cell_area.X + this.Xpad); + int y = cell_area.Y + (cell_area.Height - height) / 2; + + StateType state; + if (!sensitive) + state = StateType.Insensitive; + else if ((flags & CellRendererState.Selected) != 0) + state = StateType.Selected; + else + state = StateType.Normal; + + if (IsGroup) { + TreeGroup grp = new TreeGroup (); + grp.X = x; + grp.Y = y; + grp.Group = Text; + grp.State = state; + InternalTree tree = (InternalTree) widget; + tree.Groups.Add (grp); + } else { + window.DrawLayout (widget.Style.TextGC (state), x, y, layout); + int bx = background_area.X + background_area.Width - 1; + Gdk.GC gc = new Gdk.GC (window); + gc.RgbFgColor = tree.Style.MidColors [(int)Gtk.StateType.Normal]; + window.DrawLine (gc, bx, background_area.Y, bx, background_area.Y + background_area.Height); + } + } + } + + class HackEntry: Entry + { + EventBox box; + EditSession session; + + public HackEntry (Gtk.Widget child, EditSession session) + { + this.session = session; + box = new EventBox (); + box.ButtonPressEvent += new ButtonPressEventHandler (OnClickBox); + box.ModifyBg (StateType.Normal, Style.White); + box.Add (child); + } + + [GLib.ConnectBefore] + void OnClickBox (object s, ButtonPressEventArgs args) + { + // Avoid forwarding the button press event to the + // tree, since it would hide the cell editor. + args.RetVal = true; + } + + protected override void OnParentSet (Gtk.Widget parent) + { + base.OnParentSet (parent); + + if (Parent != null) { + if (this.ParentWindow != null) + box.ParentWindow = this.ParentWindow; + box.Parent = Parent; + box.Show (); + ((InternalTree)Parent).Editing = true; + } + else { + session.Dispose (); + ((InternalTree)parent).Editing = false; + box.Unparent (); + } + } + + protected override void OnShown () + { + // Do nothing. + } + + protected override void OnSizeAllocated (Gdk.Rectangle allocation) + { + base.OnSizeAllocated (allocation); + box.SizeRequest (); + box.Allocation = allocation; + } + } + + class InstanceData + { + public InstanceData (object instance) + { + Instance = instance; + } + + public object Instance; + } +} diff --git a/main/src/addins/MonoDevelop.GtkCore2/libsteticui/Shadow.cs b/main/src/addins/MonoDevelop.GtkCore2/libsteticui/Shadow.cs new file mode 100644 index 0000000000..45d2a62357 --- /dev/null +++ b/main/src/addins/MonoDevelop.GtkCore2/libsteticui/Shadow.cs @@ -0,0 +1,116 @@ +/* Shadow code from anders */ + +using System; +using Gdk; + +class ConvFilter +{ + public int size; + public double[] data; +} + +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); + } +} diff --git a/main/src/addins/MonoDevelop.GtkCore2/libsteticui/SignalsEditor.cs b/main/src/addins/MonoDevelop.GtkCore2/libsteticui/SignalsEditor.cs new file mode 100644 index 0000000000..d5aa7dd7c7 --- /dev/null +++ b/main/src/addins/MonoDevelop.GtkCore2/libsteticui/SignalsEditor.cs @@ -0,0 +1,90 @@ + +using System; + +namespace Stetic +{ + public class SignalsEditor: PluggableWidget + { + SignalsEditorFrontend frontend; + SignalsEditorEditSession session; + + public event EventHandler SignalActivated; + + internal SignalsEditor (Application app): base (app) + { + frontend = new SignalsEditorFrontend (this); + } + + public Signal SelectedSignal { + get { + if (session != null) + return session.SelectedSignal; + else + return null; + } + } + + protected override void OnCreatePlug (uint socketId) + { + session = app.Backend.CreateSignalsWidgetPlug (frontend, socketId); + } + + protected override void OnDestroyPlug (uint socketId) + { + app.Backend.DestroySignalsWidgetPlug (); + } + + protected override Gtk.Widget OnCreateWidget () + { + session = app.Backend.GetSignalsWidget (frontend); + return session.Editor; + } + + bool disposed = false; + + public override void Dispose () + { + if (disposed) + return; + disposed = true; + + if (session != null) + session.Dispose (); + frontend.disposed = true; + System.Runtime.Remoting.RemotingServices.Disconnect (frontend); + base.Dispose (); + } + + internal void NotifySignalActivated () + { + if (SignalActivated != null) + SignalActivated (this, EventArgs.Empty); + } + } + + internal class SignalsEditorFrontend: MarshalByRefObject + { + SignalsEditor editor; + internal bool disposed; + + public SignalsEditorFrontend (SignalsEditor editor) + { + this.editor = editor; + } + + public void NotifySignalActivated () + { + Gtk.Application.Invoke ( + delegate { + if (!disposed) editor.NotifySignalActivated (); + } + ); + } + + public override object InitializeLifetimeService () + { + // Will be disconnected when calling Dispose + return null; + } + } +} diff --git a/main/src/addins/MonoDevelop.GtkCore2/libsteticui/SignalsEditorBackend.cs b/main/src/addins/MonoDevelop.GtkCore2/libsteticui/SignalsEditorBackend.cs new file mode 100644 index 0000000000..d675804793 --- /dev/null +++ b/main/src/addins/MonoDevelop.GtkCore2/libsteticui/SignalsEditorBackend.cs @@ -0,0 +1,481 @@ +using System; +using System.Text; +using System.Collections; +using Stetic.Wrapper; +using Mono.Unix; + +namespace Stetic +{ + internal class SignalsEditorBackend: Gtk.ScrolledWindow, IObjectViewer + { + Gtk.TreeView tree; + Gtk.TreeStore store; + SignalsEditorFrontend frontend; + + ProjectBackend project; + ObjectWrapper selection; + bool internalChange; + + const int ColSignal = 0; + const int ColHandler = 1; + const int ColAfter = 2; + const int ColHasHandler = 3; + const int ColIsSignal = 4; + const int ColSignalTextWeight = 5; + + public SignalsEditorBackend (SignalsEditorFrontend frontend) + { + this.frontend = frontend; + + tree = new Gtk.TreeView (); + store = new Gtk.TreeStore (typeof(string), typeof(string), typeof(bool), typeof(bool), typeof(bool), typeof(int)); + tree.Model = store; + tree.RowActivated += new Gtk.RowActivatedHandler (OnRowActivated); + + Gtk.CellRendererText crtSignal = new Gtk.CellRendererText (); + + Gtk.CellRendererText crtHandler = new Gtk.CellRendererText (); + crtHandler.Editable = true; + crtHandler.Edited += new Gtk.EditedHandler (OnHandlerEdited); + + Gtk.CellRendererToggle crtogAfter = new Gtk.CellRendererToggle (); + crtogAfter.Activatable = true; + crtogAfter.Toggled += new Gtk.ToggledHandler (OnAfterToggled); + + tree.AppendColumn (Catalog.GetString ("Signal"), crtSignal, "text", ColSignal, "weight", ColSignalTextWeight); + tree.AppendColumn (Catalog.GetString ("Handler"), crtHandler, "markup", ColHandler, "visible", ColIsSignal); + tree.AppendColumn (Catalog.GetString ("After"), crtogAfter, "active", ColAfter, "visible", ColHasHandler); + tree.Columns[0].Resizable = true; + tree.Columns[1].Resizable = true; + tree.Columns[2].Resizable = true; + Add (tree); + ShowAll (); + } + + public SignalsEditorBackend (SignalsEditorFrontend frontend, ProjectBackend project): this (frontend) + { + ProjectBackend = project; + } + + public ProjectBackend ProjectBackend { + get { return project; } + set { + if (project != null) { + project.SelectionChanged -= OnWidgetSelected; + project.SignalAdded -= new SignalEventHandler (OnSignalAddedOrRemoved); + project.SignalRemoved -= new SignalEventHandler (OnSignalAddedOrRemoved); + project.SignalChanged -= new SignalChangedEventHandler (OnSignalChanged); + project.ProjectReloaded -= new EventHandler (OnProjectReloaded); + } + + project = value; + if (project != null) { + TargetObject = project.Selection; + project.SelectionChanged += OnWidgetSelected; + project.SignalAdded += new SignalEventHandler (OnSignalAddedOrRemoved); + project.SignalRemoved += new SignalEventHandler (OnSignalAddedOrRemoved); + project.SignalChanged += new SignalChangedEventHandler (OnSignalChanged); + project.ProjectReloaded += new EventHandler (OnProjectReloaded); + } else if (selection != null) { + selection = null; + RefreshTree (); + } + } + } + + 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); + } + } + + public object TargetObject { + get { + return selection != null ? selection.Wrapped : null; + } + set { + if (project != null) { + ObjectWrapper wrapper = ObjectWrapper.Lookup (value); + if (wrapper == selection) + return; + selection = wrapper; + RefreshTree (); + } + } + } + + void OnWidgetSelected (object s, Wrapper.WidgetEventArgs args) + { + ObjectWrapper wrapper = args != null ? args.WidgetWrapper : null; + if (wrapper == selection) + return; + selection = wrapper; + RefreshTree (); + } + + void OnSignalAddedOrRemoved (object sender, SignalEventArgs args) + { + if (!internalChange && args.Wrapper == selection) + RefreshTree (); + } + + void OnSignalChanged (object sender, SignalChangedEventArgs args) + { + if (!internalChange && args.Wrapper == selection) + RefreshTree (); + } + + void RefreshTree () + { + ArrayList status = SaveStatus (); + store.Clear (); + + if (selection == null) + return; + + ClassDescriptor klass = selection.ClassDescriptor; + + foreach (ItemGroup group in klass.SignalGroups) { + Gtk.TreeIter iter = store.AppendValues (group.Label, null, false, false, false, (int) Pango.Weight.Normal); + if (FillGroup (iter, group)) + store.SetValue (iter, ColSignalTextWeight, (int) Pango.Weight.Bold); + } + RestoreStatus (status); + } + + bool FillGroup (Gtk.TreeIter groupIter, ItemGroup group) + { + bool hasSignals = false; + foreach (SignalDescriptor sd in group) { + if (!sd.SupportsGtkVersion (project.TargetGtkVersion)) + continue; + + bool foundSignal = false; + Gtk.TreeIter parent = groupIter; + + foreach (Signal signal in selection.Signals) { + if (signal.SignalDescriptor != sd) continue; + + Gtk.TreeIter iter = store.AppendValues (parent, null, signal.Handler, false, true, true, (int) Pango.Weight.Normal); + if (!foundSignal) { + parent = iter; + store.SetValue (iter, ColSignal, sd.Name); + store.SetValue (iter, ColSignalTextWeight, (int) Pango.Weight.Bold); + hasSignals = foundSignal = true; + } + } + + InsertEmptySignalRow (parent, foundSignal ? null : sd.Name); + } + return hasSignals; + } + + void SetSignalData (Gtk.TreeIter iter, Signal signal) + { + store.SetValue (iter, ColHandler, signal.Handler); + store.SetValue (iter, ColAfter, false); + store.SetValue (iter, ColHasHandler, true); + store.SetValue (iter, ColIsSignal, true); + } + + void InsertEmptySignalRow (Gtk.TreeIter parent, string name) + { + store.AppendValues (parent, name, EmptyHandlerMarkup, false, false, true, (int) Pango.Weight.Normal); + } + + void OnRowActivated (object sender, Gtk.RowActivatedArgs args) + { + Gtk.TreeIter iter; + if (!store.GetIter (out iter, args.Path)) + return; + + SignalDescriptor sd = GetSignalDescriptor (iter); + if (sd != null) { + if (GetSignal (iter) == null) + AddHandler (iter, GetHandlerName (sd.Name)); + frontend.NotifySignalActivated (); + } + } + + string GetHandlerName (string signalName) + { + Wrapper.Widget selWidget = selection as Wrapper.Widget; + if (selWidget != null) { +// if (selWidget.IsTopLevel) +// return "On" + signalName; +// else +// return "On" + GetIdentifier (selWidget.Wrapped.Name) + signalName; + return string.Format ("{0}_{1}", + GetIdentifier (selWidget.Wrapped.Name), signalName); + } + + Wrapper.Action action = selection as Wrapper.Action; + if (action != null) { + return "On" + GetIdentifier (action.Name) + signalName; + } + + return "On" + signalName; + } + + string GetIdentifier (string name) + { + StringBuilder sb = new StringBuilder (); + + bool wstart = true; + foreach (char c in name) { + if (c == '_' || c == '-' || c == ' ' || !char.IsLetterOrDigit (c)) { + wstart = true; + continue; + } + if (wstart) { + sb.Append (char.ToUpper (c)); + wstart = false; + } else + sb.Append (c); + } + return sb.ToString (); + } + + void OnHandlerEdited (object sender, Gtk.EditedArgs args) + { + if (args.NewText == EmptyHandlerText) + return; + + Gtk.TreeIter iter; + if (!store.GetIterFromString (out iter, args.Path)) + return; + + AddHandler (iter, args.NewText); + } + + void AddHandler (Gtk.TreeIter iter, string name) + { + internalChange = true; + + Gtk.TreeIter piter = iter; + while (store.IterDepth (piter) != 0) + store.IterParent (out piter, piter); + + Signal signal = GetSignal (iter); + if (signal == null) { + if (name != "") { + SignalDescriptor sd = GetSignalDescriptor (iter); + signal = new Signal (sd); + signal.Handler = name; + selection.Signals.Add (signal); + SetSignalData (iter, signal); + store.SetValue (iter, ColSignalTextWeight, (int) Pango.Weight.Bold); + if (store.IterDepth (iter) != 1) + store.IterParent (out iter, iter); + InsertEmptySignalRow (iter, null); + } + } else { + if (name != "") { + signal.Handler = name; + store.SetValue (iter, ColHandler, signal.Handler); + } else { + selection.Signals.Remove (signal); + if (store.IterDepth (iter) == 1) { + if (store.IterNChildren (iter) == 1) { + Gtk.TreeIter parent; + store.IterParent (out parent, iter); + store.Remove (ref iter); + InsertEmptySignalRow (parent, signal.SignalDescriptor.Name); + } else { + Gtk.TreeIter citer; + store.IterChildren (out citer, iter); + Signal csignal = GetSignal (citer); + store.Remove (ref citer); + SetSignalData (iter, csignal); + if (store.IterNChildren (iter) == 1) + tree.CollapseRow (store.GetPath (iter)); + } + } else + store.Remove (ref iter); + } + } + UpdateGroupStatus (piter); + internalChange = false; + } + + void OnAfterToggled (object o, Gtk.ToggledArgs args) + { + Gtk.TreeIter it; + if (store.GetIterFromString (out it, args.Path)) { + Signal signal = GetSignal (it); + if (signal != null) { + internalChange = true; + signal.After = !signal.After; + internalChange = false; + store.SetValue (it, ColAfter, signal.After); + } + } + } + + void UpdateGroupStatus (Gtk.TreeIter iter) + { + Gtk.TreeIter signalIter; + if (store.IterChildren (out signalIter, iter)) { + do { + if (store.IterNChildren (signalIter) > 0) { + store.SetValue (iter, ColSignalTextWeight, (int) Pango.Weight.Bold); + return; + } + } while (store.IterNext (ref signalIter)); + } + store.SetValue (iter, ColSignalTextWeight, (int) Pango.Weight.Normal); + } + + Signal GetSignal (Gtk.TreeIter iter) + { + if (! (bool) store.GetValue (iter, ColHasHandler)) + return null; + string handler = (string) store.GetValue (iter, ColHandler); + foreach (Signal sig in selection.Signals) + if (sig.Handler == handler) + return sig; + return null; + } + + SignalDescriptor GetSignalDescriptor (Gtk.TreeIter iter) + { + Gtk.TreeIter group_iter; + if (! (bool) store.GetValue (iter, ColIsSignal) || !store.IterParent (out group_iter, iter)) + return null; + string name = (string) store.GetValue (iter, ColSignal); + string group_name = (string) store.GetValue (group_iter, ColSignal); + + foreach (ItemGroup igroup in selection.ClassDescriptor.SignalGroups) { + if (igroup.Label != group_name) + continue; + SignalDescriptor desc = (SignalDescriptor) igroup [name]; + if (desc != null) + return desc; + } + + return null; + } + + ArrayList SaveStatus () + { + ArrayList list = new ArrayList (); + + Gtk.TreeIter it; + if (!store.GetIterFirst (out it)) + return list; + + do { + SaveStatus (list, "", it); + } while (store.IterNext (ref it)); + + return list; + } + + void SaveStatus (ArrayList list, string path, Gtk.TreeIter iter) + { + string basePath = path + "/" + store.GetValue (iter, ColSignal); + + if (!tree.GetRowExpanded (store.GetPath (iter))) + return; + + list.Add (basePath); + + if (store.IterChildren (out iter, iter)) { + do { + SaveStatus (list, basePath, iter); + } while (store.IterNext (ref iter)); + } + } + + void RestoreStatus (ArrayList list) + { + foreach (string namePath in list) { + string[] names = namePath.Split ('/'); + + Gtk.TreeIter iter = Gtk.TreeIter.Zero; + + bool found = true; + foreach (string name in names) { + if (name == "") continue; + if (!FindChildByName (name, ref iter)) { + found = false; + break; + } + } + + if (found) + tree.ExpandRow (store.GetPath (iter), false); + } + } + + bool FindChildByName (string name, ref Gtk.TreeIter iter) + { + if (iter.Equals (Gtk.TreeIter.Zero)) { + if (!store.GetIterFirst (out iter)) + return false; + } else if (!store.IterChildren (out iter, iter)) + return false; + + do { + if (name == (string) store.GetValue (iter, ColSignal)) + return true; + } + while (store.IterNext (ref iter)); + + return false; + } + + string EmptyHandlerMarkup { + get { return "<i><span foreground=\"grey\">" + EmptyHandlerText + "</span></i>"; } + } + + string EmptyHandlerText { + get { return Catalog.GetString ("Click here to add a new handler"); } + } + } + + internal class SignalsEditorEditSession: MarshalByRefObject + { + SignalsEditorBackend backend; + + public SignalsEditorEditSession (SignalsEditorFrontend frontend) + { + backend = new SignalsEditorBackend (frontend); + } + + public SignalsEditorBackend Editor { + get { return backend; } + } + + public ProjectBackend ProjectBackend { + get { return backend.ProjectBackend; } + set { backend.ProjectBackend = value; } + } + + public Signal SelectedSignal { + get { + return backend.SelectedSignal; + } + } + + public void Dispose () + { + System.Runtime.Remoting.RemotingServices.Disconnect (this); + } + + public override object InitializeLifetimeService () + { + // Will be disconnected when calling Dispose + return null; + } + } +} diff --git a/main/src/addins/MonoDevelop.GtkCore2/libsteticui/UndoQueue.cs b/main/src/addins/MonoDevelop.GtkCore2/libsteticui/UndoQueue.cs new file mode 100644 index 0000000000..0ae6a6fc02 --- /dev/null +++ b/main/src/addins/MonoDevelop.GtkCore2/libsteticui/UndoQueue.cs @@ -0,0 +1,282 @@ + +using System; +using System.Xml; +using System.Collections; +using System.Collections.Generic; + +namespace Stetic +{ + public class UndoQueue: MarshalByRefObject + { + List<UndoRedoChange> changeList = new List<UndoRedoChange> (); + int undoListCount = 0; + static UndoQueue empty = new UndoQueue (); + + public void AddChange (UndoRedoChange change) + { + if (undoListCount < changeList.Count) { + // Destroy all undone changes + changeList.RemoveRange (undoListCount, changeList.Count - undoListCount); + } + changeList.Add (change); + undoListCount = changeList.Count; + } + + public IEnumerable<UndoRedoChange> Changes { + get { return changeList; } + } + + public static UndoQueue Empty { + get { return empty; } + } + + public bool CanUndo { + get { return undoListCount > 0; } + } + + public bool CanRedo { + get { return undoListCount < changeList.Count; } + } + + public void Undo () + { + if (undoListCount == 0) + return; + + UndoRedoChange change = (UndoRedoChange) changeList [--undoListCount]; + if (change.CheckValid ()) { + UndoRedoChange res = change.ApplyChange (); + if (res != null) + changeList [undoListCount] = res; + else + // Undo failed + changeList.RemoveAt (undoListCount); + } else { + changeList.RemoveAt (undoListCount); + Undo (); + } + } + + public void Redo () + { + if (undoListCount == changeList.Count) + return; + + UndoRedoChange change = (UndoRedoChange) changeList [undoListCount++]; + if (change.CheckValid ()) { + UndoRedoChange res = change.ApplyChange (); + if (res != null) + changeList [undoListCount - 1] = res; + else { + // Redo failed + undoListCount--; + changeList.RemoveAt (undoListCount); + } + } + else { + changeList.RemoveAt (--undoListCount); + Redo (); + } + } + + public void Purge () + { + for (int n=0; n<changeList.Count; n++) { + UndoRedoChange change = (UndoRedoChange) changeList [n]; + if (!change.CheckValid()) { + changeList.RemoveAt (n); + if (n < undoListCount) + undoListCount--; + } + } + } + } + + public abstract class UndoRedoChange: MarshalByRefObject + { + public abstract UndoRedoChange ApplyChange (); + + public virtual bool CheckValid () + { + return true; + } + } + + + class ObjectWrapperUndoRedoChange: UndoRedoChange + { + UndoRedoManager manager; + public string TargetObject; + public object Diff; + public ObjectWrapperUndoRedoChange Next; + + public ObjectWrapperUndoRedoChange (UndoRedoManager manager, string targetObject, object diff) + { + this.manager = manager; + this.TargetObject = targetObject; + this.Diff = diff; + } + + public UndoRedoManager Manager { + get { return manager; } + set { manager = value; } + } + + public override UndoRedoChange ApplyChange () + { + return manager.ApplyChange (this); + } + + public override bool CheckValid () + { + return manager.CheckValid (); + } + } + + class UndoRedoManager: IDisposable + { + UndoQueue queue; + ObjectWrapper rootObject; + bool updating; + UndoManager undoManager = new UndoManager (); + + public UndoRedoManager () + { + undoManager.UndoCheckpoint += OnUndoCheckpoint; + } + + public ObjectWrapper RootObject { + get { return rootObject; } + set { + rootObject = value; + undoManager.SetRoot (rootObject); + } + } + + public UndoQueue UndoQueue { + get { return queue; } + set { queue = value; } + } + + internal UndoManager UndoManager { + get { return undoManager; } + } + + void OnUndoCheckpoint (object sender, UndoCheckpointEventArgs args) + { + AddChange (args.ModifiedObjects); + } + + void AddChange (ObjectWrapper[] obs) + { + if (updating || queue == null) + return; + + ObjectWrapperUndoRedoChange firstChange = null; + ObjectWrapperUndoRedoChange lastChange = null; + +// Console.WriteLine ("** UNDO CHECKPOINT: {0} objects", obs.Length); + + foreach (ObjectWrapper ob in obs) { + + // Get the diff for going from the new status to the old status + object diff = GetDiff (ob); + + if (diff == null) // No differences + continue; + +// Console.WriteLine ("ADDCHANGE " + ob + " uid:" + ob.UndoId); +// PrintPatch (diff); + + if (ob.UndoId == null || ob.UndoId.Length == 0) + throw new InvalidOperationException ("Object of type '" + ob.GetType () + "' does not have an undo id."); + + ObjectWrapperUndoRedoChange change = new ObjectWrapperUndoRedoChange (this, ob.UndoId, diff); + if (lastChange == null) + lastChange = firstChange = change; + else { + lastChange.Next = change; + lastChange = change; + } + } + if (firstChange != null) + queue.AddChange (firstChange); + } + + protected virtual object GetDiff (ObjectWrapper w) + { + return w.GetUndoDiff (); + } + + public UndoRedoChange ApplyChange (ObjectWrapperUndoRedoChange first) + { + updating = true; + + try { + ObjectWrapperUndoRedoChange change = first; + ObjectWrapperUndoRedoChange lastRedo = null; + while (change != null) { + ObjectWrapperUndoRedoChange redo = ApplyDiff (change.TargetObject, change.Diff); + if (redo != null) { + redo.Next = lastRedo; + lastRedo = redo; + } + change = change.Next; + } + return lastRedo; + } catch (Exception ex) { + Console.WriteLine (ex); + return null; + } finally { + updating = false; + } + } + + ObjectWrapperUndoRedoChange ApplyDiff (string id, object diff) + { +// Console.WriteLine ("** APPLYING DIFF: uid:" + id); +// PrintPatch (diff); + + ObjectWrapper ww = rootObject.FindObjectByUndoId (id); + if (ww == null) { + Console.WriteLine ("Object with undo id '{0}' not found", id); + return null; + } + + object reverseDiff = ww.ApplyUndoRedoDiff (diff); + + if (reverseDiff != null) { +// Console.WriteLine ("** REVERSE DIFF:"); +// PrintPatch (reverseDiff); + + ObjectWrapperUndoRedoChange change = new ObjectWrapperUndoRedoChange (this, id, reverseDiff); + return change; + } else + return null; + } + + internal bool CheckValid () + { + return rootObject != null; + } + + public void Dispose () + { + rootObject = null; + if (queue != null) + queue.Purge (); + } + + internal void PrintPatch (object diff) + { + if (diff is Array) { + foreach (object ob in (Array)diff) + if (ob != null) PrintPatch (ob); + } else if (diff is XmlElement) + Console.WriteLine (((XmlElement)diff).OuterXml); + else + Console.WriteLine (diff.ToString ()); + } + } +} + diff --git a/main/src/addins/MonoDevelop.GtkCore2/libsteticui/UserInterface.cs b/main/src/addins/MonoDevelop.GtkCore2/libsteticui/UserInterface.cs new file mode 100644 index 0000000000..3eab8b8b89 --- /dev/null +++ b/main/src/addins/MonoDevelop.GtkCore2/libsteticui/UserInterface.cs @@ -0,0 +1,34 @@ + +using System; + +namespace Stetic +{ + internal class UserInterface + { + UserInterface() + { + } + + public static WidgetDesignerBackend CreateWidgetDesigner (Gtk.Container widget) + { + Stetic.Wrapper.Container wc = Stetic.Wrapper.Container.Lookup (widget); + return CreateWidgetDesigner (widget, wc.DesignWidth, wc.DesignHeight); + } + + public static WidgetDesignerBackend CreateWidgetDesigner (Gtk.Container widget, int designWidth, int designHeight) + { + return new WidgetDesignerBackend (widget, designWidth, designHeight); + } + + public static ActionGroupDesignerBackend CreateActionGroupDesigner (ProjectBackend project, ActionGroupToolbar groupToolbar) + { + Editor.ActionGroupEditor agroupEditor = new Editor.ActionGroupEditor (); + agroupEditor.Project = project; + WidgetDesignerBackend groupDesign = new WidgetDesignerBackend (agroupEditor, -1, -1); + + groupToolbar.Bind (agroupEditor); + + return new ActionGroupDesignerBackend (groupDesign, agroupEditor, groupToolbar); + } + } +} diff --git a/main/src/addins/MonoDevelop.GtkCore2/libsteticui/WidgetActionBar.cs b/main/src/addins/MonoDevelop.GtkCore2/libsteticui/WidgetActionBar.cs new file mode 100644 index 0000000000..c9db05dd57 --- /dev/null +++ b/main/src/addins/MonoDevelop.GtkCore2/libsteticui/WidgetActionBar.cs @@ -0,0 +1,251 @@ + +using System; +using System.Collections; +using Gtk; +using Mono.Unix; + +namespace Stetic +{ + + internal class WidgetActionBar: Gtk.Toolbar + { + ProjectBackend project; + Stetic.Wrapper.Widget rootWidget; + WidgetTreeCombo combo; + ToolItem comboItem; + Stetic.Wrapper.Widget selection; + Stetic.Wrapper.Container.ContainerChild packingSelection; + Hashtable editors, wrappers; + Hashtable sensitives, invisibles; + ArrayList toggles; + bool disposed; + bool updating; + bool allowBinding; + WidgetDesignerFrontend frontend; + + public WidgetActionBar (WidgetDesignerFrontend frontend, Stetic.Wrapper.Widget rootWidget) + { + this.frontend = frontend; + + editors = new Hashtable (); + wrappers = new Hashtable (); + sensitives = new Hashtable (); + invisibles = new Hashtable (); + toggles = new ArrayList (); + + IconSize = IconSize.Menu; + Orientation = Orientation.Horizontal; + ToolbarStyle = ToolbarStyle.BothHoriz; + + combo = new WidgetTreeCombo (); + comboItem = new ToolItem (); + comboItem.Add (combo); + comboItem.ShowAll (); + Insert (comboItem, -1); + ShowAll (); + RootWidget = rootWidget; + } + + public override void Dispose () + { + if (disposed) + return; + disposed = true; + combo.Destroy (); + combo = null; + RootWidget = null; + Clear (); + base.Dispose (); + } + + public bool AllowWidgetBinding { + get { return allowBinding; } + set { allowBinding = value; } + } + + public Stetic.Wrapper.Widget RootWidget { + get { return rootWidget; } + set { + if (project != null) { + project.SelectionChanged -= OnSelectionChanged; + project = null; + } + + rootWidget = value; + if (combo != null) + combo.RootWidget = rootWidget; + + if (rootWidget != null) { + project = (Stetic.ProjectBackend) rootWidget.Project; + UpdateSelection (Wrapper.Widget.Lookup (project.Selection)); + project.SelectionChanged += OnSelectionChanged; + } + } + } + + void Clear () + { + if (selection != null) { + selection.Notify -= Notified; + if (packingSelection != null) + packingSelection.Notify -= Notified; + } + + selection = null; + packingSelection = null; + + editors.Clear (); + wrappers.Clear (); + sensitives.Clear (); + invisibles.Clear (); + toggles.Clear (); + + foreach (Gtk.Widget child in Children) + if (child != comboItem) { + Remove (child); + child.Destroy (); + } + } + + void OnSelectionChanged (object s, Wrapper.WidgetEventArgs args) + { + UpdateSelection (args.WidgetWrapper); + } + + void UpdateSelection (Wrapper.Widget w) + { + Clear (); + selection = w; + + if (selection == null) { + combo.SetSelection (null); + return; + } + + // Look for the root widget, and only update the bar if the selected + // widget is a child of the root widget + + while (w != null && !w.IsTopLevel) { + w = Stetic.Wrapper.Container.LookupParent ((Gtk.Widget) w.Wrapped); + } + if (w == null || w != rootWidget) + return; + + combo.SetSelection (selection); + + selection.Notify += Notified; + packingSelection = Stetic.Wrapper.Container.ChildWrapper (selection); + if (packingSelection != null) + packingSelection.Notify += Notified; + + AddWidgetCommands (selection); + UpdateSensitivity (); + } + + protected virtual void AddWidgetCommands (ObjectWrapper wrapper) + { + if (allowBinding && wrapper != RootWidget) { + // Show the Bind to Field button only for children of the root container. + ToolButton bindButton = new ToolButton (null, Catalog.GetString ("Bind to Field")); + bindButton.IsImportant = true; + bindButton.Clicked += delegate { frontend.NotifyBindField (); }; + bindButton.Show (); + Insert (bindButton, -1); + } + AddCommands (wrapper); + } + + void AddCommands (ObjectWrapper wrapper) + { + foreach (ItemGroup igroup in wrapper.ClassDescriptor.ItemGroups) { + foreach (ItemDescriptor desc in igroup) { + if ((desc is CommandDescriptor) && desc.SupportsGtkVersion (project.TargetGtkVersion)) + AppendCommand ((CommandDescriptor) desc, wrapper); + } + } + + Stetic.Wrapper.Widget widget = wrapper as Stetic.Wrapper.Widget; + if (widget != null) { + Stetic.Wrapper.Container.ContainerChild packingSelection = Stetic.Wrapper.Container.ChildWrapper (widget); + if (packingSelection != null) + AddCommands (packingSelection); + } + } + + void AppendCommand (CommandDescriptor cmd, ObjectWrapper widget) + { + Gtk.ToolButton button; + + if (cmd.IsToggleCommand (widget.Wrapped)) { + button = new Gtk.ToggleToolButton (); + ((Gtk.ToggleToolButton)button).Active = cmd.IsToogled (widget.Wrapped); + toggles.Add (cmd); + editors[cmd.Name] = button; + } else { + button = new Gtk.ToolButton (null, null); + } + + Gtk.Image img = cmd.GetImage (); + if (img != null) { + button.IconWidget = img; + button.Label = cmd.Label; + if (cmd.Label != null && cmd.Label.Length > 0) + button.TooltipText = cmd.Label; + } + else { + button.Label = cmd.Label; + button.IsImportant = true; + } + button.Clicked += delegate (object o, EventArgs args) { + if (!updating) + cmd.Run (widget.Wrapped); + }; + button.ShowAll (); + Insert (button, -1); + + if (cmd.HasDependencies) { + editors[cmd.Name] = button; + sensitives[cmd] = cmd; + } + if (cmd.HasVisibility) { + editors[cmd.Name] = button; + invisibles[cmd] = cmd; + } + wrappers [cmd] = widget; + } + + void Notified (object s, string propertyName) + { + UpdateSensitivity (); + } + + void UpdateSensitivity () + { + foreach (ItemDescriptor item in sensitives.Keys) { + Widget w = editors[item.Name] as Widget; + if (w != null) { + ObjectWrapper wrapper = wrappers [item] as ObjectWrapper; + object ob = sensitives.Contains (item) ? wrapper.Wrapped : null; + w.Sensitive = item.EnabledFor (ob); + } + } + foreach (ItemDescriptor item in invisibles.Keys) { + Widget w = editors[item.Name] as Widget; + if (w != null) { + ObjectWrapper wrapper = wrappers [item] as ObjectWrapper; + object ob = invisibles.Contains (item) ? wrapper.Wrapped : null; + w.Visible = item.VisibleFor (ob); + } + } + foreach (CommandDescriptor cmd in toggles) { + ToggleToolButton w = editors[cmd.Name] as ToggleToolButton; + if (w != null) { + ObjectWrapper wrapper = wrappers [cmd] as ObjectWrapper; + updating = true; + w.Active = cmd.IsToogled (wrapper.Wrapped); + updating = false; + } + } + } + } +} diff --git a/main/src/addins/MonoDevelop.GtkCore2/libsteticui/WidgetComponent.cs b/main/src/addins/MonoDevelop.GtkCore2/libsteticui/WidgetComponent.cs new file mode 100644 index 0000000000..84f63413ca --- /dev/null +++ b/main/src/addins/MonoDevelop.GtkCore2/libsteticui/WidgetComponent.cs @@ -0,0 +1,122 @@ + +using System; +using System.Collections; +using System.Collections.Specialized; + +namespace Stetic +{ + public class WidgetComponent: Component + { + static WidgetComponent placeholder; + + public WidgetComponent (Application app, object backend, string name, ComponentType type): base (app, backend, name, type) + { + } + + public override string Name { + get { + if (name == null) + UpdateComponentInfo (); + return name; + } + set { + name = value; + if (app != null) + app.Backend.RenameWidget ((Wrapper.Widget)backend, value); + } + } + + public override bool GeneratePublic { + get { return ((Wrapper.Widget)backend).GeneratePublic; } + set { ((Wrapper.Widget)backend).GeneratePublic = value; } + } + + internal void UpdateName (string name) + { + this.name = name; + } + + public override Component[] GetChildren () + { + if (app == null) + return new Component [0]; + ArrayList wws = app.Backend.GetWidgetChildren ((Wrapper.Widget)backend); + if (wws == null) + return new Component [0]; + ArrayList children = new ArrayList (wws.Count); + for (int n=0; n<wws.Count; n++) { + Component c = app.GetComponent (wws[n], null, null); + if (c != null) + children.Add (c); + } + return (Component[]) children.ToArray (typeof(Component)); + } + + void UpdateComponentInfo () + { + if (app == null) + return; + string typeName; + app.Backend.GetComponentInfo (backend, out name, out typeName); + type = app.GetComponentType (typeName); + } + + public override ComponentType Type { + get { + if (type == null) + UpdateComponentInfo (); + return type; + } + } + + public ActionGroupComponent[] GetActionGroups () + { + if (app == null) + return new ActionGroupComponent [0]; + + ArrayList comps = new ArrayList (); + Wrapper.ActionGroup[] groups = app.Backend.GetActionGroups ((Wrapper.Widget)backend); + for (int n=0; n<groups.Length; n++) { + ActionGroupComponent ag = (ActionGroupComponent) app.GetComponent (groups[n], null, null); + if (ag != null) + comps.Add (ag); + } + + return (ActionGroupComponent[]) comps.ToArray (typeof(ActionGroupComponent)); + } + + public bool IsWindow { + get { return backend is Wrapper.Window; } + } + + internal static WidgetComponent Placeholder { + get { + if (placeholder == null) { + placeholder = new WidgetComponent (null, null, "", ComponentType.Unknown); + } + return placeholder; + } + } + } + + [Serializable] + public class ObjectBindInfo + { + string typeName; + string name; + + public ObjectBindInfo (string typeName, string name) + { + this.typeName = typeName; + this.name = name; + } + + public string TypeName { + get { return typeName; } + } + + public string Name { + get { return name; } + } + } +} diff --git a/main/src/addins/MonoDevelop.GtkCore2/libsteticui/WidgetDesigner.cs b/main/src/addins/MonoDevelop.GtkCore2/libsteticui/WidgetDesigner.cs new file mode 100644 index 0000000000..cbcbbbb418 --- /dev/null +++ b/main/src/addins/MonoDevelop.GtkCore2/libsteticui/WidgetDesigner.cs @@ -0,0 +1,423 @@ +using System; +using System.Collections; + +namespace Stetic +{ + public delegate void ComponentDropCallback (); + + public class WidgetDesigner: Designer + { + WidgetEditSession session; + WidgetDesignerFrontend frontend; + Component selection; + Component rootWidget; + + Project project; + int reloadCount; + + string componentName; + bool disposed; + + bool canCut, canCopy, canPaste, canDelete; + + public event EventHandler BindField; + public event EventHandler Changed; + public event EventHandler SelectionChanged; + public event EventHandler RootComponentChanged; + public event ComponentSignalEventHandler SignalAdded; + public event ComponentSignalEventHandler SignalRemoved; + public event ComponentSignalEventHandler SignalChanged; + public event ComponentNameEventHandler ComponentNameChanged; + public event EventHandler ComponentTypesChanged; + + internal WidgetDesigner (Project project, string componentName): base (project.App) + { + this.componentName = componentName; + this.project = project; + frontend = new WidgetDesignerFrontend (this); + + project.SignalAdded += OnSignalAdded; + project.SignalRemoved += OnSignalRemoved; + project.SignalChanged += OnSignalChanged; + project.ComponentNameChanged += OnComponentNameChanged; + project.ComponentTypesChanged += OnComponentTypesChanged; + project.BackendChanged += OnProjectBackendChanged; + + CreateSession (); + } + + public Component RootComponent { + get { return rootWidget; } + } + + public override ProjectItemInfo ProjectItem { + get { return project.GetWidget (rootWidget.Name); } + } + + public ComponentType[] GetComponentTypes () + { + if (!disposed) { + ArrayList types = new ArrayList (); + types.AddRange (project.GetComponentTypes ()); + + // Add actions from the local action groups + + WidgetComponent c = rootWidget as WidgetComponent; + if (c != null) { + foreach (ActionGroupComponent grp in c.GetActionGroups ()) { + foreach (ActionComponent ac in grp.GetActions ()) + types.Add (new ComponentType (app, ac)); + } + } + return (ComponentType[]) types.ToArray (typeof(ComponentType)); + } + else + return new ComponentType[0]; + } + + public void BeginComponentDrag (ComponentType type, Gtk.Widget source, Gdk.DragContext ctx) + { + Stetic.ObjectWrapper wrapper = type.Action != null ? (Stetic.ObjectWrapper) type.Action.Backend : null; + app.Backend.BeginComponentDrag (project.ProjectBackend, type.Description, type.ClassName, wrapper, source, ctx, null); + + } + + public void BeginComponentDrag (string title, string className, Gtk.Widget source, Gdk.DragContext ctx, ComponentDropCallback callback) + { + app.Backend.BeginComponentDrag (project.ProjectBackend, title, className, null, source, ctx, callback); + + } + + // Creates an action group designer for the widget being edited by this widget designer + public ActionGroupDesigner CreateActionGroupDesigner () + { + if (disposed) + throw new ObjectDisposedException ("WidgetDesigner"); + return new ActionGroupDesigner (project, componentName, null, this, true); + + } + + public bool Modified { + get { return session != null && session.Modified; } + } + + internal override void SetActive () + { + if (!disposed) + project.App.SetActiveDesignSession (project, session); + } + + public bool AllowWidgetBinding { + get { return session != null && session.AllowWidgetBinding; } + set { + if (session != null) + session.AllowWidgetBinding = value; + } + } + + public ImportFileDelegate ImportFileCallback { + get { return project.ImportFileCallback; } + set { project.ImportFileCallback = value; } + } + + public object SaveStatus () + { + return session.SaveState (); + } + + public void LoadStatus (object ob) + { + session.RestoreState (ob); + } + + void CreateSession () + { + try { + session = project.ProjectBackend.CreateWidgetDesignerSession (frontend, componentName); + ResetCustomWidget (); + rootWidget = app.GetComponent (session.RootWidget, null, null); + } catch (Exception ex) { + Console.WriteLine (ex); + Gtk.Label lab = new Gtk.Label (); + lab.Text = Mono.Unix.Catalog.GetString ("The designer could not be loaded.") + "\n\n" + ex.Message; + lab.Wrap = true; + lab.WidthRequest = 400; + AddCustomWidget (lab); + session = null; + } + } + + protected override void OnCreatePlug (uint socketId) + { + session.CreateWrapperWidgetPlug (socketId); + } + + protected override void OnDestroyPlug (uint socketId) + { + session.DestroyWrapperWidgetPlug (); + } + + protected override Gtk.Widget OnCreateWidget () + { + return session.WrapperWidget; + } + + public Component Selection { + get { + return selection; + } + } + + public void CopySelection () + { + if (session != null) + session.ClipboardCopySelection (); + } + + public void CutSelection () + { + if (session != null) + session.ClipboardCutSelection (); + } + + public void PasteToSelection () + { + if (session != null) + session.ClipboardPaste (); + } + + public void DeleteSelection () + { + if (session != null) + session.DeleteSelection (); + } + + public bool CanDeleteSelection { + get { return canDelete; } + } + + public bool CanCutSelection { + get { return canCut; } + } + + public bool CanCopySelection { + get { return canCopy; } + } + + public bool CanPasteToSelection { + get { return canPaste; } + } + + public UndoQueue UndoQueue { + get { + if (session != null) + return session.UndoQueue; + else + return UndoQueue.Empty; + } + } + + protected override void OnDestroyed () + { + try { + if (disposed) + return; + + if (project.App.ActiveProject == project) + project.App.ActiveProject = null; + + disposed = true; + frontend.disposed = true; + project.SignalAdded -= OnSignalAdded; + project.SignalRemoved -= OnSignalRemoved; + project.SignalChanged -= OnSignalChanged; + project.ComponentNameChanged -= OnComponentNameChanged; + project.ComponentTypesChanged -= OnComponentTypesChanged; + project.BackendChanged -= OnProjectBackendChanged; + + if (session != null) { + session.Dispose (); + session = null; + } + + System.Runtime.Remoting.RemotingServices.Disconnect (frontend); + frontend = null; + rootWidget = null; + selection = null; + } finally { + base.OnDestroyed (); + } + } + + public void Save () + { + if (session != null) + session.Save (); + } + + void OnComponentNameChanged (object s, ComponentNameEventArgs args) + { + if (!disposed && ComponentNameChanged != null) + ComponentNameChanged (this, args); + } + + internal void NotifyRootWidgetChanging () + { + PrepareUpdateWidget (); + } + + internal void NotifyRootWidgetChanged () + { + object rw = session.RootWidget; + if (rw != null) + rootWidget = app.GetComponent (session.RootWidget, null, null); + else + rootWidget = null; + + UpdateWidget (); + if (RootComponentChanged != null) + RootComponentChanged (this, EventArgs.Empty); + } + + internal override void OnBackendChanging () + { + reloadCount = 0; + base.OnBackendChanging (); + } + + internal override void OnBackendChanged (ApplicationBackend oldBackend) + { + // Can't do anything until the projects are reloaded + // This is checked in OnProjectBackendChanged. + } + + void OnProjectBackendChanged (ApplicationBackend oldBackend) + { + if (++reloadCount == 2) { + object sessionData = null; + +// if (oldBackend != null && !autoCommitChanges) { +// sessionData = session.SaveState (); +// session.DestroyWrapperWidgetPlug (); +// } + + // Don't dispose the session here, since it will dispose + // the underlying project, and we can't do it because + // it may need to process the OnBackendChanging event + // as well. + + CreateSession (); + + if (sessionData != null && session != null) + session.RestoreState (sessionData); + + base.OnBackendChanged (oldBackend); + NotifyRootWidgetChanged (); + } + } + + void OnComponentTypesChanged (object s, EventArgs a) + { + if (ComponentTypesChanged != null) + ComponentTypesChanged (this, a); + } + + void OnSignalAdded (object sender, Stetic.ComponentSignalEventArgs args) + { + if (SignalAdded != null) + SignalAdded (this, args); + } + + void OnSignalRemoved (object sender, Stetic.ComponentSignalEventArgs args) + { + if (SignalRemoved != null) + SignalRemoved (this, args); + } + + void OnSignalChanged (object sender, Stetic.ComponentSignalEventArgs args) + { + if (SignalChanged != null) + SignalChanged (this, args); + } + + internal void NotifyBindField () + { + if (BindField != null) + BindField (this, EventArgs.Empty); + } + + internal void NotifyChanged () + { + if (Changed != null) + Changed (this, EventArgs.Empty); + } + + internal void NotifySelectionChanged (object ob, bool canCut, bool canCopy, bool canPaste, bool canDelete) + { + this.canCut = canCut; + this.canCopy = canCopy; + this.canPaste = canPaste; + this.canDelete = canDelete; + + if (ob != null) + selection = app.GetComponent (ob, null, null); + else + selection = null; + + if (SelectionChanged != null) + SelectionChanged (this, EventArgs.Empty); + } + } + + internal class WidgetDesignerFrontend: MarshalByRefObject + { + WidgetDesigner designer; + internal bool disposed; + + public WidgetDesignerFrontend (WidgetDesigner designer) + { + this.designer = designer; + } + + public void NotifyBindField () + { + GuiDispatch.InvokeSync ( + delegate { if (!disposed) designer.NotifyBindField (); } + ); + } + + public void NotifyChanged () + { + GuiDispatch.InvokeSync ( + delegate { if (!disposed) designer.NotifyChanged (); } + ); + } + + internal void NotifySelectionChanged (object ob, bool canCut, bool canCopy, bool canPaste, bool canDelete) + { + GuiDispatch.InvokeSync ( + delegate { if (!disposed) designer.NotifySelectionChanged (ob, canCut, canCopy, canPaste, canDelete); } + ); + } + + public void NotifyRootWidgetChanged () + { + GuiDispatch.InvokeSync ( + delegate { if (!disposed) designer.NotifyRootWidgetChanged (); } + ); + } + + public void NotifyRootWidgetChanging () + { + GuiDispatch.InvokeSync ( + delegate { if (!disposed) designer.NotifyRootWidgetChanging (); } + ); + } + + public override object InitializeLifetimeService () + { + // Will be disconnected when calling Dispose + return null; + } + } +} diff --git a/main/src/addins/MonoDevelop.GtkCore2/libsteticui/WidgetDesignerBackend.cs b/main/src/addins/MonoDevelop.GtkCore2/libsteticui/WidgetDesignerBackend.cs new file mode 100644 index 0000000000..8c85049ccd --- /dev/null +++ b/main/src/addins/MonoDevelop.GtkCore2/libsteticui/WidgetDesignerBackend.cs @@ -0,0 +1,961 @@ +// +// WidgetDesignerBackend.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 System.Collections; +using System.Reflection; +using Gtk; +using Gdk; + +namespace Stetic +{ + internal class WidgetDesignerBackend: ScrolledWindow + { + ObjectWrapper wrapper; + Gtk.Widget preview; + ResizableFixed resizableFixed; + + static IObjectViewer defaultObjectViewer; + + public event EventHandler SelectionChanged; + + internal static IObjectViewer DefaultObjectViewer { + get { return defaultObjectViewer; } + set { defaultObjectViewer = value; } + } + + public object Selection { + get { + IObjectSelection sel = resizableFixed.GetSelection (); + if (sel != null) + return sel.DataObject; + else + return null; + } + } + + internal IDesignArea DesignArea { + get { return resizableFixed; } + } + + internal WidgetDesignerBackend (Gtk.Container container, int designWidth, int designHeight) + { + ShadowType = ShadowType.None; + HscrollbarPolicy = PolicyType.Automatic; + VscrollbarPolicy = PolicyType.Automatic; + + resizableFixed = new ResizableFixed (); + resizableFixed.ObjectViewer = defaultObjectViewer; + + wrapper = ObjectWrapper.Lookup (container); + TopLevelWindow window = container as TopLevelWindow; + + if (window != null) { + preview = Stetic.Metacity.Preview.Create (window); + if (preview == null) + preview = Stetic.Windows.Preview.Create (window); + if (preview == null) { + // Use a regular box. + EventBox eventBox = new EventBox (); + eventBox.Add (container); + preview = eventBox; + } + } else { + EventBox eventBox = new EventBox (); + eventBox.Add (container); + preview = eventBox; + } + + resizableFixed.Put (preview, container); + + if (designWidth != -1) { + preview.WidthRequest = designWidth; + preview.HeightRequest = designHeight; + resizableFixed.AllowResize = true; + } else { + resizableFixed.AllowResize = false; + } + + preview.SizeAllocated += new Gtk.SizeAllocatedHandler (OnResized); + + AddWithViewport (resizableFixed); + + if (wrapper != null) + wrapper.AttachDesigner (resizableFixed); + + resizableFixed.SelectionChanged += OnSelectionChanged; + } + + protected override void OnDestroyed () + { + if (preview != null) { + if (wrapper != null) + wrapper.DetachDesigner (resizableFixed); + preview.SizeAllocated -= new Gtk.SizeAllocatedHandler (OnResized); + resizableFixed.SelectionChanged -= OnSelectionChanged; + resizableFixed = null; + preview = null; + wrapper = null; + } + base.OnDestroyed (); + } + + public IObjectViewer ObjectViewer { + get { return resizableFixed.ObjectViewer; } + set { resizableFixed.ObjectViewer = value; } + } + + public void UpdateObjectViewers () + { + // This method has to be called to ensure that the property + // and signal viewers show information about the object + // selected in this designer. + resizableFixed.UpdateObjectViewers (); + } + + void OnSelectionChanged (object ob, EventArgs a) + { + if (SelectionChanged != null) + SelectionChanged (this, a); + } + + protected override void OnParentSet (Gtk.Widget previousParent) + { + base.OnParentSet (previousParent); + + if (previousParent != null) + previousParent.Realized -= OnParentRealized; + + if (Parent != null) + Parent.Realized += OnParentRealized; + } + + void OnParentRealized (object s, EventArgs args) + { + if (Parent != null) { + 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) + { + Stetic.Wrapper.Container cont = wrapper as Stetic.Wrapper.Container; + if (cont != null) { + if (cont.DesignHeight != DesignHeight) + cont.DesignHeight = DesignHeight; + if (cont.DesignWidth != DesignWidth) + cont.DesignWidth = DesignWidth; + } + + 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, IDesignArea + { + 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; + + SelectionHandleBox selectionBox; + Gtk.Widget selectionWidget; + ObjectSelection currentObjectSelection; + ArrayList topLevels = new ArrayList (); + ArrayList trackingSize = new ArrayList (); + + internal IObjectViewer ObjectViewer; + internal bool AllowResize; + + public event EventHandler SelectionChanged; + + public ResizableFixed () + { + fixd = new Fixed (); + Add (fixd); + this.CanFocus = true; + this.Events = EventMask.ButtonPressMask | EventMask.ButtonReleaseMask | EventMask.PointerMotionMask | EventMask.KeyPressMask; +// fixd.ModifyBg (Gtk.StateType.Normal, this.Style.Mid (Gtk.StateType.Normal)); +// VisibleWindow = false; + selectionBox = new SelectionHandleBox (this); + selectionBox.Show (); + } + + public ResizableFixed (IntPtr p): base (p) + { + } + + protected override void OnDestroyed () + { + if (cursorX != null) { + cursorX.Dispose (); + cursorXY.Dispose (); + cursorY.Dispose (); + cursorX = cursorXY = cursorY = null; + } + base.OnDestroyed (); + } + + internal 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); + } + + public override void Dispose () + { + if (child != null) + child.SizeRequested -= new SizeRequestedHandler (OnSizeReq); + base.Dispose (); + } + + public bool IsSelected (Gtk.Widget widget) + { + return selectionWidget == widget; + } + + public IObjectSelection GetSelection (Gtk.Widget widget) + { + if (selectionWidget == widget) + return currentObjectSelection; + else + return null; + } + + public IObjectSelection GetSelection () + { + return currentObjectSelection; + } + + public IObjectSelection SetSelection (Gtk.Widget widget, object obj) + { + return SetSelection (widget, obj, true); + } + + public IObjectSelection SetSelection (Gtk.Widget widget, object obj, bool allowDrag) + { + if (currentObjectSelection != null) { + currentObjectSelection.Dispose (); + currentObjectSelection = null; + } + + if (widget != null) { + currentObjectSelection = new ObjectSelection (this, widget, obj); + currentObjectSelection.AllowDrag = allowDrag; + } + else + currentObjectSelection = null; + + PlaceSelectionBox (widget); + // Make sure the selection box is shown before doing anything else. + // The UI looks more responsive in this way. +// while (Gtk.Application.EventsPending ()) +// Gtk.Application.RunIteration (); + + UpdateObjectViewers (); + + if (SelectionChanged != null) + SelectionChanged (this, EventArgs.Empty); + + return currentObjectSelection; + } + + void PlaceSelectionBox (Gtk.Widget widget) + { + if (selectionWidget != null) { + foreach (Gtk.Widget sw in trackingSize) + sw.SizeAllocated -= SelectionSizeAllocated; + selectionWidget.Destroyed -= SelectionDestroyed; + trackingSize.Clear (); + } + + selectionWidget = widget; + + if (widget != null) { + selectionBox.Hide (); + + // This call ensures that the old selection box is removed + // before the new one is shown +// while (Gtk.Application.EventsPending ()) +// Gtk.Application.RunIteration (); + + // The selection may have changed while dispatching events +// if (selectionWidget != widget) +// return; + + // Track the size changes of the widget and all its parents + Gtk.Widget sw = selectionWidget; + while (sw != this && sw != null) { + sw.SizeAllocated += SelectionSizeAllocated; + trackingSize.Add (sw); + sw = sw.Parent; + } + + selectionWidget.Destroyed += SelectionDestroyed; + PlaceSelectionBoxInternal (selectionWidget); + selectionBox.ObjectSelection = currentObjectSelection; + selectionBox.Show (); + } else { + selectionBox.Hide (); + } + } + + public void ResetSelection (Gtk.Widget widget) + { + if (selectionWidget == widget || widget == null) { + PlaceSelectionBox (null); + if (currentObjectSelection != null) { + currentObjectSelection.FireDisposed (); + currentObjectSelection = null; + + // This makes the property editor to flicker + // when changing widget selection + // UpdateObjectViewers (); + } + if (widget == null) { + Gtk.Container cc = this as Gtk.Container; + while (cc.Parent != null) + cc = cc.Parent as Gtk.Container; + if (cc is Gtk.Window) { + ((Gtk.Window)cc).Focus = this; + } + } + } + } + + public void UpdateObjectViewers () + { + object obj; + + if (currentObjectSelection == null) + obj = null; + else + obj = currentObjectSelection.DataObject; + + if (ObjectViewer != null) + ObjectViewer.TargetObject = obj; + } + + public void AddWidget (Gtk.Widget w, int x, int y) + { + w.Parent = this; + TopLevelChild info = new TopLevelChild (); + info.X = x; + info.Y = y; + info.Child = w; + topLevels.Add (info); + } + + public void RemoveWidget (Gtk.Widget w) + { + foreach (TopLevelChild info in topLevels) { + if (info.Child == w) { + w.Unparent (); + topLevels.Remove (info); + break; + } + } + } + + public void MoveWidget (Gtk.Widget w, int x, int y) + { + foreach (TopLevelChild info in topLevels) { + if (info.Child == w) { + info.X = x; + info.Y = y; + QueueResize (); + break; + } + } + } + + public Gdk.Rectangle GetCoordinates (Gtk.Widget w) + { + int px, py; + if (!w.TranslateCoordinates (this, 0, 0, out px, out py)) + return new Gdk.Rectangle (0,0,0,0); + + Gdk.Rectangle rect = w.Allocation; + rect.X = px - Allocation.X; + rect.Y = py - Allocation.Y; + return rect; + } + + void SelectionSizeAllocated (object obj, Gtk.SizeAllocatedArgs args) + { + PlaceSelectionBoxInternal (selectionWidget); + } + + void SelectionDestroyed (object obj, EventArgs args) + { + ResetSelection ((Gtk.Widget)obj); + } + + void PlaceSelectionBoxInternal (Gtk.Widget widget) + { + int px, py; + if (!widget.TranslateCoordinates (this, 0, 0, out px, out py)) + return; + + Gdk.Rectangle rect = widget.Allocation; + rect.X = px; + rect.Y = py; + selectionBox.Reposition (rect); + } + + + void OnSizeReq (object o, SizeRequestedArgs a) + { + if (!AllowResize) { + a.RetVal = false; + QueueDraw (); + return; + } + + 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) + { + // The Toplevel check is done to ensure that this widget is anchored, + // otherwise the Realize call will fail. + if (!child.IsRealized && Toplevel is Gtk.Window) + child.Realize (); + + req = child.SizeRequest (); + // Make some room for the border + req.Width += padding * 2 + selectionBorder * 2; + req.Height += padding * 2 + selectionBorder * 2; + selectionBox.SizeRequest (); + if (selectionBox.Allocation.Width > req.Width) + req.Width = selectionBox.Allocation.Width; + if (selectionBox.Allocation.Height > req.Height) + req.Height = selectionBox.Allocation.Height; + + foreach (TopLevelChild tchild in topLevels) { + Gtk.Requisition treq = tchild.Child.SizeRequest (); + if (tchild.X + treq.Width > req.Width) + req.Width = tchild.X + treq.Width; + if (tchild.Y + treq.Height > req.Height) + req.Height = tchild.Y + treq.Height; + } + } + + protected override void OnSizeAllocated (Gdk.Rectangle rect) + { + base.OnSizeAllocated (rect); + + if (selectionWidget != null) + PlaceSelectionBoxInternal (selectionWidget); + + foreach (TopLevelChild child in topLevels) { + Gtk.Requisition req = child.Child.SizeRequest (); + child.Child.SizeAllocate (new Gdk.Rectangle (rect.X + child.X, rect.Y + child.Y, req.Width, req.Height)); + } + } + + protected override void ForAll (bool include_internals, Gtk.Callback callback) + { + base.ForAll (include_internals, callback); + foreach (TopLevelChild child in topLevels) + callback (child.Child); + if (include_internals) + selectionBox.ForAll (include_internals, callback); + } + + 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 (AllowResize) { + 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); + if (gw != null) + gw.Select (); + else + ResetSelection (null); + + if (AllowResize) { + 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); + if (gw != null) + 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); + //FIXME Disabled checkerboard background because it's very inefficient and makes the control *very* slow to resize + // It should take the EventExpose area into account, invalidate more selectively during resizes (GTK viewport + // code would probably be a good start), and take advantage of the flat block color the parent is rendering. + /* + int size = 8; + bool squareColor = true; + bool startsquareColor = true; + int x1 = 0; + int x2 = Allocation.Width; + int y1 = 0; + int y2 = Allocation.Height; + for (int y = y1; y < y2; y += size) { + squareColor = startsquareColor; + startsquareColor = !startsquareColor; + for (int x = x1; x < x2; x += size) { + GdkWindow.DrawRectangle (squareColor ? Style.DarkGC (StateType.Normal) : Style.DarkGC (StateType.Active), true, x, y, size, size); + squareColor = !squareColor; + } + } + + foreach (Widget cw in Children) + PropagateExpose (cw, ev);*/ + + Gdk.Rectangle rect = child.Allocation; + if (Stetic.Metacity.Preview.ThemeError) + GdkWindow.DrawRectangle (this.Style.BackgroundGC (StateType.Normal), true, 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; + } + + protected override bool OnKeyPressEvent (Gdk.EventKey ev) + { + switch (ev.Key) { + case Gdk.Key.Delete: + case Gdk.Key.KP_Delete: + IObjectSelection sel = GetSelection (); + if (sel != null && sel.DataObject != null) { + Wrapper.Widget wrapper = Wrapper.Widget.Lookup (sel.DataObject) as Wrapper.Widget; + if (wrapper != null) + wrapper.Delete (); + } + return true; + default: + return base.OnKeyPressEvent (ev); + } + } + + class TopLevelChild + { + public int X; + public int Y; + public Gtk.Widget Child; + } + } + + enum BoxPos + { + Start, + Center, + End, + } + + enum BoxFill + { + Box, + VLine, + HLine + } + + class SelectionHandleBox + { + const int selectionHandleSize = 4; + const int topSelectionHandleSize = 8; + public const int selectionLineWidth = 2; + + ArrayList selection = new ArrayList (); + Gdk.Rectangle allocation; + SelectionHandlePart dragHandlePart; + public ObjectSelection ObjectSelection; + + public SelectionHandleBox (Gtk.Widget parent) + { + // Lines + selection.Add (new SelectionHandlePart (BoxFill.HLine, BoxPos.Start, BoxPos.Start, 0, -selectionLineWidth, BoxPos.End, BoxPos.Start, 0, 0)); + selection.Add (new SelectionHandlePart (BoxFill.HLine, BoxPos.Start, BoxPos.End, 0, 0, BoxPos.End, BoxPos.End, 0, selectionLineWidth)); + selection.Add (new SelectionHandlePart (BoxFill.VLine, BoxPos.Start, BoxPos.Start, -selectionLineWidth, 0, BoxPos.Start, BoxPos.End, 0, 0)); + selection.Add (new SelectionHandlePart (BoxFill.VLine, BoxPos.End, BoxPos.Start, 0, 0, BoxPos.End, BoxPos.End, selectionLineWidth, 0)); + + // Handles + selection.Add (new SelectionHandlePart (BoxFill.Box, BoxPos.Start, BoxPos.Start, -selectionHandleSize, -selectionHandleSize, BoxPos.Start, BoxPos.Start, 0, 0)); + selection.Add (new SelectionHandlePart (BoxFill.Box, BoxPos.End, BoxPos.Start, 0, -selectionHandleSize, BoxPos.End, BoxPos.Start, selectionHandleSize, 0)); + selection.Add (new SelectionHandlePart (BoxFill.Box, BoxPos.Start, BoxPos.End, -selectionHandleSize, 0, BoxPos.Start, BoxPos.End, 0, selectionHandleSize)); + selection.Add (new SelectionHandlePart (BoxFill.Box, BoxPos.End, BoxPos.End, 0, 0, BoxPos.End, BoxPos.End, selectionHandleSize, selectionHandleSize)); + + selection.Add (new SelectionHandlePart (BoxFill.Box, BoxPos.Center, BoxPos.Start, -selectionHandleSize/2, -selectionHandleSize, BoxPos.Center, BoxPos.Start, selectionHandleSize/2, 0)); + selection.Add (new SelectionHandlePart (BoxFill.Box, BoxPos.Center, BoxPos.End, -selectionHandleSize/2, 0, BoxPos.Center, BoxPos.End, selectionHandleSize/2, selectionHandleSize)); + selection.Add (new SelectionHandlePart (BoxFill.Box, BoxPos.Start, BoxPos.Center, -selectionHandleSize, -selectionHandleSize/2, BoxPos.Start, BoxPos.Center, 0, selectionHandleSize/2)); + selection.Add (new SelectionHandlePart (BoxFill.Box, BoxPos.End, BoxPos.Center, 0, -selectionHandleSize/2, BoxPos.End, BoxPos.Center, selectionHandleSize, selectionHandleSize/2)); + + dragHandlePart = new SelectionHandlePart (BoxFill.Box, BoxPos.Center, BoxPos.Start, -topSelectionHandleSize/2, -topSelectionHandleSize, BoxPos.Center, BoxPos.Start, topSelectionHandleSize/2, 0); + selection.Add (dragHandlePart); + + foreach (SelectionHandlePart s in selection) { + s.Parent = parent; + s.ParentBox = this; + } + } + + public void Show () + { + foreach (Gtk.Widget s in selection) + s.Show (); + dragHandlePart.Visible = (ObjectSelection != null && ObjectSelection.AllowDrag); + } + + public void Hide () + { + foreach (Gtk.Widget s in selection) + s.Hide (); + } + + public void Reposition (Gdk.Rectangle rect) + { + bool firstRect = true; + + foreach (SelectionHandlePart s in selection) { + s.Reposition (rect); + Gdk.Rectangle r = s.Allocation; + if (firstRect) { + allocation = r; + firstRect = false; + } else + allocation = allocation.Union (r); + } + } + + public Gdk.Rectangle Allocation { + get { return allocation; } + } + + public void ForAll (bool include_internals, Gtk.Callback callback) + { + foreach (Gtk.Widget s in selection) + callback (s); + } + + public void SizeRequest () + { + foreach (Gtk.Widget s in selection) + s.SizeRequest (); + } + } + + class SelectionHandlePart: EventBox + { + BoxPos hpos, vpos; + BoxPos hposEnd, vposEnd; + int x, y; + int xEnd, yEnd; + BoxFill fill; + public SelectionHandleBox ParentBox; + int clickX, clickY; + int localClickX, localClickY; + int ox, oy; + + public SelectionHandlePart (BoxFill fill, BoxPos hpos, BoxPos vpos, int x, int y, BoxPos hposEnd, BoxPos vposEnd, int xEnd, int yEnd) + { + this.fill = fill; + this.hpos = hpos; + this.vpos = vpos; + this.x = x; + this.y = y; + + this.hposEnd = hposEnd; + this.vposEnd = vposEnd; + this.xEnd = xEnd; + this.yEnd = yEnd; + } + + public void Reposition (Gdk.Rectangle rect) + { + int px, py; + int pxEnd, pyEnd; + + CalcPos (rect, hpos, vpos, out px, out py); + px += x; + py += y; + + CalcPos (rect, hposEnd, vposEnd, out pxEnd, out pyEnd); + pxEnd += xEnd; + pyEnd += yEnd; + + Allocation = new Gdk.Rectangle (px, py, pxEnd - px, pyEnd - py); + ox = rect.X; + oy = rect.Y; + } + + void CalcPos (Gdk.Rectangle rect, BoxPos hp, BoxPos vp, out int px, out int py) + { + if (vp == BoxPos.Start) + py = rect.Y; + else if (vp == BoxPos.End) + py = rect.Bottom; + else + py = rect.Y + rect.Height / 2; + + if (hp == BoxPos.Start) + px = rect.X; + else if (hp == BoxPos.End) + px = rect.Right; + else + px = rect.X + rect.Width / 2; + } + + protected override bool OnExposeEvent (Gdk.EventExpose ev) + { + int w, h; + this.GdkWindow.GetSize (out w, out h); + + if (fill == BoxFill.Box) { + this.GdkWindow.DrawRectangle (this.Style.WhiteGC, true, 0, 0, w, h); + this.GdkWindow.DrawRectangle (this.Style.BlackGC, false, 0, 0, w-1, h-1); + } else if (fill == BoxFill.HLine) { + Gdk.GC gc = new Gdk.GC (this.GdkWindow); + gc.SetDashes (0, new sbyte[] {1,1}, 2); + gc.SetLineAttributes (SelectionHandleBox.selectionLineWidth, Gdk.LineStyle.OnOffDash, Gdk.CapStyle.NotLast, Gdk.JoinStyle.Miter); + gc.Foreground = this.Style.Black; + this.GdkWindow.DrawLine (gc, 0, h/2, w, h/2); + gc.Foreground = this.Style.White; + this.GdkWindow.DrawLine (gc, 1, h/2, w, h/2); + } else { + Gdk.GC gc = new Gdk.GC (this.GdkWindow); + gc.SetDashes (0, new sbyte[] {1,1}, 2); + gc.SetLineAttributes (SelectionHandleBox.selectionLineWidth, Gdk.LineStyle.OnOffDash, Gdk.CapStyle.NotLast, Gdk.JoinStyle.Miter); + gc.Foreground = this.Style.Black; + this.GdkWindow.DrawLine (gc, w/2, 0, w/2, h); + gc.Foreground = this.Style.White; + this.GdkWindow.DrawLine (gc, w/2, 1, w/2, h); + } + + return true; + } + + protected override bool OnButtonPressEvent (Gdk.EventButton evb) + { + if (evb.Type == Gdk.EventType.ButtonPress && evb.Button == 1) { + clickX = (int)evb.XRoot; + clickY = (int)evb.YRoot; + localClickX = (int) evb.X; + localClickY = (int) evb.Y; + } + return true; + } + + protected override bool OnMotionNotifyEvent (Gdk.EventMotion evm) + { + if ((evm.State & Gdk.ModifierType.Button1Mask) == 0) + return false; + + if (!Gtk.Drag.CheckThreshold (this, clickX, clickY, (int)evm.XRoot, (int)evm.YRoot)) + return false; + + if (ParentBox.ObjectSelection != null && ParentBox.ObjectSelection.AllowDrag) { + int dx = Allocation.X - ox + localClickX; + int dy = Allocation.Y - oy + localClickY; + ParentBox.ObjectSelection.FireDrag (evm, dx, dy); + } + + return true; + } + } + + class ObjectSelection: IObjectSelection + { + ResizableFixed box; + Gtk.Widget widget; + object dataObject; + bool allowDrag = true; + + public ObjectSelection (ResizableFixed box, Gtk.Widget widget, object dataObject) + { + this.box = box; + this.widget = widget; + this.dataObject = dataObject; + } + + public Gtk.Widget Widget { + get { return widget; } + } + + public object DataObject { + get { return dataObject; } + } + + public void Dispose () + { + box.ResetSelection (widget); + } + + internal void FireDisposed () + { + if (Disposed != null) + Disposed (this, EventArgs.Empty); + } + + internal void FireDrag (Gdk.EventMotion evt, int dx, int dy) + { + if (Drag != null) + Drag (evt, dx, dy); + } + + public bool AllowDrag { + get { return allowDrag; } + set { allowDrag = value; } + } + + public event DragDelegate Drag; + public event EventHandler Disposed; + } +} diff --git a/main/src/addins/MonoDevelop.GtkCore2/libsteticui/WidgetEditSession.cs b/main/src/addins/MonoDevelop.GtkCore2/libsteticui/WidgetEditSession.cs new file mode 100644 index 0000000000..a999efe73c --- /dev/null +++ b/main/src/addins/MonoDevelop.GtkCore2/libsteticui/WidgetEditSession.cs @@ -0,0 +1,368 @@ +// +// WidgetEditSession.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 System.Xml; +using System.Reflection; +using System.Collections; +using System.CodeDom; +using Mono.Unix; + +namespace Stetic { + + internal class WidgetEditSession: MarshalByRefObject, IDisposable + { + string sourceWidget; + Stetic.ProjectBackend project; + + Stetic.Wrapper.Container rootWidget; + Stetic.WidgetDesignerBackend widget; + Gtk.VBox designer; + Gtk.Plug plug; + WidgetActionBar toolbar; + WidgetDesignerFrontend frontend; + bool allowBinding; + bool disposed; + + ContainerUndoRedoManager undoManager; + UndoQueue undoQueue; + + public event EventHandler RootWidgetChanged; + public event Stetic.Wrapper.WidgetEventHandler SelectionChanged; + + public WidgetEditSession (ProjectBackend sourceProject, WidgetDesignerFrontend frontend, string windowName) + { + this.frontend = frontend; + undoManager = new ContainerUndoRedoManager (); + undoQueue = new UndoQueue (); + undoManager.UndoQueue = undoQueue; + + sourceWidget = windowName; + this.project = sourceProject; + + rootWidget = sourceProject.GetTopLevelWrapper (windowName, true); + rootWidget.Select (); + undoManager.RootObject = rootWidget; + + this.project.Changed += new ProjectChangedEventHandler (OnChanged); + this.project.ProjectReloaded += new EventHandler (OnProjectReloaded); + this.project.ProjectReloading += new EventHandler (OnProjectReloading); +// this.project.WidgetMemberNameChanged += new Stetic.Wrapper.WidgetNameChangedHandler (OnWidgetNameChanged); + } + + public bool AllowWidgetBinding { + get { return allowBinding; } + set { + allowBinding = value; + if (toolbar != null) + toolbar.AllowWidgetBinding = allowBinding; + } + } + + public Stetic.Wrapper.Widget GladeWidget { + get { return rootWidget; } + } + + public Stetic.Wrapper.Container RootWidget { + get { return (Wrapper.Container) Component.GetSafeReference (rootWidget); } + } + + public Gtk.Widget WrapperWidget { + get { + if (designer == null) { + if (rootWidget == null) + return widget; + Gtk.Container wc = rootWidget.Wrapped as Gtk.Container; + if (widget == null) + widget = Stetic.UserInterface.CreateWidgetDesigner (wc, rootWidget.DesignWidth, rootWidget.DesignHeight); + + toolbar = new WidgetActionBar (frontend, rootWidget); + toolbar.AllowWidgetBinding = allowBinding; + designer = new Gtk.VBox (); + designer.BorderWidth = 3; + designer.PackStart (toolbar, false, false, 0); + designer.PackStart (widget, true, true, 3); + widget.DesignArea.SetSelection (project.Selection, project.Selection, false); + + widget.SelectionChanged += OnSelectionChanged; + + } + return designer; + } + } + + [NoGuiDispatch] + public void CreateWrapperWidgetPlug (uint socketId) + { + Gdk.Threads.Enter (); + plug = new Gtk.Plug (socketId); + plug.Add (WrapperWidget); + plug.Decorated = false; + plug.ShowAll (); + Gdk.Threads.Leave (); + } + + public void DestroyWrapperWidgetPlug () + { + if (designer != null) { + Gtk.Plug plug = (Gtk.Plug) WrapperWidget.Parent; + plug.Remove (WrapperWidget); + plug.Destroy (); + } + } + + public void Save () + { + } + + public ProjectBackend EditingBackend { + get { return project; } + } + + public void Dispose () + { + project.ComponentTypesChanged -= OnSourceProjectLibsChanged; + project.ProjectReloaded -= OnSourceProjectReloaded; + project.Changed -= new ProjectChangedEventHandler (OnChanged); + project.ProjectReloaded -= OnProjectReloaded; + project.ProjectReloading -= OnProjectReloading; +// project.WidgetMemberNameChanged -= new Stetic.Wrapper.WidgetNameChangedHandler (OnWidgetNameChanged); + + if (plug != null) + plug.Destroy (); + rootWidget = null; + frontend = null; + System.Runtime.Remoting.RemotingServices.Disconnect (this); + disposed = true; + } + + public bool Disposed { + get { return disposed; } + } + + public override object InitializeLifetimeService () + { + // Will be disconnected when calling Dispose + return null; + } + + public void SetDesignerActive () + { + widget.UpdateObjectViewers (); + } + + public bool Modified { + get { + if (project == null || RootWidget == null) + return false; + + return project.WasModified (RootWidget.Name); + } + } + + public UndoQueue UndoQueue { + get { + if (undoQueue != null) + return undoQueue; + else + return UndoQueue.Empty; + } + } + + void OnChanged (object s, ProjectChangedEventArgs a) + { + if (a.ChangedTopLevelName != RootWidget.Name) + return; + + if (frontend != null) + frontend.NotifyChanged (); + } + + void OnSourceProjectReloaded (object s, EventArgs a) + { + + } + + void OnSourceProjectLibsChanged (object s, EventArgs a) + { + } + + void OnProjectReloading (object s, EventArgs a) + { + if (frontend != null) + frontend.NotifyRootWidgetChanging (); + } + + void OnProjectReloaded (object s, EventArgs a) + { + Gtk.Widget topWidget = project.GetWidget (sourceWidget); + + if (topWidget != null) { + rootWidget = Stetic.Wrapper.Container.Lookup (topWidget); + undoManager.RootObject = rootWidget; + if (rootWidget != null) { + Gtk.Widget oldWidget = designer; + if (widget != null) { + widget.SelectionChanged -= OnSelectionChanged; + widget = null; + } + OnRootWidgetChanged (); + if (oldWidget != null) { + // Delay the destruction of the old widget, so the designer has time to + // show the new widget. This avoids flickering. + GLib.Timeout.Add (500, delegate { + oldWidget.Destroy (); + return false; + }); + } + + project.NotifyComponentTypesChanged (); + return; + } + } + SetErrorMode (); + } + + void SetErrorMode () + { + Gtk.Label lab = new Gtk.Label (); + lab.Markup = "<b>" + Catalog.GetString ("The form designer could not be loaded") + "</b>"; + Gtk.EventBox box = new Gtk.EventBox (); + box.Add (lab); + + widget = Stetic.UserInterface.CreateWidgetDesigner (box, 100, 100); + rootWidget = null; + + OnRootWidgetChanged (); + } + + void OnRootWidgetChanged () + { + if (designer != null) { + if (designer.Parent is Gtk.Plug) + ((Gtk.Plug)designer.Parent).Remove (designer); + designer = null; + } + + if (plug != null) { + Gdk.Threads.Enter (); + plug.Add (WrapperWidget); + plug.ShowAll (); + Gdk.Threads.Leave (); + } + + if (frontend != null) + frontend.NotifyRootWidgetChanged (); + if (RootWidgetChanged != null) + RootWidgetChanged (this, EventArgs.Empty); + } + + void OnSelectionChanged (object ob, EventArgs a) + { + if (frontend != null) { + bool canCut, canCopy, canPaste, canDelete; + ObjectWrapper obj = ObjectWrapper.Lookup (widget.Selection); + Stetic.Wrapper.Widget wrapper = obj as Stetic.Wrapper.Widget; + IEditableObject editable = widget.Selection as IEditableObject; + if (editable == null) + editable = obj as IEditableObject; + if (editable != null) { + canCut = editable.CanCut; + canCopy = editable.CanCopy; + canPaste = editable.CanPaste; + canDelete = editable.CanDelete; + } + else { + canCut = canCopy = canPaste = canDelete = false; + } + + frontend.NotifySelectionChanged (Component.GetSafeReference (obj), canCut, canCopy, canPaste, canDelete); + if (SelectionChanged != null) + SelectionChanged (this, new Stetic.Wrapper.WidgetEventArgs (wrapper)); + } + } + + public object SaveState () + { + return new object[] { + project.SaveStatus (), + undoQueue + }; + } + + public void RestoreState (object sessionData) + { + object[] status = (object[]) sessionData; + project.LoadStatus (status [0]); + undoQueue = (UndoQueue) status [1]; + foreach (UndoRedoChange ch in undoQueue.Changes) { + ObjectWrapperUndoRedoChange och = ch as ObjectWrapperUndoRedoChange; + if (och != null) + och.Manager = undoManager; + } + undoManager.UndoQueue = undoQueue; + } + + internal void ClipboardCopySelection () + { + IEditableObject editable = widget.Selection as IEditableObject; + if (editable == null) + editable = ObjectWrapper.Lookup (widget.Selection) as IEditableObject; + if (editable != null) + editable.Copy (); + } + + public void ClipboardCutSelection () + { + IEditableObject editable = widget.Selection as IEditableObject; + if (editable == null) + editable = ObjectWrapper.Lookup (widget.Selection) as IEditableObject; + if (editable != null) + editable.Cut (); + } + + public void ClipboardPaste () + { + IEditableObject editable = widget.Selection as IEditableObject; + if (editable == null) + editable = ObjectWrapper.Lookup (widget.Selection) as IEditableObject; + if (editable != null) + editable.Paste (); + } + + public void DeleteSelection () + { + IEditableObject editable = widget.Selection as IEditableObject; + if (editable == null) + editable = ObjectWrapper.Lookup (widget.Selection) as IEditableObject; + if (editable != null) + editable.Delete (); + } + } +} diff --git a/main/src/addins/MonoDevelop.GtkCore2/libsteticui/WidgetFactory.cs b/main/src/addins/MonoDevelop.GtkCore2/libsteticui/WidgetFactory.cs new file mode 100644 index 0000000000..780b287e16 --- /dev/null +++ b/main/src/addins/MonoDevelop.GtkCore2/libsteticui/WidgetFactory.cs @@ -0,0 +1,136 @@ +using Gtk; +using Gdk; +using System; +using System.Collections; +using System.Reflection; + +namespace Stetic { + + // This is the base class for palette items. Implements the basic + // functionality for showing the icon and label of the item. + + internal class PaletteItemFactory : EventBox + { + public PaletteItemFactory () + { + } + + public virtual void Initialize (string name, Gdk.Pixbuf icon) + { + DND.SourceSet (this); + AboveChild = true; + + Gtk.HBox hbox = new HBox (false, 6); + hbox.BorderWidth = 3; + + if (icon != null) { + icon = icon.ScaleSimple (16, 16, Gdk.InterpType.Bilinear); + hbox.PackStart (new Gtk.Image (icon), false, false, 0); + } + + Gtk.Label label = new Gtk.Label ("<small>" + name + "</small>"); + label.UseMarkup = true; + label.Justify = Justification.Left; + label.Xalign = 0; + hbox.PackEnd (label, true, true, 0); + + Add (hbox); + } + + protected override void OnDragBegin (Gdk.DragContext ctx) + { + Gtk.Widget ob = CreateItemWidget (); + if (ob != null) + DND.Drag (this, ctx, ob); + } + + protected virtual Gtk.Widget CreateItemWidget () + { + return null; + } + + protected override bool OnEnterNotifyEvent (Gdk.EventCrossing ev) + { + this.State = Gtk.StateType.Prelight; + return base.OnEnterNotifyEvent (ev); + } + + protected override bool OnLeaveNotifyEvent (Gdk.EventCrossing ev) + { + this.State = Gtk.StateType.Normal; + return base.OnLeaveNotifyEvent (ev); + } + + protected override bool OnExposeEvent (Gdk.EventExpose e) + { + base.OnExposeEvent (e); + if (State == Gtk.StateType.Prelight) + Gtk.Style.PaintShadow (this.Style, this.GdkWindow, State, Gtk.ShadowType.Out, e.Area, this, "", e.Area.X, e.Area.Y, e.Area.Width, e.Area.Height); + return false; + } + } + + + // Palette item factory which creates a widget. + internal class WidgetFactory : PaletteItemFactory { + + protected ProjectBackend project; + protected ClassDescriptor klass; + + public WidgetFactory (ProjectBackend project, ClassDescriptor klass) + { + this.project = project; + this.klass = klass; + Initialize (klass.Label, klass.Icon); + if (project == null) + Sensitive = false; + } + + protected override Gtk.Widget CreateItemWidget () + { + return klass.NewInstance (project) as Widget; + } + } + + internal class WindowFactory : WidgetFactory + { + public WindowFactory (ProjectBackend project, ClassDescriptor klass) : base (project, klass) + { + } + + protected override bool OnButtonPressEvent (Gdk.EventButton evt) + { + Gtk.Window win = klass.NewInstance (project) as Gtk.Window; + project.AddWindow (win, true); + return true; + } + + public override void Initialize (string name, Gdk.Pixbuf icon) + { + base.Initialize (name, icon); + DND.SourceUnset (this); + } + } + + // Palette item factory which allows dragging an already existing object. + internal class InstanceWidgetFactory : PaletteItemFactory + { + Gtk.Widget instance; + + public InstanceWidgetFactory (string name, Gdk.Pixbuf icon, Gtk.Widget instance) + { + this.instance = instance; + Initialize (name, icon); + } + + protected override Gtk.Widget CreateItemWidget () + { + return instance; + } + + public override void Dispose () + { + base.Dispose (); + } + } +} diff --git a/main/src/addins/MonoDevelop.GtkCore2/libsteticui/WidgetInfoEventHandler.cs b/main/src/addins/MonoDevelop.GtkCore2/libsteticui/WidgetInfoEventHandler.cs new file mode 100644 index 0000000000..1d096dcf2b --- /dev/null +++ b/main/src/addins/MonoDevelop.GtkCore2/libsteticui/WidgetInfoEventHandler.cs @@ -0,0 +1,41 @@ + +using System; + +namespace Stetic +{ + public delegate void WidgetInfoEventHandler (object sender, WidgetInfoEventArgs args); + + public class WidgetInfoEventArgs: EventArgs + { + Project project; + WidgetInfo widget; + + internal WidgetInfoEventArgs (Project p, WidgetInfo w) + { + project = p; + widget = w; + } + + public Project Project { + get { return project; } + } + + public WidgetInfo WidgetInfo { + get { return widget; } + } + } + +/* public class ComponentNameEventArgs: ComponentEventArgs + { + string oldName; + + internal ComponentNameEventArgs (Project p, Component c, string oldName): base (p, c) + { + this.oldName = oldName; + } + + public string OldName { + get { return oldName; } + } + } +*/} diff --git a/main/src/addins/MonoDevelop.GtkCore2/libsteticui/WidgetPropertyTree.cs b/main/src/addins/MonoDevelop.GtkCore2/libsteticui/WidgetPropertyTree.cs new file mode 100644 index 0000000000..3409681428 --- /dev/null +++ b/main/src/addins/MonoDevelop.GtkCore2/libsteticui/WidgetPropertyTree.cs @@ -0,0 +1,28 @@ + +using System; +using Gtk; + +namespace Stetic +{ + public class WidgetPropertyTree: PluggableWidget + { + internal WidgetPropertyTree (Application app): base (app) + { + } + + protected override void OnCreatePlug (uint socketId) + { + app.Backend.CreatePropertiesWidgetPlug (socketId); + } + + protected override void OnDestroyPlug (uint socketId) + { + app.Backend.DestroyPropertiesWidgetPlug (); + } + + protected override Gtk.Widget OnCreateWidget () + { + return app.Backend.GetPropertiesWidget (); + } + } +} diff --git a/main/src/addins/MonoDevelop.GtkCore2/libsteticui/WidgetPropertyTreeBackend.cs b/main/src/addins/MonoDevelop.GtkCore2/libsteticui/WidgetPropertyTreeBackend.cs new file mode 100644 index 0000000000..d4e7d13a5b --- /dev/null +++ b/main/src/addins/MonoDevelop.GtkCore2/libsteticui/WidgetPropertyTreeBackend.cs @@ -0,0 +1,118 @@ + +using System; + +namespace Stetic +{ + internal class WidgetPropertyTreeBackend: PropertyTree, IObjectViewer + { + ProjectBackend project; + Stetic.ObjectWrapper selection; + Stetic.ObjectWrapper newSelection; + Stetic.Wrapper.Container.ContainerChild packingSelection; + + public WidgetPropertyTreeBackend () + { + Stetic.Registry.RegistryChanging += new EventHandler (OnRegistryChanging); + } + + public ProjectBackend ProjectBackend { + get { return project; } + set { + if (project != null) { + project.SelectionChanged -= Selected; + } + + project = value; + if (project != null) { + TargetObject = project.Selection; + project.SelectionChanged += Selected; + } else { + TargetObject = null; + } + } + } + + public override void Clear () + { + base.Clear (); + Wrapper.Widget selWidget = selection as Wrapper.Widget; + if (selWidget != null) + selWidget.Notify -= Notified; + if (packingSelection != null) + packingSelection.Notify -= Notified; + } + + protected override void OnObjectChanged () + { + if (selection != null) + selection.NotifyChanged (); + } + + public object TargetObject { + get { return selection.Wrapped; } + set { + ObjectWrapper wrapper = ObjectWrapper.Lookup (value); + if (newSelection == wrapper) + return; + + newSelection = wrapper; + if (newSelection != null) + GLib.Timeout.Add (50, new GLib.TimeoutHandler (SelectedHandler)); + else + SelectedHandler (); + } + } + + void Selected (object s, Wrapper.WidgetEventArgs args) + { + TargetObject = args != null && args.Widget != null? args.Widget : null; + } + + bool SelectedHandler () + { + SaveStatus (); + + Clear (); + + selection = newSelection; + if (selection == null || selection.Wrapped is ErrorWidget || project == null) { + return false; + } + + Wrapper.Widget selWidget = selection as Wrapper.Widget; + if (selWidget != null) { + selWidget.Notify += Notified; + + PropertyDescriptor name = (PropertyDescriptor)Registry.LookupClassByName ("Gtk.Widget") ["Name"]; + AppendProperty (name, selection.Wrapped); + } + + AddProperties (selection.ClassDescriptor.ItemGroups, selection.Wrapped, project.TargetGtkVersion); + + if (selWidget != null) { + packingSelection = Stetic.Wrapper.Container.ChildWrapper (selWidget); + if (packingSelection != null) { + ClassDescriptor childklass = packingSelection.ClassDescriptor; + if (childklass.ItemGroups.Count > 0) { + AddProperties (childklass.ItemGroups, packingSelection.Wrapped, project.TargetGtkVersion); + packingSelection.Notify += Notified; + } + } + } + + RestoreStatus (); + return false; + } + + void Notified (object wrapper, string propertyName) + { + Update (); + } + + void OnRegistryChanging (object o, EventArgs args) + { + Clear (); + } + } + +} diff --git a/main/src/addins/MonoDevelop.GtkCore2/libsteticui/WidgetTree.cs b/main/src/addins/MonoDevelop.GtkCore2/libsteticui/WidgetTree.cs new file mode 100644 index 0000000000..08e692fb0a --- /dev/null +++ b/main/src/addins/MonoDevelop.GtkCore2/libsteticui/WidgetTree.cs @@ -0,0 +1,92 @@ + +using System; + +namespace Stetic +{ + public class WidgetTree: PluggableWidget + { + ProjectViewFrontend frontend; + + internal WidgetTree (Application app): base (app) + { + frontend = new ProjectViewFrontend (app); + } + + public event ComponentEventHandler ComponentActivated { + add { frontend.ComponentActivated += value; } + remove { frontend.ComponentActivated -= value; } + } + + public event ComponentEventHandler SelectionChanged { + add { frontend.SelectionChanged += value; } + remove { frontend.SelectionChanged -= value; } + } + + protected override void OnCreatePlug (uint socketId) + { + app.Backend.CreateProjectWidgetPlug (frontend, socketId); + } + + protected override void OnDestroyPlug (uint socketId) + { + app.Backend.DestroyProjectWidgetPlug (); + } + + protected override Gtk.Widget OnCreateWidget () + { + return app.Backend.GetProjectWidget (frontend); + } + + public override void Dispose () + { + frontend.disposed = true; + System.Runtime.Remoting.RemotingServices.Disconnect (frontend); + base.Dispose (); + } + } + + + internal class ProjectViewFrontend: MarshalByRefObject + { + Application app; + internal bool disposed; + + public event ComponentEventHandler ComponentActivated; + public event ComponentEventHandler SelectionChanged; + + public ProjectViewFrontend (Application app) + { + this.app = app; + } + + public void NotifyWidgetActivated (object ob, string widgetName, string widgetType) + { + Gtk.Application.Invoke ( + delegate { + if (disposed) return; + Component c = app.GetComponent (ob, widgetName, widgetType); + if (c != null && ComponentActivated != null) + ComponentActivated (null, new ComponentEventArgs (app.ActiveProject, c)); + } + ); + } + + public void NotifySelectionChanged (object ob, string widgetName, string widgetType) + { + Gtk.Application.Invoke ( + delegate { + if (disposed) return; + Component c = ob != null ? app.GetComponent (ob, widgetName, widgetType) : null; + if (SelectionChanged != null) + SelectionChanged (null, new ComponentEventArgs (app.ActiveProject, c)); + } + ); + } + + public override object InitializeLifetimeService () + { + // Will be disconnected when calling Dispose + return null; + } + } +} diff --git a/main/src/addins/MonoDevelop.GtkCore2/libsteticui/WidgetTreeCombo.cs b/main/src/addins/MonoDevelop.GtkCore2/libsteticui/WidgetTreeCombo.cs new file mode 100644 index 0000000000..159f8ec975 --- /dev/null +++ b/main/src/addins/MonoDevelop.GtkCore2/libsteticui/WidgetTreeCombo.cs @@ -0,0 +1,213 @@ + +using System; +using Gtk; + +namespace Stetic +{ + internal class WidgetTreeCombo: Button + { + Label label; + Image image; + Stetic.Wrapper.Widget rootWidget; + Stetic.IProject project; + Stetic.Wrapper.Widget selection; + WidgetTreePopup popup; + + public WidgetTreeCombo () + { + label = new Label (); + image = new Gtk.Image (); + + HBox bb = new HBox (); + bb.PackStart (image, false, false, 3); + bb.PackStart (label, true, true, 3); + label.Xalign = 0; + label.HeightRequest = 18; + bb.PackStart (new VSeparator (), false, false, 1); + bb.PackStart (new Arrow (ArrowType.Down, ShadowType.None), false, false, 1); + Child = bb; + this.WidthRequest = 300; + Sensitive = false; + } + + public override void Dispose () + { + if (popup != null) + popup.Destroy (); + base.Dispose (); + } + + + public Stetic.Wrapper.Widget RootWidget { + get { return rootWidget; } + set { + rootWidget = value; + Sensitive = rootWidget != null; + if (rootWidget != null) + project = rootWidget.Project; + Update (); + } + } + + public void SetSelection (Stetic.Wrapper.Widget widget) + { + selection = widget; + Update (); + } + + void Update () + { + if (selection != null) { + label.Text = selection.Wrapped.Name; + image.Pixbuf = selection.ClassDescriptor.Icon.ScaleSimple (16, 16, Gdk.InterpType.Bilinear); + image.Show (); + } else { + label.Text = " "; + image.Hide (); + } + } + + protected override void OnPressed () + { + base.OnPressed (); + if (popup == null) { + popup = new WidgetTreePopup (project); + popup.WidgetActivated += OnPopupActivated; + popup.SetDefaultSize (Allocation.Width, 500); + } + else if (popup.Visible) { + popup.Hide (); + return; + } + + int x, y; + ParentWindow.GetOrigin (out x, out y); + x += Allocation.X; + y += Allocation.Y + Allocation.Height; + + popup.Fill (RootWidget.Wrapped); + popup.Move (x, y); + popup.ShowAll (); + } + + protected override bool OnFocusOutEvent (Gdk.EventFocus evnt) + { + if (popup != null) + popup.Hide (); + return base.OnFocusOutEvent (evnt); + } + + + void OnPopupActivated (object s, EventArgs a) + { + popup.Hide (); + Stetic.Wrapper.Widget wrapper = Stetic.Wrapper.Widget.Lookup (popup.Selection); + GLib.Timeout.Add (10, delegate { + wrapper.Select (); + return false; + }); + } + } + + class WidgetTreePopup: Window + { + TreeView tree; + TreeStore store; + Gtk.Widget selection; + Stetic.IProject project; + + public event EventHandler WidgetActivated; + + public WidgetTreePopup (Stetic.IProject project): base (WindowType.Popup) + { + this.project = project; + Gtk.Frame frame = new Frame (); + frame.ShadowType = Gtk.ShadowType.Out; + Add (frame); + + Gtk.ScrolledWindow sc = new ScrolledWindow (); + sc.VscrollbarPolicy = PolicyType.Automatic; + sc.HscrollbarPolicy = PolicyType.Automatic; + frame.Add (sc); + + tree = new TreeView (); + store = new TreeStore (typeof(Gdk.Pixbuf), typeof(string), typeof(Widget)); + tree.Model = store; + tree.HeadersVisible = false; + + TreeViewColumn col = new TreeViewColumn (); + CellRendererPixbuf cr = new CellRendererPixbuf (); + col.PackStart (cr, false); + col.AddAttribute (cr, "pixbuf", 0); + + CellRendererText tr = new CellRendererText (); + col.PackStart (tr, true); + col.AddAttribute (tr, "markup", 1); + + tree.AppendColumn (col); + + tree.ButtonReleaseEvent += OnButtonRelease; + tree.RowActivated += OnButtonRelease; + sc.Add (tree); + tree.GrabFocus (); + + } + + public void Fill (Gtk.Widget widget) + { + store.Clear (); + Fill (TreeIter.Zero, widget); + } + + public void Fill (TreeIter iter, Gtk.Widget widget) + { + Stetic.Wrapper.Widget wrapper = Stetic.Wrapper.Widget.Lookup (widget); + if (wrapper == null) return; + + if (!wrapper.Unselectable) { + + Gdk.Pixbuf icon = wrapper.ClassDescriptor.Icon.ScaleSimple (16, 16, Gdk.InterpType.Bilinear); + string txt; + if (widget == project.Selection) + txt = "<b>" + GLib.Markup.EscapeText (widget.Name) + "</b>"; + else + txt = GLib.Markup.EscapeText (widget.Name); + + if (!iter.Equals (TreeIter.Zero)) + iter = store.AppendValues (iter, icon, txt, widget); + else + iter = store.AppendValues (icon, txt, widget); + } + + Gtk.Container cc = widget as Gtk.Container; + if (cc != null && wrapper.ClassDescriptor.AllowChildren) { + foreach (Gtk.Widget child in cc.Children) + Fill (iter, child); + } + if (widget == project.Selection) { + tree.ExpandToPath (store.GetPath (iter)); + tree.ExpandRow (store.GetPath (iter), false); + tree.Selection.SelectIter (iter); + } + } + + public Gtk.Widget Selection { + get { return selection; } + } + + void OnButtonRelease (object s, EventArgs a) + { + NotifyActivated (); + } + + void NotifyActivated () + { + TreeIter iter; + if (!tree.Selection.GetSelected (out iter)) + return; + selection = (Gtk.Widget) store.GetValue (iter, 2); + if (WidgetActivated != null) + WidgetActivated (this, EventArgs.Empty); + } + } +} diff --git a/main/src/addins/MonoDevelop.GtkCore2/libsteticui/Windows/Preview.cs b/main/src/addins/MonoDevelop.GtkCore2/libsteticui/Windows/Preview.cs new file mode 100644 index 0000000000..aee001e559 --- /dev/null +++ b/main/src/addins/MonoDevelop.GtkCore2/libsteticui/Windows/Preview.cs @@ -0,0 +1,109 @@ +using System; +using System.Collections.Generic; +using System.Text; +using Gtk; +using Gdk; + +namespace Stetic.Windows +{ + class Preview: Bin + { + Gtk.Widget child; + WindowsTheme wtheme; + string caption; + + public Preview ( ) + { + DoubleBuffered = false; + AppPaintable = true; + } + + public static Preview Create (TopLevelWindow window) + { + if (System.IO.Path.DirectorySeparatorChar != '\\') + return null; + try { + Preview p = new Preview (); + p.Add (window); + return p; + } + catch { + return null; + } + } + + public string Title { + get { return caption; } + set { + caption = value; + QueueDraw (); + } + } + + protected override void OnDestroyed ( ) + { + if (wtheme != null) + wtheme.Dipose (); + base.OnDestroyed (); + } + + protected override void OnAdded (Widget widget) + { + base.OnAdded (widget); + child = widget; + if (child is TopLevelWindow) { + ((TopLevelWindow) child).PropertyChanged += Preview_TitleChanged; + Title = ((TopLevelWindow) child).Title; + } + } + + void Preview_TitleChanged (object sender, EventArgs e) + { + Title = ((TopLevelWindow) child).Title; + } + + protected override void OnRemoved (Widget widget) + { + base.OnRemoved (widget); + if (widget == child) { + if (child is TopLevelWindow) + ((TopLevelWindow) child).PropertyChanged -= Preview_TitleChanged; + child = null; + } + } + + protected override void OnSizeRequested (ref Requisition requisition) + { + if (child != null) + requisition = child.SizeRequest (); + } + + protected override void OnSizeAllocated (Gdk.Rectangle allocation) + { + base.OnSizeAllocated (allocation); + if (child != null) { + if (wtheme != null) + child.Allocation = wtheme.GetWindowClientArea (allocation); + else + child.Allocation = allocation; + } + } + + protected override void OnRealized ( ) + { + base.OnRealized (); + wtheme = new WindowsTheme (GdkWindow); + if (child != null) + child.Allocation = wtheme.GetWindowClientArea (Allocation); + } + + protected override bool OnExposeEvent (Gdk.EventExpose evnt) + { +// Gdk.Rectangle rect = new Gdk.Rectangle (Allocation.X+50, Allocation.Y+50, Allocation.Width - 1, Allocation.Height - 1); + wtheme.DrawWindowFrame (this, caption, Allocation.X, Allocation.Y, Allocation.Width, Allocation.Height); + foreach (Widget child in Children) + PropagateExpose (child, evnt); + return false; + } + } +} diff --git a/main/src/addins/MonoDevelop.GtkCore2/libsteticui/Windows/WindowsTheme.cs b/main/src/addins/MonoDevelop.GtkCore2/libsteticui/Windows/WindowsTheme.cs new file mode 100644 index 0000000000..bdc4a3a1eb --- /dev/null +++ b/main/src/addins/MonoDevelop.GtkCore2/libsteticui/Windows/WindowsTheme.cs @@ -0,0 +1,201 @@ +using System; +using System.Collections.Generic; +using System.Text; +using System.Runtime.InteropServices; + +namespace Stetic.Windows +{ + class WindowsTheme + { + IntPtr hWnd; + IntPtr hTheme; + + public WindowsTheme (Gdk.Window win) + { + hWnd = gdk_win32_drawable_get_handle (win.Handle); + hTheme = OpenThemeData (hWnd, "WINDOW"); + } + + public void Dipose ( ) + { + CloseThemeData (hTheme); + } + + public void DrawWindowFrame (Gtk.Widget w, string caption, int x, int y, int width, int height) + { + Gdk.Drawable drawable = w.GdkWindow; + Gdk.Pixmap pix = new Gdk.Pixmap (drawable, width, height, drawable.Depth); + + Gdk.GC gcc = new Gdk.GC (pix); + gcc.Foreground = w.Style.Backgrounds [(int)Gtk.StateType.Normal]; + pix.DrawRectangle (gcc, true, 0, 0, width, height); + + IntPtr hdc = gdk_win32_hdc_get (pix.Handle, gcc.Handle, 0); + + RECT r = new RECT (0, 0, width, height); + SIZE size; + GetThemePartSize (hTheme, hdc, WP_CAPTION, CS_ACTIVE, ref r, 1, out size); + + r.Bottom = size.cy; + DrawThemeBackground (hTheme, hdc, WP_CAPTION, CS_ACTIVE, ref r, ref r); + + RECT rf = new RECT (FrameBorder, FrameBorder, width - FrameBorder * 2, size.cy); + LOGFONT lf = new LOGFONT (); + GetThemeSysFont (hTheme, TMT_CAPTIONFONT, ref lf); + IntPtr titleFont = CreateFontIndirect (ref lf); + IntPtr oldFont = SelectObject (hdc, titleFont); + SetBkMode (hdc, 1 /*TRANSPARENT*/); + DrawThemeText (hTheme, hdc, WP_CAPTION, CS_ACTIVE, caption, -1, DT_LEFT | DT_SINGLELINE | DT_WORD_ELLIPSIS, 0, ref rf); + SelectObject (hdc, oldFont); + DeleteObject (titleFont); + + int ny = r.Bottom; + r = new RECT (0, ny, width, height); + DrawThemeBackground (hTheme, hdc, WP_FRAMEBOTTOM, 0, ref r, ref r); + + gdk_win32_hdc_release (pix.Handle, gcc.Handle, 0); + + Gdk.Pixbuf img = Gdk.Pixbuf.FromDrawable (pix, pix.Colormap, 0, 0, 0, 0, width, height); + drawable.DrawPixbuf (new Gdk.GC (drawable), img, 0, 0, x, y, width, height, Gdk.RgbDither.None, 0, 0); + drawable.DrawRectangle (w.Style.BackgroundGC (Gtk.StateType.Normal), true, x + FrameBorder, y + size.cy, width - FrameBorder * 2, height - FrameBorder - size.cy); + } + + public Gdk.Rectangle GetWindowClientArea (Gdk.Rectangle allocation) + { + IntPtr hdc = GetDC (hWnd); + RECT r = new RECT (allocation.X, allocation.Y, allocation.X + allocation.Width, allocation.Y + allocation.Height); + SIZE size; + GetThemePartSize (hTheme, hdc, WP_CAPTION, CS_ACTIVE, ref r, 1, out size); + ReleaseDC (hWnd, hdc); + + return new Gdk.Rectangle (allocation.X + FrameBorder, allocation.Y + size.cy, allocation.Width - FrameBorder * 2, allocation.Height - size.cy - FrameBorder); + } + + const int FrameBorder = 8; + + const int WP_CAPTION = 1; + const int WP_FRAMEBOTTOM = 9; + const int CS_ACTIVE = 1; + const int TMT_CAPTIONFONT = 801; + + const int DT_LEFT = 0x0; + const int DT_WORD_ELLIPSIS = 0x40000; + const int DT_SINGLELINE = 0x20; + + + [DllImport ("uxtheme", ExactSpelling = true)] + extern static Int32 DrawThemeBackground (IntPtr hTheme, IntPtr hdc, int iPartId, + int iStateId, ref RECT pRect, ref RECT pClipRect); + + [DllImport ("uxtheme.dll", ExactSpelling = true, CharSet = CharSet.Unicode)] + static extern IntPtr OpenThemeData (IntPtr hWnd, String classList); + + [DllImport ("uxtheme.dll", ExactSpelling = true)] + extern static Int32 CloseThemeData (IntPtr hTheme); + + [DllImport ("uxtheme", ExactSpelling = true)] + extern static Int32 GetThemePartSize (IntPtr hTheme, IntPtr hdc, int part, int state, ref RECT pRect, int eSize, out SIZE size); + + [DllImport ("uxtheme", ExactSpelling = true)] + extern static Int32 GetThemeBackgroundExtent (IntPtr hTheme, IntPtr hdc, int iPartId, int iStateId, ref RECT pBoundingRect, out RECT pContentRect); + + [DllImport ("uxtheme", ExactSpelling = true)] + extern static Int32 GetThemeMargins (IntPtr hTheme, IntPtr hdc, int iPartId, int iStateId, int iPropId, out MARGINS pMargins); + + [DllImport ("uxtheme", ExactSpelling = true, CharSet = CharSet.Unicode)] + extern static Int32 DrawThemeText (IntPtr hTheme, IntPtr hdc, int iPartId, int iStateId, String text, int textLength, UInt32 textFlags, UInt32 textFlags2, ref RECT pRect); + + [DllImport ("uxtheme", ExactSpelling = true, CharSet = CharSet.Unicode)] + extern static Int32 GetThemeSysFont (IntPtr hTheme, int iFontId, ref LOGFONT plf); + + [DllImport ("gdi32.dll")] + static extern IntPtr CreateFontIndirect ([In] ref LOGFONT lplf); + + [DllImport ("gdi32.dll")] + static extern int SetBkMode (IntPtr hdc, int iBkMode); + + [DllImport ("gdi32.dll", ExactSpelling = true, PreserveSig = true, SetLastError = true)] + static extern IntPtr SelectObject (IntPtr hdc, IntPtr hgdiobj); + + [DllImport ("gdi32.dll")] + static extern bool DeleteObject (IntPtr hObject); + + [DllImport ("user32.dll")] + static extern IntPtr GetDC (IntPtr hWnd); + + [DllImport ("user32.dll")] + static extern int ReleaseDC (IntPtr hWnd, IntPtr hDC); + + [DllImport ("libgdk-win32-2.0-0.dll")] + static extern IntPtr gdk_win32_drawable_get_handle (IntPtr raw); + + [DllImport ("libgdk-win32-2.0-0.dll")] + static extern IntPtr gdk_win32_hdc_get (IntPtr drawable, IntPtr gc, int usage); + + [DllImport ("libgdk-win32-2.0-0.dll")] + static extern void gdk_win32_hdc_release (IntPtr drawable, IntPtr gc, int usage); + } + + + [Serializable, StructLayout (LayoutKind.Sequential)] + public struct RECT + { + public int Left; + public int Top; + public int Right; + public int Bottom; + + public RECT (int left_, int top_, int right_, int bottom_) + { + Left = left_; + Top = top_; + Right = right_; + Bottom = bottom_; + } + + public int Height { get { return Bottom - Top; } } + public int Width { get { return Right - Left; } } + } + + [StructLayout (LayoutKind.Sequential)] + public struct SIZE + { + public int cx; + public int cy; + + public SIZE (int cx, int cy) + { + this.cx = cx; + this.cy = cy; + } + } + + [StructLayout (LayoutKind.Sequential)] + public struct MARGINS + { + public int leftWidth; + public int rightWidth; + public int topHeight; + public int bottomHeight; + } + + [StructLayout (LayoutKind.Sequential, CharSet = CharSet.Auto)] + public struct LOGFONT + { + public int lfHeight; + public int lfWidth; + public int lfEscapement; + public int lfOrientation; + public int lfWeight; + public byte lfItalic; + public byte lfUnderline; + public byte lfStrikeOut; + public byte lfCharSet; + public byte lfOutPrecision; + public byte lfClipPrecision; + public byte lfQuality; + public byte lfPitchAndFamily; + [MarshalAs (UnmanagedType.ByValTStr, SizeConst = 32)] + public string lfFaceName; + } +} diff --git a/main/src/addins/MonoDevelop.GtkCore2/libsteticui/action.png b/main/src/addins/MonoDevelop.GtkCore2/libsteticui/action.png Binary files differnew file mode 100644 index 0000000000..fa6a6c8a12 --- /dev/null +++ b/main/src/addins/MonoDevelop.GtkCore2/libsteticui/action.png diff --git a/main/src/addins/MonoDevelop.GtkCore2/libsteticui/bin/Release/libstetic2.dll.config b/main/src/addins/MonoDevelop.GtkCore2/libsteticui/bin/Release/libstetic2.dll.config new file mode 100644 index 0000000000..8c4c6ab9a9 --- /dev/null +++ b/main/src/addins/MonoDevelop.GtkCore2/libsteticui/bin/Release/libstetic2.dll.config @@ -0,0 +1,8 @@ +<configuration> + <dllmap dll="libgobject-2.0-0.dll" target="libgobject-2.0.so.0" os="!osx,windows" /> + <dllmap dll="libgobject-2.0-0.dll" target="libgobject-2.0.dylib" os="osx" /> + <dllmap dll="libgtk-win32-2.0-0.dll" target="libgtk-x11-2.0.so.0" os="!osx,windows"/> + <dllmap dll="libgtk-win32-2.0-0.dll" target="libgtk-quartz-2.0.dylib" os="osx"/> + <dllmap dll="libgdk-win32-2.0-0.dll" target="libgdk-x11-2.0.so.0" os="!osx,windows"/> + <dllmap dll="libgdk-win32-2.0-0.dll" target="libgdk-quartz-2.0.dylib" os="osx"/> +</configuration> diff --git a/main/src/addins/MonoDevelop.GtkCore2/libsteticui/bin/Release/libsteticui2.dll.config b/main/src/addins/MonoDevelop.GtkCore2/libsteticui/bin/Release/libsteticui2.dll.config new file mode 100644 index 0000000000..8c4c6ab9a9 --- /dev/null +++ b/main/src/addins/MonoDevelop.GtkCore2/libsteticui/bin/Release/libsteticui2.dll.config @@ -0,0 +1,8 @@ +<configuration> + <dllmap dll="libgobject-2.0-0.dll" target="libgobject-2.0.so.0" os="!osx,windows" /> + <dllmap dll="libgobject-2.0-0.dll" target="libgobject-2.0.dylib" os="osx" /> + <dllmap dll="libgtk-win32-2.0-0.dll" target="libgtk-x11-2.0.so.0" os="!osx,windows"/> + <dllmap dll="libgtk-win32-2.0-0.dll" target="libgtk-quartz-2.0.dylib" os="osx"/> + <dllmap dll="libgdk-win32-2.0-0.dll" target="libgdk-x11-2.0.so.0" os="!osx,windows"/> + <dllmap dll="libgdk-win32-2.0-0.dll" target="libgdk-quartz-2.0.dylib" os="osx"/> +</configuration> diff --git a/main/src/addins/MonoDevelop.GtkCore2/libsteticui/libsteticui.csproj b/main/src/addins/MonoDevelop.GtkCore2/libsteticui/libsteticui.csproj new file mode 100644 index 0000000000..27b35ca797 --- /dev/null +++ b/main/src/addins/MonoDevelop.GtkCore2/libsteticui/libsteticui.csproj @@ -0,0 +1,172 @@ +<?xml version="1.0" encoding="utf-8"?> +<Project DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003" ToolsVersion="3.5"> + <PropertyGroup> + <Configuration Condition=" '$(Configuration)' == '' ">Debug</Configuration> + <Platform Condition=" '$(Platform)' == '' ">AnyCPU</Platform> + <ProductVersion>9.0.21022</ProductVersion> + <SchemaVersion>2.0</SchemaVersion> + <ProjectGuid>{8951D80F-B2D6-4B4E-B119-28FFE3B7B1C0}</ProjectGuid> + <OutputType>Library</OutputType> + <TargetFrameworkVersion>v3.5</TargetFrameworkVersion> + <AssemblyName>libsteticui2</AssemblyName> + <RootNamespace>libsteticui</RootNamespace> + </PropertyGroup> + <PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|AnyCPU' "> + <DebugSymbols>true</DebugSymbols> + <DebugType>full</DebugType> + <Optimize>false</Optimize> + <OutputPath>..\..\..\..\build\AddIns\MonoDevelop.GtkCore2</OutputPath> + <DefineConstants>DEBUG</DefineConstants> + <ErrorReport>prompt</ErrorReport> + <WarningLevel>4</WarningLevel> + <additionalargs>-unsafe</additionalargs> + <Execution> + <Execution clr-version="Net_2_0" /> + </Execution> + <AllowUnsafeBlocks>true</AllowUnsafeBlocks> + </PropertyGroup> + <PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|AnyCPU' "> + <DebugType>none</DebugType> + <Optimize>false</Optimize> + <OutputPath>bin\Release</OutputPath> + <ErrorReport>prompt</ErrorReport> + <WarningLevel>4</WarningLevel> + <Execution> + <Execution clr-version="Net_2_0" /> + </Execution> + <AllowUnsafeBlocks>true</AllowUnsafeBlocks> + </PropertyGroup> + <ItemGroup> + <Reference Include="Mono.Posix" /> + <Reference Include="System" /> + <Reference Include="System.Runtime.Remoting" /> + <Reference Include="System.Xml" /> + <Reference Include="glade-sharp, Version=2.12.0.0, Culture=neutral, PublicKeyToken=35e10195dab3c99f"> + <SpecificVersion>False</SpecificVersion> + </Reference> + <Reference Include="glib-sharp, Version=2.12.0.0, Culture=neutral, PublicKeyToken=35e10195dab3c99f"> + <SpecificVersion>False</SpecificVersion> + </Reference> + <Reference Include="pango-sharp, Version=2.12.0.0, Culture=neutral, PublicKeyToken=35e10195dab3c99f"> + <SpecificVersion>False</SpecificVersion> + </Reference> + <Reference Include="atk-sharp, Version=2.12.0.0, Culture=neutral, PublicKeyToken=35e10195dab3c99f"> + <SpecificVersion>False</SpecificVersion> + </Reference> + <Reference Include="gdk-sharp, Version=2.12.0.0, Culture=neutral, PublicKeyToken=35e10195dab3c99f"> + <SpecificVersion>False</SpecificVersion> + </Reference> + <Reference Include="gtk-sharp, Version=2.12.0.0, Culture=neutral, PublicKeyToken=35e10195dab3c99f"> + <SpecificVersion>False</SpecificVersion> + </Reference> + <Reference Include="System.Core" /> + </ItemGroup> + <ItemGroup> + <ProjectReference Include="..\..\..\..\contrib\Mono.Cecil\Mono.Cecil.csproj"> + <Project>{3EC06433-F168-4C5B-A885-99CE4AB617E1}</Project> + <Name>Mono.Cecil</Name> + <Private>False</Private> + </ProjectReference> + <ProjectReference Include="..\..\MonoDevelop.GtkCore2\libstetic\libstetic.csproj"> + <Project>{F870E2E7-FA64-4B2F-968A-90B36AB7AAA9}</Project> + <Name>libstetic2</Name> + </ProjectReference> + </ItemGroup> + <ItemGroup> + <Compile Include="ActionComponent.cs" /> + <Compile Include="ActionGroupComponent.cs" /> + <Compile Include="ActionGroupDesigner.cs" /> + <Compile Include="ActionGroupDesignerBackend.cs" /> + <Compile Include="ActionGroupEditSession.cs" /> + <Compile Include="ActionGroupToolbar.cs" /> + <Compile Include="Application.cs" /> + <Compile Include="ApplicationBackend.cs" /> + <Compile Include="ApplicationBackendController.cs" /> + <Compile Include="AssemblyResolver.cs" /> + <Compile Include="AssemblyWidgetLibrary.cs" /> + <Compile Include="CecilClassDescriptor.cs" /> + <Compile Include="CecilPropertyDescriptor.cs" /> + <Compile Include="CecilSignalDescriptor.cs" /> + <Compile Include="CecilWidgetLibrary.cs" /> + <Compile Include="CodeGenerationResult.cs" /> + <Compile Include="CodeGenerator.cs" /> + <Compile Include="CodeGeneratorInternalClass.cs" /> + <Compile Include="CodeGeneratorPartialClass.cs" /> + <Compile Include="Component.cs" /> + <Compile Include="ComponentEventHandler.cs" /> + <Compile Include="ComponentSignalEventHandler.cs" /> + <Compile Include="ComponentType.cs" /> + <Compile Include="ContainerUndoRedoManager.cs" /> + <Compile Include="ContextMenu.cs" /> + <Compile Include="Designer.cs" /> + <Compile Include="Glade.cs" /> + <Compile Include="Grid.cs" /> + <Compile Include="GuiDispatchServerSink.cs" /> + <Compile Include="GuiDispatchServerSinkProvider.cs" /> + <Compile Include="LibraryCache.cs" /> + <Compile Include="Metacity\ButtonFunction.cs" /> + <Compile Include="Metacity\ButtonLayout.cs" /> + <Compile Include="Metacity\FrameFlags.cs" /> + <Compile Include="Metacity\FrameType.cs" /> + <Compile Include="Metacity\ObjectManager.cs" /> + <Compile Include="Metacity\Preview.cs" /> + <Compile Include="Metacity\Theme.cs" /> + <Compile Include="Palette.cs" /> + <Compile Include="PaletteBackend.cs" /> + <Compile Include="PluggableWidget.cs" /> + <Compile Include="Project.cs" /> + <Compile Include="ProjectBackend.cs" /> + <Compile Include="ProjectViewBackend.cs" /> + <Compile Include="PropertyEditor.cs" /> + <Compile Include="PropertyGrid.cs" /> + <Compile Include="PropertyTree.cs" /> + <Compile Include="Shadow.cs" /> + <Compile Include="SignalsEditor.cs" /> + <Compile Include="SignalsEditorBackend.cs" /> + <Compile Include="UndoQueue.cs" /> + <Compile Include="UserInterface.cs" /> + <Compile Include="WidgetActionBar.cs" /> + <Compile Include="WidgetComponent.cs" /> + <Compile Include="WidgetDesigner.cs" /> + <Compile Include="WidgetDesignerBackend.cs" /> + <Compile Include="WidgetEditSession.cs" /> + <Compile Include="WidgetFactory.cs" /> + <Compile Include="WidgetInfoEventHandler.cs" /> + <Compile Include="WidgetPropertyTree.cs" /> + <Compile Include="WidgetPropertyTreeBackend.cs" /> + <Compile Include="WidgetTree.cs" /> + <Compile Include="WidgetTreeCombo.cs" /> + <Compile Include="Windows\Preview.cs" /> + <Compile Include="Windows\WindowsTheme.cs" /> + </ItemGroup> + <ItemGroup> + <EmbeddedResource Include="action.png"> + <LogicalName>action.png</LogicalName> + </EmbeddedResource> + <EmbeddedResource Include="missing.png"> + <LogicalName>missing.png</LogicalName> + </EmbeddedResource> + </ItemGroup> + <ItemGroup> + <None Include="libsteticui.dll.config"> + <CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory> + </None> + </ItemGroup> + <Import Project="$(MSBuildBinPath)\Microsoft.CSharp.targets" /> + <ProjectExtensions> + <MonoDevelop> + <Properties> + <MonoDevelop.Autotools.MakefileInfo IntegrationEnabled="true" RelativeMakefileName="Makefile.am" BuildTargetName="" CleanTargetName="" SyncReferences="true" IsAutotoolsProject="true" RelativeConfigureInPath="../../../.."> + <BuildFilesVar Sync="true" Name="FILES" /> + <DeployFilesVar /> + <ResourcesVar Sync="true" Name="RES" /> + <OthersVar /> + <GacRefVar Sync="true" Name="REFS" Prefix="-r:" /> + <AsmRefVar Sync="true" Name="REFS" Prefix="-r:" /> + <ProjectRefVar Sync="true" Name="DEPS" /> + </MonoDevelop.Autotools.MakefileInfo> + </Properties> + </MonoDevelop> + <VisualStudio /> + </ProjectExtensions> +</Project> diff --git a/main/src/addins/MonoDevelop.GtkCore2/libsteticui/libsteticui.dll.config b/main/src/addins/MonoDevelop.GtkCore2/libsteticui/libsteticui.dll.config new file mode 100644 index 0000000000..8c4c6ab9a9 --- /dev/null +++ b/main/src/addins/MonoDevelop.GtkCore2/libsteticui/libsteticui.dll.config @@ -0,0 +1,8 @@ +<configuration> + <dllmap dll="libgobject-2.0-0.dll" target="libgobject-2.0.so.0" os="!osx,windows" /> + <dllmap dll="libgobject-2.0-0.dll" target="libgobject-2.0.dylib" os="osx" /> + <dllmap dll="libgtk-win32-2.0-0.dll" target="libgtk-x11-2.0.so.0" os="!osx,windows"/> + <dllmap dll="libgtk-win32-2.0-0.dll" target="libgtk-quartz-2.0.dylib" os="osx"/> + <dllmap dll="libgdk-win32-2.0-0.dll" target="libgdk-x11-2.0.so.0" os="!osx,windows"/> + <dllmap dll="libgdk-win32-2.0-0.dll" target="libgdk-quartz-2.0.dylib" os="osx"/> +</configuration> diff --git a/main/src/addins/MonoDevelop.GtkCore2/libsteticui/libsteticui2.csproj b/main/src/addins/MonoDevelop.GtkCore2/libsteticui/libsteticui2.csproj new file mode 100644 index 0000000000..6db4c76953 --- /dev/null +++ b/main/src/addins/MonoDevelop.GtkCore2/libsteticui/libsteticui2.csproj @@ -0,0 +1,188 @@ +<?xml version="1.0" encoding="utf-8"?> +<Project DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003" ToolsVersion="3.5"> + <PropertyGroup> + <Configuration Condition=" '$(Configuration)' == '' ">Debug</Configuration> + <Platform Condition=" '$(Platform)' == '' ">AnyCPU</Platform> + <ProductVersion>9.0.21022</ProductVersion> + <SchemaVersion>2.0</SchemaVersion> + <ProjectGuid>{8951D80F-B2D6-4B4E-B119-28FFE3B7B1C0}</ProjectGuid> + <OutputType>Library</OutputType> + <TargetFrameworkVersion>v3.5</TargetFrameworkVersion> + <AssemblyName>libsteticui2</AssemblyName> + <RootNamespace>libsteticui</RootNamespace> + </PropertyGroup> + <PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|AnyCPU' "> + <DebugSymbols>true</DebugSymbols> + <DebugType>full</DebugType> + <Optimize>false</Optimize> + <OutputPath>..\..\..\..\build\AddIns\MonoDevelop.GtkCore2</OutputPath> + <DefineConstants>DEBUG</DefineConstants> + <ErrorReport>prompt</ErrorReport> + <WarningLevel>4</WarningLevel> + <additionalargs>-unsafe</additionalargs> + <Execution> + <Execution clr-version="Net_2_0" /> + </Execution> + <AllowUnsafeBlocks>true</AllowUnsafeBlocks> + </PropertyGroup> + <PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|AnyCPU' "> + <DebugType>none</DebugType> + <Optimize>false</Optimize> + <OutputPath>bin\Release</OutputPath> + <ErrorReport>prompt</ErrorReport> + <WarningLevel>4</WarningLevel> + <Execution> + <Execution clr-version="Net_2_0" /> + </Execution> + <AllowUnsafeBlocks>true</AllowUnsafeBlocks> + </PropertyGroup> + <ItemGroup> + <Reference Include="Mono.Posix" /> + <Reference Include="System" /> + <Reference Include="System.Runtime.Remoting" /> + <Reference Include="System.Xml" /> + <Reference Include="glade-sharp, Version=2.12.0.0, Culture=neutral, PublicKeyToken=35e10195dab3c99f"> + <SpecificVersion>False</SpecificVersion> + </Reference> + <Reference Include="glib-sharp, Version=2.12.0.0, Culture=neutral, PublicKeyToken=35e10195dab3c99f"> + <SpecificVersion>False</SpecificVersion> + </Reference> + <Reference Include="pango-sharp, Version=2.12.0.0, Culture=neutral, PublicKeyToken=35e10195dab3c99f"> + <SpecificVersion>False</SpecificVersion> + </Reference> + <Reference Include="atk-sharp, Version=2.12.0.0, Culture=neutral, PublicKeyToken=35e10195dab3c99f"> + <SpecificVersion>False</SpecificVersion> + </Reference> + <Reference Include="gdk-sharp, Version=2.12.0.0, Culture=neutral, PublicKeyToken=35e10195dab3c99f"> + <SpecificVersion>False</SpecificVersion> + </Reference> + <Reference Include="gtk-sharp, Version=2.12.0.0, Culture=neutral, PublicKeyToken=35e10195dab3c99f"> + <SpecificVersion>False</SpecificVersion> + </Reference> + <Reference Include="System.Core" /> + <Reference Include="Mono.Cecil, Version=0.6.9.0, Culture=neutral, PublicKeyToken=0738eb9f132ed756"> + <Package>monodevelop</Package> + </Reference> + <Reference Include="MonoDevelop.Core, Version=2.4.0.0, Culture=neutral"> + <Package>monodevelop</Package> + </Reference> + <Reference Include="MonoDevelop.Ide, Version=2.4.0.0, Culture=neutral"> + <Package>monodevelop</Package> + </Reference> + <Reference Include="NRefactory, Version=2.1.1.0, Culture=neutral, PublicKeyToken=efe927acf176eea2"> + <Package>monodevelop</Package> + </Reference> + <Reference Include="Mono.TextEditor, Version=1.0.0.0, Culture=neutral"> + <Package>monodevelop</Package> + </Reference> + <Reference Include="Mono.Debugging, Version=0.0.0.0, Culture=neutral, PublicKeyToken=9307d64546e0580d"> + <Package>monodevelop</Package> + </Reference> + </ItemGroup> + <ItemGroup> + <ProjectReference Include="..\libstetic\libstetic2.csproj"> + <Project>{90CBA7FD-CB46-4711-97BB-2420DC01F016}</Project> + <Name>libstetic2</Name> + </ProjectReference> + </ItemGroup> + <ItemGroup> + <Compile Include="ActionComponent.cs" /> + <Compile Include="ActionGroupComponent.cs" /> + <Compile Include="ActionGroupDesigner.cs" /> + <Compile Include="ActionGroupDesignerBackend.cs" /> + <Compile Include="ActionGroupEditSession.cs" /> + <Compile Include="ActionGroupToolbar.cs" /> + <Compile Include="Application.cs" /> + <Compile Include="ApplicationBackend.cs" /> + <Compile Include="ApplicationBackendController.cs" /> + <Compile Include="AssemblyResolver.cs" /> + <Compile Include="AssemblyWidgetLibrary.cs" /> + <Compile Include="CecilClassDescriptor.cs" /> + <Compile Include="CecilPropertyDescriptor.cs" /> + <Compile Include="CecilSignalDescriptor.cs" /> + <Compile Include="CecilWidgetLibrary.cs" /> + <Compile Include="CodeGenerationResult.cs" /> + <Compile Include="CodeGenerator.cs" /> + <Compile Include="CodeGeneratorPartialClass.cs" /> + <Compile Include="Component.cs" /> + <Compile Include="ComponentEventHandler.cs" /> + <Compile Include="ComponentSignalEventHandler.cs" /> + <Compile Include="ComponentType.cs" /> + <Compile Include="ContainerUndoRedoManager.cs" /> + <Compile Include="ContextMenu.cs" /> + <Compile Include="Designer.cs" /> + <Compile Include="Glade.cs" /> + <Compile Include="Grid.cs" /> + <Compile Include="GuiDispatchServerSink.cs" /> + <Compile Include="GuiDispatchServerSinkProvider.cs" /> + <Compile Include="LibraryCache.cs" /> + <Compile Include="Metacity\ButtonFunction.cs" /> + <Compile Include="Metacity\ButtonLayout.cs" /> + <Compile Include="Metacity\FrameFlags.cs" /> + <Compile Include="Metacity\FrameType.cs" /> + <Compile Include="Metacity\ObjectManager.cs" /> + <Compile Include="Metacity\Preview.cs" /> + <Compile Include="Metacity\Theme.cs" /> + <Compile Include="Palette.cs" /> + <Compile Include="PaletteBackend.cs" /> + <Compile Include="PluggableWidget.cs" /> + <Compile Include="Project.cs" /> + <Compile Include="ProjectBackend.cs" /> + <Compile Include="ProjectViewBackend.cs" /> + <Compile Include="PropertyEditor.cs" /> + <Compile Include="PropertyGrid.cs" /> + <Compile Include="PropertyTree.cs" /> + <Compile Include="Shadow.cs" /> + <Compile Include="SignalsEditor.cs" /> + <Compile Include="SignalsEditorBackend.cs" /> + <Compile Include="UndoQueue.cs" /> + <Compile Include="UserInterface.cs" /> + <Compile Include="WidgetActionBar.cs" /> + <Compile Include="WidgetComponent.cs" /> + <Compile Include="WidgetDesigner.cs" /> + <Compile Include="WidgetDesignerBackend.cs" /> + <Compile Include="WidgetEditSession.cs" /> + <Compile Include="WidgetFactory.cs" /> + <Compile Include="WidgetInfoEventHandler.cs" /> + <Compile Include="WidgetPropertyTree.cs" /> + <Compile Include="WidgetPropertyTreeBackend.cs" /> + <Compile Include="WidgetTree.cs" /> + <Compile Include="WidgetTreeCombo.cs" /> + <Compile Include="Windows\Preview.cs" /> + <Compile Include="Windows\WindowsTheme.cs" /> + <Compile Include="IProjectDesignInfo.cs" /> + </ItemGroup> + <ItemGroup> + <EmbeddedResource Include="action.png"> + <LogicalName>action.png</LogicalName> + </EmbeddedResource> + <EmbeddedResource Include="missing.png"> + <LogicalName>missing.png</LogicalName> + </EmbeddedResource> + </ItemGroup> + <ItemGroup> + <None Include="libsteticui2.dll.config"> + <CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory> + </None> + </ItemGroup> + <Import Project="$(MSBuildBinPath)\Microsoft.CSharp.targets" /> + <ProjectExtensions> + <MonoDevelop> + <Properties> + <MonoDevelop.Autotools.MakefileInfo IntegrationEnabled="true" RelativeMakefileName="Makefile.am" BuildTargetName="" CleanTargetName="" SyncReferences="true" IsAutotoolsProject="true" RelativeConfigureInPath="../../../.."> + <BuildFilesVar Sync="true" Name="FILES" /> + <DeployFilesVar /> + <ResourcesVar Sync="true" Name="RES" /> + <OthersVar /> + <GacRefVar Sync="true" Name="REFS" Prefix="-r:" /> + <AsmRefVar Sync="true" Name="REFS" Prefix="-r:" /> + <ProjectRefVar Sync="true" Name="DEPS" /> + </MonoDevelop.Autotools.MakefileInfo> + </Properties> + </MonoDevelop> + <VisualStudio /> + </ProjectExtensions> + <ItemGroup> + <Folder Include="Windows\" /> + </ItemGroup> +</Project> diff --git a/main/src/addins/MonoDevelop.GtkCore2/libsteticui/libsteticui2.dll.config b/main/src/addins/MonoDevelop.GtkCore2/libsteticui/libsteticui2.dll.config new file mode 100644 index 0000000000..8c4c6ab9a9 --- /dev/null +++ b/main/src/addins/MonoDevelop.GtkCore2/libsteticui/libsteticui2.dll.config @@ -0,0 +1,8 @@ +<configuration> + <dllmap dll="libgobject-2.0-0.dll" target="libgobject-2.0.so.0" os="!osx,windows" /> + <dllmap dll="libgobject-2.0-0.dll" target="libgobject-2.0.dylib" os="osx" /> + <dllmap dll="libgtk-win32-2.0-0.dll" target="libgtk-x11-2.0.so.0" os="!osx,windows"/> + <dllmap dll="libgtk-win32-2.0-0.dll" target="libgtk-quartz-2.0.dylib" os="osx"/> + <dllmap dll="libgdk-win32-2.0-0.dll" target="libgdk-x11-2.0.so.0" os="!osx,windows"/> + <dllmap dll="libgdk-win32-2.0-0.dll" target="libgdk-quartz-2.0.dylib" os="osx"/> +</configuration> diff --git a/main/src/addins/MonoDevelop.GtkCore2/libsteticui/missing.png b/main/src/addins/MonoDevelop.GtkCore2/libsteticui/missing.png Binary files differnew file mode 100644 index 0000000000..589da692bb --- /dev/null +++ b/main/src/addins/MonoDevelop.GtkCore2/libsteticui/missing.png diff --git a/main/src/addins/MonoDevelop.GtkCore2/monodevelop-slim.sln b/main/src/addins/MonoDevelop.GtkCore2/monodevelop-slim.sln new file mode 100644 index 0000000000..cf252d90be --- /dev/null +++ b/main/src/addins/MonoDevelop.GtkCore2/monodevelop-slim.sln @@ -0,0 +1,146 @@ +
+Microsoft Visual Studio Solution File, Format Version 10.00
+# Visual Studio 2008
+Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "MonoDevelop.Core", "..\main\src\core\MonoDevelop.Core\MonoDevelop.Core.csproj", "{7525BB88-6142-4A26-93B9-A30C6983390A}"
+EndProject
+Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "MonoDevelop.Projects.Formats.MSBuild", "..\main\src\core\MonoDevelop.Projects.Formats.MSBuild\MonoDevelop.Projects.Formats.MSBuild.csproj", "{A437F1A3-78DF-4F00-8053-D32A8B1EB679}"
+EndProject
+Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Mono.Cecil", "..\main\contrib\Mono.Cecil\Mono.Cecil\Mono.Cecil.csproj", "{D8F63DFF-5230-43E4-9AB2-DA6E721A1FAE}"
+EndProject
+Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Mono.Cecil.Mdb", "..\main\contrib\Mono.Cecil\Mono.Cecil.Mdb.csproj", "{201F7AC0-D2D5-4F51-85A8-17475DADBED3}"
+EndProject
+Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Mono.TextEditor", "..\main\src\core\Mono.Texteditor\Mono.TextEditor.csproj", "{A2329308-3751-4DBD-9A75-5F7B8B024625}"
+EndProject
+Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Mono.Debugging", "..\main\src\core\Mono.Debugging\Mono.Debugging.csproj", "{90C99ADB-7D4B-4EB4-98C2-40BD1B14C7D2}"
+EndProject
+Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "NRefactory", "..\main\contrib\NRefactory\Project\NRefactory.csproj", "{3A9AE6AA-BC07-4A2F-972C-581E3AE2F195}"
+EndProject
+Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "MonoDevelop.Ide", "..\main\src\core\MonoDevelop.Ide\MonoDevelop.Ide.csproj", "{27096E7F-C91C-4AC6-B289-6897A701DF21}"
+EndProject
+Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "MonoDevelop.Startup", "..\main\src\core\MonoDevelop.Startup\MonoDevelop.Startup.csproj", "{DA8EDEA6-7DA8-435D-B1A0-F3A0CA07F424}"
+EndProject
+Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "MonoDevelop.DesignerSupport", "..\main\src\addins\MonoDevelop.DesignerSupport\MonoDevelop.DesignerSupport.csproj", "{2C24D515-4A2C-445C-8419-C09231913CFA}"
+EndProject
+Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "MonoDevelop.Deployment", "..\main\src\addins\Deployment\MonoDevelop.Deployment\MonoDevelop.Deployment.csproj", "{9BC670A8-1851-40EC-9685-279F4C98433D}"
+EndProject
+Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "stetic2", "stetic2", "{FA38092D-B853-42E3-B7B7-D88A57F97BE9}"
+ ProjectSection(MonoDevelopProperties) = preProject
+ Policies = $0
+ $0.VersionControlPolicy = $1
+ $1.inheritsSet = Mono
+ $0.ChangeLogPolicy = $2
+ $2.UpdateMode = ProjectRoot
+ $2.MessageStyle = $3
+ $3.LineAlign = 0
+ $2.inheritsSet = Mono
+ EndProjectSection
+EndProject
+Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "libstetic2", "..\main\src\addins\MonoDevelop.GtkCore2\libstetic\libstetic2.csproj", "{90CBA7FD-CB46-4711-97BB-2420DC01F016}"
+EndProject
+Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "libsteticui2", "..\main\src\addins\MonoDevelop.GtkCore2\libsteticui\libsteticui2.csproj", "{8951D80F-B2D6-4B4E-B119-28FFE3B7B1C0}"
+EndProject
+Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "MonoDevelop.GtkCore2", "..\main\src\addins\MonoDevelop.GtkCore2\MonoDevelop.GtkCore2.csproj", "{4F2E994F-E4F5-407A-8D80-80E3377DEF6E}"
+EndProject
+Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "MonoDevelop.Debugger", "..\main\src\addins\MonoDevelop.Debugger\MonoDevelop.Debugger.csproj", "{2357AABD-08C7-4808-A495-8FF2D3CDFDB0}"
+EndProject
+Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "MonoDevelop.Refactoring", "..\main\src\addins\MonoDevelop.Refactoring\MonoDevelop.Refactoring.csproj", "{100568FC-F4E8-439B-94AD-41D11724E45B}"
+EndProject
+Global
+ GlobalSection(SolutionConfigurationPlatforms) = preSolution
+ Debug|Any CPU = Debug|Any CPU
+ Release|Any CPU = Release|Any CPU
+ Debug|x86 = Debug|x86
+ EndGlobalSection
+ GlobalSection(ProjectConfigurationPlatforms) = postSolution
+ {100568FC-F4E8-439B-94AD-41D11724E45B}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
+ {100568FC-F4E8-439B-94AD-41D11724E45B}.Debug|Any CPU.Build.0 = Debug|Any CPU
+ {100568FC-F4E8-439B-94AD-41D11724E45B}.Debug|x86.ActiveCfg = Debug|Any CPU
+ {100568FC-F4E8-439B-94AD-41D11724E45B}.Debug|x86.Build.0 = Debug|Any CPU
+ {100568FC-F4E8-439B-94AD-41D11724E45B}.Release|Any CPU.ActiveCfg = Release|Any CPU
+ {100568FC-F4E8-439B-94AD-41D11724E45B}.Release|Any CPU.Build.0 = Release|Any CPU
+ {201F7AC0-D2D5-4F51-85A8-17475DADBED3}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
+ {201F7AC0-D2D5-4F51-85A8-17475DADBED3}.Debug|Any CPU.Build.0 = Debug|Any CPU
+ {201F7AC0-D2D5-4F51-85A8-17475DADBED3}.Release|Any CPU.ActiveCfg = Release|Any CPU
+ {201F7AC0-D2D5-4F51-85A8-17475DADBED3}.Release|Any CPU.Build.0 = Release|Any CPU
+ {2357AABD-08C7-4808-A495-8FF2D3CDFDB0}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
+ {2357AABD-08C7-4808-A495-8FF2D3CDFDB0}.Debug|Any CPU.Build.0 = Debug|Any CPU
+ {2357AABD-08C7-4808-A495-8FF2D3CDFDB0}.Debug|x86.ActiveCfg = Debug|Any CPU
+ {2357AABD-08C7-4808-A495-8FF2D3CDFDB0}.Debug|x86.Build.0 = Debug|Any CPU
+ {2357AABD-08C7-4808-A495-8FF2D3CDFDB0}.Release|Any CPU.ActiveCfg = Release|Any CPU
+ {2357AABD-08C7-4808-A495-8FF2D3CDFDB0}.Release|Any CPU.Build.0 = Release|Any CPU
+ {27096E7F-C91C-4AC6-B289-6897A701DF21}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
+ {27096E7F-C91C-4AC6-B289-6897A701DF21}.Debug|Any CPU.Build.0 = Debug|Any CPU
+ {27096E7F-C91C-4AC6-B289-6897A701DF21}.Release|Any CPU.ActiveCfg = Release|Any CPU
+ {27096E7F-C91C-4AC6-B289-6897A701DF21}.Release|Any CPU.Build.0 = Release|Any CPU
+ {2C24D515-4A2C-445C-8419-C09231913CFA}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
+ {2C24D515-4A2C-445C-8419-C09231913CFA}.Debug|Any CPU.Build.0 = Debug|Any CPU
+ {2C24D515-4A2C-445C-8419-C09231913CFA}.Debug|x86.ActiveCfg = Debug|Any CPU
+ {2C24D515-4A2C-445C-8419-C09231913CFA}.Debug|x86.Build.0 = Debug|Any CPU
+ {2C24D515-4A2C-445C-8419-C09231913CFA}.Release|Any CPU.ActiveCfg = Release|Any CPU
+ {2C24D515-4A2C-445C-8419-C09231913CFA}.Release|Any CPU.Build.0 = Release|Any CPU
+ {3A9AE6AA-BC07-4A2F-972C-581E3AE2F195}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
+ {3A9AE6AA-BC07-4A2F-972C-581E3AE2F195}.Debug|Any CPU.Build.0 = Debug|Any CPU
+ {3A9AE6AA-BC07-4A2F-972C-581E3AE2F195}.Release|Any CPU.ActiveCfg = Release|Any CPU
+ {3A9AE6AA-BC07-4A2F-972C-581E3AE2F195}.Release|Any CPU.Build.0 = Release|Any CPU
+ {4F2E994F-E4F5-407A-8D80-80E3377DEF6E}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
+ {4F2E994F-E4F5-407A-8D80-80E3377DEF6E}.Debug|Any CPU.Build.0 = Debug|Any CPU
+ {4F2E994F-E4F5-407A-8D80-80E3377DEF6E}.Debug|x86.ActiveCfg = Debug|Any CPU
+ {4F2E994F-E4F5-407A-8D80-80E3377DEF6E}.Debug|x86.Build.0 = Debug|Any CPU
+ {4F2E994F-E4F5-407A-8D80-80E3377DEF6E}.Release|Any CPU.ActiveCfg = Release|Any CPU
+ {4F2E994F-E4F5-407A-8D80-80E3377DEF6E}.Release|Any CPU.Build.0 = Release|Any CPU
+ {7525BB88-6142-4A26-93B9-A30C6983390A}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
+ {7525BB88-6142-4A26-93B9-A30C6983390A}.Debug|Any CPU.Build.0 = Debug|Any CPU
+ {7525BB88-6142-4A26-93B9-A30C6983390A}.Release|Any CPU.ActiveCfg = Release|Any CPU
+ {7525BB88-6142-4A26-93B9-A30C6983390A}.Release|Any CPU.Build.0 = Release|Any CPU
+ {8951D80F-B2D6-4B4E-B119-28FFE3B7B1C0}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
+ {8951D80F-B2D6-4B4E-B119-28FFE3B7B1C0}.Debug|Any CPU.Build.0 = Debug|Any CPU
+ {8951D80F-B2D6-4B4E-B119-28FFE3B7B1C0}.Debug|x86.ActiveCfg = Debug|Any CPU
+ {8951D80F-B2D6-4B4E-B119-28FFE3B7B1C0}.Debug|x86.Build.0 = Debug|Any CPU
+ {8951D80F-B2D6-4B4E-B119-28FFE3B7B1C0}.Release|Any CPU.ActiveCfg = Release|Any CPU
+ {8951D80F-B2D6-4B4E-B119-28FFE3B7B1C0}.Release|Any CPU.Build.0 = Release|Any CPU
+ {90C99ADB-7D4B-4EB4-98C2-40BD1B14C7D2}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
+ {90C99ADB-7D4B-4EB4-98C2-40BD1B14C7D2}.Debug|Any CPU.Build.0 = Debug|Any CPU
+ {90C99ADB-7D4B-4EB4-98C2-40BD1B14C7D2}.Debug|x86.ActiveCfg = Debug|Any CPU
+ {90C99ADB-7D4B-4EB4-98C2-40BD1B14C7D2}.Debug|x86.Build.0 = Debug|Any CPU
+ {90C99ADB-7D4B-4EB4-98C2-40BD1B14C7D2}.Release|Any CPU.ActiveCfg = Release|Any CPU
+ {90C99ADB-7D4B-4EB4-98C2-40BD1B14C7D2}.Release|Any CPU.Build.0 = Release|Any CPU
+ {90CBA7FD-CB46-4711-97BB-2420DC01F016}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
+ {90CBA7FD-CB46-4711-97BB-2420DC01F016}.Debug|Any CPU.Build.0 = Debug|Any CPU
+ {90CBA7FD-CB46-4711-97BB-2420DC01F016}.Debug|x86.ActiveCfg = Debug|Any CPU
+ {90CBA7FD-CB46-4711-97BB-2420DC01F016}.Debug|x86.Build.0 = Debug|Any CPU
+ {90CBA7FD-CB46-4711-97BB-2420DC01F016}.Release|Any CPU.ActiveCfg = Release|Any CPU
+ {90CBA7FD-CB46-4711-97BB-2420DC01F016}.Release|Any CPU.Build.0 = Release|Any CPU
+ {9BC670A8-1851-40EC-9685-279F4C98433D}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
+ {9BC670A8-1851-40EC-9685-279F4C98433D}.Debug|Any CPU.Build.0 = Debug|Any CPU
+ {9BC670A8-1851-40EC-9685-279F4C98433D}.Debug|x86.ActiveCfg = Debug|Any CPU
+ {9BC670A8-1851-40EC-9685-279F4C98433D}.Debug|x86.Build.0 = Debug|Any CPU
+ {9BC670A8-1851-40EC-9685-279F4C98433D}.Release|Any CPU.ActiveCfg = Release|Any CPU
+ {9BC670A8-1851-40EC-9685-279F4C98433D}.Release|Any CPU.Build.0 = Release|Any CPU
+ {A2329308-3751-4DBD-9A75-5F7B8B024625}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
+ {A2329308-3751-4DBD-9A75-5F7B8B024625}.Debug|Any CPU.Build.0 = Debug|Any CPU
+ {A2329308-3751-4DBD-9A75-5F7B8B024625}.Release|Any CPU.ActiveCfg = Release|Any CPU
+ {A2329308-3751-4DBD-9A75-5F7B8B024625}.Release|Any CPU.Build.0 = Release|Any CPU
+ {A437F1A3-78DF-4F00-8053-D32A8B1EB679}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
+ {A437F1A3-78DF-4F00-8053-D32A8B1EB679}.Debug|Any CPU.Build.0 = Debug|Any CPU
+ {A437F1A3-78DF-4F00-8053-D32A8B1EB679}.Release|Any CPU.ActiveCfg = Release|Any CPU
+ {A437F1A3-78DF-4F00-8053-D32A8B1EB679}.Release|Any CPU.Build.0 = Release|Any CPU
+ {D8F63DFF-5230-43E4-9AB2-DA6E721A1FAE}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
+ {D8F63DFF-5230-43E4-9AB2-DA6E721A1FAE}.Debug|Any CPU.Build.0 = Debug|Any CPU
+ {D8F63DFF-5230-43E4-9AB2-DA6E721A1FAE}.Release|Any CPU.ActiveCfg = Release|Any CPU
+ {D8F63DFF-5230-43E4-9AB2-DA6E721A1FAE}.Release|Any CPU.Build.0 = Release|Any CPU
+ {DA8EDEA6-7DA8-435D-B1A0-F3A0CA07F424}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
+ {DA8EDEA6-7DA8-435D-B1A0-F3A0CA07F424}.Debug|Any CPU.Build.0 = Debug|Any CPU
+ {DA8EDEA6-7DA8-435D-B1A0-F3A0CA07F424}.Debug|x86.ActiveCfg = Debug|x86
+ {DA8EDEA6-7DA8-435D-B1A0-F3A0CA07F424}.Debug|x86.Build.0 = Debug|x86
+ {DA8EDEA6-7DA8-435D-B1A0-F3A0CA07F424}.Release|Any CPU.ActiveCfg = Release|Any CPU
+ {DA8EDEA6-7DA8-435D-B1A0-F3A0CA07F424}.Release|Any CPU.Build.0 = Release|Any CPU
+ EndGlobalSection
+ GlobalSection(NestedProjects) = preSolution
+ {90CBA7FD-CB46-4711-97BB-2420DC01F016} = {FA38092D-B853-42E3-B7B7-D88A57F97BE9}
+ {8951D80F-B2D6-4B4E-B119-28FFE3B7B1C0} = {FA38092D-B853-42E3-B7B7-D88A57F97BE9}
+ {4F2E994F-E4F5-407A-8D80-80E3377DEF6E} = {FA38092D-B853-42E3-B7B7-D88A57F97BE9}
+ EndGlobalSection
+ GlobalSection(MonoDevelopProperties) = preSolution
+ StartupItem = ..\main\src\core\MonoDevelop.Startup\MonoDevelop.Startup.csproj
+ EndGlobalSection
+EndGlobal
diff --git a/main/src/addins/MonoDevelop.GtkCore2/templates/ActionGroup.xft.xml b/main/src/addins/MonoDevelop.GtkCore2/templates/ActionGroup.xft.xml new file mode 100644 index 0000000000..e0214ea640 --- /dev/null +++ b/main/src/addins/MonoDevelop.GtkCore2/templates/ActionGroup.xft.xml @@ -0,0 +1,66 @@ +<?xml version="1.0"?> +<Template Originator="Lluis Sanchez" Created="3/09/2001" LastModified="3/09/2001"> + + <TemplateConfiguration> + <_Name>ActionGroup</_Name> + <Icon>md-gui-file</Icon> + <_Category>Gtk</_Category> + <LanguageName>*</LanguageName> + <_Description>Creates a global Action Group.</_Description> + </TemplateConfiguration> + + <Conditions> + <PartialTypeSupport Requirement="Disabled" /> + </Conditions> + + <TemplateFiles> + <Widget DefaultName="${Name}"> + <SteticTemplate> + <action-group name="${FullName}"> + </action-group> + </SteticTemplate> + <CodeDomFile> + <CompileUnit> + <Namespaces> + <Namespace Name=""> + <Imports> + <NamespaceImport Namespace="System" /> + </Imports> + </Namespace> + <Namespace Name="${Namespace}"> + <Types> + <TypeDeclaration Name="${Name}" IsClass="true"> + <BaseTypes> + <TypeReference BaseType="Gtk.ActionGroup" /> + </BaseTypes> + <Members> + <Constructor Attributes="Public, Final"> + <BaseConstructorArgs> + <PrimitiveExpression Value="${FullName}"/> + </BaseConstructorArgs> + <Statements> + <MethodInvokeExpression> + <Method> + <MethodReferenceExpression MethodName="Build"> + <TargetObject> + <TypeReferenceExpression Type="Stetic.Gui" /> + </TargetObject> + </MethodReferenceExpression> + </Method> + <Parameters> + <ThisReferenceExpression/> + <TypeOfExpression Type="${FullName}" /> + </Parameters> + </MethodInvokeExpression> + </Statements> + </Constructor> + </Members> + </TypeDeclaration> + </Types> + </Namespace> + </Namespaces> + </CompileUnit> + </CodeDomFile> + </Widget> + </TemplateFiles> +</Template> diff --git a/main/src/addins/MonoDevelop.GtkCore2/templates/ActionGroupPartial.xft.xml b/main/src/addins/MonoDevelop.GtkCore2/templates/ActionGroupPartial.xft.xml new file mode 100644 index 0000000000..5f8d81245b --- /dev/null +++ b/main/src/addins/MonoDevelop.GtkCore2/templates/ActionGroupPartial.xft.xml @@ -0,0 +1,62 @@ +<?xml version="1.0"?> +<Template Originator="Lluis Sanchez" Created="3/09/2001" LastModified="3/09/2001"> + + <TemplateConfiguration> + <_Name>ActionGroup</_Name> + <Icon>md-gui-file</Icon> + <_Category>Gtk</_Category> + <LanguageName>*</LanguageName> + <_Description>Creates a global Action Group.</_Description> + </TemplateConfiguration> + + <Conditions> + <PartialTypeSupport Requirement="Enabled" /> + </Conditions> + + <TemplateFiles> + <Widget DefaultName="${Name}"> + <SteticTemplate> + <action-group name="${FullName}"> + </action-group> + </SteticTemplate> + <CodeDomFile> + <CompileUnit> + <Namespaces> + <Namespace Name=""> + <Imports> + <NamespaceImport Namespace="System" /> + </Imports> + </Namespace> + <Namespace Name="${Namespace}"> + <Types> + <TypeDeclaration Name="${Name}" IsClass="true" IsPartial="true"> + <BaseTypes> + <TypeReference BaseType="Gtk.ActionGroup" /> + </BaseTypes> + <Members> + <Constructor Attributes="Public, Final"> + <BaseConstructorArgs> + <PrimitiveExpression Value="${FullName}"/> + </BaseConstructorArgs> + <Statements> + <MethodInvokeExpression> + <Method> + <MethodReferenceExpression MethodName="Build"> + <TargetObject> + <ThisReferenceExpression/> + </TargetObject> + </MethodReferenceExpression> + </Method> + </MethodInvokeExpression> + </Statements> + </Constructor> + </Members> + </TypeDeclaration> + </Types> + </Namespace> + </Namespaces> + </CompileUnit> + </CodeDomFile> + </Widget> + </TemplateFiles> +</Template> diff --git a/main/src/addins/MonoDevelop.GtkCore2/templates/ChangeLog b/main/src/addins/MonoDevelop.GtkCore2/templates/ChangeLog new file mode 100644 index 0000000000..01d4fb5ad6 --- /dev/null +++ b/main/src/addins/MonoDevelop.GtkCore2/templates/ChangeLog @@ -0,0 +1,4 @@ +2010-09-20 Krzysztof Marecki <marecki.krzysztof@gmail.com> + + * WidgetPartial.xft.xml: + diff --git a/main/src/addins/MonoDevelop.GtkCore2/templates/Dialog.xft.xml b/main/src/addins/MonoDevelop.GtkCore2/templates/Dialog.xft.xml new file mode 100644 index 0000000000..dd1f056707 --- /dev/null +++ b/main/src/addins/MonoDevelop.GtkCore2/templates/Dialog.xft.xml @@ -0,0 +1,126 @@ +<?xml version="1.0"?> +<Template Originator="Lluis Sanchez" Created="3/09/2001" LastModified="3/09/2001"> + + <TemplateConfiguration> + <_Name>Dialog</_Name> + <Icon>md-gui-file</Icon> + <_Category>Gtk</_Category> + <LanguageName>*</LanguageName> + <_Description>Creates a Gtk dialog.</_Description> + </TemplateConfiguration> + + <Conditions> + <PartialTypeSupport Requirement="Disabled" /> + </Conditions> + + <TemplateFiles> + <Widget DefaultName="${Name}"> + <SteticTemplate> + <widget class="Gtk.Dialog" id="${FullName}" design-size="400 300"> + <property name="Events">0</property> + <property name="Title" translatable="yes">dialog1</property> + <property name="WindowPosition">CenterOnParent</property> + <property name="Buttons">2</property> + <property name="HelpButton">False</property> + <property name="HasSeparator">False</property> + <child internal-child="VBox"> + <widget class="Gtk.VBox" id="dialog1_VBox"> + <property name="MemberName" /> + <property name="Events">0</property> + <property name="BorderWidth">2</property> + <child> + <placeholder /> + </child> + </widget> + </child> + <child internal-child="ActionArea"> + <widget class="Gtk.HButtonBox" id="dialog1_ActionArea"> + <property name="MemberName" /> + <property name="Events">0</property> + <property name="Spacing">10</property> + <property name="BorderWidth">5</property> + <property name="Size">2</property> + <property name="LayoutStyle">End</property> + <child> + <widget class="Gtk.Button" id="buttonCancel"> + <property name="MemberName" /> + <property name="CanDefault">True</property> + <property name="CanFocus">True</property> + <property name="Events">0</property> + <property name="UseStock">True</property> + <property name="Type">StockItem</property> + <property name="StockId">gtk-cancel</property> + <property name="IsDialogButton">True</property> + <property name="ResponseId">-6</property> + <property name="label">gtk-cancel</property> + </widget> + <packing> + <property name="Expand">False</property> + <property name="Fill">False</property> + </packing> + </child> + <child> + <widget class="Gtk.Button" id="buttonOk"> + <property name="MemberName" /> + <property name="CanDefault">True</property> + <property name="CanFocus">True</property> + <property name="Events">0</property> + <property name="UseStock">True</property> + <property name="Type">StockItem</property> + <property name="StockId">gtk-ok</property> + <property name="IsDialogButton">True</property> + <property name="ResponseId">-5</property> + <property name="label">gtk-ok</property> + </widget> + <packing> + <property name="Position">1</property> + <property name="Expand">False</property> + <property name="Fill">False</property> + </packing> + </child> + </widget> + </child> + </widget> + </SteticTemplate> + <CodeDomFile> + <CompileUnit> + <Namespaces> + <Namespace Name=""> + <Imports> + <NamespaceImport Namespace="System" /> + </Imports> + </Namespace> + <Namespace Name="${Namespace}"> + <Types> + <TypeDeclaration Name="${Name}" IsClass="true"> + <BaseTypes> + <TypeReference BaseType="Gtk.Dialog" /> + </BaseTypes> + <Members> + <Constructor Attributes="Public, Final"> + <Statements> + <MethodInvokeExpression> + <Method> + <MethodReferenceExpression MethodName="Build"> + <TargetObject> + <TypeReferenceExpression Type="Stetic.Gui" /> + </TargetObject> + </MethodReferenceExpression> + </Method> + <Parameters> + <ThisReferenceExpression/> + <TypeOfExpression Type="${FullName}" /> + </Parameters> + </MethodInvokeExpression> + </Statements> + </Constructor> + </Members> + </TypeDeclaration> + </Types> + </Namespace> + </Namespaces> + </CompileUnit> + </CodeDomFile> + </Widget> + </TemplateFiles> +</Template> diff --git a/main/src/addins/MonoDevelop.GtkCore2/templates/DialogPartial.xft.xml b/main/src/addins/MonoDevelop.GtkCore2/templates/DialogPartial.xft.xml new file mode 100644 index 0000000000..3fb9feee35 --- /dev/null +++ b/main/src/addins/MonoDevelop.GtkCore2/templates/DialogPartial.xft.xml @@ -0,0 +1,122 @@ +<?xml version="1.0"?> +<Template Originator="Lluis Sanchez" Created="3/09/2001" LastModified="3/09/2001"> + + <TemplateConfiguration> + <_Name>Dialog</_Name> + <Icon>md-gui-file</Icon> + <_Category>Gtk</_Category> + <LanguageName>*</LanguageName> + <_Description>Creates a Gtk dialog.</_Description> + </TemplateConfiguration> + + <Conditions> + <PartialTypeSupport Requirement="Enabled" /> + </Conditions> + + <TemplateFiles> + <Widget DefaultName="${Name}"> + <SteticTemplate> + <widget class="Gtk.Dialog" id="${FullName}" design-size="400 300"> + <property name="Events">0</property> + <property name="Title" translatable="yes">dialog1</property> + <property name="WindowPosition">CenterOnParent</property> + <property name="Buttons">2</property> + <property name="HelpButton">False</property> + <property name="HasSeparator">False</property> + <child internal-child="VBox"> + <widget class="Gtk.VBox" id="dialog1_VBox"> + <property name="MemberName" /> + <property name="Events">0</property> + <property name="BorderWidth">2</property> + <child> + <placeholder /> + </child> + </widget> + </child> + <child internal-child="ActionArea"> + <widget class="Gtk.HButtonBox" id="dialog1_ActionArea"> + <property name="MemberName" /> + <property name="Events">0</property> + <property name="Spacing">10</property> + <property name="BorderWidth">5</property> + <property name="Size">2</property> + <property name="LayoutStyle">End</property> + <child> + <widget class="Gtk.Button" id="buttonCancel"> + <property name="MemberName" /> + <property name="CanDefault">True</property> + <property name="CanFocus">True</property> + <property name="Events">0</property> + <property name="UseStock">True</property> + <property name="Type">StockItem</property> + <property name="StockId">gtk-cancel</property> + <property name="IsDialogButton">True</property> + <property name="ResponseId">-6</property> + <property name="label">gtk-cancel</property> + </widget> + <packing> + <property name="Expand">False</property> + <property name="Fill">False</property> + </packing> + </child> + <child> + <widget class="Gtk.Button" id="buttonOk"> + <property name="MemberName" /> + <property name="CanDefault">True</property> + <property name="CanFocus">True</property> + <property name="Events">0</property> + <property name="UseStock">True</property> + <property name="Type">StockItem</property> + <property name="StockId">gtk-ok</property> + <property name="IsDialogButton">True</property> + <property name="ResponseId">-5</property> + <property name="label">gtk-ok</property> + </widget> + <packing> + <property name="Position">1</property> + <property name="Expand">False</property> + <property name="Fill">False</property> + </packing> + </child> + </widget> + </child> + </widget> + </SteticTemplate> + <CodeDomFile> + <CompileUnit> + <Namespaces> + <Namespace Name=""> + <Imports> + <NamespaceImport Namespace="System" /> + </Imports> + </Namespace> + <Namespace Name="${Namespace}"> + <Types> + <TypeDeclaration Name="${Name}" IsClass="true" IsPartial="true"> + <BaseTypes> + <TypeReference BaseType="Gtk.Dialog" /> + </BaseTypes> + <Members> + <Constructor Attributes="Public, Final"> + <Statements> + <MethodInvokeExpression> + <Method> + <MethodReferenceExpression MethodName="Build"> + <TargetObject> + <ThisReferenceExpression /> + </TargetObject> + </MethodReferenceExpression> + </Method> + </MethodInvokeExpression> + </Statements> + </Constructor> + </Members> + </TypeDeclaration> + </Types> + </Namespace> + </Namespaces> + </CompileUnit> + </CodeDomFile> + </Widget> + </TemplateFiles> +</Template> diff --git a/main/src/addins/MonoDevelop.GtkCore2/templates/DrawingArea.xft.xml b/main/src/addins/MonoDevelop.GtkCore2/templates/DrawingArea.xft.xml new file mode 100644 index 0000000000..842ba2aca7 --- /dev/null +++ b/main/src/addins/MonoDevelop.GtkCore2/templates/DrawingArea.xft.xml @@ -0,0 +1,171 @@ +<?xml version="1.0"?> +<Template Originator="Mike Kestner" Created="2/11/2009" LastModified="2/11/2009"> + <TemplateConfiguration> + <_Name>Custom Drawn Widget</_Name> + <Icon>md-gui-file</Icon> + <_Category>Gtk</_Category> + <LanguageName>*</LanguageName> + <_Description>Creates a custom Gtk.DrawingArea subclass.</_Description> + </TemplateConfiguration> + <TemplateFiles> + <CodeDomFile> + <CompileUnit> + <Namespaces> + <Namespace Name=""> + <Imports> + <NamespaceImport Namespace="System" /> + </Imports> + </Namespace> + <Namespace Name="${Namespace}"> + <Types> + <TypeDeclaration Name="${Name}" IsClass="true"> + <BaseTypes> + <TypeReference BaseType="Gtk.DrawingArea" /> + </BaseTypes> + <CustomAttributes> + <AttributeDeclaration Name="System.ComponentModel.ToolboxItem"> + <Arguments> + <AttributeArgument> + <Value><PrimitiveExpression Value="True" ValueType="System.Boolean"/></Value> + </AttributeArgument> + </Arguments> + </AttributeDeclaration> + </CustomAttributes> + <Members> + <Constructor Attributes="Public, Final"> + <Statements> + <CommentStatement> + <Comment> + <Comment Text="Insert initialization code here." /> + </Comment> + </CommentStatement> + </Statements> + </Constructor> + <MemberMethod Name="OnButtonPressEvent" Attributes="Family, Override"> + <Parameters> + <ParameterDeclarationExpression Name="ev" Type="Gdk.EventButton"/> + </Parameters> + <ReturnType><TypeReference BaseType="System.Boolean"/></ReturnType> + <Statements> + <CommentStatement> + <Comment> + <Comment Text="Insert button press handling code here." /> + </Comment> + </CommentStatement> + <MethodReturnStatement> + <Expression> + <MethodInvokeExpression> + <Method> + <MethodReferenceExpression MethodName="OnButtonPressEvent"> + <TargetObject> + <BaseReferenceExpression/> + </TargetObject> + </MethodReferenceExpression> + </Method> + <Parameters> + <ArgumentReferenceExpression ParameterName="ev" /> + </Parameters> + </MethodInvokeExpression> + </Expression> + </MethodReturnStatement> + </Statements> + </MemberMethod> + <MemberMethod Name="OnExposeEvent" Attributes="Family, Override"> + <Parameters> + <ParameterDeclarationExpression Name="ev" Type="Gdk.EventExpose"/> + </Parameters> + <ReturnType><TypeReference BaseType="System.Boolean"/></ReturnType> + <Statements> + <MethodInvokeExpression> + <Method> + <MethodReferenceExpression MethodName="OnExposeEvent"> + <TargetObject> + <BaseReferenceExpression/> + </TargetObject> + </MethodReferenceExpression> + </Method> + <Parameters> + <ArgumentReferenceExpression ParameterName="ev" /> + </Parameters> + </MethodInvokeExpression> + <CommentStatement> + <Comment> + <Comment Text="Insert drawing code here." /> + </Comment> + </CommentStatement> + <MethodReturnStatement> + <Expression> + <PrimitiveExpression Value="True" ValueType="System.Boolean"/> + </Expression> + </MethodReturnStatement> + </Statements> + </MemberMethod> + <MemberMethod Name="OnSizeAllocated" Attributes="Family, Override"> + <Parameters> + <ParameterDeclarationExpression Name="allocation" Type="Gdk.Rectangle" /> + </Parameters> + <Statements> + <MethodInvokeExpression> + <Method> + <MethodReferenceExpression MethodName="OnSizeAllocated"> + <TargetObject> + <BaseReferenceExpression/> + </TargetObject> + </MethodReferenceExpression> + </Method> + <Parameters> + <ArgumentReferenceExpression ParameterName="allocation" /> + </Parameters> + </MethodInvokeExpression> + <CommentStatement> + <Comment> + <Comment Text="Insert layout code here." /> + </Comment> + </CommentStatement> + </Statements> + </MemberMethod> + <MemberMethod Name="OnSizeRequested" Attributes="Family, Override"> + <Parameters> + <ParameterDeclarationExpression Name="requisition" Type="Gtk.Requisition" Direction="Ref" /> + </Parameters> + <Statements> + <CommentStatement> + <Comment> + <Comment Text="Calculate desired size here." /> + </Comment> + </CommentStatement> + <AssignStatement> + <Left> + <FieldReferenceExpression FieldName="Height"> + <TargetObject> + <ArgumentReferenceExpression ParameterName="requisition" /> + </TargetObject> + </FieldReferenceExpression> + </Left> + <Right> + <PrimitiveExpression Value="50" ValueType="System.Int32" /> + </Right> + </AssignStatement> + <AssignStatement> + <Left> + <FieldReferenceExpression FieldName="Width"> + <TargetObject> + <ArgumentReferenceExpression ParameterName="requisition" /> + </TargetObject> + </FieldReferenceExpression> + </Left> + <Right> + <PrimitiveExpression Value="50" ValueType="System.Int32" /> + </Right> + </AssignStatement> + </Statements> + </MemberMethod> + </Members> + </TypeDeclaration> + </Types> + </Namespace> + </Namespaces> + </CompileUnit> + </CodeDomFile> + </TemplateFiles> +</Template> diff --git a/main/src/addins/MonoDevelop.GtkCore2/templates/Widget.xft.xml b/main/src/addins/MonoDevelop.GtkCore2/templates/Widget.xft.xml new file mode 100644 index 0000000000..e391069234 --- /dev/null +++ b/main/src/addins/MonoDevelop.GtkCore2/templates/Widget.xft.xml @@ -0,0 +1,76 @@ +<?xml version="1.0"?> +<Template Originator="Lluis Sanchez" Created="3/09/2001" LastModified="3/09/2001"> + + <TemplateConfiguration> + <_Name>Widget</_Name> + <Icon>md-gui-file</Icon> + <_Category>Gtk</_Category> + <LanguageName>*</LanguageName> + <_Description>Creates a custom Gtk Widget.</_Description> + </TemplateConfiguration> + + <Conditions> + <PartialTypeSupport Requirement="Disabled" /> + </Conditions> + + <TemplateFiles> + <Widget DefaultName="${Name}"> + <SteticTemplate> + <widget class="Gtk.Bin" id="${FullName}" design-size="300 300"> + <property name="Visible">false</property> + <child> + <placeholder /> + </child> + </widget> + </SteticTemplate> + <CodeDomFile> + <CompileUnit> + <Namespaces> + <Namespace Name=""> + <Imports> + <NamespaceImport Namespace="System" /> + </Imports> + </Namespace> + <Namespace Name="${Namespace}"> + <Types> + <TypeDeclaration Name="${Name}" IsClass="true"> + <BaseTypes> + <TypeReference BaseType="Gtk.Bin" /> + </BaseTypes> + <CustomAttributes> + <AttributeDeclaration Name="System.ComponentModel.ToolboxItem"> + <Arguments> + <AttributeArgument> + <Value><PrimitiveExpression Value="True" ValueType="System.Boolean"/></Value> + </AttributeArgument> + </Arguments> + </AttributeDeclaration> + </CustomAttributes> + <Members> + <Constructor Attributes="Public, Final"> + <Statements> + <MethodInvokeExpression> + <Method> + <MethodReferenceExpression MethodName="Build"> + <TargetObject> + <TypeReferenceExpression Type="Stetic.Gui" /> + </TargetObject> + </MethodReferenceExpression> + </Method> + <Parameters> + <ThisReferenceExpression/> + <TypeOfExpression Type="${FullName}" /> + </Parameters> + </MethodInvokeExpression> + </Statements> + </Constructor> + </Members> + </TypeDeclaration> + </Types> + </Namespace> + </Namespaces> + </CompileUnit> + </CodeDomFile> + </Widget> + </TemplateFiles> +</Template> diff --git a/main/src/addins/MonoDevelop.GtkCore2/templates/WidgetPartial.xft.xml b/main/src/addins/MonoDevelop.GtkCore2/templates/WidgetPartial.xft.xml new file mode 100644 index 0000000000..1f911a10c4 --- /dev/null +++ b/main/src/addins/MonoDevelop.GtkCore2/templates/WidgetPartial.xft.xml @@ -0,0 +1,72 @@ +<?xml version="1.0"?> +<Template Originator="Lluis Sanchez" Created="3/09/2001" LastModified="3/09/2001"> + + <TemplateConfiguration> + <_Name>Widget</_Name> + <Icon>md-gui-file</Icon> + <_Category>Gtk</_Category> + <LanguageName>*</LanguageName> + <_Description>Creates a custom Gtk Widget.</_Description> + </TemplateConfiguration> + + <Conditions> + <PartialTypeSupport Requirement="Enabled" /> + </Conditions> + + <TemplateFiles> + <Widget DefaultName="${Name}"> + <SteticTemplate> + <widget class="Gtk.Bin" id="${FullName}" design-size="300 300"> + <property name="Visible">false</property> + <child> + <placeholder /> + </child> + </widget> + </SteticTemplate> + <CodeDomFile> + <CompileUnit> + <Namespaces> + <Namespace Name=""> + <Imports> + <NamespaceImport Namespace="System" /> + </Imports> + </Namespace> + <Namespace Name="${Namespace}"> + <Types> + <TypeDeclaration Name="${Name}" IsClass="true" IsPartial="true"> + <BaseTypes> + <TypeReference BaseType="Gtk.Bin" /> + </BaseTypes> + <CustomAttributes> + <AttributeDeclaration Name="System.ComponentModel.ToolboxItem"> + <Arguments> + <AttributeArgument> + <Value><PrimitiveExpression Value="True" ValueType="System.Boolean"/></Value> + </AttributeArgument> + </Arguments> + </AttributeDeclaration> + </CustomAttributes> + <Members> + <Constructor Attributes="Public, Final"> + <Statements> + <MethodInvokeExpression> + <Method> + <MethodReferenceExpression MethodName="Build"> + <TargetObject> + <ThisReferenceExpression/> + </TargetObject> + </MethodReferenceExpression> + </Method> + </MethodInvokeExpression> + </Statements> + </Constructor> + </Members> + </TypeDeclaration> + </Types> + </Namespace> + </Namespaces> + </CompileUnit> + </CodeDomFile> + </Widget> + </TemplateFiles> +</Template> diff --git a/main/src/addins/MonoDevelop.GtkCore2/templates/Window.xft.xml b/main/src/addins/MonoDevelop.GtkCore2/templates/Window.xft.xml new file mode 100644 index 0000000000..22fba55176 --- /dev/null +++ b/main/src/addins/MonoDevelop.GtkCore2/templates/Window.xft.xml @@ -0,0 +1,75 @@ +<?xml version="1.0"?> +<Template Originator="Lluis Sanchez" Created="3/09/2001" LastModified="3/09/2001"> + + <TemplateConfiguration> + <_Name>Window</_Name> + <Icon>md-gui-file</Icon> + <_Category>Gtk</_Category> + <LanguageName>*</LanguageName> + <_Description>Creates a Gtk Window</_Description> + </TemplateConfiguration> + + <Conditions> + <PartialTypeSupport Requirement="Disabled" /> + </Conditions> + + <TemplateFiles> + <Widget DefaultName="${Name}"> + <SteticTemplate> + <widget class="Gtk.Window" id="${FullName}" design-size="400 300"> + <property name="Title" translatable="yes">${Name}</property> + <property name="WindowPosition">CenterOnParent</property> + <child> + <placeholder /> + </child> + </widget> + </SteticTemplate> + <CodeDomFile> + <CompileUnit> + <Namespaces> + <Namespace Name=""> + <Imports> + <NamespaceImport Namespace="System" /> + </Imports> + </Namespace> + <Namespace Name="${Namespace}"> + <Types> + <TypeDeclaration Name="${Name}" IsClass="true"> + <BaseTypes> + <TypeReference BaseType="Gtk.Window" /> + </BaseTypes> + <Members> + <Constructor Attributes="Public, Final"> + <BaseConstructorArgs> + <FieldReferenceExpression FieldName="Toplevel"> + <TargetObject> + <TypeReferenceExpression Type="Gtk.WindowType" /> + </TargetObject> + </FieldReferenceExpression> + </BaseConstructorArgs> + <Statements> + <MethodInvokeExpression> + <Method> + <MethodReferenceExpression MethodName="Build"> + <TargetObject> + <TypeReferenceExpression Type="Stetic.Gui" /> + </TargetObject> + </MethodReferenceExpression> + </Method> + <Parameters> + <ThisReferenceExpression/> + <TypeOfExpression Type="${FullName}" /> + </Parameters> + </MethodInvokeExpression> + </Statements> + </Constructor> + </Members> + </TypeDeclaration> + </Types> + </Namespace> + </Namespaces> + </CompileUnit> + </CodeDomFile> + </Widget> + </TemplateFiles> +</Template> diff --git a/main/src/addins/MonoDevelop.GtkCore2/templates/WindowPartial.xft.xml b/main/src/addins/MonoDevelop.GtkCore2/templates/WindowPartial.xft.xml new file mode 100644 index 0000000000..382113c771 --- /dev/null +++ b/main/src/addins/MonoDevelop.GtkCore2/templates/WindowPartial.xft.xml @@ -0,0 +1,71 @@ +<?xml version="1.0"?> +<Template Originator="Lluis Sanchez" Created="3/09/2001" LastModified="3/09/2001"> + + <TemplateConfiguration> + <_Name>Window</_Name> + <Icon>md-gui-file</Icon> + <_Category>Gtk</_Category> + <LanguageName>*</LanguageName> + <_Description>Creates a Gtk Window</_Description> + </TemplateConfiguration> + + <Conditions> + <PartialTypeSupport Requirement="Enabled" /> + </Conditions> + + <TemplateFiles> + <Widget DefaultName="${Name}"> + <SteticTemplate> + <widget class="Gtk.Window" id="${FullName}" design-size="400 300"> + <property name="Title" translatable="yes">${Name}</property> + <property name="WindowPosition">CenterOnParent</property> + <child> + <placeholder /> + </child> + </widget> + </SteticTemplate> + <CodeDomFile> + <CompileUnit> + <Namespaces> + <Namespace Name=""> + <Imports> + <NamespaceImport Namespace="System" /> + </Imports> + </Namespace> + <Namespace Name="${Namespace}"> + <Types> + <TypeDeclaration Name="${Name}" IsClass="true" IsPartial="true"> + <BaseTypes> + <TypeReference BaseType="Gtk.Window" /> + </BaseTypes> + <Members> + <Constructor Attributes="Public, Final"> + <BaseConstructorArgs> + <FieldReferenceExpression FieldName="Toplevel"> + <TargetObject> + <TypeReferenceExpression Type="Gtk.WindowType" /> + </TargetObject> + </FieldReferenceExpression> + </BaseConstructorArgs> + <Statements> + <MethodInvokeExpression> + <Method> + <MethodReferenceExpression MethodName="Build"> + <TargetObject> + <ThisReferenceExpression/> + </TargetObject> + </MethodReferenceExpression> + </Method> + </MethodInvokeExpression> + </Statements> + </Constructor> + </Members> + </TypeDeclaration> + </Types> + </Namespace> + </Namespaces> + </CompileUnit> + </CodeDomFile> + </Widget> + </TemplateFiles> +</Template> |