source files: xgtx.[ch]
(SEND <xgtx> :GET <:PROPERTY> [<default-value>]) (SEND <xgtx> :SET <:PROPERTY> <value>) (SEND <xgtx> :REMPROP <:PROPERTY>) (SEND <xgtx> :PROPERTY-LIST-LENGTH) (SEND <xgtx> :PROPERTY-LIST-NTH <fix:index> [<default-value>])
As usual, :GET/:SET are used to manipulate both values with special significance to the MENU instance, and propertylist values passively stored for the benefit of the user.
If :GET does not find the requested property, it returns <default-value> if one was provided, otherwise signals an error.
Numeric properties may in general be supplied as float or ints indifferently. If NIL is provided where a numeric property was expected, nothing is done. (This is a feature, not a bug.)
:REMPROP removes the given property from the propertylist, returning (:PROPERTY . <val>) if the property was successfully removed, else NIL.
:PROPERTY-LIST-LENGTH and :PROPERTY-LIST-NTH are provided to allow iteration through all properties on thing, the latter's <default-value> works just as on :GET.
:LABEL is a lisp string constituting a title for the menu.
:LABEL-FONT and :STRING-FONT are integers from 0 to 11 inclusive indentifying the hershey font in which to display the label and the choices (respectively) of the menu.
:STRING is the current value of the string being entered by user.
:STRING-AS-FLOAT is the current value of the string being entered by user, interpreted as a floating point number. Provided only because I can't locate xlisp's sscanf equivalent.
:VERTICAL-MARGIN is the spacing between the menu holes, expressed as a fraction of the total width of the widget.
:HORIZONTAL-MARGIN is the spacing between the menu holes and the sides of the widget, expressed as a fraction of the total width of the widget.
:STRING-HEIGHT is the height of the bottom of the slot in which the user enters the string, expressed as a fraction of the total width of the widget.
:LABEL-HEIGHT is the height of the bottom of the slot containing the label and value, expressed as a fraction of the total width of the widget. If this is set to zero, the widget will lack visible label and value.
:FRUSTUM-DEPTH is the depth of the main frustum, expressed as a fraction of the total width of the widget.
:STRING-DEPTH is the depth of the slot containing the user-entered string, expressed as a fraction of the total width of the widget.
:LABEL-DEPTH is the depth of the slot containing the label, expressed as a fraction of the total width of the widget.
class-string-reader instances tend to silently ignore or modify values for the above quantities if they consider them silly.
:CHANGE-HOOK function(s) will be called whenever the currently selected string changes for any reason. EXCEPTION: If the value of a menu is changed by a change-hook, the change-hook functions are *not* re-invoked. This is to prevent infinite recursions in the common case of a changehook wishing to adjust the menu value. Actually, I'm still pondering what the semantics of this hook should be, or even if it serves any purpose. Should it fire on each char the user enters/deletes, or only when he hits return, or ?
When change-hook functions are invoked, XG.3D.GUI-CURRENT-WIDGET is set to the current menu object: :GET may then be used to read the currently selected :STRING from it. I'm not sure if this should be the normal way of having a string-reader control something!
The remaining hooks are primarily for specialized needs -- if you want to highlight an object while it is being controlled, you may do so with appropriate click hooks, for example.
If a :DOWN-CLICK-HOOK, :DRAG-HOOK, or :UPCLICK-HOOK is provided, they will be invoked whenever the user downclicks (respectively, drags or upclicks) the menu proper (as opposed to the body, label or limit fields).