|
Ideas for a new command system: msg#00040gnome.mono.monodevelop.general
Hi! The next target in my quest for improving the architecture of MD is the command system. There are two reasons why I don't like the current design: * It is not possible to change the behavior of a command depending on the context in which it is run. For example, the Delete command deletes the selected text in the editor, but we should be able to use the same command for deleting the selected file in the solution pad (if the pad has the focus), or whatever. Any addin should be able to provide a custom behavior for an existing command. * It is not easy to handle the status of commands. Commands can be enabled/disabled using conditions, but conditions must be specified in the addin XML file and are very limited. What I propose is a very different approach, so feedback is greatly welcome (BTW, the main concept is taken from MS's MFC class library, not a great library, but I like the approach it uses for command handling). First of all, there is a global list of commands, which is independent from where those commands are used. The command list would be defined/extended in the addin xml like this: <Extension path = "/SharpDevelop/Commands"> <Command id = "EditCommands.Copy" _label = "Copy" icon = "Icons.16x16.CopyIcon" shortcut = "Control|C"/> <Command id = "EditCommands.Paste" _label = "_Paste" icon = "Icons.16x16.PasteIcon" shortcut = "Control|V"/> <Command id = "EditCommands.Delete" _label = "_Delete" icon = "Icons.16x16.DeleteIcon" shortcut = "Del"/> </Extension> Then, we can define menus and toolbars by refering those commands: <Extension path = "/SharpDevelop/Views/ProjectBrowser/ContextMenu/ProjectFileNode"> <MenuItem id = "Copy" command = "EditCommands.Copy"/> <MenuItem id = "Paste" command = "EditCommands.Paste"/> <MenuItem id = "Delete" command = "EditCommands.Delete"/> </Extension> The big change is how commands are executed. Instead of implementing a single class for each command, we can implement command handler methods in any class. For example, to handle the Delete command in the text editor I would write a handler like this: [CommandHandler (EditCommands.Delete)] void OnDeleteCommand () { // Delete the selection } If we want to implement the Delete command in a custom pad, we would add a similar command handler in that pad. So, we have two handlers for the same command in two different classes. Which one of them will be executed when clicking on the Delete menu item? It depends on the context. When the command is clicked, the command manager looks for a command handler by following a command route. This route begins at the widget that has the focus and goes up in the parent chain. This means that if we are editing some text in the editor, the delete command handler in the editor will be executed. If we move the focus to the solution pad, then the pad will get the commands. The command manager will also automatically disable or hide commands for which there isn't a handler in the active command route. This gives a lot a consistency to the menu and toolbars, since options and buttons will be grayed out when they can't be used (and there is no need to write code for this, it comes for free). If the status of a command depends on some internal logic, we can implement that logic in some special command update handlers. For example: [CommandUpdateHandler (EditCommands.Delete)] void OnUpdateDeleteCommand (CommandInfo commandInfo) { if (the_selected_tree_node_can_be_deleted()) { commandInfo.Enabled = true; commandInfo.Text = "Delete " + current_node.Name; } else { commandInfo.Enabled = false; } } The command manager will look for a command update handler in the current command route. If found, it will call the handler and will update the menu items and buttons linked to that command accordingly. If not found, it will disable them. This is more or less the idea. There are many more details, such as being able to customize the command route, defining global command handlers for global commands, menu builders for the "Windows" menu list, etc., but I just described the fundamental idea. Comments? Lluis. |
|
| <Prev in Thread] | Current Thread | [Next in Thread> |
|---|---|---|
| Previous by Date: | AW: UML CanvasItem: 00040, Rodehueser, Joerg |
|---|---|
| Next by Date: | Problem running monodevelop on linux: 00040, Steve Willcock |
| Previous by Thread: | AW: UML CanvasItemi: 00040, Rodehueser, Joerg |
| Next by Thread: | Re: Ideas for a new command system: 00040, Rafael Teixeira |
| Indexes: | [Date] [Thread] [Top] [All Lists] |
| News | FAQ | advertise |