From f5db2c21737fa223def728a557b7712ea6eea78e Mon Sep 17 00:00:00 2001 From: alcexhim Date: Mon, 23 Jun 2014 23:58:57 -0400 Subject: [PATCH] Implementing Commands on Linux --- .../MainWindow.cs | 63 +++++++++ .../gtk-gui/MainWindow.cs | 36 +++-- .../gtk-gui/gui.stetic | 51 +++---- .../UniversalEditor.UserInterface/Command.cs | 71 ++++++++++ .../CommandItem.cs | 25 ++++ .../UniversalEditor.UserInterface/Engine.cs | 126 ++++++++++++++++++ .../EngineMainMenu.cs | 16 +++ .../HostApplication.cs | 9 ++ .../StockCommandType.cs | 9 ++ .../UniversalEditor.UserInterface.csproj | 4 + 10 files changed, 377 insertions(+), 33 deletions(-) create mode 100644 CSharp/Libraries/UniversalEditor.UserInterface/Command.cs create mode 100644 CSharp/Libraries/UniversalEditor.UserInterface/CommandItem.cs create mode 100644 CSharp/Libraries/UniversalEditor.UserInterface/EngineMainMenu.cs create mode 100644 CSharp/Libraries/UniversalEditor.UserInterface/StockCommandType.cs diff --git a/CSharp/Environments/GTK/Engines/UniversalEditor.Environments.GTK/MainWindow.cs b/CSharp/Environments/GTK/Engines/UniversalEditor.Environments.GTK/MainWindow.cs index b450b52d..80163c2c 100644 --- a/CSharp/Environments/GTK/Engines/UniversalEditor.Environments.GTK/MainWindow.cs +++ b/CSharp/Environments/GTK/Engines/UniversalEditor.Environments.GTK/MainWindow.cs @@ -1,11 +1,74 @@ using System; using Gtk; +using UniversalEditor.UserInterface; + public partial class MainWindow: Gtk.Window { public MainWindow (): base (Gtk.WindowType.Toplevel) { Build (); + InitializeMenuBar(); + } + + private void InitializeMenuBar() + { + foreach (CommandItem item in Engine.CurrentEngine.MainMenu.Items) + { + CreateCommandItem(item, null); + } + menubar1.ShowAll (); + } + private void CreateCommandItem(CommandItem item, Menu parentMenu) + { + Gtk.MenuItem menuItem = null; + + if (item is CommandReferenceCommandItem) + { + CommandReferenceCommandItem crci = (item as CommandReferenceCommandItem); + Command cmd = Engine.CurrentEngine.Commands[crci.CommandID]; + if (cmd == null) + { + HostApplication.Messages.Add(HostApplicationMessageSeverity.Warning, "The command '" + crci.CommandID + "' was not found"); + return; + } + + menuItem = new Gtk.MenuItem(cmd.Title); + if (cmd.Items.Count > 0) + { + Menu submenu = CreateCommandItemSubmenu(cmd); + menuItem.Submenu = submenu; + } + } + else if (item is SeparatorCommandItem) + { + menuItem = new Gtk.SeparatorMenuItem(); + } + + if (menuItem != null) + { + if (parentMenu == null) + { + menubar1.Append(menuItem); + } + else + { + parentMenu.Append(menuItem); + } + } + } + private Menu CreateCommandItemSubmenu(Command cmd) + { + Menu menu = new Menu(); + if (Engine.CurrentEngine.MainMenu.EnableTearoff && cmd.EnableTearoff) + { + menu.Append(new TearoffMenuItem()); + } + foreach (CommandItem item in cmd.Items) + { + CreateCommandItem(item, menu); + } + return menu; } protected void OnDeleteEvent (object sender, DeleteEventArgs a) diff --git a/CSharp/Environments/GTK/Engines/UniversalEditor.Environments.GTK/gtk-gui/MainWindow.cs b/CSharp/Environments/GTK/Engines/UniversalEditor.Environments.GTK/gtk-gui/MainWindow.cs index 93e8cd32..27727a31 100644 --- a/CSharp/Environments/GTK/Engines/UniversalEditor.Environments.GTK/gtk-gui/MainWindow.cs +++ b/CSharp/Environments/GTK/Engines/UniversalEditor.Environments.GTK/gtk-gui/MainWindow.cs @@ -20,6 +20,8 @@ public partial class MainWindow private global::Gtk.Action CutAction; private global::Gtk.VBox vbox1; private global::Gtk.MenuBar menubar1; + private global::Gtk.Toolbar toolbar1; + private global::Gtk.Notebook notebook1; private global::Gtk.Statusbar statusbar1; private global::Gtk.Label lblStatus; @@ -151,7 +153,7 @@ public partial class MainWindow this.vbox1.Name = "vbox1"; this.vbox1.Spacing = 6; // Container child vbox1.Gtk.Box+BoxChild - this.UIManager.AddUiFromString (""); + this.UIManager.AddUiFromString (""); this.menubar1 = ((global::Gtk.MenuBar)(this.UIManager.GetWidget ("/menubar1"))); this.menubar1.Name = "menubar1"; this.vbox1.Add (this.menubar1); @@ -160,6 +162,24 @@ public partial class MainWindow w2.Expand = false; w2.Fill = false; // Container child vbox1.Gtk.Box+BoxChild + this.UIManager.AddUiFromString (""); + this.toolbar1 = ((global::Gtk.Toolbar)(this.UIManager.GetWidget ("/toolbar1"))); + this.toolbar1.Name = "toolbar1"; + this.toolbar1.ShowArrow = false; + this.vbox1.Add (this.toolbar1); + global::Gtk.Box.BoxChild w3 = ((global::Gtk.Box.BoxChild)(this.vbox1 [this.toolbar1])); + w3.Position = 1; + w3.Expand = false; + w3.Fill = false; + // Container child vbox1.Gtk.Box+BoxChild + this.notebook1 = new global::Gtk.Notebook (); + this.notebook1.CanFocus = true; + this.notebook1.Name = "notebook1"; + this.notebook1.CurrentPage = -1; + this.vbox1.Add (this.notebook1); + global::Gtk.Box.BoxChild w4 = ((global::Gtk.Box.BoxChild)(this.vbox1 [this.notebook1])); + w4.Position = 2; + // Container child vbox1.Gtk.Box+BoxChild this.statusbar1 = new global::Gtk.Statusbar (); this.statusbar1.Name = "statusbar1"; this.statusbar1.Spacing = 6; @@ -170,19 +190,19 @@ public partial class MainWindow this.lblStatus.Xalign = 0F; this.lblStatus.LabelProp = global::Mono.Unix.Catalog.GetString ("Ready"); this.statusbar1.Add (this.lblStatus); - global::Gtk.Box.BoxChild w3 = ((global::Gtk.Box.BoxChild)(this.statusbar1 [this.lblStatus])); - w3.Position = 0; + global::Gtk.Box.BoxChild w5 = ((global::Gtk.Box.BoxChild)(this.statusbar1 [this.lblStatus])); + w5.Position = 0; this.vbox1.Add (this.statusbar1); - global::Gtk.Box.BoxChild w4 = ((global::Gtk.Box.BoxChild)(this.vbox1 [this.statusbar1])); - w4.Position = 2; - w4.Expand = false; - w4.Fill = false; + global::Gtk.Box.BoxChild w6 = ((global::Gtk.Box.BoxChild)(this.vbox1 [this.statusbar1])); + w6.Position = 3; + w6.Expand = false; + w6.Fill = false; this.Add (this.vbox1); if ((this.Child != null)) { this.Child.ShowAll (); } this.DefaultWidth = 400; - this.DefaultHeight = 300; + this.DefaultHeight = 299; this.Show (); this.DeleteEvent += new global::Gtk.DeleteEventHandler (this.OnDeleteEvent); } diff --git a/CSharp/Environments/GTK/Engines/UniversalEditor.Environments.GTK/gtk-gui/gui.stetic b/CSharp/Environments/GTK/Engines/UniversalEditor.Environments.GTK/gtk-gui/gui.stetic index a37f2c64..0118b136 100644 --- a/CSharp/Environments/GTK/Engines/UniversalEditor.Environments.GTK/gtk-gui/gui.stetic +++ b/CSharp/Environments/GTK/Engines/UniversalEditor.Environments.GTK/gtk-gui/gui.stetic @@ -6,9 +6,9 @@ - + - + Action @@ -93,27 +93,7 @@ - - - - - - - - - - - - - - - - - - - - - + 0 @@ -123,7 +103,28 @@ - + + + False + + + + 1 + True + False + False + + + + + + True + -1 + + + 2 + False + @@ -143,7 +144,7 @@ - 2 + 3 True False False diff --git a/CSharp/Libraries/UniversalEditor.UserInterface/Command.cs b/CSharp/Libraries/UniversalEditor.UserInterface/Command.cs new file mode 100644 index 00000000..2aba0fb8 --- /dev/null +++ b/CSharp/Libraries/UniversalEditor.UserInterface/Command.cs @@ -0,0 +1,71 @@ +using System; + +namespace UniversalEditor.UserInterface +{ + public class Command + { + public class CommandCollection + : System.Collections.ObjectModel.Collection + { + public Command this[string ID] + { + get + { + foreach (Command command in this) + { + if (command.ID == ID) return command; + } + return null; + } + } + } + + private bool mvarEnableTearoff = false; + public bool EnableTearoff { get { return mvarEnableTearoff; } set { mvarEnableTearoff = value; } } + + private string mvarID = String.Empty; + /// + /// The ID of the command, used to reference it in . + /// + public string ID { get { return mvarID; } set { mvarID = value; } } + + private string mvarTitle = String.Empty; + /// + /// The title of the command (including mnemonic prefix, if applicable). + /// + public string Title { get { return mvarTitle; } set { mvarTitle = value; } } + + private StockCommandType mvarStockCommandType = StockCommandType.None; + /// + /// A that represents a predefined, platform-themed command. + /// + public StockCommandType StockCommandType { get { return mvarStockCommandType; } set { mvarStockCommandType = value; } } + + private string mvarImageFileName = String.Empty; + /// + /// The file name of the image to be displayed on the command. + /// + public string ImageFileName { get { return mvarImageFileName; } set { mvarImageFileName = value; } } + + + private CommandItem.CommandItemCollection mvarItems = new CommandItem.CommandItemCollection(); + /// + /// The child s that are contained within this . + /// + public CommandItem.CommandItemCollection Items { get { return mvarItems; } } + + /// + /// The event that is fired when the command is executed. + /// + public event EventHandler Executed; + + /// + /// Executes this . + /// + public void Execute() + { + if (Executed != null) Executed(this, EventArgs.Empty); + } + } +} + diff --git a/CSharp/Libraries/UniversalEditor.UserInterface/CommandItem.cs b/CSharp/Libraries/UniversalEditor.UserInterface/CommandItem.cs new file mode 100644 index 00000000..e0775aa5 --- /dev/null +++ b/CSharp/Libraries/UniversalEditor.UserInterface/CommandItem.cs @@ -0,0 +1,25 @@ +using System; +namespace UniversalEditor.UserInterface +{ + public abstract class CommandItem + { + public class CommandItemCollection + : System.Collections.ObjectModel.Collection + { + } + } + public class CommandReferenceCommandItem : CommandItem + { + private string mvarCommandID = String.Empty; + public string CommandID { get { return mvarCommandID; } set { mvarCommandID = value; } } + + public CommandReferenceCommandItem(string commandID) + { + mvarCommandID = commandID; + } + } + public class SeparatorCommandItem : CommandItem + { + } +} + diff --git a/CSharp/Libraries/UniversalEditor.UserInterface/Engine.cs b/CSharp/Libraries/UniversalEditor.UserInterface/Engine.cs index 90d98aaa..c2e4286e 100644 --- a/CSharp/Libraries/UniversalEditor.UserInterface/Engine.cs +++ b/CSharp/Libraries/UniversalEditor.UserInterface/Engine.cs @@ -3,10 +3,14 @@ using System.Collections.Generic; using System.Linq; using System.Reflection; using System.Text; + using UniversalEditor.Accessors; using UniversalEditor.ObjectModels.FileSystem; using UniversalEditor.ObjectModels.PropertyList; +using UniversalEditor.DataFormats.Markup.XML; +using UniversalEditor.ObjectModels.Markup; + namespace UniversalEditor.UserInterface { public abstract class Engine @@ -77,6 +81,23 @@ namespace UniversalEditor.UserInterface protected abstract void MainLoop(); + private Command.CommandCollection mvarCommands = new Command.CommandCollection(); + /// + /// The commands defined for this application. + /// + public Command.CommandCollection Commands { get { return mvarCommands; } } + + private EngineMainMenu mvarMainMenu = new EngineMainMenu(); + /// + /// The main menu of this application, which can hold multiple s. + /// + public EngineMainMenu MainMenu { get { return mvarMainMenu; } } + + /// + /// The aggregated raw markup of all the various XML files loaded in the current search path. + /// + private MarkupObjectModel mvarRawMarkup = new MarkupObjectModel(); + private PropertyListObjectModel mvarConfiguration = new PropertyListObjectModel(); public PropertyListObjectModel Configuration { get { return mvarConfiguration; } } @@ -125,6 +146,108 @@ namespace UniversalEditor.UserInterface } } + protected virtual void InitializeXMLConfiguration() + { + #region Load the XML files + string[] xmlfiles = System.IO.Directory.GetFiles(mvarBasePath, "*.xml", System.IO.SearchOption.AllDirectories); + + XMLDataFormat xdf = new XMLDataFormat(); + foreach (string xmlfile in xmlfiles) + { + MarkupObjectModel markup = new MarkupObjectModel(); + Document doc = new Document(markup, xdf, new FileAccessor(xmlfile)); + doc.Accessor.Open (); + doc.Load (); + doc.Close (); + + markup.CopyTo (mvarRawMarkup); + } + + #endregion + #region Initialize the configuration with the loaded data + + MarkupTagElement tagCommands = (mvarRawMarkup.FindElement ("UniversalEditor", "Application", "Commands") as MarkupTagElement); + if (tagCommands != null) + { + foreach (MarkupElement elCommand in tagCommands.Elements) + { + MarkupTagElement tagCommand = (elCommand as MarkupTagElement); + if (tagCommand == null) continue; + if (tagCommand.FullName != "Command") continue; + + MarkupAttribute attID = tagCommand.Attributes["ID"]; + if (attID == null) continue; + + Command cmd = new Command(); + cmd.ID = attID.Value; + + MarkupAttribute attTitle = tagCommand.Attributes["Title"]; + if (attTitle != null) + { + cmd.Title = attTitle.Value; + } + + MarkupTagElement tagItems = (tagCommand.Elements["Items"] as MarkupTagElement); + if (tagItems != null) + { + foreach (MarkupElement el in tagItems.Elements) + { + MarkupTagElement tag = (el as MarkupTagElement); + if (tag == null) continue; + + InitializeMainMenuItem(tag, cmd); + } + } + + mvarCommands.Add (cmd); + } + } + + MarkupTagElement tagMainMenuItems = (mvarRawMarkup.FindElement ("UniversalEditor", "Application", "MainMenu", "Items") as MarkupTagElement); + foreach (MarkupElement elItem in tagMainMenuItems.Elements) + { + MarkupTagElement tagItem = (elItem as MarkupTagElement); + if (tagItem == null) continue; + InitializeMainMenuItem(tagItem, null); + } + + #endregion + } + + private void InitializeMainMenuItem(MarkupTagElement tag, Command parent) + { + CommandItem item = null; + switch (tag.FullName) + { + case "CommandReference": + { + MarkupAttribute attCommandID = tag.Attributes["CommandID"]; + if (attCommandID != null) + { + item = new CommandReferenceCommandItem(attCommandID.Value); + } + break; + } + case "Separator": + { + item = new SeparatorCommandItem(); + break; + } + } + + if (item != null) + { + if (parent == null) + { + mvarMainMenu.Items.Add(item); + } + else + { + parent.Items.Add(item); + } + } + } + protected virtual void InitializeBranding() { @@ -161,6 +284,9 @@ namespace UniversalEditor.UserInterface // overridden with a switch (/basepath:...) ? mvarBasePath = System.IO.Path.GetDirectoryName(System.Reflection.Assembly.GetExecutingAssembly().Location); + // Initialize the XML files + InitializeXMLConfiguration(); + // Initialize the branding for the selected application InitializeBranding(); diff --git a/CSharp/Libraries/UniversalEditor.UserInterface/EngineMainMenu.cs b/CSharp/Libraries/UniversalEditor.UserInterface/EngineMainMenu.cs new file mode 100644 index 00000000..6c3a088b --- /dev/null +++ b/CSharp/Libraries/UniversalEditor.UserInterface/EngineMainMenu.cs @@ -0,0 +1,16 @@ +using System; +namespace UniversalEditor.UserInterface +{ + public class EngineMainMenu + { + private bool mvarEnableTearoff = false; + /// + /// Determines whether menus can be torn off to display their contents in a separate window. + /// + public bool EnableTearoff { get { return mvarEnableTearoff; } set { mvarEnableTearoff = value; } } + + private CommandItem.CommandItemCollection mvarItems = new CommandItem.CommandItemCollection(); + public CommandItem.CommandItemCollection Items { get { return mvarItems; } } + } +} + diff --git a/CSharp/Libraries/UniversalEditor.UserInterface/HostApplication.cs b/CSharp/Libraries/UniversalEditor.UserInterface/HostApplication.cs index cb3f6c10..06f3b22a 100644 --- a/CSharp/Libraries/UniversalEditor.UserInterface/HostApplication.cs +++ b/CSharp/Libraries/UniversalEditor.UserInterface/HostApplication.cs @@ -8,12 +8,21 @@ namespace UniversalEditor.UserInterface public static class HostApplication { private static IHostApplicationWindow mvarCurrentWindow = null; + /// + /// Gets or sets the current window of the host application. + /// public static IHostApplicationWindow CurrentWindow { get { return mvarCurrentWindow; } set { mvarCurrentWindow = value; } } private static HostApplicationOutputWindow mvarOutputWindow = new HostApplicationOutputWindow(); + /// + /// Gets or sets the output window of the host application, where other plugins can read from and write to. + /// public static HostApplicationOutputWindow OutputWindow { get { return mvarOutputWindow; } set { mvarOutputWindow = value; } } private static HostApplicationMessage.HostApplicationMessageCollection mvarMessages = new HostApplicationMessage.HostApplicationMessageCollection(); + /// + /// A collection of messages to display in the Error List panel. + /// public static HostApplicationMessage.HostApplicationMessageCollection Messages { get { return mvarMessages; } } } } diff --git a/CSharp/Libraries/UniversalEditor.UserInterface/StockCommandType.cs b/CSharp/Libraries/UniversalEditor.UserInterface/StockCommandType.cs new file mode 100644 index 00000000..6b1b38f6 --- /dev/null +++ b/CSharp/Libraries/UniversalEditor.UserInterface/StockCommandType.cs @@ -0,0 +1,9 @@ +using System; +namespace UniversalEditor.UserInterface +{ + public enum StockCommandType + { + None + } +} + diff --git a/CSharp/Libraries/UniversalEditor.UserInterface/UniversalEditor.UserInterface.csproj b/CSharp/Libraries/UniversalEditor.UserInterface/UniversalEditor.UserInterface.csproj index 981af14e..3de047ad 100644 --- a/CSharp/Libraries/UniversalEditor.UserInterface/UniversalEditor.UserInterface.csproj +++ b/CSharp/Libraries/UniversalEditor.UserInterface/UniversalEditor.UserInterface.csproj @@ -74,6 +74,10 @@ + + + +