HyperTree - Draft #1
by Robert John Churchill
April 6, 1998

Summary: This document will describe functionality of the HyperTree (HT), a layer between Netscape Front-Ends (FEs) and the Resource Description Framework (RDF) engine.

Background: RDF, in its most simple form, is a directed labelled graph. Most people, including end users, are familar with hierarchies... from file systems to Netscape's bookmark window, a hierachy helps to indicate organization via a tree structure. By defining a standard vocabulary that includes definitions for parent and child relationships, it becomes possible to layer a strict hierarchical view on top of RDF's graph. An example of this is Netscape's HyperTree which enables different views of data (such as bookmarks, history, the local file system, Appletalk, LDAP, etc.) from RDF.

HyperTree Concepts:

HT_View: a collection of related data. For example, there are HT_Views for bookmarks, history, etc.
HT_Pane: a collection of HT_Views. For example, a browser window can have a HT_Pane embedded in it.
HT_Columns: every HT_View can have a variable number of columns... such as "Name", "URL", etc.
HT_Notification function: this function listens for events from the RDF engine and passes appropriate events up to the FEs.


An FE will normally implement a HT_Notification function and register it with HT upon creation of an HT_Pane. When the FE wants to make a change to either HT's state or RDF's graph, it can call the appropriate function. Upon successful completion of the operation, the notification routine will be called.

HT_Notification:

A HT_Notification is a simple structure:
typedef uint32 HT_NotificationMask;
typedef uint32 HT_Event;

struct _HT_NotificationStruct;
typedef void (*HT_NotificationProc)(struct _HT_NotificationStruct*, HT_Resource node, HT_Event whatHappened);

typedef struct _HT_NotificationStruct {
        HT_NotificationProc notifyProc;
        void* data;
} HT_NotificationStruct;

typedef HT_NotificationStruct* HT_Notification;

As assertions are made on RDF's graph, or as HT's state (such as selection) changes, notification events will be sent to the registered function. Events include:
#define HT_EVENT_NODE_ADDED                     0x00000001UL
#define HT_EVENT_NODE_DELETED_DATA              0x00000002UL
#define HT_EVENT_NODE_DELETED_NODATA            0x00000004UL
#define HT_EVENT_NODE_VPROP_CHANGED             0x00000008UL
#define HT_EVENT_NODE_SELECTION_CHANGED         0x00000010UL
#define HT_EVENT_NODE_OPENCLOSE_CHANGED         0x00000020UL
#define HT_EVENT_VIEW_CLOSED                    0x00000040UL /* same as HT_EVENT_VIEW_DELETED */
#define HT_EVENT_VIEW_DELETED                   0x00000040UL /* same as HT_EVENT_VIEW_CLOSED */
#define HT_EVENT_VIEW_SELECTED                  0x00000080UL
#define HT_EVENT_VIEW_ADDED                     0x00000100UL
#define HT_EVENT_NODE_OPENCLOSE_CHANGING        0x00000200UL
#define HT_EVENT_VIEW_SORTING_CHANGED           0x00000400UL
#define HT_EVENT_VIEW_REFRESH                   0x00000800UL
#define HT_EVENT_VIEW_WORKSPACE_REFRESH         0x00001000UL
#define HT_EVENT_NODE_EDIT                      0x00002000UL
#define HT_EVENT_WORKSPACE_EDIT                 0x00004000UL

#define HT_EVENT_NO_NOTIFICATION_MASK           0x00000000UL
#define HT_EVENT_DEFAULT_NOTIFICATION_MASK      0xFFFFFFFFUL

After creating a pane, its possible to obtain as well as change a HT_Pane's notification mask with the following routines:
PR_PUBLIC_API(HT_Error)   HT_GetNotificationMask (HT_Pane node, HT_NotificationMask *mask);
PR_PUBLIC_API(HT_Error)   HT_SetNotificationMask (HT_Pane node, HT_NotificationMask mask);

HT_Panes:

Functions to create and delete HT_Panes include:
PR_PUBLIC_API(HT_Pane) HT_NewPane (HT_Notification notify);
PR_PUBLIC_API(HT_Pane) HT_PaneFromResource(RDF_Resource r, HT_Notification n, PRBool autoFlush);
PR_PUBLIC_API(HT_Pane) HT_NewQuickFilePane (HT_Notification notify);
PR_PUBLIC_API(HT_Pane) HT_NewPersonalToolbarPane (HT_Notification notify);

PR_PUBLIC_API(HT_Error) HT_DeletePane (HT_Pane pane);

HT_NewPane() is the standard function to use. It will return a HT_Pane that will be populated with appropriate HT_Views (such as bookmarks, history, the file system, along with any user-created views).

HT_PaneFromResource() allows creation of a HT_Pane will a specific view specified by an RDF_Resource. (Look at RDF's vocabulary for possible RDF_Resources to use.) HT_NewQuickFilePane() and HT_NewPersonalToolbarPane() actually call HT_PaneFromResource() with appropriate vocabulary items to create an instance of a bookmark pane or an personal toolbar.

Its important for a FE to be able to associate private, front-end specific data with HT_Panes (and even HT_Views and HT_Resources). The following functions provide help:
PR_PUBLIC_API(void*) HT_GetPaneFEData (HT_Pane pane);
PR_PUBLIC_API(void)  HT_SetPaneFEData (HT_Pane pane, void* data);

PR_PUBLIC_API(void*) HT_GetViewFEData (HT_View node);
PR_PUBLIC_API(void)  HT_SetViewFEData (HT_View node, void* data);

PR_PUBLIC_API(void*) HT_GetNodeFEData (HT_Resource node);
PR_PUBLIC_API(void)  HT_SetNodeFEData (HT_Resource node, void* data);

HT_Views:

An HT_View equates to a list of related nodes in RDF's graph (for example, bookmarks).

Every HT_View will have a set of columns that the FE can optionally display. Functions for managing colums include:
enum    _HT_ColumnType {
        HT_COLUMN_UNKNOWN=0, HT_COLUMN_STRING, HT_COLUMN_DATE_STRING,
        HT_COLUMN_DATE_INT, HT_COLUMN_INT, HT_COLUMN_RESOURCE
        };
typedef enum _HT_ColumnType  HT_ColumnType;

PR_PUBLIC_API(HT_Cursor) HT_NewColumnCursor (HT_View view);
PR_PUBLIC_API(PRBool)    HT_GetNextColumn(HT_Cursor cursor, char **colName,
                                             uint32 *colWidth, void **token, uint32 *tokenType);
PR_PUBLIC_API(void)      HT_DeleteColumnCursor(HT_Cursor cursor);
PR_PUBLIC_API(void)      HT_SetColumnOrder(HT_View view, void *srcColToken, void *destColToken, PRBool afterDestFlag);
PR_PUBLIC_API(void)      HT_SetSortColumn(HT_View view, void *token, uint32 tokenType, PRBool descendingFlag);
PR_PUBLIC_API(PRBool)    HT_ContainerSupportsNaturalOrderSort(HT_Resource container);

Changing the selected column to sort on will sent a HT_EVENT_VIEW_SORTING_CHANGED event.

For a given HT_View, users will see a list of HT_Resources representing bookmarked URLs. Useful functions for managing lists of HT_Resources include:
PR_PUBLIC_API(HT_Resource)  HT_GetNthItem (HT_View view, uint32 theIndex);
PR_PUBLIC_API(uint32)       HT_GetNodeIndex(HT_View view, HT_Resource node);
PR_PUBLIC_API(uint32)       HT_GetItemListCount(HT_View view);
PR_PUBLIC_API(uint16)       HT_GetItemIndentation(HT_Resource r);

To create a new HT_View (for example, if the users wants to create a new workspace), use:
PR_PUBLIC_API(void)     HT_NewWorkspace(HT_Pane pane, char *id, char *optionalTitle);

which will send a HT_EVENT_VIEW_ADDED event.

HT_Resources:

A HT_Resource equates to a node in RDF's graph.

As a user clicks on various nodes, or moves up and down via the arrow keys, the selection will change. Useful functions for managing selection:
PR_PUBLIC_API(PRBool)      HT_IsSelected (HT_Resource node);
PR_PUBLIC_API(HT_Error)    HT_GetSelectedState (HT_Resource node, PRBool *selectedState);
PR_PUBLIC_API(HT_Error)    HT_SetSelectedState (HT_Resource node, PRBool isSelected);

PR_PUBLIC_API(HT_Error)    HT_SetSelection (HT_Resource node);
PR_PUBLIC_API(HT_Error)    HT_SetSelectionAll (HT_View view, PRBool selectedState);
PR_PUBLIC_API(HT_Error)    HT_SetSelectionRange (HT_Resource node1, HT_Resource node2);
PR_PUBLIC_API(void)        HT_ToggleSelection(HT_Resource node);

PR_PUBLIC_API(HT_Resource) HT_GetNextSelection(HT_View view, HT_Resource startingNode);

Note: HT_GetNextSelection() is especially useful as it enables enumeration of all the selected nodes. Begin with "startingNode" set to NULL and continue calling HT_GetNextSelection until NULL is returned (i.e. no more selected nodes are available).

Changing the selection will send a HT_EVENT_NODE_SELECTION_CHANGED event.

When a user opens/closes a HT_Resource which is a container, the FE can change the open state in HT and enumerate container's children. Useful functions:
PR_PUBLIC_API(PRBool)      HT_IsContainer (HT_Resource node);

PR_PUBLIC_API(PRBool)      HT_IsContainerOpen (HT_Resource node);
PR_PUBLIC_API(HT_Error)    HT_GetOpenState (HT_Resource containerNode, PRBool *openState);
PR_PUBLIC_API(HT_Error)    HT_SetOpenState (HT_Resource containerNode, PRBool isOpen);
PR_PUBLIC_API(uint32)      HT_GetCountVisibleChildren(HT_Resource node);

PR_PUBLIC_API(HT_Cursor)   HT_NewCursor (HT_Resource node);
PR_PUBLIC_API(HT_Resource) HT_GetNextItem (HT_Cursor cursor);
PR_PUBLIC_API(HT_Error)    HT_DeleteCursor (HT_Cursor cursor);

Opening or closing a container will send HT_EVENT_NODE_OPENCLOSE_CHANGING (before) and HT_EVENT_NODE_OPENCLOSE_CHANGED (after) events.

The data associated with a given HT_Resource and a given column may be editable by the yser. If the FE supports inline editing, the following functions are useful:
PR_PUBLIC_API(PRBool)       HT_GetNodeData (HT_Resource node, void *token, uint32 tokenType, void **data);
PR_PUBLIC_API(PRBool)       HT_IsNodeDataEditable(HT_Resource node, void *token, uint32 tokenType);
PR_PUBLIC_API(HT_Error)     HT_SetNodeData (HT_Resource node, void *token, uint32 tokenType, void *data);
PR_PUBLIC_API(HT_Error)     HT_SetNodeName (HT_Resource node, void *data);

Changing data associated with a node will sent a HT_EVENT_NODE_VPROP_CHANGED event.


If a new container needs to be created, use:
PR_PUBLIC_API(HT_Resource)  HT_MakeNewContainer(HT_Resource parent, char* name);
which will send a HT_EVENT_NODE_ADDED event.


If a node needs to be deleted, use:
PR_PUBLIC_API(PRBool)       HT_RemoveChild  (HT_Resource parent, HT_Resource child);

which will sent either a HT_EVENT_NODE_DELETED_DATA or a HT_EVENT_NODE_DELETED_NODATA event, depending on whether FE-specific data is associated with the node, followed by a HT_EVENT_VIEW_REFRESH event. (Multiple deletion events can be sent before a refresh event is sent, allowing for bulk deletion of nodes.)

Contextual Menus:

Contextual menu support is available with the following functions:
typedef enum    _HT_MenuCmd     HT_MenuCmd;

PR_PUBLIC_API(HT_Cursor)   HT_NewContextMenuCursor(HT_Resource r);
PR_PUBLIC_API(HT_Cursor)   HT_NewContextualMenuCursor (HT_View view, PRBool workspaceMenuCmds, PRBool backgroundMenuCmds);
PR_PUBLIC_API(PRBool)      HT_NextContextMenuItem(HT_Cursor c, HT_MenuCmd *menuCmd);
PR_PUBLIC_API(void)        HT_DeleteContextMenuCursor(HT_Cursor c);
PR_PUBLIC_API(char *)      HT_GetMenuCmdName(HT_MenuCmd menuCmd);
PR_PUBLIC_API(HT_Error)    HT_DoMenuCmd(HT_Pane pane, HT_MenuCmd menuCmd);
PR_PUBLIC_API(PRBool)      HT_IsMenuCmdEnabled(HT_Pane pane, HT_MenuCmd menuCmd);

Drag and Drop:

The following functions are the FE to determine whether a node can be drag&dropped, (within a given HT_View or between HT_Views) and allow the actual drag&drop to occur:
typedef uint8 HT_DropAction;

#define DROP_NOT_ALLOWED  0
#define COPY_MOVE_CONTENT 1
#define UPLOAD_RDF        2
#define COPY_MOVE_LINK    3
#define UPLOAD_LFS        4

PR_PUBLIC_API(HT_DropAction)   HT_CanDropHTROn(HT_Resource dropTarget, HT_Resource obj);
PR_PUBLIC_API(HT_DropAction)   HT_CanDropURLOn(HT_Resource dropTarget, char* url);
PR_PUBLIC_API(HT_DropAction)   HT_DropHTROn(HT_Resource dropTarget, HT_Resource obj);
PR_PUBLIC_API(HT_DropAction)   HT_DropURLOn(HT_Resource dropTarget, char* url);
PR_PUBLIC_API(HT_DropAction)   HT_DropURLAndTitleOn(HT_Resource dropTarget, char* url, char *title);

PR_PUBLIC_API(HT_DropAction)   HT_CanDropHTRAtPos(HT_Resource dropTarget, HT_Resource obj, PRBool before);
PR_PUBLIC_API(HT_DropAction)   HT_CanDropURLAtPos(HT_Resource dropTarget, char* url, PRBool before);
PR_PUBLIC_API(HT_DropAction)   HT_DropHTRAtPos(HT_Resource dropTarget, HT_Resource obj, PRBool before);
PR_PUBLIC_API(HT_DropAction)   HT_DropURLAtPos(HT_Resource dropTarget, char* url, PRBool before);
PR_PUBLIC_API(HT_DropAction)   HT_DropURLAndTitleAtPos(HT_Resource dropTarget, char* url, char *title, PRBool before);

To allow drag&drop reordering of HT_Views, use:
PR_PUBLIC_API(void)   HT_SetWorkspaceOrder(HT_View src, HT_View dest, PRBool afterDestFlag);

Miscellaneous:

Certain FEs (such as Windows) draw a hierarchy using dashed lines from a container to each of its children. The following functions are useful:
PR_PUBLIC_API(PRBool) HT_ItemHasForwardSibling(HT_Resource r);
PR_PUBLIC_API(PRBool) HT_ItemHasBackwardSibling(HT_Resource r);

To obtain icon URLs for nodes:
PR_PUBLIC_API(char *) HT_GetWorkspaceLargeIconURL (HT_View view);
PR_PUBLIC_API(char *) HT_GetWorkspaceSmallIconURL (HT_View view);
PR_PUBLIC_API(char *) HT_GetNodeLargeIconURL (HT_Resource r);
PR_PUBLIC_API(char *) HT_GetNodeSmallIconURL (HT_Resource r);

Other useful routines:
PR_PUBLIC_API(HT_Resource)  HT_TopNode (HT_View view);
PR_PUBLIC_API(HT_Resource)  HT_GetParent (HT_Resource node);

PR_PUBLIC_API(RDF_Resource) HT_GetRDFResource (HT_Resource node);
PR_PUBLIC_API(RDF)          RDF_GetNavCenterDB();

PR_PUBLIC_API(PRBool)       HT_IsLocalData (HT_Resource node);
PR_PUBLIC_API(char *)       HT_DataSource (HT_Resource node);

PR_PUBLIC_API(HT_Pane)      HT_GetHTPaneList ();
PR_PUBLIC_API(HT_Pane)      HT_GetNextHTPane (HT_Pane pane);

PR_PUBLIC_API(PRBool)       HT_IsSeparator (HT_Resource node);

PR_PUBLIC_API(void)         HT_Properties (HT_Resource r);