Motif/Lesstif Application Development
Motif provides a simple menu bar that is easy to build but makes some assumptions about menu behavior. For a more flexible widget with more involved menus, you will want to explore XmMenuBar. Note that the menu bar is created as a child of the form. The menu bar built on line 114 specifies a single menu as a cascade button (line 115). If you want multiple pull-down menus, you simply add more lines. The string is the name of the menu as it will appear in the menu bar, and the single letter is the meta keystroke that will cause the menu to pull down (in this case, alt-F or meta-F).
Once the menu bar is constructed, the actual pull-down menus can be created as children of the menu-bar widget. Line 133 specifies the parent widget and name for the “File” menu; the arguments indicate the initial item and the callback function invoked if the user selects a menu item. Each of the subsequent lines describes a single menu item and each item begins with its type. The Menus can contain more than just the traditional push buttons; for more information, refer to the Motif Programming Manual. The next argument is the string displayed for the menu item, followed by a hot key the user can press when the menu is displayed, then an accelerator key sequence the user can press to invoke the menu item without actually pulling down the menu. The last argument for the item is the display string for the accelerator keystroke—this will be displayed right-justified in the menu.
Horizontal lines (separators) can be placed in the menu by specifying XmSEPARATOR for the type (with no associated values) as in line 135. This is another case where columnizing your source is a very good idea. It is easy to leave out one of the items, resulting in catastrophic (or at least bizarre) behavior at runtime. If you don't want to specify one of the options, a place holder such as an empty string must be used.
Once all the pull-down menus are created, the menu bar must be managed (line 142), so that when the form gets managed, it will be free to display the menu bar. In this case (as with some of the specialty manager widgets), it is not necessary to manage the pull-down menus. Remember, they aren't actually displayed until the user does something to make them appear.
The next widget we instantiate is the file selection dialog. It will not actually appear until invoked by the user (by a menu selection or button press), but I chose to build it here since it is logically related to the file menu. Motif provides a number of very nice specialty dialog boxes; one of the most interesting is the File Selection Dialog, XmFileSelectionDialog. This widget is derived from XmSelectionBox, so when you are looking for some of the resources in the Motif Reference Manual, you may need to refer to both widgets.
At times, it may be more convenient to assign callbacks after creating a widget, either because you don't have all the information you need at the time, or the callbacks cannot be easily supplied to the create function as in our example. Another reason is the explicit call to XtAddCallback makes it obvious the assignment took place; in addition, you get the benefit of compile-time-type checking.
The stock file-selection dialog handles all heavy lifting for you, file name globing, directory navigation and even file name filtering. The default dialog also provides a few extra buttons I will not use. To avoid confusing the user, set their XmNSensitive resource to false (causing them to be grayed out) or remove them altogether. Motif provides a convenience function for all widgets derived from the Selection Box to get the widget ID of specific children widgets in the dialog (line 150), XmSelectionBoxGetChild. Once I have the widget ID, a call to XtUnmanageChild will prevent that particular widget from appearing when the rest of the dialog is displayed.
The code on lines 157 to 204 is concerned with adding the remaining components to the display. I will use these widgets to explain the way XmForm handles the layout of its children. Attachments describe a widget's relationship with other widgets within the form; it may take a while to get used to the way attachments work. Widgets appear in the form in the order they are created—important to keep in mind as you code. I will describe the most basic aspects of form attachments.
Each widget parented by a form has attachment resources for the top, bottom, left and right sides. I will cover how to use XmATTACH_FORM and XmATTACH_WIDGET and attachment offsets. Other attachment types include XmATTACH_NONE, XmATTACH_SELF, XmATTACH_POSITION and some based on form and widget opposing sides. On line 116, you see the top, left and right sides of the menu bar are attached to the form. This means each of the sides will “stick” to the respective sides of the form, stretching the widget as needed. The bottom attachment is left as XmATTACH_NONE, since I need to use the remaining portion of the form for other display elements. If the attachments were not specified, the size and position of the menu bar would default to a fairly unattractive box in the upper left corner of the form.
On line 158, I specify that the top of the label is attached to the menu bar widget and line 159 specifies this attachment will stay 10 pixels off the menu. The left side of the label is attached to the form and the right and bottom sides are left unattached. If attachments were specified and a border was visible for the label, you would see it stretch as the position of the other widgets changed during a resize operation.
Mistakes in attachments can hide a widget altogether or generate ugly screens; in some cases, the errors are bad enough to be printed on STDERR (e.g., circular dependencies). If you specify a widget attachment, you must also specify the widget to which the side should be attached. Since no compile-time checking is done on these things, you won't discover your omission until runtime.
I want the text field used to enter a file name to stretch horizontally; so once the Browse button is created, I add a final attachment to the text field (line 181). This is an excellent example of the strength of using XmForm for your layouts.
Special Reports: DevOps
Have projects in development that need help? Have a great development operation in place that can ALWAYS be better? Regardless of where you are in your DevOps process, Linux Journal can help!
With deep focus on Collaborative Development, Continuous Testing and Release & Deployment, we offer here the DEFINITIVE DevOps for Dummies, a mobile Application Development Primer, advice & help from the experts, plus a host of other books, videos, podcasts and more. All free with a quick, one-time registration. Start browsing now...
- The Ubuntu Conspiracy
- Science on Android
- A First Look at IBM's New Linux Servers
- Disney's Linux Light Bulbs (Not a "Luxo Jr." Reboot)
- Vigilante Malware
- Bluetooth Hacks
- Vagrant Simplified
- Libreboot on an X60, Part I: the Setup
- System Status as SMS Text Messages
- October 2015 Issue of Linux Journal: Raspberry Pi