|
Re: Ideas for a new command system: msg#00043gnome.mono.monodevelop.general
Looks very nice. Just performance-wise I would be carefull to transform the attributes metadata into some indexed form when first scanning for command handlers to avoid repetitive reflection costs... May be a premature optimization, but I can't help thinking it will effectively be needed to attain adequate UI responsiveness. Have fun, On Apr 8, 2005 9:22 PM, Lluis Sanchez <lluis@xxxxxxxxxx> wrote: > 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. > > _______________________________________________ > Monodevelop-list mailing list > Monodevelop-list@xxxxxxxxxxxxxxxx > http://lists.ximian.com/mailman/listinfo/monodevelop-list > -- Rafael "Monoman" Teixeira --------------------------------------- I'm trying to become a "Rosh Gadol" before my own eyes. See http://www.joelonsoftware.com/items/2004/12/06.html for enlightment. It hurts! |
|
| <Prev in Thread] | Current Thread | [Next in Thread> |
|---|---|---|
| Previous by Date: | Re: Problem running monodevelop on linux: 00043, Todd Berman |
|---|---|
| Next by Date: | German Translation: 00043, Gustav Schauwecker |
| Previous by Thread: | Ideas for a new command systemi: 00043, Lluis Sanchez |
| Next by Thread: | Re: Ideas for a new command system: 00043, Lluis Sanchez |
| Indexes: | [Date] [Thread] [Top] [All Lists] |
| News | FAQ | advertise |