Enhancing nf
Writing Tools
If you want to write a tool, simply write a tcl file in
/users/jepler/nf/tools. The special command "tool"
works like "proc", but creates a new tool. If you write "tool
nice_name_here", it will display in the menu as "Nice name here".
Your proc should take one parameter—the selected widget—and
perform some operation. For instance, if you are bothered by the fact
that I only let you "Cut" widgets, not "Destroy" them, you could write
the following tool:
tool destroy {w} {
set $p [winfo parent $w]
set ::nf::currentwidget $p
destroy $w
::nf::tarnish
::nf::update_tree $p
}
restart nf, and your new entry should appear under Tools. (After the
entry is here, you can use "source" in the code window to test changes,
but the contents of the main Tools menu is fixed at startup)
You will need to understand a few nf internal commands and variables
(they all start with "::nf::") to successfully write a tool:
- ::nf::tarnish
- Mark the current screen "changed". Almost
any tool will tarnish the screen.
- ::nf::update_tree widget
- update the tree widget at
[widget] and below. This is needed when a widget is destroyed or
created.
- ::nf::install_bindtags widget
- Make sure nf's special
widget bindings are installed on widget and its children. This is
needed when a widget is created
- $::nf::currentwidget
- If you destroy the current widget,
make sure you set ::nf::currentwidget to another widget (usually the
parent of the current widget, but "." if you can't determine a widget
that's sure to exist when you're done). Do this before you destroy
$::nf::currentwidget.
- ::nf::cut, ::nf::copy, ::nf::paste
widget
- Cut/Copy/Paste functionality. Note that this is usually
unsafe to use paste unless you use cut/copy earlier in the command, because
the state of the cut buffer is not saved with the undo step.
Tools with prerequisites
Most tools only work for some tasks. If your tool only works under
some conditions, write "prereq" block that returns 1 when the
tool can run, 0 otherwise. This block should be "quick", since it is
evaluated frequently (once for each widget displayed in the context menu,
each time an undo step is saved, and each time the active widget changes).
For example:
prereq destroy {w} { expr {$w != "." && [winfo children $w] == ""} }
Tools with parameters
Tools can now take parameters. The parameters are returned in a list from
the block created with the "params" command. For example,
params new_tab {} {
::nf::ew::prompt "Add Tab" {
{id str {Tab ID} "" 100}
{name str {Tab Name} "" 100}
}
}
You can do anything you like here. nf's widget edit
library ("ew") has a rudimentary prompt library, invoked with
::nf::ew::prompt.
Composites
The easiest way to create a composite is by using Tools→Save as
composite. The body of the file is a series of tcl commands to create
the widgets, and the first line of the file is a tcl comment which
names the highest-level widget created. (This is exactly the same as
the cutbuffer format as well as the format xf used, and in fact most of
the xf items worked just fine under nf) Example:
# .buttons
frame .buttons
button .buttons.save -text OK -width 8
button .buttons.cancel -text Cancel -width 8
button .buttons.reset -text Reset -width 8
button .buttons.help -text Help -width 8
pack .buttons.save .buttons.cancel .buttons.reset .buttons.help -side left
pack .buttons -anchor se
New widget types
nf is intended to be able to accommodate new widget types, including
composite widgets defined in tcl.
nf makes the following assumptions about all widgets it supports:
- The widget constructor is the same as the widget class in all lowercase. In particular, the widget constructor must exist in the :: namespace.
- The widget obeys the "configure" interface
- (there are probably other implicit assumptions)
For items which have requirements above creation and basic configuration, nf
supports the following tweaks:
- The function ::nf::nosave_attr returns a list of attributes which are not saved by default. For instance, the -labelwidget of a Labelframe must not be set until the widget is actually created.
- The function ::nf::nosave_children returns a list of children which are not saved. For instance, the combobox widget creates three internal children (an entry, a button, and a toplevel) which should not be written in the nf script.
- A "postconfgure" command which is executed after all children of the widget are saved. This is where widget-specific stuff (for instance, the contents of menus or comboboxes, or the -labelwidget of a labelframe) is saved.
For editing widgets, nf supports the following tweaks:
- ::nf::ew::shortprops returns the list of properties that should be displayed when "show all properties" is not enabled.
- ::nf::ew::item_class is called to create an edit control for a configuration option of class class. Most of these just dispatch to a generic edit control, such as item_Spinner, item_Color, etc.
Currently, nf doesn't have a nice interface for editing other stuff such as menu contents.