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:

For items which have requirements above creation and basic configuration, nf supports the following tweaks:

For editing widgets, nf supports the following tweaks:

Currently, nf doesn't have a nice interface for editing other stuff such as menu contents.