Introduction

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

Why nf is better than xf

The Main nf screen

Like xf, nf operates primarily from a separate toplevel window. This consists of a menubar, toolbar, the code area, and a tree view.

The menubar

The "File" and "Edit" menus have the customary items and the edit menu also includes items to insert both standard widgets (label, entry, etc) and standard composite widgets (work_frame, setup_buttons). Edit→Natural Size will redisplay the window at its requested size, useful if you've manually resized the window or the size has changed due to removal or movement of widgets. (Edit→Natural Size might as well be a tool, but it was written before tool support was implemented) "Tools" includes items to manipulate existing widgets. For instance, Tools→Group converts a group-with-title into a labelframe. "Procedures" lets you create and edit the tcl "proc"s which will be stored with your screen. When you choose to edit one, the contents of the proc are placed in the code area, and changes are actually saved by hitting the Execute button. Likewise "Variables" and "Bindings" are manipulated through the next two menus, and changes finalized by clicking the Execute button. Note that the bindings menu applies to the currently selected widget, so you must first select the widget whose bindings you wish to modify.

The toolbar

New screen Open screen Save this screen Cut widget
Copy widget Paste here Undo Redo
Edit properties Print screen
Toolbar icons
Commonly-used actions are placed in the toolbar. Currently, these are not configurable. The items are grayed out when the corresponding menu entry is. If you hover over a toolbar item for a second, a tooltip will appear.

The code area

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
Widget icons
You can enter code here, like "destroy .w.g0", ".w.g1.f0.l configure -textv section_size". To execute the code, either click the Execute button or press Control-Enter. The tab key inserts a tab character, press ctrl-tab to traverse forward. When you edit Procedures, Variables, or Bindings, the corresponding code is placed in the code area. After you edit it, Execute the code to make the change actually take effect. If the code returns a value or generates an error, the result is displayed next to the Execute button.

The tree view

This shows a live tree view of the screen. If you (Control-)Tab to this widget, you can use the cursor keys to move around in the tree. You can click a widget to select it as the current widget (for inserting widgets, running tools, or setting bindings) or right-click to get a context menu.

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.

Drag & Drop

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.

Resizing the code area and tree view

Between the code area and the tree view is a thin horizontal line with a larger rectangle. You can change the division between the code area and tree view by dragging this rectangle (called the thumb) up or down.

The edited window

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)

The context menu

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.

The widget properties window

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.

Tools

Tools can do anything that you could do by executing tcl code. (If you want to be sds/2 buzzword compliant, think of them as Parametrics for nf) Note that currently there is nothing to cause a properties window to update if widget options are changed through a Tool. (however, if a tool destroys a widget, any palette displayed for it should disappear at the same time) This will be fixed in a future version if it turns out to be a problem. See the tools document for more information about tools.

Apply to multiple widgets

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).

Undo, temporary files and recovery

A word or two about undo

After each operation, the command that produced the operation is saved to a temporary file. "Undo" operates by destroying all widgets and reloading every one of these temporary files. "Redo" operates by reloading one of these temporary files.

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.

Recovering after a crash

If you are working with undo enabled, and nf exits abnormally (for instance, with a signal 11 or due to "destroy ."), you should be able to recover your work. The next time you start nf, you will be presented with the "Recover files" dialog. If you select an item and click "Recover" or press Return, it will be loaded into nf. Use "Save as" to save the file (the filename is not recovered). Click "Don't recover" or press Escape if you want to ignore the file and start nf normally. Use "Delete" to remove the files permanently, if you are sure you don't want to recover the session.

Troubleshooting

nf won't even load my screen!

There are still a few things that nf has problems with.

XF_LOAD_PATH

I think this error is related to using "save as" in xf. You can try: This problem should "go away" after you save the screen as an nf file.

Unknown commands

Sometimes a screen calls sds/2 commands during its creation. For instance, a few screens call [debug_dsndata] to configure themselves differently at user sites, or [get_arch] to configure themselves differently on NT and Unix. If you load the screen in "sds2 nf", the information about the configuration differences will be lost.

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.

I got a signal 11 while editing my screen.

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.)

I keep getting "unknown command" errors while running my screen.

The screen may be trying to use some command defined in sds/2, but which does not exist in standalone nf. You can most likely make things work by defining it as a command that does nothing and returns nothing:
    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.

It still doesn't look right!

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.

It sure would be nice to have a tool to do X

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.