Previous | Contents | Index |
The SVN widget is unlike other widgets in that, when your application needs to change one or more components in an entry, the application calls the DXmSvnInvalidateEntry routine to make the SVN widget reflect the change.
For example, assume that your application uses a CSText widget as a subwidget component to store text. To change the text in this component, your application would:
The components of an entry are internal to the SVN widget and cannot be set by calls to XtSetArg and XtSetValues. However, SVN resources not related to the components of an entry---for example, DXmSvnNtreePerpendicularLines---can be set by calls to XtSetArg and XtSetValues.
Your application can also call the DXmSvnValidateAll routine to make
the SVN widget reflect changes to all the entries.
9.1.10 Outer Scroll Bar Arrows
The DXmSvnNuseScrollButtons resource creates outer arrows on a scroll bar. Outer arrows perform operations that are a magnitude greater than the inner, or stepper, arrows. Clicking on the up stepper arrow moves the display up one unit, which is the number of rows in the display. Clicking on the upper outer arrow moves the display to the top level of the hierarchy the user is currently viewing. The DXmSvnNuseScrollButtons resource is TRUE by default.
For example, if a screen displays messages 20 through 40 in a folder that contains 200 mail messages, clicking on the upper outer arrow causes messages 1 to 20 to be displayed; clicking on the lower outer arrow causes messages 180 to 200 to be displayed.
If the hierarchy is a single-rooted hierarchy, that is, it has one level-zero entry, then clicking Shift/MB1 on the outer arrows scrolls to the top or bottom.
If the hierarchy has multiple level-zero entries, clicking Shift/MB1 on the outer arrows scrolls the display to the top or bottom of each level 0 hierarchy.
In an application like DECwindows mail, which has multiple drawers (all at level 0) and multiple folders (at level 1), clicking Shift/MB1 on the outer arrows scrolls from drawer to drawer (level 0). Clicking MB1 scrolls from folder to folder.
The Ctrl/Up Arrow and Ctrl/Down Arrow keyboard sequences perform the
same functions as the outer arrows without modifiers.
9.1.11 Scroll Bar Index Window
The SVN widget supports smooth scrolling for outline and column display mode when the DXmSvnNliveScrolling resource is set to TRUE. This is the default action.
However, if you set the DXmSvnNliveScrolling resource to FALSE, the SVN
widget implements an index window. The index window is
a special window, attached to the scroll bar, that offers a guide to
the material to be displayed in the window when a user releases the
mouse button.
Your application can call the DXmSvnSetEntryIndexWindow routine to make
sure an entry is displayed in the index window.
9.2 SVN Widget Programming Considerations
This section discusses SVN widget programming considerations, including
topics related to the data hierarchy, enabling and disabling the SVN
widget, manipulating components, and callbacks.
9.2.1 Creating the Data Hierarchy
The SVN widget displays the hierarchical structure supplied by the application. The actual information in the hierarchy is transparent to the SVN widget; the application is responsible for creating the hierarchy and supplying the individual lines of text to the SVN widget.
Your application must therefore implement a mechanism for tracking data in the hierarchy. The data is usually arranged as initial entries, children, and siblings. For example, the SVN demo application uses the following node data structure to define its hierarchy:
typedef struct node { int level; int number; XmString text; struct node *sibling; struct node *children; Widget stext; Boolean opened; }_Node, *NodePtr; |
Table 9-1 describes the fields in the _Node data structure.
Field | Description |
---|---|
level | The level number of children. |
number | The number of children. |
text | Text (XmString) associated with an entry. |
sibling | Pointer to the first sibling of this entry. |
children | Pointer to the first child of this entry. If there are multiple children, they are tracked as siblings of the first child. |
stext | CSText widget associated with an entry. |
opened | Boolean value that indicates whether the entry is opened; that is, whether children are showing. |
The _Node data structure lets you visualize the relationship of the data in the hierarchy.
The code fragment shown in Example 9-1 implements part of the data hierarchy for the SVN demo application. B, P1, P2, and so forth are _Node data structures.
Example 9-1 Portion of the SVN Demo Application Data Hierarchy |
---|
. . . /* ** Fill in the child pointers for the book, parts, and chapters */ B.children = &P1; P1.children = &C11; P2.children = &C21; P3.children = &C31; P4.children = &C41; P5.children = &C51; P6.children = &C61; P7.children = NULL; C11.children = NULL; C12.children = &C121; C13.children = &C131; C14.children = &C141; C15.children = NULL; C16.children = &C161; C17.children = NULL; C21.children = &C211; C22.children = &C221; C23.children = &C231; C31.children = &C311; C32.children = &C321; C33.children = &C331; C41.children = &C411; C42.children = &C421; C43.children = &C431; C44.children = NULL; C51.children = NULL; C52.children = &C521; C53.children = &C531; C54.children = NULL; C55.children = &C551; C61.children = NULL; C62.children = &C621; C63.children = NULL; C64.children = NULL; C65.children = NULL; C66.children = NULL; /* ** Fill in the sibling pointers for the book */ B.sibling = NULL; /* ** Fill in the sibling pointers for the parts */ P1.sibling = &P2; P2.sibling = &P3; P3.sibling = &P4; P4.sibling = &P5; P5.sibling = &P6; P6.sibling = &P7; P7.sibling = NULL; /* ** Fill in the sibling pointers for the chapters */ C11.sibling = &C12; C12.sibling = &C13; C13.sibling = &C14; C14.sibling = &C15; C15.sibling = &C16; C16.sibling = &C17; C17.sibling = &P2; C21.sibling = &C22; C22.sibling = &C23; C23.sibling = &P3; C31.sibling = &C32; C32.sibling = &C33; C33.sibling = &P4; C41.sibling = &C42; C42.sibling = &C43; C43.sibling = &C44; C44.sibling = &P5; C51.sibling = &C52; C52.sibling = &C53; C53.sibling = &C54; C54.sibling = &C55; C55.sibling = &P6; C61.sibling = &C62; C62.sibling = &C63; C63.sibling = &C64; C64.sibling = &C65; C65.sibling = &C66; C66.sibling = &P7; . . . |
The node->children field is a pointer to the first child of an entry. In the case of P1, there are seven children, C11 through C17. (The first child has six siblings.)
Note that the node->sibling field of C17 points at P2, not C21; C17 and C21 do not have the same parent. This organization reflects how the SVN demo equates the entry_number supplied in the callback with an entry in the data hierarchy. (See Section 9.2.1.2 for more information.)
The data is arranged so that the application does not have to go back
up the hierarchy to the P level to find the next entry in the
hierarchy. If the C21 entry is not opened, the SVN demo code travels
down the C21 path to find the first sibling of C2. (If the C2 entry is
opened, the last child of C21, C212, has C22 as its sibling.)
9.2.1.1 Attaching to Data---The DXmSvnNattachToSourceCallback Callback
After you create an instance of the SVN widget, you must attach it to the data for the hierarchy. The attachment is done in the DXmSvnNattachToSourceCallback callback routine, which is invoked when the SVN widget is realized.
Your application's DXmSvnNattachToSourceCallback callback establishes the data in a parent/child/sibling hierarchy and then calls the DXmSvnAddEntries routine to specify the initial entries (and number of entries) in the hierarchy.
One of the required arguments to the DXmSvnAddEntries routine is the entry number after which to add the new entries, which for the initial entry is zero. In this way, the SVN widget refers to the first entry as number 1.
An application can also specify an application-specific entry_tag argument to be associated with the entry.
For example, the SVN demo application call to DXmAddEntries is as follows:
entry_tags[0] = (unsigned int) &B; DXmSvnAddEntries (svnw, 0, 1, 0, entry_tags, TRUE); |
This call adds one entry (starting after zero) with a level of zero. The address of the first entry in the data hierarchy, _Node, is passed as a tag, and the entry appears in the scroll index window (if activated) when the user drags the slider.
The DXmSvnNattachToSourceCallback callback does not provide information
about what the entries contain; that information is obtained by the
GetEntry callbacks.
9.2.1.2 Understanding the entry_number Field
Your application must be able to equate the entry_number field supplied in the callback with an entry in your data hierarchy.
The SVN widget numbering sequence is sequential, starting with 1. The number associated with subsequent entries depends on whether these entries are opened and have children or siblings. If an entry is opened and has children, the children are included in the entry numbers. Otherwise, only the siblings are included.
Consider the following example from the demo program. Assume the entry_number field in the callback has a value of 5.
entry_number 1 OSF/Motif Style Guide 2 1. User Interface Design Principles 3 2. Input and Navigation Models 4 3. Selection and Component Activation 5 4. Application Design Principles |
In this example, entry number 1 is opened and has children. However, the child of entry 1, "User Interface Design Principles", and that child's siblings are not opened. In this case, the entry_number value of 5 means that the user double clicked on "Application Design Principles".
If the user then double clicked on the child of entry 1, "User Interface Design Principles", and it had children, the possible entry numbers would be as follows:
entry_number 1 OSF/Motif Style Guide 2 1. User Interface Design Principles 3 1.1 Adopt the User's Perspective 4 1.2 Give the User Control 5 1.3 Use Real-World Metaphors 6 1.4 Keep Interfaces Natural 7 1.5 Keep Interfaces Consistent 8 1.6 Communicate Application Actions to the User 9 1.7 Avoid Common Design Pitfalls 10 2. Input and Navigation Models 11 3. Selection and Component Activation 12 4. Application Design Principles |
In this case, an entry_number value of 5 means that the user double clicked on "Use Real-World Metaphors".
The SVN demo application uses the following code to map the entry_number field, called node_number in the code, to a _Node data structure. (Do not confuse node_number with references in the code to the node->number field, which tells if there are children.)
. . . NodePtr LclGetNodePtr (node_number) int node_number; { int i; NodePtr current_node = &B; if (node_number != 1) for (i = 2; i <= node_number; i++) if (current_node == NULL) break; else if (current_node->opened) current_node = current_node->children; else current_node = current_node->sibling; return current_node; |
This code loops through, trying to find the fifth entry. Assume the
entry_number field in the callback has a value of 5.
The code would go through four parent/sibling tests (2 through 5). The
current_node field then contains the address of either
a child or sibling, depending on which entries were opened.
9.2.1.3 Getting Information About an Entry
Once the data is attached to the SVN widget, the SVN widget triggers DXmSvnNgetEntryCallback to get information associated with the first entry, such as the number of components and the text from the data hierarchy to associate with the entry. Note that DXmSvnNgetEntryCallback is triggered to get information about any entry in the hierarchy not just the first entry.
In the case of SVN demo application, the DXmSvnNgetEntryCallback callback routine performs the following functions:
Your application is responsible for linking the data in the hierarchy to entries in the SVN widget. To do this, your application callback routines call the DXmSvnAddEntries routine based on knowledge of the hierarchy data.
As described in Section 9.2.1.1, the top-level entry in the hierarchy is known by the SVN widget as entry number 1. When a user double clicks on this entry, the DXmSvnNselectAndConfirm callback is generated. The callback includes the entry_number of the entry, in this case 1. (The DXmSvnCallbackStruct callback data structure is described in Section 9.4.)
The callback indicates that the user wants to expand (or contract) this entry.
The demo SVN application's _Node data structure includes fields that track siblings (sibling), children (children), and whether or not the children of the element are expanded (opened). The DXmSvnNselectAndConfirm callback routine opens the entry if it is not already opened and calls the DXmSvnAddEntry routine to add any children that the element might have.
For example, when a user double clicks on entry number 1, the call to DXmSvnAddEntries is translated as follows:
DXmSvnAddEntries (Svn, node_number, node->number, node->level, NULL, FALSE); |
This call adds four children (node->number) to entry number 1 (node_number). The actual text of these entries is unspecified.
The SVN widget then calls your application's DXmSvnNgetEntry callback
routine for each displayed entry, as described in Section 9.2.1.3.
9.2.2 Disabling/Enabling the SVN Widget
Disabling an instance of the SVN widget prohibits the user from altering the selected entries and allows your application to modify the underlying data hierarchy. For the changes to appear as expected, your application must disable the SVN widget before calling the DXmSvnInvalidateEntry routine.
The following example disables the SVN widget, changes the label string associated with the menu entry, and enables the SVN widget.
void MenuToggleEditable() { /* ** Local data declarations */ XmString cs; Arg arguments[2]; /* ** Disable the widget. This would not be necessary if this routine was ** being called in response to an SVN callback. */ DXmSvnDisableDisplay (Svn); /* ** Turn it on or off... */ if (Editable) { cs = XmStringCreate("Editable Text", XmSTRING_DEFAULT_CHARSET); } else { cs = XmStringCreate("Non-editable Text", XmSTRING_DEFAULT_CHARSET); }; /* ** Change the label */ XtSetArg (arguments[0], XmNlabelString, cs); XtSetValues (editableEntry, arguments, 1); XmStringFree (cs); /* ** Tell the source module to make the change */ SourceToggleEditable(); /* ** Re-enable the SVN Widget. */ DXmSvnEnableDisplay (Svn); } |
Your application does not need to disable and enable the SVN widget in response to an SVN callback. The SVN widget automatically disables the widget prior to issuing the callback and automatically enables the widget upon return. |
Your application can set the DXmSvnNstartLocationCursor resource to specify which entry the location cursor should be first drawn on. By default, the location cursor begins on entry 1.
This resource can be set only when the SVN widget is created. An
application is not able to change the position of this location cursor
at any other time. If an XtSetValues is done on this resource, the
value is ignored.
9.2.4 Invalidating an Entry
Your application can invalidate an entry to force the SVN widget to update the entry. As described in Section 9.1.9, your application can call the SVN DXmSvnInvalidateEntry routine to update an entry. The DXmSvnInvalidateEntry routine in turn invokes your DXmSvnNgetEntryCallback callback routine to obtain the new information.
The DXmSvnInvalidateEntry routine therefore allows your application to generate DXmSvnNgetEntryCallbacks as needed.
For example:
/* ** Traverse tree and unmanage all editable fields and invalidate ** the entries. */ while (node_number <= SourceNumEntries) { node = LclGetNodePtr (1); if (node->stext) XtUnmanageChild(node->stext); DXmSvnInvalidateEntry(Svn, node_number); node_number++; }; |
For each entry, test to see if there is an associated CSText widget. If
there is, unmanage the widget and call DXmSvnInvalidateEntry to invoke
the DXmSvnNgetEntryCallback callback.
9.2.5 Setting a Tree Style
If your application is in tree mode, it can specify one of the following constants to set the DXmSvnNtreeStyle resource:
The following example sets the tree style to DXmSvnKtopTree:
cs = XmStringCreate("Top Tree Navigation", XmSTRING_DEFAULT_CHARSET); XtSetArg (arguments[0], DXmSvnNnavWindowTitle, cs); XtSetArg (arguments[1], DXmSvnNtreeStyle, DXmSvnKtopTree); XtSetValues (Svn, arguments, 2); XtFree (cs); |
Your application can specify one of the following constants to set the DXmSvnNdisplayMode resource:
The following example sets the display mode to DXmSvnKdisplayTree:
XtSetArg (arguments[0], DXmSvnNdisplayMode, DXmSvnKdisplayTree); XtSetValues (Svn, arguments, 1); |
Previous | Next | Contents | Index |