Design Data has always used the xf tool for designing screens. xf has many limitations, and this has caused me to write nf, meaning "not xf".
I hope you'll find working with nf more pleasing than xf. This tour will introduce you to the major features of nf
| New screen | | Open screen | | Save this screen | | Cut widget |
| Copy widget | | Paste here | | Undo | | Redo |
| Edit properties | | Print screen
|
| Button | | Canvas | | Checkbutton | | Control Frame |
| Combobox | | Entry | | Frame | | Hierbox |
| Horizontal Rule | | Horizontal Space | | Labelframe | | Label |
| Listbox | | Mclistbox | | Menubutton | | Menu |
| Message | | Radiobutton | | Scale |
| Scrolledframe |
| Scrollbar | | Table | | Tabset | | Text |
| Toplevel | | Vertical Rule | | Vertical Space |
| Unrecognized Widget
|
Each different type of widget displays a different icon. However, since they were historically created in a different way, speical types of frames may display as plain frames in the tree view. This includes:
Widgets are matched to their items by their [winfo class]. If there is no matching icon, the blue C icon is used.
The tree view supports "drag & drop" of existing widgets. While dragging, you are given visual feedback about the operation. If a line is shown above or below a widget, the dragged widget will be moved to be the previous or next sibling of that widget. If a widget is shown with red shading, the dragged widget will be moved to be the first child of that widget. Pressing escape before releasing the left mouse button will cancel the drag operation.
Note that the order in the tree reflects stacking order, but the drag result indicator shows the packing order that will result from the operation. For instance, if you have ".w" and ".buttons", packed with -side top and -side bottom, there will be no visible change if .buttons is dragged to be the prior pack sibling of .w, because the stacking and traversal order always lists items packed on the top or left before items packed on the right or bottom.
Do not use "drag & drop" in the presence of grid-managed widgets.
This is the window you are editing. Many widgets are "live": most of
the time, left-clicks and keyboard presses will be passed to them and
interpreted normally. This is often undesirable, because the commands
invoked can do destructive things (like "destroy .") or
invoke commands that don't exist inside nf's wish
interpreter (like "enable"/"disable")
The current widget is shown with a red handle-box drawn around the area it occupies. (the handles don't actually perform any function—you can't resize a widget this way)
Access the context menu by right-clicking either on the widget itself or
on the tree-view item. (This also makes the clicked widget the
"current" widget for future operations, unless an ancestor is selected
from the context menu) You can perform actions on the widget or any of
its ancestors. Cut/Copy/Paste have the normal effect (You cannot cut
the "." window). Properties shows the properties window for the
selected widgets. In the Tools cascade, or below the separator in the
ancestor cascades, you will find the items from the main Tools menu.
Almost all "Insert" operations, and most "Tools" operations must actually be performed on a frame, but when clicking within the screen you'll usually select a non-frame widget such as a button, entry, or label. In these cases, use the cascade corresponding to the ancestor frame you wish to manipulate.
In the Properties window, you can set any of the configuration options
for a widget, and the options for the widget's geometry manager (pack,
grid, or place). For entry widgets, the new value is set only when you
focus out or close the window.
Just click "OK" or use your window manager to close a properties window.
You can open a properties window for any number of widgets simultaneously, even two widgets of the same type.
You can either view a restricted subset of widget properties (those which I judged to be "commonly" changed) or all widget properties. When you toggle Edit→Full properties, only newly displayed properties windows are affected. So, if you've already opened properties for a particular widget you must close the window and then redisplay it to see all properties.
This window lets you apply a tool or command of your choice to multiple
widgets very easily. First, choose whether the tool will be applied to
the clicked widget or one of its ancestors. Then, either choose a tool
from the drop-down list or enter a tcl command to execute with %W
for the selected widget. For instance, to change the external padding
of a packed widget, you would use
pack %W -pady 3
and to change the width of a label to a desired value you would use
%W configure -width 9
Then, use left-click in the edited window (not the tree view) to apply
the tool or command. Once you close the "Apply" window, left-clicks
have their normal effect (to focus an entry, etc).
Unlike in previous versions, where the entire file was written
out when an action was performed, nf can't detect whether
a particular operation actually changed anything about the screen.
This effect is most obvious when using the code window. Even if you're
using it to do something without side-effects (for instance, using it
to inspect the value of some variables), an undo step is added whenever
you press the "Execute" button.
Often the desire to do this is misguided, but if it cannot be avoided, then a feature of the nf2tcl script should be used to cause this code to run when the screen is actually used in sds/2.
On each widget affected by the [debug_dsndata] or [get_arch], add a binding for an event named <<PostInit>>. In the body of the event, put the lines of code which should be executed after the widget is created.
See also the advice just below on unknown commands.
If you run nf by executing "/sds2/bin/sds2_6.3 nf" (I refer to this as "sds2 nf"), and then do something in the edited window that calls a function defined in C, you risk getting a segmentation fault if that function uses global variables that have not been initialized.
For this reason, I recommend running nf by executing "/sds2/bin/nf" (I refer to this as "standalone nf"). This uses a standalone wish binary which has been compiled with all the special widgets and patches sds/2 uses, but without all the tcl commands sds/2 defines in C. Instead of a signal 11, you'll get an "invalid command name" dialog box.
(Historically, I advocated running xf under sds/2 because it would allow use of features that were available under sds/2, but not in the standalone wish program. I now recommend running nf under a special "wish" binary which has all those special features built in. So this isn't so much a reversal of opinion as having found a better way to achieve the same end.)
proc some_name {args} {}
If the command needs to return a value, then just insert a "return"
statement:
proc some_name {args} { return 1 }
Don't add these through the "Procedures" menu, or they will be saved with
the screen, which will override the normal meaning when you finally run
the screen in sds/2.
If you can't make a widget look "right" by editing just the short properties list, you can turn on "Full properties". But if you have to (for instance) set the -padx of a widget to make several widgets line up, think twice. Will your change look right on both Unix and Windows? Is the need to make this change indicative of a deeper problem with the screen's layout?
One exception to this rule is when the widget has the look it does because its appearance was changed from the defaults before. In this case, it's just fine to set the appearance back to the default. Personally, I recommend doing this in emacs by editing the .nf files. This makes it easier to find the configuration options which are different from the default, since only these options are written to the output file.
If you find yourself doing something over and over again, and can describe the task in a programmable way, then a tool can be written to do it. If you are comfortable with tcl, you could write one yourself by following the directions in the Enhancing nf document. Otherwise, I or someone else with enough tcl expertise could do it from a clear description of the conditions the tool should recognize and the actions it should perform.
If the task is very simple (unconditionally changing some configuration or packing option of the selected widget), you should be able to use the "Apply to multiple widgets" tool with a command that you enter.