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 behavoir 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.
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
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_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_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.
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.hfor the widget object definitions, and
standard_slots.hfor 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.6 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 (Am_TOP, 10)
.Set (Am_COMMAND,"Push Me");
// a string in the Am_COMMAND slot specifies the button's label: see below
6.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.
220.127.116.11 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 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.
18.104.22.168 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 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()
22.214.171.124 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.
6.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.
6.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_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. Any look will eventually be available on any platform, but currently only
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.
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
true. The default value is
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_ACTIVEslot, but this one should not normally be used. The widget-level slot contains a constraint that depends on the
Am_ACTIVEslot 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_Border_Rectanglehas 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_LABELslot of the Am_COMMAND part of the widget, which itself should be a string or object, as described below.
The various panel objects (that display a set of buttons) and the menus (that display a set of buttons) all take an
Am_ITEMSslot which must contain an
Am_VALUE_LIST. The items in this value list can be:
char*), in which case this string is displayed as the label,
Am_LABELfield of the command object is used as the item's label. The
Am_LABELfield itself can contain either a C string or a graphical object.
Am_DO_METHODof 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_ITEMSslot of the widget contains an
Am_VALUE_LISTof strings. In this case, the top-level command object's Am_DO_METHOD will be called, and it typically will look in its
Am_VALUEslot 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_Value_Listthat contains some commands and some strings.
Am_LABEL: This slot can contain a string or a graphical object, which will be drawn as the label for this item.
Am_ID: Normally, buttons set the
Am_VALUEslot to the
Am_LABELof the command. However, this typically requires doing string matching. Therefore, if the
Am_IDfield is non-zero, then the
Am_VALUEslot is set with the value of the
Am_IDslot 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_ACTIVEslot 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_ACTIVEslot of the command associated with a single item will be
false, signaling that just that one item should be greyed out.
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_CHOICE_LIST_TOGGLE, then this slot will always contain an
Am_Value_Listwith 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_VALUEslot 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_SETset to be
Am_VALUEslot is set to the single button's label or ID, or 0 if nothing is selected.
The interface to the accelerator lists for windows is available in widget_advanced.h through the functions Am_Add_Accelerator_Command_To_Window and Am_Remove_Accelerator_Command_From_Window, which take the window and command object.
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 126.96.36.199.
Am_Menu_Line_Command has no customizable slots, and it is an inactive menu item.
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_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_OFFSETpixels, 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_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
Am_Button_Panelis 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_Mapuses are also used by
Am_Button_Panel. See the Opal chapter for a description of
Am_Mapslots are described below along with slots specific to
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
Am_WIDTH, Am_HEIGHT: The width and height slots contain the standard Amulet formulas
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
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
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_TOGGLEwill allow the selected item to be turned off by clicking it again.
Am_CHOICE_LIST_TOGGLEallows 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_Layoutis the default, and
Am_Horizontal_Layoutis 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_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_ITEMS: This slot specifies the items which are to be put in the button panel. An
Am_Value_Listshould be used to specify specific items to add to the panel. See section 188.8.131.52 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_COMMAND: This slot contains an
Am_Commandobject. See section 184.108.40.206 for a complete description.
Am_ITEMSslot 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_METHODmethod is called each time the button is pressed, and the button's label or graphical object is obtained from the command object's
Am_LABELslot. The following code specifies a button panel with three 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);
// my button panel:
Am_Object My_Button_Panel = Am_Button_Panel.Create ("My Button Panel")
.Add ("Push me.")
.Add (my_command = Am_Command.Create()
.Set (Am_LABEL, "Push me too.")
.Set (Am_DO_METHOD, My_Custom_Do_Method)));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_Objectdrawn 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.
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_VALUEslot 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 any of the other buttons in the panel are pressed, the do action of
My_Button_Panel's command object (in its
Am_COMMANDslot) will be called, with the command object as an argument. The
Am_VALUEof 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_PARENTslot to contain the button panel's command object. For example, after executing the following code,
My_Other_Custom_Do_Methodin 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);
Am_Radio_Button_Panelis 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_VALUEslot of the top-level
Am_COMMANDis 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
Am_H_ALIGN: This slot contains a formula which evaluates to
Am_RIGHT_ALIGNif it is
Am_FIXED_WIDTH: The default is
falsefor this slot in a radio button panel.
Am_FINAL_FEEDBACK_WANTED: The default is
truefor 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_Checkbox_Panelis 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_VALUEslot of the top-level
Am_VALUE_LISTof the labels or IDs of the selected items.
Am_Menuis 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
The following slots of an
Am_Menudiffer from those in an
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_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_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"))
.Set(Am_LABEL, "Not active"))
.Set(Am_LABEL, ("Active item"))
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_VALUEslot. 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_ACTIVEslot 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_PARENTslot 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_Baris 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 abitrary Amulet object, just like with other button-type objects.
The interface to menu bars is similar to other button widgets: the
Am_ITEMSslot 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_ITEMSslot containing an
Am_Value_Listof 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 ()
.Set(Am_ITEMS, Am_Value_List ()
.Add ("Save As...")
.Set(Am_ITEMS, Am_Value_List ()
.Add (Am_Menu_Line_Command.Create("my menu line"))
)If a sub-menu item has a command (like Quit or Undo above), then its
Am_DO_METHODis 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_doin the command object named
Edit_Commandwill be called for Cut and Paste, and the
Am_VALUEslot of the
Edit_Commandwill 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_PARENTslot of a command to the menu_bar's command object. The
Am_VALUEof 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_Barsallow 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_ACTIVEfield of the command object for that item to false. If the
Am_ACTIVEfield 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_Horizontal_Scroll_Barare widget objects that allow the selection of a single value from a specified range of values, either as a
float(see section 220.127.116.11). 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. Unfortunately, auto-repeat (repeatedly incrementing while the mouse button is held down) is not implemented yet. 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_METHODof the command is also continuously called. The
Am_VALUEslot of the widget can also be set by a program to adjust the position of the scroll bar indicator.
Am_Scrolling_Groupprovides 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_VALUEslot 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
coutdisplay floats without decimal parts as integers, but the scroll bar still treats them as floats.
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_VALUEslot 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.
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_1is 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 defauls type is an int, but it can also hold a float. The default is 100. Note that
Am_VALUE_2is not required to be bigger than
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_Scrolling_Groupjust 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_WIDTHand
Am_Scrolling_Groupitself. 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
By default, the
Am_ACTIVEslots 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_V_LARGE_INCREMENTare also calculated based on the screen size.
Am_INNER_HEIGHTslots, such as
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_Liststored in the
Am_GRAPHICAL_PARTSslot of the group, which will only contain the objects you added. The
Am_GRAPHICAL_PARTSslot can also be used for normal groups (instances of
Am_Map), so you can write code that will operate on either scrolling groups or regular groups.
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_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: 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_STYLEslot 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_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_Height_Of_Parts). It is OK if these are smaller than the scrolling group's
Am_HEIGHT: this just means that the entire area is visible, and so the appropriate scroll bars will be disabled.
Am_Scrolling_Group, simply create an instance of it, customize the
Am_HEIGHTslots of the group to define its size, set the
Am_INNER_HEIGHTbased on the contents, and add graphical parts to the group.
my_scrolling_group = Am_Scrolling_Group.Create("scroll_group")
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_Widgetis used to get a single line of text input from the user, for example for filenames.
The widget has an optional label to the left of a text type-in field. The label is the value of the
Am_LABELfield 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_VALUEof the command in the
Am_COMMANDslot is set to the new string, and the command's
Am_DO_METHODis called. The command's default
Am_VALUEand 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.
The text input widget could also be used as an output-only text display by setting the Am_ACTIVE_2 slot (see Section 6.2.1) to false, which will disable the interactors.
The special slots of the
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_LABELslot 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_LABELof the command in the
Am_Text_Input_Widgetis 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_VALUEof the widget is set with the value the user types, and the
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:
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
Slots that control the Am_Selection_Widget are:
//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")
//put the scroller in the window
//put the selection widget and the created_objs as parts of the scrolling group
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_VALUEof 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 18.104.22.168.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.
22.214.171.124 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. Unfortunately, selecting objects by dragging out a region is not yet supported.
6.3 Dialog boxes
Amulet provides three standard dialog box widgets with different appearances but similar operation to be used for simple messages and queries. We also provide several functions to make the dialog boxes easier to use. The dialog boxes are:
void Am_Show_Alert_Dialog (Am_Value_List alert_texts, int x = 100,
int y = 100, bool modal = false)This routine brings up an alert dialog box at the location (x, y) on the main screen, and 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 "Okay" 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.
Am_Value Am_Get_Choice_From_Dialog (Am_Value_List prompt_texts,
int x = 100, int y = 100, bool modal = false);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 "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 = 100, int y = 100,
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."
Am_Value Am_Show_Dialog_And_Wait (Am_Object the_dialog,
bool modal = false)This routine displays a preconfigured dialog box, waits for the user to complete interaction with it, and then returns its value. The only slots the dialog box changes before displaying the dialog box are its command's Am_DO_METHOD and Am_ABORT_METHOD. This routine is useful for reusing a commonly displayed dialog box without the overhead of reallocating and reinitializing the dialog box each time it is displayed. The dialog is added to Am_Screen if it is not already there, but it is not removed when the routine is finished.
Most of these commands operate on the currently selected objects, so they require that you pass in an instance of a selection widget (Section 6.2.6) in the Am_SELECTION_WIDGET slot of the command object. If you implement your own selection handles and do not use the selection widget, you still may be able to use the following commands, if your selection handles object provides the set of selected objects in the Am_VALUE slot, and allows that slot to be set to change the selection.
The supplied command objects are as follows. See the tables in the Summary chapter, Section 11.7 for a list of the slots to be set in each.
Am_Graphics_Clear_Command: delete the selected objects. The label is ``Clear'' and the accelerator is ``DELETE''. Must be passed a Am_SELECTION_WIDGET.
Am_Graphics_Clear_All_Command: The label is ``Select All'' and the accelerator is ``CONTROL_a''. Must be passed a Am_SELECTION_WIDGET.
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.
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.
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.
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.
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.
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.
Am_Graphics_Group_Command: Make a group out of the selected objects. Creates an instance of Am_Resize_Parts_Group (see Section 4.7.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.
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 ``Select All'' and the accelerator is ``CONTROL_h''. Must be passed a Am_SELECTION_WIDGET.
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_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 6.4.2. Must be passed a Am_SELECTION_WIDGET.
menu_bar = Am_Menu_Bar.Create(``menu_bar'')
.Set(Am_ITEMS, Am_Value_List ()
.Set(Am_IMPLEMENTATION_PARENT, true) //top command not queued for undo
.Set(Am_ITEMS, Am_Value_List ()
.Set(Am_IMPLEMENTATION_PARENT, true) //top command not queued for undo
.Set(Am_ITEMS, Am_Value_List ()
.Add (Am_Undo_Command.Create()) //these get the undo_handler from
.Add (Am_Redo_Command.Create()) // menubar's window
.Set(Am_IMPLEMENTATION_PARENT, true) //top command not queued for undo
.Set(Am_ITEMS, Am_Value_List ()
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.
Because the command does not necessarily know how to get the correct value out of the palette or menu or how to update and read the property from the graphical object, a number of methods can be overridden in the command to control how the command gets and sets the value from the palette and from the graphical object. The slots that control the Am_Graphics_Set_Property_Command are:
(Am_Object command_obj, Am_Value &new_value));
(Am_Object command_obj, Am_Object object,
(Am_Object command_obj, Am_Object object,
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.
en 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.
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.