Amulet provides a full set of widgets, including buttons, menus, scroll bars, and text input fields. Eventually, these will display themselves in different looks, corresponding to the various platforms. The built-in widgets have a large number of parameters to allow programmers to customize them, and the programmer can also create new kinds of widgets by writing new methods.
The intent of the Amulet Widget set is to supply several frequently used objects that can be easily customized by the designer. By importing these pre-constructed objects into a larger Amulet interface, the designer is able to specify in detail the desired appearance and behavior of the interface, while avoiding the programming that this specification would otherwise entail.
This document is a guide to using Amulet's Widgets. The objects were constructed using the complete Amulet system, and their descriptions assume that the reader has some knowledge of the components of this system: Opal, Interactors, and ORE.
All of the widgets (except the Am_Selection_Widget) are set up to operate with the left mouse button, and ignore the modifier keys. Thus, clicking on a scroll bar with
SHIFT_CONTROL_LEFT_DOWN
does the same as regular left down. The default widget start character is exported as Am_Default_Widget_Start_Char
.Dialog boxes and windows that use the widgets can often be created interactively using the Gilt interface builder, described in a different chapter.
Am_Border_Rectangle
: a rectangle with a raised (or lowered) edge, but no interaction.
Am_Button
: a single button
Am_Button_Panel
: a panel consisting of multiple buttons with the labels inside the buttons.
Am_Checkbox_Panel
: a panel of toggle checkboxes with the labels next to the checkboxes.
Am_Radio_Button_Panel
: a panel of mutually exclusively selectable radio buttons with the labels next to the radio buttons.
Am_Menu
: a menu panel
Am_Menu_Bar
: a menu bar used to select from several different menu panels
Am_Pop_Up_Menu_Interactor
: An interactor that pops up a menu. Often used with start-when as the right-button to get Windows95 style behaviors.
Am_Vertical_Scroll_Bar
:
scroll bar for choosing a value from a range of values.
Am_Horizontal_Scroll_Bar
: scroll bar for choosing a value from a range of values.
Am_Vertical_Up_Down_Counter
: Two arrows (like the top and bottom of a scroll bar) for incrementing and decrementing a number.
Am_Scrolling_Group
: an Amulet group with (optional) vertical and horizontal scrollbars
Am_Text_Input_Widget
: a field to accept text input, like for a filename.
Am_Number_Input_Widget
: Text input widget that is limited to integer or floating point numbers.
Am_Password_Input_Widget
: Text input widget that shows ``*''s instead of the characters that are typed.
Am_Show_File_Dialog_For_Open
: Eventually, this will display a standard scrolling list of files. Currently it just uses a text-input widget, and can be used for forward compatibility.
Am_Show_File_Dialog_For_Save
: Eventually, this will display a standard scrolling list of files. Currently it just uses a text-input widget, and can be used for forward compatibility
Am_Graphics_Set_Property_Command
: to set the color, line style or other property of the selected objects.
Am_Graphics_Clear_Command
: delete the selected objects (``Clear'')
Am_Graphics_Clear_All_Command
: ``Clear all''
Am_Graphics_Copy_Command
: Copy to the clipboard.
Am_Graphics_Cut_Command
: Copy objects to the clipboard and then delete them
Am_Graphics_Paste_Command
: Paste a copy of the objects in the clipboard.
Am_Undo_Command
: Perform a single undo.
Am_Redo_Command
: Perform a single redo.
Am_Graphics_To_Bottom_Command
: Make the selected objects be covered by all other objects.
Am_Graphics_To_Top_Command
: Make the selected objects be covered by no other objects.
Am_Graphics_Duplicate_Command
: Duplicate the selected objects.
Am_Graphics_Group_Command
: Make a group out of the selected objects.
Am_Graphics_Ungroup_Command:
Ungroup the selected objects.
Am_Quit_No_Ask_Command
: Quit the application immediately without asking for confirmation.
Am_Open_Command, Am_Save_Command, Am_Save_As_Command
: For opening and saving files using the built-in load-save mechanism.
Am_Standard_OK_Command, Am_Standard_Cancel_Command
: Useful for the buttons in dialog boxes that have been popped up with Am_Pop_Up_Window_And_Wait
.
Am_About_Amulet_Command
- brings up the standard About Amulet dialog box.
Am_Cycle_Value_Command
: Cycles the label through a list of values.
The visual appearance and the functionality of a widget is affected by values set in its slots. When instances of widgets are created, the instances inherit all of the slots and slot values from the prototype object. The designer can then change the values of these slots to customize the widget. Instances of the custom widget will inherit the customized values. The slot values in a widget prototype can be considered ``default'' values for the instances.
widgets.h
for the widget object definitions, and standard_slots.h
for the widget slot definitions. These files are included in amulet.h
, providing a simple way to make sure all needed files are included. Programmers who are designing their own custom widget objects will also need widgets_advanced.h
. For a complete description of Amulet header files and how to use them most effectively in your project, see Section 1.8 in the Overview chapter.
Widgets are standard Amulet objects, and are created and modified in the same way as any other Amulet object. The following sample code creates an instance of
Am_Button
, and changes the values of a few of its slots.Am_Object my_button = Am_Button.Create("My Button")
.Set (Am_LEFT, 10)
// set the position of the button
.Set (Am_TOP, 10)
.Set (Am_COMMAND,"Push Me");
// a string in the Am_COMMAND slot specifies the button's label: see below
7.1.4 Application Interface
Like interactors, widgets interface to application code through command objects added as parts of the widgets. Please see Section 5.6 on Commands in the Interactor's chapter. In summary, instead of executing a call-back procedure as in other toolkits, Amulet widgets call the Am_DO_METHOD
of the command object stored as the Am_COMMAND
part of the widget. For lots of examples of using widgets and commands in widgets, see the samples (in amulet/samples/*) especially the examples in samples/examples/example*.cc.
7.1.4.1 Accessing and Setting Widget Values
In addition to the Am_DO_METHOD
, each command also contains the other typical slots of command objects. In particular, the Am_VALUE
slot of the command object is normally set with the result of the widget. Of course, the type of this value is dependent on the type of the widget. For scroll bars, the value will be a number, and for a checkbox panel, it will be a list of the selected items.Am_VALUE
slot of the widget is also set with the current value of the widget. If you want to set the value of the widget (change the displayed value of the widget), you can set the value of the Am_VALUE
slot of the widget to the correct value. Note: Set the Am_VALUE slot of the widget not of the command object, to change the value of the widget. It is also appropriate to put a constraint into the Am_VALUE
slot of the widget if you want the value shown by the widget to track a slot of another object.Am_VALUE
slot. This constraint can perform side effects like updating an external data base or even setting slots in Amulet objects or creating or destroying new objects. Other times, the programmer will need to write an Am_DO_METHOD
which will typically access the value in the command's Am_VALUE
slot. An example of each of these methods can be found below. Of course, if you write your own Am_DO_METHOD
and you want the widget to be undo-able, you will also need to write a corresponding Am_UNDO_METHOD
, etc. See Section 5.6 in the Interactors chapter on commands for more information.
7.1.4.2 Commands in Widgets
All of the widgets are designed so the command objects are completely replaceable. Thus, you can put the commands from the library (see Section 7.4) or your new commands into any widget. Alternatively, you can get the default commands in the widgets (which has all blank methods) and override the methods. For example:
vscroll = Am_Vertical_Scroll_Bar.Create()
.Set(Am_LEFT, 450)
.Set(Am_TOP, 80)
;
vscroll.Get(Am_COMMAND)
.Set(Am_DO_METHOD, my_do)
.Set(Am_UNDO_METHOD, my_undo)
;
Normally, the command objects should be parts of the widgets, so that if an instance is made of the widget, an instance will also be made of the command object. However, the widgets will still work if the command is just Set into the Am_COMMAND
slot:vscroll.Set_Part(Am_COMMAND, my_command); //command objects should be parts
7.1.4.3 Undoing Widgets
Internally, each widget is implemented using graphical objects and interactors. Each internal interactor has its own associated command objects, but these are normally irrelevant to the programmer, since the internal command objects will call the top-level widget command object automatically. This is achieved because the internal commands have their Am_IMPLEMENTATION_PARENT
slot of the internal command objects to be the widget's command object, and then Amulet automatically does the right thing.7.2 The Standard Widget Objects
This section describes the widgets in detail. Each object contains customizable slots, but the designer may choose to ignore many of them in any given application. Any slots not explicitly set by the application are inherited from the widget's prototype.7.2.1 Slots Common to All Widgets
There are several slots the programmer can set which are used by all widgets in a similar way:
Am_TOP, Am_LEFT
: As with all graphical objects, these slots describe the location of the widget, in coordinates relative to the object's parent's location. Default values are 0 for both top and left.
Am_VISIBLE
: If this boolean is true, the object is visible; otherwise, it is not drawn on the screen. Default is true
.
Am_VALUE
: The current value computed by the widget. This slot can also be set to change the widget's value.
Am_WIDGET_LOOK
: The value of this slot tells Amulet how you want your widgets to look when drawn on the screen. Possible values are Am_MOTIF_LOOK, Am_WINDOWS_LOOK
, or Am_MACINTOSH_LOOK
, or Am_NATIVE_LOOK
which is whatever is the current machine. See Section 7.2.2.
Am_FILL_STYLE
: This slot determines the color of the widget. Amulet automatically figures out appropriate foreground, background, shadow, and highlight colors given a fill color. Acceptable values are any Am_Style
, and the default is Am_Amulet_Purple
. The only part of the style used is the color of the style. On a black and white screen, a default set of stipples are used to make sure the widgets are visible. Unfortunately, you cannot set the style for the text labels shown in widgets, but the system picks either black or white text based on how dark the Am_FILL_STYLE
is.
Am_ACTIVE_2
: This slot turns off interaction with the widget without turning it grey. This is mainly aimed at interactive tools like Interface Builders that want to allow users to select and move widgets around. It might also be useful in a multi-user situation where users who do not have the ``floor'' should not have their widgets responding. For a widget to operate, both Am_ACTIVE_2
and Am_ACTIVE
must be true
. The default value is true.
Am_ACTIVE
: This slot in the command is used to determine whether the widget is enabled or not (greyed out). Often, this slot will contain a formula dependent on some system state. The default value is true
. (Actually, the widget itself also contains an Am_ACTIVE
slot, but this one should not normally be used. The widget-level slot contains a constraint that depends on the Am_ACTIVE
slot of the command object part of the widget.)
Am_VALUE
: This slot is set to the current value of the widget. Do not set this slot in the command object to try to change the widget's value (see the Am_VALUE
of the widget instead).
Am_DO_METHOD
: The method to be called when the widget executes. This procedure takes one parameter: the command object.
Am_DEFAULT
: for buttons, shows whether this is the default selection by drawing an extra thick border. Be sure to set the Am_ACCELERATOR
slot of this command to ``RETURN''
.
Am_CHECKED_ITEM
: for menus and menubars, whether this item has a check mark next to it.
Am_IMPLEMENTATION_PARENT
: If you want the command to invoke another command, you can set this slot in the widget's command to the other command object. For example, if the widget is the ``OK'' button of a dialog box, the Am_IMPLEMENTATION_PARENT
of the OK widget's command might be the command object for the entire dialog box. Then Amulet will correctly know how to handle Undo, and it will call the parent command automatically.
Am_WIDGET_LOOK
slot controls which look-and-feel is used to draw the widget. Possible values are Am_MOTIF_LOOK,
Am_WINDOWS_LOOK
, or Am_MACINTOSH_LOOK
, or Am_NATIVE_LOOK
which is whatever is the current machine. The default value for this slot is a formula which depends on the Am_WIDGET_LOOK
slot of the Am_Screen
object, which makes it easy to change all the looks at once. You can override the look locally for an individual widget just by overriding the slot. You can use the following function to change the look of all the widgets at the same time:
void Am_Set_Default_Look( Am_Widget_Look inLook = Am_NATIVE_LOOK );or else just set the slot of
Am_Screen
:
Am_Screen.Set(Am_WIDGET_LOOK, new_look);The default look and feel is the native look for the machine currently being used. When in compiled with debugging enabled, the key sequence CONTROL_SHIFT_META_L will change the look among the three values, so you can see what your application would look like in the three looks.
Am_Border_Rectangle
has a raised or lowered edge of a lighter or darker shade of the Am_FILL_STYLE
. It ignores the Am_LINE_STYLE
. It looks pressed in if Am_SELECTED
is true, and sticking out of the screen if Am_SELECTED
is false. This widget has no interaction or response to the mouse.
For a single, stand-alone button, the
Am_COMMAND
slot can either be the string or object to display in the button, or it can be an Am_COMMAND
object, in which case, the label of the widget is determined by the Am_LABEL
slot of the Am_COMMAND
part of the widget, which itself should be a string or object, as described below.
Am_ITEMS
slot which must contain an Am_VALUE_LIST
. The items in this value list can be:
char*
) or Am_String
, in which case this string is displayed as the label,
Am_LABEL
field of the command object is used as the item's label. The Am_LABEL
field itself can contain any type. In particular, if the Am_LABEL
is:
Am_String
, then this is displayed in the widget
cout
) and the string is displayed in the widget. Note that in this case, the Am_VALUE
of the widget will be the original Am_LABEL
value, not the string of that value, so, for example, if the Am_LABEL
is the integer 15, and this item is selected, then the Am_VALUE
of the widget will be 15, not ``15''. (A better way to do this though is probably to set the Am_ID
field of the command.)
Am_DO_METHOD
of this command does the important work of the item. This would typically be how menus of operations like Cut, Copy, and Paste would be implemented.
Am_ITEMS
slot of the widget contains an Am_VALUE_LIST
of strings. In this case, the top-level command object's Am_DO_METHOD
will be called, and it typically will look in its Am_VALUE
slot to determine which item was selected. This method is most appropriate when the panel or menu is a list of values, like colors or fonts, and you do not want to create a command for each item.
Am_IMPLEMENTATION_PARENT
of the item's command to be the widget's command. It would be unusual, but is perfectly legal, to have a Am_Value_List
that contains some commands and some strings.Slots of the command object used by buttons and menus are as follows. More details are available in Section 5.6 of the Interactor chapter.
Am_LABEL
: This slot can contain a string or a graphical object, which will be drawn as the label for this item. See Section 7.2.4.1 for details.
Am_ID
: Normally, buttons set the Am_VALUE
slot to the Am_LABEL
of the command. However, this typically requires doing string matching. Therefore, if the Am_ID
field is non-zero, then the Am_VALUE
slot is set with the value of the Am_ID
slot instead of the Am_LABEL
slot. The Am_ID
slot can contain any type of value.
Am_ACTIVE
: This controls whether the widget is active or not (greyed out). If the Am_ACTIVE
slot of the top-level command in a panel or menu is set to false, then all the items are greyed out. More typically, the Am_ACTIVE
slot of the command associated with a single item will be false
, signaling that just that one item should be greyed out.
Am_ACCELERATOR
: For menus, menu-bars and option-buttons, this can contain an Am_Input_Char
or a string representing the character, and will make that character be an accelerator for this command in the window. See Section 7.2.4.3 for more details.
Am_VALUE
: This slot is set by the widget with the label(s) or ID(s) of currently the selected button(s). In a single button, this contains 0 if the button is not selected, or the button's label or ID if it is selected. Thus, you can use Valid() to determine if the button is pressed. If multiple items can be selected, as in a check box panel or for a button panel if you set Am_HOW_SET
to be Am_CHOICE_LIST_TOGGLE
, then this slot will always contain an Am_Value_List
with the labels or IDs of the selected items. If no items are selected, then the list will be empty. Note: the value of the Am_VALUE
slot will not be 0; it will be a list that is empty, so you cannot use Valid() since an empty Am_Value_List
is still valid. For panels where only a single item can be selected, such as a radio button panel or button panels with Am_HOW_SET
set to be Am_CHOICE_SET
, the Am_VALUE
slot is set to the single button's label or ID, or 0 if nothing is selected.
Am_DEFAULT
: for buttons, shows whether this is the default selection by drawing an extra thick border. Be sure to set the Am_ACCELERATOR
slot of this command to ``RETURN''
.
Am_CHECKED_ITEM
: for menus and menubars, whether this item has a check mark next to it.
Am_ACCELERATOR
slot of a Command object for a menu item is set with an Am_Input_Char
(see Section 5.3.3.1) or a string that can be converted into a character description, like "CONTROL_F7"
, then Amulet will automatically create an accelerator for that command in the window the widget is attached to. In addition, the menu item will show the accelerator using the ``short string'' form of Am_Input_Char
s. This accelerator will only be active when the command is active.
The following function can be used if you want two or more windows to have the same accelerator keys. This might be used, for example, if the main window has the menubar, but you still want the accelerators to work in other windows, which don't have a menubar in them.
void Am_Share_Accelerators(Am_Object &source_window,
The low-level interface to the accelerator lists for windows is available in
Am_Object &new_window);
widget_advanced.h
through the functions Am_Check_Accelerator_Char_For_Window,
Am_Add_Accelerator_ Command_To_Window
and Am_Remove_Accelerator_Command_From_Window
, which take the window and command object. 7.2.4.4 Am_Menu_Line_Command
Am_Menu_Line_Command
is a special purpose type of command object provided by Amulet to draw horizontal dividing lines in menus. To add a horizontal line in a menu, simply include an instance of Am_Menu_Line_Command
in the menu's Am_ITEMS
list. An example of this can be found in section 6.2.3.7. Am_Menu_Line_Command
has no customizable slots, and it is an inactive menu item.7.2.4.5 Am_Button
The Am_Button
object is a single stand-alone button. A button can have a text label, or can contain an arbitrary graphical object when drawn.Am_BUTTON
s are:
Am_WIDTH, Am_HEIGHT
: By default, the width and height of the button are automatically calculated by formulas in these slots. A button is made big enough to contain its text label or graphical object, including borders, and offset pixels (see below). A user can replace the width and height formulas by setting these slots directly. Once the values are set with new values or formulas, the formulas will be removed.
Am_ITEM_OFFSET
: The string or object displayed inside the button is set away from the border of the button by Am_ITEM_OFFSET
pixels, in both the horizontal and vertical directions. The default is 5.
Am_FONT
: The button's text label (if any) is drawn in this font. Acceptable values are any Am_Font
, and the default is Am_Default_Font
.
Am_FINAL_FEEDBACK_WANTED
: This determines if the button should be drawn as if it is still selected, even after user interaction has stopped. This is useful if you want to use the button to show whether it is selected or not. The default is false
.
Am_DEFAULT
: Whether this button is shown as the default. The value is usually set in the command associated with the button. Be sure to set the Am_ACCELERATOR
slot of this command to ``RETURN''
. For example, the Am_Standard_OK_Command
has Am_DEFAULT
as true.
Am_LEAVE_ROOM_FOR_FRINGE
: Whether room should be left around the button to draw the fringe indicating that it is the default, or that it is key selected. If the value of Am_LEAVE_ROOM_FOR_FRINGE
is true
then the inside of the button will not change size whether the button is shown as the default or not.
Am_Button_Panel
is a panel of Am_Buttons
, with a single interactor in charge of all the buttons. Since an Am_Button_Panel
's prototype object is a Am_Map
, all the slots that Am_Map
uses are also used by Am_Button_Panel
. See the Opal chapter for a description of Am_Map
. Some Am_Map
slots are described below along with slots specific to Am_Button_Panel
.
Special slots of
Am_Button_Panel
are:
Am_FONT
: The font used for the button labels.
Am_FINAL_FEEDBACK_WANTED
: Whether to show which item is selected or not. The default is false.
Am_WIDTH, Am_HEIGHT
: The width and height slots contain the standard Amulet formulas Am_Width_Of_Parts
and Am_Height_Of_Parts
, respectively. If these slots are set to specific values by the designer, those values replace the formulas, and the panel will no longer resize itself if its contents change.
Am_FIXED_WIDTH
: This slot determines how the buttons in a panel get their width. An integer value of 0, or a boolean value of false
, means each button is as wide as its calculated width based on the contents. Thus, each button will be a different size. An integer value of 1, or a boolean value of true
, means that all the buttons in the panel are set to be as wide as the calculated width of the widest button in the panel. An integer value greater than 1 sets the width of all buttons in the panel to that specific value. The default is true.
Am_FIXED_HEIGHT
: This slot determines the height of buttons in a panel. It acts the same way as Am_FIXED_WIDTH
. The default is false.
Am_HOW_SET
: This slot determines whether single or multiple buttons can be selected. Its default value is Am_CHOICE_SET
, which allows a single selection. Changing this to Am_CHOICE_TOGGLE
will allow the selected item to be turned off by clicking it again. Am_CHOICE_LIST_TOGGLE
allows there to be multiple selections. See the Interactors manual for a complete description of the legal values.
Am_LAYOUT
: This specifies a function determining how the button panel should be arranged. A more complete description of the slot can be found in section 4.7.2. Am_Vertical_Layout
is the default, and Am_Horizontal_Layout
is another good value.
Am_H_ALIGN
: In a vertically arranged button panel with variable width buttons, this determines how the buttons should be arranged in the panel. The default is Am_LEFT_ALIGN
, and other possible values are Am_CENTER_ALIGN
and Am_RIGHT_ALIGN
.
Am_V_ALIGN
: This slot works like Am_H_ALIGN
, except is only used in horizontally arranged panels width variable height buttons. Possible values are Am_TOP_ALIGN
, Am_CENTER_ALIGN
, and Am_BOTTOM_ALIGN
.
Am_ITEMS
: This slot specifies the items which are to be put in the button panel. An Am_Value_List
should be used to specify specific items to add to the panel. See section 6.2.3.1 for a complete description. In summary, elements of the value list can be either strings, graphical objects, or command objects. A string value is used as the label for the button in the panel. A graphical object is displayed in the button. A command object is used to specify a custom command for that particular button in the panel. For commands, the button's string label or graphical object is taken from the command object's Am_LABEL
slot.
Am_COMMAND
: This slot contains an Am_Command
object. See Section 7.2.4.2 for a complete description.
Am_LEAVE_ROOM_FOR_FRINGE
: This slot determines whether room is left around the buttons in a panel to draw the fringe indicating which button is the default, or is key selected. If the value of Am_LEAVE_ROOM_FOR_FRINGE
is false
then the buttons in the panel will touch each other, and the inside of a button which is the default or selected will change size depending on it is shown as the default or not.
Am_Value_List
in the Am_ITEMS
slot tells the button panel what to put inside each button. If a string is specified, it is used as the button's label. If a graphical object is specified, it is drawn in the button. If a command object is specified, that command object's Am_DO_METHOD
method is called each time the button is pressed, and the button's label or graphical object is obtained from the command object's Am_LABEL
slot. The following code specifies a button panel with four buttons in it.
// a graphical object and custom do action, defined elsewhere:
extern Am_Object My_Graphical_Object;
extern void My_Custom_Do_METHOD (Am_Object command_obj);
Am_Object my_command;
// my button panel:
Am_Object My_Button_Panel = Am_Button_Panel.Create ("My Button Panel")
.Set (Am_ITEMS,
Am_Value_List ()
.Add ("Push me.")
.Add (My_Graphical_Object)
.Add (my_command = Am_Command.Create()
.Set (Am_LABEL, "Push me too.")
.Set (Am_DO_METHOD, My_Custom_Do_Method))
.Add (Am_Quit_No_Ask_Command.Create()));The first button in the panel is drawn with the text label ``Push me.'' and does not have its own command object. The second button in the panel is drawn containing
My_Graphical_Object
drawn inside it, and also does not have its own command. The third button in the panel is drawn with the text label ``Push me too.'' and has its own command object associated with it. The fourth button uses the standard, built-in quit command, which comes pre-set with the methods and label.When the third button is pressed, My_Custom_Do_Method is called, with the button's command object (
my_command
) as an argument. The command object's Am_VALUE
slot will already have been set with either 0, if the button was not selected, or ``Push me too.'' if the button was selected. We assume that this command is not undoable since there is no custom Undo action to go with My_Custom_Do_Method.If either of the first two buttons in the panel are pressed, the do action of
My_Button_Panel
's command object (in its Am_COMMAND
slot) will be called, with the command object as an argument. The Am_VALUE
of the command object is set with the labels or objects corresponding to the currently selected buttons.If you wanted the button panel's command to be invoked when the third button was pressed, you would have to set the third button's command object's
Am_IMPLEMENTATION_PARENT
slot to contain the button panel's command object. For example, after executing the following code, My_Other_Custom_Do_Method
in the panel will be called when any of the buttons are selected.
Am_Object panel_command = My_Button_Panel.Get(Am_COMMAND);
panel_command.Set (Am_DO_METHOD, My_Other_Custom_Do_Method);
my_command.Set (Am_IMPLEMENTATION_PARENT, panel_command);
An
Am_Radio_Button_Panel
is essentially the same as an Am_Button_Panel
, with a few exceptions. There are a few new slots, and some of the defaults of the other slots are different. All other slots not listed below act the same way as in an Am_Button_Panel
. Since radio buttons always only allow a single selection, the Am_VALUE
slot of the top-level Am_COMMAND
is always set with either 0 or the ID or label of the selected item.
Am_BOX_HEIGHT, Am_BOX_WIDTH
: These specify the size in pixels of the small radio button box that is drawn next to the item in the button. The defaults are 15 for each.
Am_BOX_ON_LEFT
: This boolean determines whether the radio box should be drawn to the left of the item, or to the right. If true
, the box is drawn on the left, and if false,
it is drawn on the right. The default is true
.
Am_H_ALIGN
: This slot contains a formula which evaluates to Am_LEFT_ALIGN
if the Am_BOX_ON_LEFT
is true
, or Am_RIGHT_ALIGN
if it is false
.
Am_FIXED_WIDTH
: The default is false
for this slot in a radio button panel.
Am_FINAL_FEEDBACK_WANTED
: The default is true
for this slot in a radio button panel. This makes sure the user selected button stays selected after interaction is complete.
Am_HOW_SET
: Since radio buttons are only allowed to have a single selection, this slot defaults to Am_CHOICE_SET
. However, if you want to allow the user to turn off the current selection by clicking on it again, you can set this slot to be Am_CHOICE_TOGGLE
. It would be wrong to use Am_CHOICE_LIST_TOGGLE
.
An
Am_Checkbox_Panel
is essentially the same as an Am_Radio_Button_Panel
. It is drawn slightly differently, and the following slot is different:
Am_HOW_SET
: The default for a checkbox panel is Am_CHOICE_LIST_TOGGLE
, which allows multiple items to be selected at the same time.
Am_Checkbox_Panel
, the Am_VALUE
slot of the top-level Am_COMMAND
contains an Am_VALUE_LIST
of the labels or IDs of the selected items.
Am_Menu
is a single menu panel, implemented as another form of Am_Button_Panel
. A menu panel has a background rectangle behind it, and the items are drawn differently than in Am_Buttons
.The following slots of an
Am_Menu
differ from those in an Am_Button_Panel
:
Am_WIDTH, Am_HEIGHT
: The default formulas in these slots calculate the width and height of the menu's items, and add enough width and height to contain the menu's outer border.
Am_HOW_SET
: The default for a menu is Am_CHOICE_SET
.
Am_X_OFFSET, Am_Y_OFFSET
: These slots cause the menu items to be offset from the upper left corner of the menu. The defaults are 2 for X and Y, to make room for the outer border around the menu.
Am_V_SPACING
: This creates extra space between the items in a menu. The default value is -2
, which pushes the menu items vertically closer together in the menu.
Am_TEXT_OFFSET
: This offset is used only in the horizontal direction when a text label is being displayed in the menu item (as opposed to a graphical object). This allows greater horizontal spacing for text, while keeping the standard vertical spacing. The default value is 2 pixels.
Am_Menu
object.
Am_Object my_menu = Am_Menu.Create("my_menu")
.Set (Am_LEFT, 150)
.Set (Am_TOP, 200)
.Set (Am_ITEMS, Am_Value_List()
.Add ("Menu item")
.Add (Am_Menu_Line_Command.Create("my menu line"))
.Add (Am_Command.Create("item2")
.Set(Am_ACTIVE, false)
.Set(Am_LABEL, "Not active"))
.Add (Am_Command.Create("item2")
.Set(Am_LABEL, ("Active item"))
.Set(Am_ACCELERATOR, "CONTROL_a"));
my_window.Add_Part(my_menu);The menu has three menu items with a line between the first and second items. The first item appears as ``Menu item'' in the menu, and has no corresponding command object. If that item is selected by the user, the do action of my_menu's command object will be called with ``Menu item'' in its
Am_VALUE
slot. Since there is no command object associated with the first menu item, there is no way to make it inactive without making the whole menu inactive.The second menu item appears in the menu as ``Not active''. It will be grayed out, because the
Am_ACTIVE
slot of its corresponding button command object is set to false. This item cannot be chosen from the menu because it is inactive.The third menu item appears in the menu as ``Active item ^a''. It does have a command object associated with it, so if it is selected by the user, that command's do action will be executed, and the widget's top level command will not be executed. The widget's top level command object is not called unless you set the individual button command object's
Am_IMPLEMENTATION_PARENT
slot to point to it. This command has an accelerator, so if the user hits control-a in my_window
, the command will be executed.
Am_Menu_Bar
is a menubar like you might find at the top of a window that has a horizontal row of items you can select, and each one pops down a menu of further options. Sometimes it is called a pull-down menu. Amulet's menu bar currently supports a single level of sub-menus (no pull-outs from the pull-downs). However, any menu item (either at the top level or a sublevel) can be an arbitrary Amulet object, just like with other button-type objects.The interface to menu bars is similar to other button widgets: the
Am_ITEMS
slot of the menu_bar object should contain an Am_Value_List
. However, unlike other objects, the list must contain command objects. The label field of this command object serves as the top-level menubar item. In the command object should be an Am_ITEMS
slot containing an Am_Value_List
of the sub-menu items. This list can contain command objects, strings or Amulet objects, as with other menus and button panels. For example:
my_menu_bar = Am_Menu_Bar.Create()
.Set(Am_ITEMS, Am_Value_List ()
.Add (Am_Command.Create("File_Command")
.Set(Am_LABEL, "File")
.Set(Am_DO_METHOD, my_file_do)
.Set(Am_ITEMS, Am_Value_List ()
.Add ("Open...")
.Add ("Save As...")
.Add (Am_Command.Create("Quit_Command")
.Set(Am_DO_METHOD, my_quit)
.Set(Am_LABEL, "Quit")
.Set(Am_ACCELERATOR, "^q"))
)
)
.Add (Am_Command.Create("Edit_Command")
.Set(Am_LABEL, "Edit")
.Set(Am_DO_METHOD, my_edit_do)
.Set(Am_ITEMS, Am_Value_List ()
.Add (undo_command.Create())
.Add ("Cut")
.Add ("Copy")
.Add ("Paste")
.Add (Am_Menu_Line_Command.Create("my menu line"))
.Add ("Find...")
)
)
)If a sub-menu item has a command (like Quit or Undo above), then its
Am_DO_METHOD
is called when the item is chosen by the user. If it does not have a command object (like Cut and Paste above), then the command object of the main item is used (here, the do method called my_edit_do
in the command object named Edit_Command
will be called for Cut and Paste, and the Am_VALUE
slot of the Edit_Command
will be set to the string of the particular item selected). Note that because the first level value list must contain command objects, the command object stored in the menu_bar object itself will never be used unless the programmer explicitly sets the Am_IMPLEMENTATION_PARENT
slot of a command to the menu_bar's command object. The Am_VALUE
of whatever command object is executed will be set to the label or ID of the selected item. Menu bars can also contain accelerators, as shown by the Quit command in the example.
Am_Menu_Bars
allow the top level item to be chosen (unlike, say the Macintosh), in which case its command object is called with its own label or ID as the Am_VALUE
. The programmer should ignore this selection if, as usually is the case, pressing and releasing on a top-level item should do nothing.Individual items can be made unselectable by simply setting the
Am_ACTIVE
field of the command object for that item to false. If the Am_ACTIVE
field of a top-level command object is false, then the entire sub-menu is greyed out, although it will still pop up so the user can see what's in it.Unlike regular menus and panels, the Am_Menu_Bar will not show the selected value after user lets up with the mouse. That is, you cannot have
Am_FINAL_FEEDBACK_WANTED
as true.Slots that behave different for the
Am_Menu_Bar
are:
Am_WIDTH, Am_HEIGHT
: By default, these slots contain formulas that make the menubar be the width of its owner (usually the width of the window) and the height of the current font. However, you can override these defaults with constant values or other formulas.
Am_CHECKED_ITEM
slot of the command. It is the responsibility of the programmer to insure that only the proper items are checked. Amulet does not un-check one item if a different item is checked! And Amulet does not check an item if the user selects it--the application should do this with the command's DO method. For example, the following code is used by Gilt for the check marks on the current Look and Feel.
//return true if the current look matches the value in my widget look slot
Am_Define_Formula (bool, look_is_me) {
Am_Value my_look = self.Get(Am_WIDGET_LOOK);
Am_Value current_look = Am_Screen.Get(Am_WIDGET_LOOK);
return my_look == current_look;
}
Am_Define_Method( Am_Object_Method, void, set_look, (Am_Object cmd) ) {
Am_Value my_look = cmd.Get(Am_WIDGET_LOOK);
Am_Set_Default_Look(my_look);
}
... the rest of the menu items
.Set(Am_ITEMS, Am_Value_List ()
.Add (Am_Command.Create(``Motif_Command'')
.Set(Am_LABEL, ``Motif Look'')
.Add(Am_WIDGET_LOOK, Am_MOTIF_LOOK)
.Add(Am_CHECKED_ITEM, look_is_me)
.Set(Am_DO_METHOD, set_look)
.Set(Am_IMPLEMENTATION_PARENT, true)) //not undoable
.Add (Am_Command.Create(``Win_Command'')
.Set(Am_LABEL, ``Windows Look'')
.Add(Am_WIDGET_LOOK, Am_WINDOWS_LOOK)
.Add(Am_CHECKED_ITEM, look_is_me)
.Set(Am_DO_METHOD, set_look)
.Set(Am_IMPLEMENTATION_PARENT, true)) //not undoable
.Add (Am_Command.Create(``Mac_Command'')
.Set(Am_LABEL, ``Macintosh Look'')
.Add(Am_WIDGET_LOOK, Am_MACINTOSH_LOOK)
.Add(Am_CHECKED_ITEM, look_is_me)
.Set(Am_DO_METHOD, set_look)
.Set(Am_IMPLEMENTATION_PARENT, true)) //not undoable
...
Am_Option_Button
are the same as those to a Menu, except that Am_FINAL_FEEDBACK_WANTED
is ignored, and Am_HOW_SET
must stay Am_CHOICE_SET.
Am_Pop_Up_Menu_Interactor
is actually a one shot interactor combined with a pop-up menu. It is intended for when a menu should pop up when a mouse button is hit, such as how the right button works under Windows95. The Am_Pop_Up_Menu_Interactor
takes the regular Am_One_Shot_Interactor
slots, plus Am_FILL_STYLE
, Am_ITEMS
(which should contain an Am_Value_List
as in other panels), and Am_WIDGET_LOOK
which affect the sub-menu. The Am_COMMAND
in the interactor is called if item doesn't have a command. Am_VALUE of the interactor is set with selection from menu.
Am_Vertical_Scroll_Bar
and Am_Horizontal_Scroll_Bar
are widget objects that allow the selection of a single value from a specified range of values, either as a int
or a float
(see section 6.2.4.1). You specify a minimum and maximum legal value, and the scroll bar allows the user to pick any number in between. The user can click on the indicator and drag it to set the value. As the indicator is dragged, the value is updated continuously. If the user clicks on the arrows, in the scroll bar, the scroll bar increments or decrements the current value by Am_SMALL_INCREMENT
. If the user clicks above or below the scroll bar, the value jumps by Am_LARGE_INCREMENT
. You can also adjust the indicator's size to show what percent of the entire contents is visible.Like all other widgets, the
Am_Vertical_Scroll_Bar
and Am_Horizontal_Scroll_Bar
store the value in the Am_VALUE
slot of the widget and in the Am_VALUE
slot of the Am_COMMAND
object. As the value is changed by the user, the Am_DO_METHOD
of the command is also continuously called. The Am_VALUE
slot of the widget can also be set by a program to adjust the position of the scroll bar indicator.The
Am_Vertical_Up_Down_Counter
widget is like a vertical scroll bar without the middle: it just has the up and down arrows.The
Am_Scrolling_Group
provides a convenient interface for a scrollable area. It operates similarly to a regular Am_Group
(see the Opal chapter), except that it optionally displays two scroll bars which the user can use to see different parts.
Am_VALUE_1, Am_VALUE_2, Am_SMALL_INCREMENT
, and Am_LARGE_INCREMENT
. If all of these slots hold values of type integer, then the result stored into the Am_VALUE
slot will also be an integer. If any of these values is a float, however, then the result will be a float. The default values are 0, 100, 1 and 10, so the default result is an integer. Note that the Inspector and cout
display floats without decimal parts as integers, but the scroll bar still treats them as floats.
Am_VALUE
slot.
Am_ACTIVE
: This determines whether the scroll bar is active or not. Inactive scroll bars do not respond to user input. However, in the default Motif look and feel, they are not drawn any differently.
Am_VALUE
: This holds the currently selected value on the scroll bar. As discussed above, it will either be an integer or float value.
Am_VALUE
slot and the displayed value to the previous value. However, most applications do not allow scrolling operations to be undone, in which case, you should make sure that the scrolling command is not queued on the undo list (see the section on Undo in the Interactors manual).For scrolling groups, the default is not to be undoable. If you want the scrolling group commands to be queued for undoing, set the
Am_COMMAND
slot of the scrolling group to be NULL.
Am_Vertical_Scroll_Bar
. An Am_Horizontal_Scrollbar
has the same defaults, except it's 200 pixels wide and 20 pixels high.Here is a description of the customizable slots of a scroll bar:
Am_WIDTH
: This determines the width of the scroll bar. This includes the height of the arrows at the ends of horizontal scroll bars. The default is 20 for vertical bars, and 200 for horizontal bars.
Am_HEIGHT
: This determines the height of the scroll bar. This includes the height of the arrows at the ends of vertical scroll bars. The default is 200 for vertical bars, and 20 for horizontal bars.
Am_VALUE_1
: This is the value selected in the scroll bar when the indicator is at the top (for vertical scroll bars) or left (for horizontal) end of the scroll bar. The default type is an int, but it can also be a float. The default is 0. Note that Am_VALUE_1
is not required to be less than Am_VALUE_2
, in case you want the bigger value to be at the top or left.
Am_VALUE_2
: This is the value selected in the scroll bar when the indicator is at the bottom (for vertical scroll bars) or right (for horizontal) end of the scroll bar. The default type is an int
, but it can also hold a float
. The default is 100
. Note that Am_VALUE_2
is not required to be bigger than Am_VALUE_1.
Am_SMALL_INCREMENT
: This is the amount the value is changed when the user clicks on the arrows at the end of the scroll bar. The default value is 1 of type int. The slot can contain either an int or a float.
Am_LARGE_INCREMENT
: This is the amount the value is changed when the user clicks on the scroll area on either side of scroll handle. The default value is 10 of type int. The slot can contain either an int or a float.
Am_PERCENT_VISIBLE
: This slot specifies how large the indicator will be with respect to the region it is dragged back and forth in. The slot should hold a float between 0.0 and 1.0, and the default is 0.2. If this value determines a thumb smaller than 6 pixels long, a 6 pixel thumb is drawn instead.
Am_Vertical_Up_Down_Counter
widget is like a vertical scroll bar without the middle: it just has the up and down arrows. Unlike for scroll bars, for a Am_Vertical_Up_Down_Counter
, the Am_VALUE_1
and Am_VALUE_2
fields can be Am_No_Value
which means there is no maximum and minimum values.
Am_Scrolling_Group
just like a regular group, but the user will be able to scroll around using the optional vertical and horizontal scrollbars.A scrolling group has two distinct rectangular regions. One is the region that is drawn on the screen, and contains scroll bars, and a rectangle with a visible portion of the group. This region is defined by the
Am_LEFT, Am_TOP, Am_WIDTH
and Am_HEIGHT
of the Am_Scrolling_Group
itself. The other region is called the inner region which is the size of all the objects, some of which might not be visible. This area is controlled by the Am_INNER_WIDTH
and Am_INNER_HEIGHT
slots.By default, the
Am_ACTIVE
slots of the scroll bars are calculated based on whether the scroll bars are needed (whether any of the group is hidden in that direction). The percent-visible is also calculated based on the amount of the group that is visible. The Am_H_LARGE_INCREMENT
and Am_V_LARGE_INCREMENT
are also calculated based on the screen size.
Add_Part
and Remove_Part
methods (be sure to adjust the inner size of the group if the new members change it--you can arrange for this to happen automatically by putting an appropriate constraint into the Am_INNER_WIDTH
and Am_INNER_HEIGHT
slots, such as Am_Width_Of_Parts
and Am_Height_Of_Parts.
). However, when enumerating the parts of a Am_Scrolling_Group
, do not use a Am_Part_Iterator
, since this will also list the scroll bars. Instead, use the Am_Value_List
stored in the Am_GRAPHICAL_PARTS
slot of the group, which will only contain the objects you added. The Am_GRAPHICAL_PARTS
slot can also be used for normal groups (instances of Am_Group
and Am_Map
), so you can write code that will operate on either scrolling groups or regular groups.
Am_WIDTH
, Am_HEIGHT
: These default to 150 in a scrolling group. The width and height determine the size of the group's graphical appearance on the screen, including space for scroll bars.
Am_X_OFFSET
, Am_Y_OFFSET
: These are the coordinates of the visual region, in relation to the origin of the inner region. The slots always contain a nonnegative integer, with 0 corresponding to no offset (meaning that the scrollable region's top and left are the same at the top, left of the visible area). The default is 0 for both X and Y offset. You may also Get or Set these slots, and the slots can even contain formulas. Getting the slot gives you the current scrollbar position, and setting the slot changes the current scrollbar position and scrolls the area.
Am_FILL_STYLE
: The filling style (color) used to draw the scroll bars (and the background of the window if Am_INNER_FILL_STYLE
is 0).
Am_INNER_FILL_STYLE
: This determines what the background fill of the group will be. If it is an Am_Style
, that style is used. If it contains 0, the Am_FILL_STYLE
slot is used.
Am_LINE_STYLE
: This determines what the border of the scrolling region. The default is Am_Thin_Line
. The size of the scrolling area is adjusted inward to make room for the specified line thickness. If 0, then no line is drawn.
Am_H_SCROLL_BAR
, Am_V_SCROLL_BAR
: These booleans determine whether the group will have vertical and/or horizontal scroll bars. These slots default to true
.
Am_H_SCROLL_BAR_ON_TOP, Am_V_SCROLL_BAR_ON_LEFT
: These booleans determine which side of the group the scroll bars appear on. The defaults are false for both, which puts the horizontal scroll bar at the bottom of the group, and the vertical scroll bar at the right of the group as on most standard windows.
Am_H_SMALL_INCREMENT, Am_V_SMALL_INCREMENT
: This is the small increment in pixels of the horizontal and vertical scroll bars. The value determines how much the scrolling group is moved when the user clicks on the scroll arrows. The default is 10 pixels.
Am_H_LARGE_INCREMENT, Am_V_LARGE_INCREMENT
: This is the large increment, in pixels, of the horizontal and vertical scroll bars. The value determines how much the scrolling group is moved when the user clicks on the scroll areas beside the scroll indicators. The default is calculated by a formula to jump one visible screen full.
Am_INNER_WIDTH, Am_INNER_HEIGHT
: This is the size of the entire group, not just the visible portion. The defaults are 400 for both. This will usually be calculated by a formula based on the contents of the scrolling group (e.g., Am_Width_Of_Parts
and Am_Height_Of_Parts
). It is OK if these are smaller than the scrolling group's Am_WIDTH
and Am_HEIGHT
: this just means that the entire area is visible, and so the appropriate scroll bars will be disabled.
Am_COMMAND
: You rarely will need to call a method when the scrolling group is used, so the Am_COMMAND
slot has the value Am_NOT_USUALLY_UNDONE
. You can change it to NULL to get the internal scrolling operations queued for undo, or you can supply a command to be executed after each scrolling operation.
Am_Scrolling_Group
, simply create an instance of it, customize the Am_TOP, Am_LEFT
, Am_WIDTH
, and Am_HEIGHT
slots of the group to define its size, set the Am_INNER_WIDTH
and Am_INNER_HEIGHT
based on the contents, and add graphical parts to the group.
my_scrolling_group = Am_Scrolling_Group.Create("scroll_group")
.Set(Am_LEFT, 10)
.Set(Am_TOP, 10)
.Set(Am_WIDTH, 200)
.Set(Am_HEIGHT, 300)
.Add_Part(Am_Rectangle.Create()
.Set(Am_LEFT, 0)
.Set(Am_TOP, 0)
.Set(Am_WIDTH, 15)
.Set(Am_HEIGHT, 15)
.Set(Am_FILL_STYLE, Am_Blue)
);
my_window.Add_Part(my_scrolling_group);This creates a scrolling group with an area of 200 by 300 pixels, and an internal region 400 by 400 pixels (the default values are inherited since none were specified). The scrolling group is displayed at location 10,10 in
my_window
. It contains a single object, a blue square 15 pixels on a side, in the upper left corner of the inner region. The scrolling group will have a vertical scroll bar on the right side of the group, and a horizontal scroll bar on the bottom of the group, as specified by the defaults.
Am_Text_Input_Widget
is used to get a single line of text input from the user, for example for filenames. The Am_Number_Input_Widget
(see Section 7.2.6.3) will only allow numbers to be entered, and the Am_Password_Input_Widget
works like a Am_Text_Input_Widget
but displays *'s instead of the text typed.
The widget has an optional label to the left of a text type-in field. The label is the value of the
Am_LABEL
field of the command object (and can be a string or arbitrary Amulet graphical object, or an empty string for no label). The user can click the mouse button in the field, and then type in a new value. The Am_VALUE
of the command in the Am_COMMAND
slot is set to the new string, and the command's Am_DO_METHOD
is called. The command's default Am_UNDO_METHOD
restores the Am_VALUE
and the displayed string to its previous value. As the user types, if the string gets too long to be displayed, it scrolls left and right as appropriate so the cursor is always visible. The user can finish the typing by typing return on the keyboard, or by clicking outside the text input field.Am_ACTIVE_2
slot (see Section 7.2.1) to false, which will disable the interactors.
The special slots of the
Am_Text_Input_Widget
are:
Am_WIDTH
- unlike most widgets, the default width is a constant (150) since the widget scrolls the text to fit. You will probably want to set the width to some other constant or formula.
Am_HEIGHT
- the default formula for the height uses the maximum of the height of the label and the height of the string.
Am_FONT
- this slot holds the font of the string that the user edits, and the default is the regular default font.
Am_LABEL_FONT
- this slot holds the font used for the label if the label is a string (the label comes from the Am_LABEL
slot of the command object in the widget). The default is a bold font.
Am_FILL_STYLE
- the color used for the user type-in field.
Am_Start_Widget
-- Section 7.5), the entire string is selected so the next character (unless it is a cursor movement character) will delete the entire string. Also, Am_WANT_PENDING_DELETE enables a double-click of the mouse to select the entire string so that the next character will delete the entire string.
Am_TEXT_CHECK_LEGAL_METHOD
: see Section 7.2.6.1
Am_TEXT_CHECK_LEGAL_METHOD
slot of any of the text widgets can contain a method of type Am_Text_Check_Legal_Method
, which will check the value typed by the user when the user types RETURN or tries to exit the field by clicking outside or by tabbing. The general form of the method is described in Section 5.3.5.5.2 in the Interactors chapter. Note that the object passed to the method will still be the interactor, and the widget is the owner of the interactor. The method can explicitly set the value of the widget. For example, the built-in Am_Number_Input_Filter_Method
used by the Am_Number_Input_Widget
sets the widget's value to the number converted from the string. For example:
Am_Define_Method(Am_Text_Check_Legal_Method, Am_Text_Abort_Or_Stop_Code,
my_filter, ( Am_Object &text, Am_Object& inter) ) {
Am_String str = text.Get(Am_TEXT);
Am_Object widget = inter.Get_Owner();
char *ptr;
long i = strtol(s, &ptr, 10);
if (ptr < s+len) {
Am_POP_UP_ERROR_WINDOW(``Value must be a number.'')
return Am_TEXT_ABORT_AND_RESTORE;
}
else {
widget.Set(Am_VALUE, result);
return Am_TEXT_OK;
}
}
7.2.6.2 Command in the Text Input Widget
The Am_LABEL
of the command in the Am_Text_Input_Widget
is used as the label of the input field, so if you do not want a label, make the slot be the null string "". The Am_VALUE
of the widget is set with the value the user types, and the Am_DO_METHOD
is called.7.2.6.3 Am_Number_Input_Widget
The Am_Number_Input_Widget
works similarly to the Am_Text_Input_Widget
except you can only input numbers.
Am_VALUE_1
and Am_VALUE_2
: can hold any numbers and the value typed will be restricted to be in that range. These slots must be the same type and they both should be floats if want to get a float value (otherwise, only int values will be accepted). If they are Am_No_Value then the numbers are not restricted.
Am_USE_ERROR_DIALOG
: If true, then the widget will pop up an explanatory error dialog if the value is illegal. If false, then just beeps on bad values.
Am_Tab_To_Next_Widget_Interactor
, and its command object support tabbing from one Am_Text_Input_Widget
to another in the same window.If you add an instance of the
Am_Tab_To_Next_Widget_Interactor
to a window or group, then by default, hitting the TAB
key will move from the one Am_Text_Input_Widget
to the next, and SHIFT_TAB
will move backwards. As the cursor is moved to the Am_Text_Input_Widget
, a box is drawn around the widget to show it is selected, and the widget is started with the old contents of the widget selected in ``pending-delete'' mode, so that if the next character typed is a normal printing character, it will replace the old string. If another widget was operating when the TAB
key was hit, then that widget is stopped, which will call its DO_METHOD
. There is no way to distinguish leaving a Am_Text_Input_Widget
because the user hit RETURN
to confirm the value, versus clicking outside, versus hitting TAB
to go to the next field. Therefore, it is recommended that you do not use the DO_METHOD
of the command in the widget to anything if you are using the Am_Tab_To_Next_Widget_Interactor.
The command used by this interactor is not undoable, so moving from field to field is not queued on the undo history.Note: In toolkits such as Motif and MS Windows, you can TAB to other widgets besides text input widgets, for example to use the arrow keys to select which button to press. This is not yet supported in Amulet, so the TAB interactor just goes from text widget to text widget, skipping all other kinds of widgets.
The
Am_Tab_To_Next_Widget_Interactor
has a number of slots that can be used to customize the behavior:
Am_START_WHEN
: Default value is Am_Inter_Char("ANY_TAB")
, which accepts the TAB key with any modifier. The internal code checks for the SHIFT
modifier down to decide whether to go forwards or backwards, but you can use any character to start this interactor.
Am_LIST_OF_TEXT_WIDGETS
: This must contain a list of Am_Text_Input_Widgets
. By default, it contains a formula which computes the list of text widgets by looking through the owner of the interactor for all of its parts which are instances of Am_Text_Input_Widget
. The default order of the widgets is back to front, so if you add your Am_Text_Input_Widgets
to the group from top to bottom, left to right, this will be the correct order. If you want to compute the list of Am_Text_Input_Widgets
some other way, simply set the Am_LIST_OF_TEXT_WIDGETS
slot with the list sorted in the correct way, or else set it with a formula which returns the desired list.
Am_Selection_Widget
is used for selecting, moving, and resizing graphical objects.Most graphical applications need to have ``selection handles,'' which are small squares that show which object(s) are selected and which allow the objects to be moved and changed size. Surprisingly, most toolkits require each application to reimplement this basic functionality. Amulet supplies this behavior through the supplied Am_Selection_Widget object, which you simply can add to your application, and then its objects will be selectable and manipulatable. There are lots of parameters to the selection widget, but most programs will only use a few of these. See the file samples/examples/example1.cc for a simple example.
Slots that control the Am_Selection_Widget are:
Am_OPERATES_ON
: Must be set with a group, scrolling group or window that contains the objects that can be selected. The Am_Selection_Widget will allow the user to select any element of this group.
Am_FILL_STYLE
: The color of the selection handles. The default is Am_Black
. The handles are drawn with this color on the inside, and a line style of Am_White
. This insures that the handles are almost always visible, independent of the color of the objects and the background (XOR is not used, as in most other toolkits, since this often results in invisible handles).
true
.
Am_START_WHEN
: This is the character that the widget will start on. The default is Am_Input_Char("ANY_LEFT_DOWN")
.
Am_START_WHERE_TEST
: How to test the group in Am_OPERATES_ON
for which objects to select. The default is Am_Inter_In_Part
.
Am_REGION_WHERE_TEST
: How to select the objects when the user draws a rectangle in the background, and need to select everything in the area. The default method is Am_Group_Parts_Inside.
Am_GRID_METHOD, Am_GRID_X, Am_GRID_Y
: These can be specified in the Am_Selection_Widget
to affect the moving and growing. These are described in Section 5.3.5.3.2.
Am_VALUE
: The set of selected objects is supplied as an Am_Value_List
in this slot. You can also set this slot with a Am_Value_List
of objects you want to have selected.
Am_OPERATES_ON
group be a different group from the group that the Am_Selection_Widget
is in. Typically, there will be a top level group, and the Am_OPERATES_ON
group and the Am_Selection_Widget
will be put into the top level group. For example:
//scroller is the top-level scrolling group to put things in
scroller = Am_Scrolling_Group.Create("scroller")
.Set (Am_LEFT, 55)
.Set (Am_TOP, 40)
.Set (Am_INNER_WIDTH, 1000)
.Set (Am_INNER_HEIGHT, 1000)
.Set (Am_INNER_FILL_STYLE, Am_White)
.Set (Am_WIDTH, scroll_width_formula) //width and height will be
.Set (Am_HEIGHT, scroll_height_formula) // based on window's
;
//all objects that will be created and that can be selected and moved will be put into created_objs
created_objs = Am_Group.Create("created_objs")
.Set (Am_LEFT, 0)
.Set (Am_TOP, 0)
.Set (Am_WIDTH, 1000)
.Set (Am_HEIGHT, 1000)
;
//the selection widget operates on the group created_objs
my_selection = Am_Selection_Widget.Create("my_selection")
.Set(Am_OPERATES_ON, created_objs)
//put the scroller in the window
my_window.Add_Part(scroller);
//put the selection widget and the created_objs as parts of the scrolling group
scroller.Add_Part(created_objs);scroller.Add_Part(my_selection);
As mentioned above, you can access the list of selected objects in the
Am_VALUE
slot of the Am_Selection_Widget. You can also set this slot to change the set of selected objects. Be sure to only set this slot to an Am_Value_List
, even if you want no objects or a single object selected. For example, to clear the selection, use:
my_selection.Set(Am_VALUE, Am_Value_List());There are also two command objects you can use to monitor the selection widget's activities. The Am_COMMAND part is used when the selection changes. The Am_VALUE of the
Am_COMMAND
object is set with the current selection, and its Am_DO_METHOD
is called whenever the selection changes. The Am_IMPLEMENTATION_PARENT of this command is Am_NOT_USUALLY_UNDONE by default, since normally changing the selection is not undoable. If you want the selections to be undoable, set the Am_IMPLEMENTATION_PARENT slot of the Am_COMMAND
of the selection widget to be NULL. This is done automatically by the undo dialog box (see Section 5.6.2.3.2) when the user clicks on the undo selections check box.
The other command is used when the user moves or grows an object. This command is in the Am_MOVE_GROW_COMMAND named part. You should probably not replace this command, because it has a built-in formula to make the label be correct based on the operation, but it is fine to override the various DO and UNDO methods. By default, the move and grow operations are undoable, if there is an undo handler attached to the window the selection widgets are in.
Am_INACTIVE_COMMANDS
slot of the graphical object under the mouse to see if that object is selectively disabled for selection, moving or growing. The Am_INACTIVE_COMMANDS
slot can contain an instance of Am_Command, with the slots Am_MOVE_INACTIVE
, Am_GROW_INACTIVE
, and Am_SELECT_INACTIVE
. See also Section 5.4.7.
7.2.7.2 User Interface to Am_Selection_Widget
The selection widget operates in the standard way of the selection handles on the Macintosh and Windows. The user can click with the specified button (usually the left button) over an object to select it. Holding down the shift key while clicking will add or remove the object under the mouse to the selected set. Thus, to select multiple objects, you can click on them with the shift key held down. If you click in the background, all objects will be de-selected. You can also click in the background and drag out a region to select all the objects wholely enclosed in the region.7.2.7.3 Highlighting one Handle of a Am_Selection_Widget
Sometimes it is useful to know which end of a line the user selected on, or which corner of a box. If this is desired, the Am_Selection_Widget can be configured to supply this information. Simply set the Am_SELECT_CLOSEST_POINT_STYLE
slot with some color, and the handle closest to the mouse click will be shown in this different color. The Am_SELECT_CLOSEST_POINT_OBJ
will be set to the object under the mouse, which will be selected (the Am_VALUE
of the selection_widget is not sufficient because sometimes multiple objects are selected, and the Am_SELECT_CLOSEST_POINT_OBJ
will then contain the one object last clicked on). The Am_SELECT_CLOSEST_POINT_WHERE
slot is set with the handle that is turned color. The method in the Am_SELECT_CLOSEST_POINT_METHOD
slot can be set to customize how the closest point is picked.7.2.7.4 Multiple Am_Selection_Widgets
Multiple Am_Selection_Widgets
can be connected together so there is only one selection across multiple windows. (Actually, multiple Am_Selection_Widgets
can be in the same window, but this is rarely a good idea.) As shown in the test file amulet/src/widgets/testdragdrop.cc
, the Am_MULTI_SELECTIONS
slot of each of the Am_Selection_Widgets
should be set with an Am_Value_List
containing all of the selection widgets. Multiple selections must all be in the same window, however, and the Am_VALUE
of each selection widget will reflect the selections in that window. For example: Am_Object select1 = Am_Selection_Widget.Create (``select1'')
... ;
Am_Object select2 = Am_Selection_Widget.Create (``select2'')
... ;
Am_Object select3 = Am_Selection_Widget.Create (``select3'')
... ;
Am_Value_List select_list = Am_Value_List ()
.Add (select1).Add (select2).Add (select3);
select1.Set (Am_MULTI_SELECTIONS, select_list);
select2.Set (Am_MULTI_SELECTIONS, select_list);
select3.Set (Am_MULTI_SELECTIONS, select_list);
The Am_MULTI_SELECTIONS
slot will link all the selection widgets together. A selected object dragged from one widget can be dropped on any of the other widgets. Widgets can be linked as long as they are in the same program. Widgets in separate windows or widgets that are nested within one another will work correctly.7.2.7.5 Drag and Drop
Amulet's drag and drop feature has been added as an automatic feature to the normal selection widget. Drag and drop permits the following activities:
The manner in which the object is dropped onto a selection widget is determined by a method in the
Am_DROP_TARGET_TEST
slot. A drop test is a method of type Am_Where_Method
which looks like:
Am_Define_Method(Am_Where_Method, Am_Object, my_where_test
(Am_Object inter, Am_Object widget,
Am_Object event_window, int x, int y)) {
... }The widget parameter refers to the selection widget that is the current target of the drag, the inter parameter is the interactor that is moving the object (this can normally be ignored). The event_window, x, and y parameters are the current location of the mouse pointer. The purpose of the where_test is to provide a means for the widget to reject a possible source. If the where_test is ``true,'' which it is by default, then all objects are accepted. If the where_test method exists and it returns
Am_No_Object
, the drop is rejected. If the method returns an object, then that object is tested for a Am_DROP_TARGET
command which will be used for further processing. See below for discussion of Am_DROP_TARGET
and Am_Drop_Target_Command
.A generic where method is provided in Amulet called
Am_In_Target
. This command returns the topmost object that contains a Am_DROP_TARGET
slot. This method is useful when the selection widget contains other objects that can serve as drop targets.Objects other than selection widgets can also serve as drop targets. In such cases the position data is lost but value is transferred by way of a special ``drop target command'' stored in the object. The drop command must be an instance of the type
Am_Drop_Target_Command
and must be stored in the slot Am_DROP_TARGET
of the object that is the potential target.The Am_Drop_Target_Command has several method slots:
Am_DROP_TARGET_TEST
: Type = Am_Drop_Target_Interim_Do_Method
Am_DO_METHOD
: Type = Am_Drop_Target_Do_Method
Am_UNDO_METHOD
: Type = Am_Object_Method
Am_REDO_METHOD
: Type = Am_Object_Method
Am_INTERIM_SELECTED
: Type = bool
(set by system)
Am_Drop_Target_Interim_Do_Method
has the form:
Am_Define_Method_Type(Am_Drop_Target_Interim_Do_Method, bool,
(Am_Object& command_obj, const Am_Value& value))The command parameter is a self reference to the command object and the value parameter is the object being dragged. The test method should return true or false depending on whether the object is acceptable to the target. The source of the object can be determined by looking at the object's owner.
If the object is accepted, the system will set the
Am_INTERIM_SELECTED
slot to true. If the mouse passes outside of the target, or the target rejects the object, it will be made false. It is also cleared when the mouse button is released. This slot can be used to change the object's look to show that it is accepting the source.Once an object is accepted by a target (and dropped by releasing the mouse) Amulet will call the
Am_DO_METHOD
on the Drop_Target_Command
. The do method has an extra parameter from the usual Am_Object_Method
.The value parameter is the object being dropped. The do method may do whatever it wants with the value. Provided the command has a NULL or valid
Am_IMPLEMENTATION_PARENT
, the command will be queued on the undo handler. There the Am_UNDO_METHOD
and Am_REDO_METHOD
may be called when appropriate.For drop target commands that are stored on groups for a selection widget (the group of a selection widget is the object pointed to by the
Am_OPERATES_ON
slot), the DO, UNDO, and REDO methods are ignored. Instead, normal dragging behavior is performed if the TEST method returns true.
All of these dialog boxes can be displayed as modal or not. A modal dialog box does not let any other interaction happen until the dialog box is dismissed. If modal = false, then the dialog box, and other interactions can all happen, at the user's discretion.
The built-in dialog boxes are:
Am_Alert_Dialog
displays several lines of informational text, and an "OK"
button below the text. It is used to alert the user of an error or to give the user information, and returns no value.
Am_Choice_Dialog
displays several lines of prompt text, and "OK"
and "Cancel"
buttons below the text. It is used to prompt the user to make a choice, and returns the value of the button they chose (either "OK"
or "Cancel"
).
Am_Text_Input_Dialog
displays several lines of prompt text, a text input widget, and "OK"
and "Cancel"
buttons. It is used to prompt the user for text input. It returns the value of the text input widget if the user clicks on "OK"
or presses the RETURN key, and Am_No_Value if the user cancels.
void Am_Show_Alert_Dialog (Am_Value_List alert_texts,
int x = Am_AT_CENTER_SCREEN,
int y = Am_AT_CENTER_SCREEN,
bool modal = false);
void Am_Show_Alert_Dialog (Am_String alert_text,
int x = Am_AT_CENTER_SCREEN,
int y = Am_AT_CENTER_SCREEN,
bool modal = true);This routine brings up an alert dialog box at the location (x, y) on the main screen. The special value
Am_AT_CENTER_SCREEN
is converted into the center of the screen. The routine waits for the user to close it by clicking the "OK"
button. The list alert_texts
is a list of char*
or Am_String
values which will be displayed, one per line, above the "OK"
button. If modal
is true, the dialog box will be run modally, otherwise it will be run non-modally. This routine does not return until the user clicks on either OK or Cancel. The second form just takes a single line of text.
Am_Value Am_Get_Choice_From_Dialog (Am_Value_List prompt_texts,
int x = Am_AT_CENTER_SCREEN,This routine brings up a choice dialog box at the location (x, y) on the main screen, and waits for the user to close it by clicking either the
int y = Am_AT_CENTER_SCREEN,
bool modal = false);
"OK"
or "Cancel"
button. The list prompt_texts
is a list of char*
or Am_String
values which will be displayed, one per line, above the buttons. If modal
is true, the dialog box will be run modally, otherwise it will be run non-modally. The return value will be a string, either "OK"
or "Cancel"
depending on which button the user pressed.
Am_Value Am_Get_Input_From_Dialog (Am_Value_List prompt_texts,
Am_String initial_value = "",
int x = Am_AT_CENTER_SCREEN,
int y = Am_AT_CENTER_SCREEN,
bool modal = false);This routine brings up an input dialog box at the location (x, y) on the main screen, and waits for the user to close it by clicking either the
"OK"
or "Cancel"
button. The list prompt_texts
is a list of char*
or Am_String
values which will be displayed, one per line, above the text input line and buttons. If modal
is true, the dialog box will be run modally, otherwise it will be run non-modally. The return value will be a string, the value of the text widget, if the user clicks "OK"
or presses RETURN to close the dialog box. The routine returns Am_No_Value
if the user clicks "Cancel."
// these are called automatically from the Am_Open_Command, Am_Save_Command and
// Am_Save_As_Command
extern Am_String Am_Show_File_Dialog_For_Open(Am_String initial_value='''');
extern Am_String Am_Show_File_Dialog_For_Save(Am_String initial_value='''');Eventually, these routines will display a standard scrolling list of files. Currently they just use a text-input widget, and can be used for forward compatibility.
To display a custom dialog box, you can use
Am_Pop_Up_Window_And_Wait
, described in Section 5.4.6. Be sure your custom dialog boxes use the method Am_Default_Pop_Up_Window_Destroy_Method
in the Am_DESTROY_WINDOW_METHOD
of the dialog box's window, so the dialog box will exit correctly if the user closes it using the window manager's close box.
The macro
Am_POP_UP_ERROR_WINDOW
takes something that can be passed to cout
and displays it in a single line of an Alert dialog box. To use this function, you need to include strstream
in your code. For example:// strstream is needed for Am_POP_UP_ERROR_WINDOW
#include STR_STREAM__H
...
Am_POP_UP_ERROR_WINDOW("Accelerator " << i << " already in use by " << cmd);
7.3.2 Slots of dialog boxes
Am_X_OFFSET
: 5
Am_Y_OFFSET
: 5, The elements of the dialog box are put in a group inside the dialog box window. The Am_X_OFFSET
and Am_Y_OFFSET
are the size of the empty border area between this group and the edge of the window.
Am_WIDTH
: formula depending on contents.
Am_HEIGHT
: formula depending on contents. Dialog boxes automatically resize themselves to fit the dialog box elements with a border around them. You may override the formula by explicitly setting the Am_WIDTH
and Am_HEIGHT
slots, but then the dialog box will no longer resize itself.
Am_FILL_STYLE
: Am_Motif_Gray
. This specifies the fill style of the dialog box window and all widgets contained in it.
Am_WIDGET_LOOK
: Am_MOTIF_LOOK
Am_ITEMS
: 0. Must be NULL or an Am_Value_List
of char*
or Am_String
. This is a list of string items which will be displayed, one per line, above the dialog box widgets.
Am_V_SPACING
: 5. These slots control the layout of the multiple strings specified in Am_ITEMS
Am_H_SPACING
: 10
Am_H_ALIGN
: Am_CENTER_ALIGN
Am_WIDGET_START_METHOD
: Am_Show_Dialog_Method
Am_WIDGET_STOP_METHOD
: Am_Finish_Dialog_Method
Am_WIDGET_ABORT_METHOD
: Am_Finish_Dialog_Method
Am_VALUE
: "" or a formula depending on the user's selection. This contains the current value of a dialog box for choice and input dialog boxes. In input dialog boxes, it can be set with an initial value to be displayed in the text input widget.
Am_WINDOW
.
Am_VALID_INPUT
: true. In text input dialog boxes, this slot tells the dialog box whether the text input field is a valid input or not. If Am_VALID_INPUT
is false, the "OK"
button will be inactive (greyed out), and the RETURN key will not close the dialog box (making "Cancel"
the only valid operation). The intended use of this slot is to contain a constraint on the dialog's Am_VALUE
slot which determines whether the input value is valid or not, and returns true or false appropriately.
src/widgets/testselectionwidget
and samples/examples/example1.cc
.Most of these commands operate on the currently selected objects, so they require that you pass in an instance of a selection widget (Section 7.2.7) in the
Am_SELECTION_WIDGET
slot of the command object. Alternatively, you can put the selection widget into the Am_SELECTION_WIDGET
slot of the widget the commands are part of (like the menubar). If you implement your own selection mechanism and do not use the selection widget, you still may be able to use the following commands, if your selection handles object provides the selected objects as an Am_Value_List
in the Am_VALUE
slot, and allows that slot to be set to change the selection.
Most of the built-in commands can be disabled for a particular object by setting the appropriate slot of a command object in the Am_INACTIVE_COMMANDS
slot of the object. See also Section 5.4.7.
The supplied command objects are as follows. See the tables in the Summary chapter, Section 11.9 for a list of the slots to be set in each.
Am_SELECTION_WIDGET
.
Am_Graphics_Clear_Command
: delete the selected objects. The label is ``Clear'' and the accelerator is ``DELETE''. Must be passed a Am_SELECTION_WIDGET
or find one in the widget the command is in. Disabled by the Am_CLEAR_INACTIVE
slot.
Am_Graphics_Clear_All_Command
: The label is ``Clear All'' and the accelerator is ``CONTROL_a''. Must be passed a Am_SELECTION_WIDGET
or find one in the widget the command is in. Disabled by the Am_CLEAR_INACTIVE
slot.
Am_Graphics_Copy_Command
: Copy to the clipboard. The label is ``Copy'' and the accelerator is ``CONTROL_c''. Must be passed a Am_SELECTION_WIDGET
or find one in the widget the command is in. Disabled by the Am_COPY_INACTIVE
slot.
Am_Graphics_Cut_Command
: Copy objects to the clipboard and then delete them. The label is ``Cut'' and the accelerator is ``CONTROL_x''. Must be passed a Am_SELECTION_WIDGET
or find one in the widget the command is in. Disabled by the Am_CUT_INACTIVE
slot.
Am_Graphics_Paste_Command
: Paste a copy of the objects in the clipboard. The label is ``Paste'' and the accelerator is ``CONTROL_v''. Must be passed a Am_SELECTION_WIDGET
or find one in the widget the command is in.
Am_Graphics_To_Bottom_Command
: Make the selected objects be covered by all other objects. The label is ``To Bottom'' and the accelerator is ``CONTROL_<''. Must be passed a Am_SELECTION_WIDGET
or find one in the widget the command is in. Disabled by the Am_TO_BOTTOM_INACTIVE
slot.
Am_Graphics_To_Top_Command
: Make the selected objects be covered by no other objects. The label is ``To Top'' and the accelerator is ``CONTROL_>''. Must be passed a Am_SELECTION_WIDGET
or find one in the widget the command is in. Disabled by the Am_TO_TOP_INACTIVE
slot.
Am_Graphics_Duplicate_Command
: Duplicate the selected objects. The label is ``Duplicate'' and the accelerator is ``CONTROL_d''. Must be passed a Am_SELECTION_WIDGET
or find one in the widget the command is in. Disabled by the Am_DUPLICATE_INACTIVE
slot.
Am_Graphics_Group_Command
: Make a group out of the selected objects. Creates an instance of Am_Resize_Parts_Group
(see Section 4.8.3 in the Opal chapter) and adds the selected objects to it. The new group has its Am_CREATED_GROUP
slot set to true
, which is used by ungroup and change property. The label of the command is ``Group'' and the accelerator is ``CONTROL_p''. (We would have made it ^G, but that is used for aborting all interactors and widgets). Must be passed a Am_SELECTION_WIDGET
or find one in the widget the command is in. Disabled by the Am_GROUP_INACTIVE
slot.
Am_Graphics_Ungroup_Command
: Ungroup the selected objects. This will only operate on objects that have the Am_CREATED_GROUP
slot set to true
, which are typically those groups created by the Am_Graphics_Group_Command
. The label is ``Ungroup'' and the accelerator is ``CONTROL_h''. Must be passed a Am_SELECTION_WIDGET
or find one in the widget the command is in. Disabled by the Am_UNGROUP_INACTIVE
slot.
Am_Undo_Command
: Perform a single undo. The label is ``Undo'' and the accelerator is ``Control_z''. This finds the undo handler by looking for the window of the object in the Am_SELECTION_WIDGET
slot (which can be any object whose Am_WINDOW is the window containing the undo handler--for this command, this slot doesn't have to contain a selection widget). If the Am_SELECTION_WIDGET
slot is null, then gets the window from the widget the command is attached to, and looks for that window's undo handler.
Am_Redo_Command
: Perform a single redo. The label is ``Redo'' and the accelerator is ``CONTROL_SHIFT_Z''. Looks for an undo handler the same way as Am_Undo_Command
.
Am_Quit_No_Ask_Command
: Quit the application immediately without asking for confirmation. The label is ``Quit'' if the Am_WIDGET_LOOK is Am_MOTIF_LOOK or
Am_MACINTOSH_LOOK
, and ``Exit'' if the Am_WIDGET_LOOK is Am_WINDOWS_LOOK
. The accelerator is always ``CONTROL_q''. Does not use the Am_SELECTION_WIDGET
.
Am_Open_Command, Am_Save_Command, Am_Save_As_Command
: For opening and saving files using the built-in load-save mechanism. See Section 7.4.2.
Am_Standard_OK_Command, Am_Standard_Cancel_Command
: Useful for the buttons in dialog boxes that have been popped up with Am_Pop_Up_Window_And_Wait
.
Am_About_Amulet_Command
- brings up the standard About Amulet dialog box.
Am_Cycle_Value_Command
: Cycles the label through a list of values. See Section 7.4.3.
Am_Gesture_Select_And_Do_Command
: Useful for gestures, this performs an operation (like Am_Cut_Command) on the objects under the gesture. Must be passed a Am_SELECTION_WIDGET
or find one in the widget the command is in. See Section 7.4.4.
Am_Gesture_Create_Command
: Useful for gestures, this helps create a new object using the bounding box of the gesture. See Section 7.4.4.
Am_Gesture_Unrecognized_Command
: Standard response to an unrecognized gesture. See Section 7.4.4.
Am_Graphics_Set_Property_Command
: to set the color, line style or other property of the selected objects. This has a slightly more complicated interface, as described in Section 7.4.5. Must be passed a Am_SELECTION_WIDGET
or find one in the widget the command is in.
Am_Object grid_command = Am_Cycle_Value_Command.Create("grid")
.Set(Am_LABEL_LIST, Am_Value_List()
.Add("Turn Grid On")
.Add("Turn Grid Off"));
Am_Object open_commmand;
menu_bar = Am_Menu_Bar.Create("menu_bar")
.Set(Am_SELECTION_WIDGET, sel_widget)
.Set(Am_ITEMS, Am_Value_List ()
.Add (Am_Command.Create("File_Command")
.Set(Am_LABEL, "File")
.Set(Am_IMPLEMENTATION_PARENT, true) //not undoable
.Set(Am_ITEMS, Am_Value_List ()
.Add (open_command = Am_Open_Command.Create()
.Set(Am_HANDLE_OPEN_SAVE_METHOD, use_file_contents))
.Add (Am_Save_As_Command.Create()
.Set(Am_HANDLE_OPEN_SAVE_METHOD, contents_for_save))
.Add (Am_Save_Command.Create()
.Set(Am_HANDLE_OPEN_SAVE_METHOD, contents_for_save))
.Add (Am_Command.Create("Save ")
.Set(Am_LABEL, "Generate c++")
.Set(Am_ACTIVE, true)
.Set(Am_DO_METHOD, savecppcmd))
.Add (Am_Quit_No_Ask_Command.Create())))
.Add (Am_Command.Create("Edit_Command")
.Set(Am_LABEL, "Edit")
.Set(Am_IMPLEMENTATION_PARENT, true) //not undoable
.Set(Am_ITEMS, Am_Value_List ()
.Add (Am_Undo_Command.Create())
.Add (Am_Redo_Command.Create())
.Add (Am_Menu_Line_Command.Create())
.Add (Am_Graphics_Cut_Command.Create())
.Add (Am_Graphics_Copy_Command.Create())
.Add (Am_Graphics_Paste_Command.Create())
.Add (Am_Graphics_Clear_Command.Create())
.Add (Am_Graphics_Clear_All_Command.Create())
.Add (Am_Menu_Line_Command.Create())
.Add (Am_Graphics_Duplicate_Command.Create())
.Add (Am_Selection_Widget_Select_All_Command.Create())
.Add (Am_Menu_Line_Command.Create())
.Add (Am_Command.Create()
.Set(Am_LABEL, "Properties...")
.Set(Am_ACTIVE, Am_Active_If_Selection)
.Set(Am_DO_METHOD, customize_selected)
.Set(Am_UNDO_METHOD, undo_set_properties)
.Set(Am_REDO_METHOD, undo_set_properties))))
.Add (Am_Command.Create("Arrange_Command")
.Set(Am_LABEL, "Arrange")
.Set(Am_IMPLEMENTATION_PARENT, true) //not undoable
.Set(Am_ITEMS, Am_Value_List ()
.Add (Am_Graphics_To_Top_Command.Create())
.Add (Am_Graphics_To_Bottom_Command.Create())
.Add (Am_Menu_Line_Command.Create())
.Add (Am_Graphics_Group_Command.Create())
.Add (Am_Graphics_Ungroup_Command.Create())
.Add (Am_Menu_Line_Command.Create())
.Add (grid_command)
Am_VALUE
slot contains an Am_Value_List of objects. You can specify a particular clipboard to use by passing a clipboard object in the Am_CLIPBOARD
slot of the command object. If this is NULL, Amulet uses the global Am_Global_Clipboard
object. Note that Amulet does not yet interoperate with the standard Windows or Macintosh clipboards. The ``clipboard'' is currently just local to the Amulet application.
The
Am_Open_Command
takes a method in the Am_HANDLE_OPEN_SAVE_METHOD
slot of type Am_Handle_Loaded_Items_Method
which takes the items loaded from the file and puts them in the window. For example,Am_Define_Method (Am_Handle_Loaded_Items_Method, void, use_file_contents,
(Am_Object command, Am_Value_List &contents)) {
Am_Object created_objs = command.Get_Object(Am_SAVED_OLD_OWNER)
.Get_Object(Am_WINDOW).Get(CREATED_OBJS);
Am_Value_List current = created_objs.Get (Am_GRAPHICAL_PARTS);
Am_Object item;
//first delete all of the current contents of the window
for (current.Start (); !current.Last (); current.Next ()) {
item = current.Get ();
item.Destroy ();
}
//now add the new objects
for (contents.Start (); !contents.Last (); contents.Next ()) {
item = contents.Get ();
created_objs.Add_Part (item);
}
}
The Save and Save As commands take a method in the same slot (Am_HANDLE_OPEN_SAVE_METHOD
) of type Am_Items_To_Save_Method
which generates the list of objects to be saved to a file. For example://This method should return the list of objects to save
Am_Define_Method (Am_Items_To_Save_Method, Am_Value_List,
contents_for_save, (Am_Object command)) {
Am_Object created_objs = command.Get_Object(Am_SAVED_OLD_OWNER)
.Get_Object(Am_WINDOW).Get(CREATED_OBJS);
Am_Value_List obs_to_save = created_objs.Get (Am_GRAPHICAL_PARTS);
return obs_to_save;
}
These commands use the Am_Show_File_Dialog_For_Open
and Am_Show_File_Dialog_For_Save
dialog boxes, which temporarily are just text input strings.Am_Standard_Open_From_Filename
which takes the command object used for open and the string. This is why the instance of Am_Open_Command
is saved in a variable in the menu_bar example above. For example: if (argc > 1) {
Am_String s = (char *)argv[1];
Am_Standard_Open_From_Filename(open_command, s);
}
7.4.3 Cycle_Value_Command
The Am_Cycle_Value_Command
can be used to have a widget whose label changes each time it is clicked on. The list of labels is supplied as an Am_Value_List
in the Am_LABEL_LIST
slot. The Am_VALUE
of the command is set with the index of the current label in the list (from 0
). If the list has 2 values, then this will be a toggle, like ``Turn Grid On'' <-> ``Turn Grid Off'' with the Am_VALUE
taking on 0
and 1
, as shown by the grid_command
in the menu bar example above. Undoing returns the Am_VALUE
and label to the original values. You can also explicitly set the Am_VALUE
slot of the command to change the current state. Typically, a constraint would depend on the Am_VALUE
of the command. Examples of the use of this command are in src/widgets/testselectionwidget
(turning grid on and off) and samples/circuit/circuit.cc
(turning animation on and off) and src/widgets/testwidgets
.Am_VALUE
slot takes on a string value temporarily before settling down with the correct value, so constraints on the value have to be prepared for this. (E.g., Get the value into an Am_Value
, and check the type, and ignore strings).7.4.4 Commands to help with Gestures
Freehand gestures (see Section 5.3.5.6) usually create objects or perform some command on the objects (like Cut). Some built-in commands will help implement these.
Am_Gesture_Select_And_Do_Command
must be passed a Am_SELECTION_WIDGET
or find one in the widget the command is in. The Am_LABEL of the command will be the string name of the gesture defined in Agate. It then looks for all the graphical objects in the bounding box of the gesture, and causes those objects to be selected. The Am_IMPLEMENTATION_PARENT
of the Am_Gesture_Select_And_Do_Command
command should be set with the command to be executed on the selected objects, which can be the same command as used in the menu bar. For example:.Add (Am_Gesture_Select_And_Do_Command.Create ("gesture_cut")
.Set (Am_LABEL, ":CUT")
.Set (Am_IMPLEMENTATION_PARENT, cut_command)
The other common operation is to create a new object with a gesture. The .Set (Am_SELECTION_WIDGET, my_selection))
Am_Gesture_Create_Command
can help with this. This command needs a method of the same form as for Am_New_Points_Interactor
to create the new object set into the Am_CREATE_NEW_OBJECT_METHOD
slot. For example:Am_Define_Method(Am_Create_New_Object_Method, Am_Object, gesture_creator,
(Am_Object cmd, Am_Inter_Location data,
Am_Object old_object )) { ... }
The command also needs to know whether the object to be created is like a line or not, set into the Am_AS_LINE
slot (default = false). And the programmer can specify an extra command to be executed by setting the Am_Gesture_Create_Command
's Am_IMPLEMENTATION_PARENT
slot, but this is optional. For example: .Add (Am_Gesture_Create_Command.Create(``rect_gesture'')
.Set (Am_LABEL, ``:RECTANGLE'')
.Set (Am_AS_LINE, false)
.Set (Am_CREATE_NEW_OBJECT_METHOD, gesture_create_rect))
.Add (Am_Gesture_Create_Command.Create()
.Set (Am_LABEL, ``line'')
.Set (Am_AS_LINE, true)
.Set (Am_CREATE_NEW_OBJECT_METHOD, gesture_create_line)
.Set (Am_IMPLEMENTATION_PARENT,
Finally, a standard
undo_create_line_cmd.Create()))
Am_Gesture_Unrecognized_Command
is supplied, which prints out a message and beeps.7.4.5 Am_Graphics_Set_Property_Command
The Am_Graphics_Set_Property_Command
is designed to set properties like fill color, line style and fonts of graphical objects from menus or palettes. It iterates through all the selected objects setting a specified property to the value gotten from a widget (such as a palette or menu). If a selected object has the Am_CREATED_GROUP
slot set to true
(as do all groups created by the Am_Graphics_Group_Command
), then the Am_Graphics_Set_Property_Command
will recursively change the property of all of its parts. Of course, the Am_Graphics_Set_Property_Command
is fully undoable and repeatable.Am_Graphics_Set_Property_Command
are:
Am_SLOT_FOR_VALUE
: The slot of the object and widget that the default methods use to get the value of. The default value is the Am_FILL_STYLE
slot.
Am_SELECTION_WIDGET
: As with other commands in this section, the Am_SELECTION_WIDGET
slot should be set with the selection widget that contains the list of selected objects whose property should be changed.
Am_GET_WIDGET_VALUE_METHOD
: The method in this slot should be of type Am_Get_Widget_Property_Value_Method
:
Am_Define_Method_Type(Am_Get_Widget_Property_Value_Method, void,
(Am_Object command_obj, Am_Value &new_value));
new_value
parameter) the value that the widget currently is providing as the new value of the property. The default method uses the object the command is attached to as the widget, and gets that widget's Am_VALUE
. If the contents of the Am_VALUE
is an object, then that object's Am_SLOT_FOR_VALUE
slot is accessed to get the value. Thus, if the widget is a button panel of where each item is a rectangle having the correct color, then the default method will correctly return the color of the item. Alternatively, if the widget is a menu, where each command in the menu has an Am_ID
containing the correct value to use, the default method will return the correct value.
Am_GET_OBJECT_VALUE_METHOD
: The method in this slot should be of type Am_Get_Object_Property_Value_Method
:
Am_Define_Method_Type(Am_Get_Object_Property_Value_Method, void,
(Am_Object command_obj, Am_Object object,
Am_Value &old_value));
old_value
) the current value of the property for object
, which is used in case the command needs to be undone. The default method just gets the value of the Am_SLOT_FOR_VALUE
slot of object
.
Am_SET_OBJECT_VALUE_METHOD
: The method in this slot should be of type Am_Set_Object_Property_Value_Method
:
Am_Define_Method_Type(Am_Set_Object_Property_Value_Method, void,
(Am_Object command_obj, Am_Object object,
Am_Value new_value));
object
so its property now has value new_value
. The default method just sets the Am_SLOT_FOR_VALUE
slot of object
to be new_value
.
Am_SAVED_OLD_OWNER
: As in all other command objects, this slot is automatically set with the widget the command is attached to. (Do not set this slot.) This is assumed by the default methods to be the widget from which the value is to be fetched.
extern void Am_Start_Widget(Am_Object widget,
Am_Value initial_value = Am_No_Value);Explicitly start a widget running. If already running, does nothing. If an initial value is provided, then the widget is started with this as its value. It is up to the programmer to make sure the
initial_value
is legal for the type of widget. If no initial_value
is supplied, the widget is started with its current value, if any.
extern void Am_Abort_Widget(Am_Object widget_or_inter_or_command);Explicitly abort a widget, interactor or command object. Often, this will be called with a command object, and the system will then find the associated widget or interactor and abort it. If that widget or interactor is not running, then this does nothing. The function tries to make sure the command object passed in (or the command object associated with the widget or interactor) is not entered into the command history.
extern void Am_Stop_Widget(Am_Object widget,
Am_Value final_value = Am_No_Value);Explicitly stop a widget. If not running, raises an error. If
final_value
is supplied, then this is the value used as the value of the widget. If final_value
is not supplied, the widget uses its current value. Commands associated with the widget will be invoked just as if the widget had completed normally.