Programming in XPCE/Prolog: Section 11.4

## 11.4 Library ``pce_toc'': displaying hierarchies

The table-of-content library defines a window displaying a tree in an explorer-like style. This library is programmed by refining its base-class toc_window. We will introduce this library using an example exploring the filesystem. A screendump of this application is in figure 21.

Figure 21 : Exploring the filesystem

    :- pce_autoload(toc_window, library(pce_toc)).
    :- pce_autoload(report_dialog, library(pce_report)).

    :- pce_begin_class(explorer, frame, "Explore the filesystem").

    initialise(E, Dir:directory) :->
            "Explore from directory"::
            send_super(E, initialise, 'Simple explorer'),
            send(E, append, new(DH, directory_hierarchy(Dir))),
            send(new(view), right, DH),
            send(new(report_dialog), below, DH).

    open_node(E, Node:file) :->
            "Show file content of opened node"::
            get(E, member, view, View),
            send(View, load, Node).

    :- pce_end_class.

    :- pce_begin_class(directory_hierarchy, toc_window,
                       "Browser for a directory-hierarchy").

    initialise(FB, Root:directory) :->
            send(FB, send_super, initialise),
            get(Root, name, Name),
            send(FB, root, toc_folder(Name, Root)).

    expand_node(FB, D:directory) :->
            "Called if a node is to be expanded"::
            new(SubDirsNames, chain),
            new(FileNames, chain),
            send(D, scan, FileNames, SubDirsNames),

            get(SubDirsNames, map, ?(D, directory, @arg1), SubDirs),
            send(SubDirs, for_all,
                 message(FB, son, D,
                         create(toc_folder, @arg1?name, @arg1))),
            get(FileNames, map, ?(D, file, @arg1), SubFiles),
            send(SubFiles, for_all,
                 message(FB, son, D,
                         create(toc_file, @arg1?base_name, @arg1))).

    open_node(FB, Node:file) :->
            "Called if a file is double-clicked"::
            send(FB?frame, open_node, Node).

    :- pce_end_class.

Programming is achieved by subclassing toc_window and in some cases the support classes toc_folder and toc_file, representing expandable and leaf-nodes.

Each node is assigned an identifier, a unique reference to the node. In the example below we used file and directory objects for this purpose. The identifier is the second argument to the creation of the node. When omitted, the node is turned into an identifier of itself. This distinction is used to hide the existence of graphical node objects for users of the basic functionality.

Below we describe the important methods of this package. We start with the virtual methods on class toc_window that should be refined by most applications.

toc_window ->expand_node: Id:any
  The user clicked the `[+]` sign or double-clicked a toc_folder. This method is normally refined to add sub-nodes for Id to the current node using `toc_window`->`son'. If the implementation of toc_window is activated at the end the window will scroll such that as much as possible of the subtree below Id is visible.
toc_window ->open_node: Id:any
  Called on double-click on a toc_file node. The implementation of toc_window is empty.
toc_window ->select_node: Id:any
  Called after single-click on toc_folder or toc_file. Note that double-clicking activates both `->`select_node and `->`open_node and therefore the action following select_node should execute quickly.
toc_window <-popup: Id:any
  Popup:popup This method is called on a right-down. If it returns a popup object this is displayed.

The methods below are used for general querying and manipulation of the hierarchy.

toc_window <-selection:
  ChainOfNodes Returns a chain holding the node objects that are currently selected.
toc_window <-node: Id:any
  Node:toc_node Map a node-identifier to a node. Fails silently if this identifier is not in the tree.
toc_window ->root: Root:toc_folder
  Assign the hierarchy a (new) root.
toc_window ->son: Parent:any, Son:toc_node
  Make a new node below the node representing Parent. If the node is a leaf, Son is a subclass of toc_file, otherwise it is a subclass of toc_folder.
toc_window ->expand_root:
  Expands the root-node. This is normally called from `->`initialise to get a sensible initial hierarchy.

The classes toc_folder and toc_file are summarised below. Subclassing may be used to modify interaction and/or store additional information with the node.

toc_folder ->initialise:
  Create an expandable node. Id defaults to the node object itself and the two images to the standard opened/closed folder images. Folders assume they can be expanded, CanExpand may be set to @off to indicate `an empty folder'.
toc_file ->indicate:
  Create a `file'-node from its Label, Id (defaults to the created node object) and Image (defaults to a `document' icon).