This message doesn't pertain to the internal development of McCLIM, but is rather a general CLIM question. The only CLIM mailing list that I've found seems to have next to no traffic on it, so this seemed the best place to send my questions. Perhaps it would be prudent (if messages like this become a hassle) to create a mcclim-user mailing list on common-lisp.net?
What is the proper way to go about defining presentation types with their associated methods, especially accept? For some background, I'm working on an application for working with a set of objects that I've defined. In defining these objects, I've done some MOP-ery to allow me to specify for a given slot on an object, which values are allowed:
(defclass my-class () ((slot-a :allowed-values ("some" "allowed" "values"))) (:metaclass restricted-slot-value-class))
I've also got the necessary machinery to easily get the allowable values for a given slot of an object. Now, I'd like to use this machinery to ease the creation of dialogs pertaining to these objects. For example, if a user is needing to supply a value for slot-a, I'd like to display a menu to the user containing the valid values.
The way that I've tried to accomplish this is that I've created a presentation type for each slot in the object (I know there must be a more general solution...). Then I've defined an accept method for these presentation types. Now, in my accept method, I'm trying to use menu-choose as follows:
(clim:define-presentation-method clim:accept ((type slot-a) stream view &key &allow-other-keys) (declare (ignore view)) (clim:menu-choose (allowed-values 'slot-a)))
I then create a dialog using accepting-values, which in turn calls this accept method. This isn't giving me the desired behavior though. When I click on the input field for slot-a, I do get the proper menu displayed, but when I first choose an option, it doesn't appear to have any effect, but does redisplay the menu again. After choosing a menu option a second time, the choice does indeed seem to stick.
Am I just missing a step, or have I wondered down a wrong path entirely? Does anyone have any advice for how better to handle such a situation?
Anthony W. Juckel
On Jan 15, 2005, at 7:35 AM, Anthony Juckel wrote:
This message doesn't pertain to the internal development of McCLIM, but is rather a general CLIM question. The only CLIM mailing list that I've found seems to have next to no traffic on it, so this seemed the best place to send my questions. Perhaps it would be prudent (if messages like this become a hassle) to create a mcclim-user mailing list on common-lisp.net?
If we get to that point, sure, though I don't think we're quite there yet :) For the moment these kinds of discussions tend to point out shortcomings in McCLIM and for that reason are valuable to have on the developer's list. Also, few of here are experienced users of the commercial CLIM implementation, so in a sense we're all finding the true way together.
What is the proper way to go about defining presentation types with their associated methods, especially accept? For some background, I'm working on an application for working with a set of objects that I've defined. In defining these objects, I've done some MOP-ery to allow me to specify for a given slot on an object, which values are allowed:
(defclass my-class () ((slot-a :allowed-values ("some" "allowed" "values"))) (:metaclass restricted-slot-value-class))
I've also got the necessary machinery to easily get the allowable values for a given slot of an object. Now, I'd like to use this machinery to ease the creation of dialogs pertaining to these objects. For example, if a user is needing to supply a value for slot-a, I'd like to display a menu to the user containing the valid values.
The way that I've tried to accomplish this is that I've created a presentation type for each slot in the object (I know there must be a more general solution...). Then I've defined an accept method for these presentation types. Now, in my accept method, I'm trying to use menu-choose as follows:
There are a couple of ways you can go here, depending on how much flexibility you need in accepting the values. CLIM has useful presentation types for accepting one of several values, MEMBER and COMPLETION. The accept method for COMPLETION doesn't directly present a menu; it's a text field in which one can use tab completion and get a menu by right clicking. I'll return to just using a menu in a second.
You can define presentation types that inherit from completion or directly use the COMPLETION type to accept values (either within ACCEPTING-VALUES) or elsewhere:
(setf (slot-value obj 'slot-a) (accept `(completion ,(allowed-values 'slot-a)) stream))
This is nice because it can be abstracted in a function in the obvious way.
You could also define a presentation type that uses the slot name as an argument:
(define-presentation-type slot-val (slot-name) :inherit-from t) (define-presentation-method accept (type slot-val) stream view &key) (accept `(completion ,(allowed-values ,slot-name)) stream view))
(clim:define-presentation-method clim:accept ((type slot-a) stream view &key &allow-other-keys) (declare (ignore view)) (clim:menu-choose (allowed-values 'slot-a)))
I then create a dialog using accepting-values, which in turn calls this accept method. This isn't giving me the desired behavior though.
I believe that's because the control flow within accepting-values is very strange. I'm a bit surprised that this works at all. Are you looking for a pop-up menu, or a list of choices embedded in the dialog? The right way to do this is probably with gadgets and gadget views. Gadget views are not implemented yet in McCLIM, but they are certainly on our list. In an ideal world the view in a dialog for the completion type would present a pop-up menu.
If you do implement a custom accept method like this, you should probably define your own view and specialize this method on the view so that you can textually input values in other input contexts.
When I click on the input field for slot-a, I do get the proper menu displayed, but when I first choose an option, it doesn't appear to have any effect, but does redisplay the menu again. After choosing a menu option a second time, the choice does indeed seem to stick.
What do you mean by "choose an option;" another option in the dialog box? It's possible that a recent update to the dialog code would fix your problem. Otherwise I'd need to see your code to figure out what's going on as I certainly haven't considered yet doing things like calling menu-choose within accepting values.
Am I just missing a step, or have I wondered down a wrong path entirely? Does anyone have any advice for how better to handle such a situation?
There are a lot of different paths :)
Tim
On Sat, 15 Jan 2005 15:39:35 +0100, Timothy Moore moore@bricoworks.com wrote:
On Jan 15, 2005, at 7:35 AM, Anthony Juckel wrote:
[...snip...]
The way that I've tried to accomplish this is that I've created a presentation type for each slot in the object (I know there must be a more general solution...). Then I've defined an accept method for these presentation types. Now, in my accept method, I'm trying to use menu-choose as follows:
There are a couple of ways you can go here, depending on how much flexibility you need in accepting the values. CLIM has useful presentation types for accepting one of several values, MEMBER and COMPLETION. The accept method for COMPLETION doesn't directly present a menu; it's a text field in which one can use tab completion and get a menu by right clicking. I'll return to just using a menu in a second.
This is actually the way that I started out (using MEMBER), so perhaps I'll settle with that for now. One thing about the usability though, it would be nice if you could navigate the dialog completely without using the mouse. Currently, I have to (at least, I believe I have to) click on the first field, then I can type in my value and hit enter to move to the next, but I have to again use the mouse to click the exit button.
You can define presentation types that inherit from completion or directly use the COMPLETION type to accept values (either within ACCEPTING-VALUES) or elsewhere:
(setf (slot-value obj 'slot-a) (accept `(completion ,(allowed-values 'slot-a)) stream))
This is nice because it can be abstracted in a function in the obvious way.
You could also define a presentation type that uses the slot name as an argument:
(define-presentation-type slot-val (slot-name) :inherit-from t) (define-presentation-method accept (type slot-val) stream view &key) (accept `(completion ,(allowed-values ,slot-name)) stream view))
(clim:define-presentation-method clim:accept ((type slot-a) stream view &key &allow-other-keys) (declare (ignore view)) (clim:menu-choose (allowed-values 'slot-a)))
I then create a dialog using accepting-values, which in turn calls this accept method. This isn't giving me the desired behavior though.
I believe that's because the control flow within accepting-values is very strange. I'm a bit surprised that this works at all. Are you looking for a pop-up menu, or a list of choices embedded in the dialog? The right way to do this is probably with gadgets and gadget views. Gadget views are not implemented yet in McCLIM, but they are certainly on our list. In an ideal world the view in a dialog for the completion type would present a pop-up menu.
I was looking for a pop-up menu, which is what I get with the above. When I click on the field to edit, a popup menu is drawn with the allowed values for that field.
If you do implement a custom accept method like this, you should probably define your own view and specialize this method on the view so that you can textually input values in other input contexts.
When I click on the input field for slot-a, I do get the proper menu displayed, but when I first choose an option, it doesn't appear to have any effect, but does redisplay the menu again. After choosing a menu option a second time, the choice does indeed seem to stick.
What do you mean by "choose an option;" another option in the dialog box? It's possible that a recent update to the dialog code would fix your problem. Otherwise I'd need to see your code to figure out what's going on as I certainly haven't considered yet doing things like calling menu-choose within accepting values.
By "choose an option" I was referring to clicking on a particular menu item in the popup menu. I use the term field to refer to the different elements that I'm editing within accepting-values. So I would click on a field, select an item from the menu, select an item from the new menu to get the value to stick.
Thank you for your ideas.
Anthony W. Juckel
On Jan 15, 2005, at 8:02 PM, Anthony Juckel wrote:
On Sat, 15 Jan 2005 15:39:35 +0100, Timothy Moore moore@bricoworks.com wrote:
...
This is actually the way that I started out (using MEMBER), so perhaps I'll settle with that for now. One thing about the usability though, it would be nice if you could navigate the dialog completely without using the mouse. Currently, I have to (at least, I believe I have to) click on the first field, then I can type in my value and hit enter to move to the next, but I have to again use the mouse to click the exit button.
You can specify :initially-select-query-identifier to accepting-values. Perhaps a sensible default would be the first query. I agree that it would be nice if leaving the last query field would exit accepting-values and will look at implementing that behavior.
I was looking for a pop-up menu, which is what I get with the above. When I click on the field to edit, a popup menu is drawn with the allowed values for that field.
A pop-up menu is nice. However, special effects like this should be done with accept-present-default. There's no documentation on what accept-present-default should do either in the CLIM spec or the Franz user guide. I just checked in an implementation of a pop-up menu which you can use via the climi::+pop-up-menu-view+ parameter. I also added some documentation to dialog.lisp about the internals of accepting-values. This should get people started on writing better input gadgets for accepting-values. Note that this uses internals of McCLIM and is subject to change, especially when we get around to implementing accepting-values panes. Also, the climi internal symbols will probably be exported from clim-extensions.
Tim