Hi,
Consider the attached code, which demonstrates that it is possible with current McCLIM to change the contents of menus from within the app. So far, no surprises -- we have a nice dynamic UI, right?
The surprise is that it isn't possible to do this to the contents of the menu bar itself: the menus there are fixed when the pane is instantiated, I believe. So my question: is this intentional? Is it desireable? (And what does Legacy CLIM do? :-)
Cheers,
Christophe
On 1/5/07, Christophe Rhodes csr21@cantab.net wrote:
The surprise is that it isn't possible to do this to the contents of the menu bar itself: the menus there are fixed when the pane is instantiated, I believe. So my question: is this intentional? Is it desireable? (And what does Legacy CLIM do? :-)
I can't object to this behaving in the expected way, if you want to take the effort to make it work. It makes sense to me. On the other hand, since a command table (and its menu) are shared global resources rather than part of the local state of a frame, I'm having trouble imagining uses other than resolving the obvious "I just added a new command, why can't I see it?" situation, which shouldn't arise often anyway if you organize your commands into logical menus.
"Andy Hefner" ahefner@gmail.com writes:
On 1/5/07, Christophe Rhodes csr21@cantab.net wrote:
The surprise is that it isn't possible to do this to the contents of the menu bar itself: the menus there are fixed when the pane is instantiated, I believe. So my question: is this intentional? Is it desireable? (And what does Legacy CLIM do? :-)
I can't object to this behaving in the expected way, if you want to take the effort to make it work. It makes sense to me.
OK. (No promises yet: my main use case is the one that already works :-)
On the other hand, since a command table (and its menu) are shared global resources rather than part of the local state of a frame, I'm having trouble imagining uses other than resolving the obvious "I just added a new command, why can't I see it?" situation, which shouldn't arise often anyway if you organize your commands into logical menus.
Well, one use case is for applications (such as gsharp and climacs), with some notion of input state: for instance, if in lyrics mode in gsharp, there should be a lyrics menu in the menubar, where there probably shouldn't be if in notes mode. Similarly, if in Lisp/SWINE mode in climacs, there should probably be menus for lisp interaction, which shouldn't be there for a buffer in Fundamental Syntax. (GNU Emacs, at least, performs manipulations of its own menu bar in much this way).
I quite agree that uses of this facility would have to ensure that they modify a frame-specific command table and not a global one... Oh. For some reason I thought it was possible to have anonymous command tables, as in the GENERATE-PANES method in MAKE-SINGLE-GENERATE-PANES-FORM in frames.lisp (naming it with NIL), but maybe this isn't in fact allowed...
Cheers,
Christophe
On 1/5/07, Christophe Rhodes csr21@cantab.net wrote:
Well, one use case is for applications (such as gsharp and climacs), with some notion of input state: for instance, if in lyrics mode in gsharp, there should be a lyrics menu in the menubar, where there probably shouldn't be if in notes mode. Similarly, if in Lisp/SWINE mode in climacs, there should probably be menus for lisp interaction, which shouldn't be there for a buffer in Fundamental Syntax. (GNU Emacs, at least, performs manipulations of its own menu bar in much this way).
Interesting. I'd never considered the possibility of using anonymous command tables, but the command table functions seem to support the concept. I'm not sure I understand the problem in using them - if the only hangup is how to sneak it through define-application-frame to make all the frame instantiating grunge cooperate, you can always write your own read-frame-command, or extend mcclim.
Being able to add and remove menu items like this sounds useful and is exactly the sort of low level interface I ought to like, but to actually use it in an application is probably wrong in the same way that making frequent use of (setf command-enabled) is stupid and wrong (compared with using mgr's much nicer conditional-commands extension).
Here's an alternative approach I dreamed up a while ago which (I think) addresses the uses you've described: Put the menu bar under the control of accept (or possibly read-frame-command), driven by the current input context. It would combine the menus for every command table in the current input context via some protocol, updating the menu items when the input context changes (if necessary).
I don't know how the command reading is done in the applications you mention, but I'd expect you have a command table for commands on the application instance (Quit, etc), one or more command tables for the current buffer and its syntax/mode, and yet another for the current input mode, all of which should be part of the current input context (or somehow inherited together). So, commands from any of these tables should satisfy the accept done by read-frame-command, and as such our extension would merge their menus to populate the current menu bar.
Recalling your example the other day of reading a command you don't intend to accept, perhaps putting this under the control of read-frame-command makes the most sense (rather than occuring in response to every accept of 'command, regardless of what you intend to do with the command).
If implemented, this ought to be unnoticable unless the application is highly modal. In particular, it should not flicker every time through the command loop. :) I'd also expect that entering accepting-values should also not cause my menu bar to change, so it shouldn't apply unconditionally.
On 1/5/07, Andy Hefner ahefner@gmail.com wrote:
(compared with using mgr's much nicer conditional-commands extension).
Sorry, I take this bit back. I don't understand his extension at all. I assumed, going by the name, that it implemented the simple and obvious thing that CLIM commands should be able to do but don't, namely to compute whether the command is enabled or disabled as a function of the application state, rather than forcing the programmer to manually enable/disable things from other commands. Bah.