Tab Panel Component

The VkTabPanel class, derived from VkComponent, displays a row or column of overlaid tabs. A tab can contain text, a pixmap, or both. The user can click on a tab with the left mouse button to select it. One tab is always selected, and appears on top of all the others. When the user selects a tab, VkTabPanel activates an ObjectPak member function callback indicating which tab the user selected. You can register callback functions to perform actions based on the tabs selected.

Figure 54. shows an example of a horizontal VkTabPanel component.

Figure 54. Example of a Horizontal VkTabPanel Component

Figure 55. shows an example of a vertical VkTabPanel component.

Figure 55. Example of a Vertical VkTabPanel Component

Collapsed tabs

When the tabs do not fit within the provided space, the VkTabPanel object "collapses" tabs on the left and right ends of the component (or top and bottom if the VkTabPanel object is vertical). The example in Figure 56. shows these collapsed tabs.

Figure 56. Collapsed Tabs in a VkTabPanel Component

Selecting a tab with the popup menu

The user can click on the collapsed tabs with either the left or right mouse button to display a popup menu listing all the tabs, as shown in Figure 57.. The user can then select a tab by choosing the corresponding menu item.

Figure 57. Selecting a Collapsed Tab in a VkTabPanel Component with the Popup Menu

The VkTabPanel class also provides work areas implemented as OSF/Motif Form widgets to the left and right of the tab display (or top and bottom if the VkTabPanel object is vertical). By default, these work areas are empty. You can access these work area widgets and implement additional displays or controls if you desire. "Tab Panel Access Functions" describes the work area access functions.

Tab Panel Constructor

The VkTabPanel constructor initializes the tab panel and allocates all resources required by the component:

VkTabPanel(char* name, Widget parent,
Boolean horizOrientation = TRUE, int tabHeight = 0)

name and parent are the standard component name and parent widget arguments.

Optional arguments

The optional horizOrientation argument determines the orientation of the tab panel. If horizOrientation is TRUE, the tab panel is horizontal; if it is FALSE, the tab panel is vertical.

The optional tabHeight argument determines the height of the tab display area. The default value, 0, indicates that tab height is determined by the default label height. If you plan to include pixmaps in your tabs, you should specify a height sufficient to contain your largest pixmap. You can also set the tab height by setting the value of the VkTabPanel object's "tabHeight" resource. For example, to set the tab height of the VkTabPanel object tabs to 30, you could include the following line in an app-default file:

*tabs*tabHeight: 30

Note: In most cases when you display a vertical tab panel, you must explicitly set the height of the tab display area. As described above, the default tab display area height is determined by the tab label's font height rather than the width of the label. As a result, the tabs might not be large enough to display all of the label text.


Adding Tabs to a Tab Panel

Once you have created a tab panel, you can add a tab to it using VkTabPanel::addTab():

int addTab(char *label, void *clientData, Boolean sorted = FALSE)

label specifies the label displayed by the tab. You should use a distinct label for each tab. addTab() first treats this argument as a resource name which is looked up relative to the tab panel's name. If the resource exists, its value is used as the tab label. If no resource is found, or if the string contains spaces or newline characters, the string itself is used as the tab label.

When the user selects this tab, the VkTabPanel object activates either VkTabPanel::tabSelectCallback or VkTabPanel::tabPopupCallback (depending on how the user selected the tab). If you provide a pointer to some data as the clientData argument to addTab(), the tab panel includes that data as part of the VkTabCallbackStruct returned as call data by the callbacks. "Responding to Tab Selection" describes in depth these callbacks and how to use them.

The sorted flag determines where the new tab is added in relation to existing tabs. If sorted is FALSE, addTab() adds the tab after all existing tabs; if sorted is TRUE, addTab() inserts the tab before the first tab whose label alphabetically succeeds the new tab's label.


Note: addTab() compares the labels actually displayed in the tabs, so if you use resources to specify tab labels, addTab() correctly uses the labels specified by the resource values.


Return value of addTab()

The return value of addTab() is the position of the newly-added tab in the tab panel. Tabs are numbered sequentially, with 0 representing the left-most tab in a horizontal tab panel or the top-most tab in a vertical tab panel.

New tabs

New tabs initially have a NULL pixmap. (To add a pixmap to a label, refer to "Adding a Pixmap to a Tab" .) If the new tab is the first tab in the group, addTab() automatically selects the tab by calling VkTabPanel::selectTab(). selectTab() activates VkTabPanel::tabSelectCallback, so if you register a callback function before adding a tab, you activate that callback function when you add your first tab. Refer to "Responding to Tab Selection" for more information.

Adding more than one tab

You can add more than one tab at a time using VkTabPanel::addTabs():

void addTabs(char **labels, void **clientDatas, int numTabs,
Boolean sorted = FALSE)

labels is an array of tab label strings. As with addTab(), these label strings are first treated as resource names which are looked up relative to the tab panel's name. If the resources exist, their values are used as the tab labels. If a particular resource name is not found, or if the string contains spaces or newline characters, the label string itself is used as the tab label. clientDatas is an array of client data; the data for a particular tab is included as part of the VkTabCallbackStruct returned as call data by the selection callbacks. numLabels specifies the number of tabs to be added by addTabs(). sorted determines whether or not the tabs are sorted as addTabs() adds them.

Removing a Tab from a Tab Panel

To remove a tab from a tab panel, use VkTabPanel::removeTab():

Boolean removeTab(int index)
Boolean removeTab(char *label)

Specify the tab to remove using either its position index or its label. If removeTab() removes the tab, it returns TRUE. Otherwise, if the position index is out of range or cannot find a tab with the specified label string, it returns FALSE.


Note: If you use the same label for two or more tabs and provide a label string to removeTab(), it removes the first tab (the tab with the lowest index) that matches the label string. In general, avoid using duplicate label strings.


Adding a Pixmap to a Tab

To set or change a pixmap associated with a tab, use VkTabPanel::setTabPixmap():

Boolean setTabPixmap(int index, Pixmap pixmap)
Boolean setTabPixmap(char *label, Pixmap pixmap)

You can specify the tab using either its position index or its label. If setTabPixmap() successfully sets the tab, it redraws the tabs and returns TRUE. Otherwise, if the position index was out of range or it couldn't find a tab with the label string you specified, it returns FALSE. Pixmap can be either a bitmap (Pixmap of depth 1) or a full color Pixmap.


Note: If you use the same label for two or more tabs and provide a label string to setTabPixmap(), it sets the pixmap for the first tab (the tab with the lowest index) that matches the label string. In general, avoid using duplicate label strings.


Removing and existing pixmap

To remove an existing pixmap from a tab, call setTabPixmap() with a NULL pixmap.

You can retrieve the pixmap currently installed in a tab using VkTabPanel::tabPixmap():

Boolean tabPixmap(int index, Pixmap *pixmap_return)
Boolean tabPixmap(char *label, Pixmap *pixmap_return)

You can specify the tab using either its position index or its label. If tabPixmap() is successful, the function returns TRUE and the value of the pixmap_return argument is set to point to the tab's pixmap; otherwise, if the position index was out of range or the function couldn't find a tab with the label string you specified, tabPixmap() returns FALSE.

Responding to Tab Selection

Selecting a tab

The user can select a tab using either of the following methods:

  1. By clicking on a tab with the left mouse button
  2. By clicking on a group of collapsed tabs with either the left or right mouse button and choosing a menu item corresponding to a tab.

When the user selects a tab, the VkTabPanel object activates its VkTabPanel::tabSelectCallback. You can register callback functions to perform actions based on the tabs selected. When activated, tabSelectCallback provides a pointer to a VkTabCallbackStruct as call data. The format of VkTabCallbackStruct is as follows:

typedef struct {
char *label;
void *clientData;
int tabIndex;
XEvent *event;
} VkTabCallbackStruct

Arguments

label is the label displayed by the tab. Note that if you set the label by specifying a resource name when you added this tab, the value of label is the value of the resource you specified.

clientData is the client data you provided when you added this tab to the tab panel.

tabIndex is the position index of the tab. Tabs are numbered sequentially, with 0 representing the left-most tab in a horizontal tab panel or the top-most tab in a vertical tab panel.

If the user selected the tab directly (that is, not through the popup menu), event is the ButtonPress event that triggered the selection. Otherwise, event is NULL.

In your callback function, cast the call data to (VkTabCallbackStruct *), determine which tab the user selected, and perform the appropriate action.

The VkTabPanel object also detects when the user clicks the right mouse button on one of the tabs. Doing so does not select the tab, but it does cause VkTabPanel to activate its VkTabPanel::tabPopupCallback. When activated, tabPopupCallback provides a pointer to a VkTabCallbackStruct as call data. You can register callback functions to handle this event and perform any actions that you want.

To programmatically select a tab, use VkTabPanel::selectTab():

Boolean selectTab(int index, XEvent *event = NULL);
Boolean selectTab(char *label, XEvent *event = NULL);

Specifying a tab to use its position index or label

To specify the tab to select using either its position index or its label. If selectTab() successfully selects the tab, it returns TRUE. Otherwise, if the position index is out of range or it can't find a tab with the label string you specified, it returns FALSE.


Note: If you use the same label for two or more tabs and provide a label string to selectTab(), it selects the first tab (the tab with the lowest index) that matches the label string. In general, avoid using duplicate label strings.


You can optionally provide an event argument that selectTab() places in a VkTabCallbackStruct structure, which is then passed as call data to tabSelectCallback.

You can also determine the currently selected tab with VkTabPanel::selectedTab():

int selectedTab()

selectedTab() returns the index of the currently selected tab. Tabs are numbered sequentially, with 0 representing the left-most tab in a horizontal tab panel or the top-most tab in a vertical tab panel.

Tab Panel Access Functions

VkTabPanel provides several functions for accessing information about a tab panel and its tabs:

  • VkTabPanel::getTab() retrieves information about a specific tab. Specify the position index of the tab with the index argument. getTab() sets the value of the label_return argument to point to the tab's label. Note that if you set the label by specifying a resource name when you added this tab, the value of label_return is the value of the resource you specified. getTab() sets the value of the clientData_return argument to point to the client data you provided when you added the tab.

    getTab() returns TRUE if it is successful, and FALSE if the position index was out of range.

    Boolean getTab(int index, char **label_return,

    void **clientData_return)

  • VkTabPanel::horiz() returns TRUE if the tab component is horizontally oriented, and FALSE if it is vertically oriented.
    Boolean horiz()

  • VkTabPanel::size() returns the number of tabs in the tab panel.
    int size()

  • VkTabPanel::tabHeight() returns the height of the tab display area. This is the maximum display height for pixmaps. Larger pixmaps are truncated, and smaller pixmaps are centered. The height of the tab display area is determined by the following conditions:

Determining height of tab

    1. Value you specify in the VkTabPanel constructor.
    2. Value of the VkTabPanel component's "tabHeight" resource.
    3. Value of the "height" resource of the "tabLabel" widget created by VkTabPanel.
    4. Height of the tab label's font as specified by the "fontList" resource of the "tabLabel" widget created by VkTabPanel.

      If you attempt to set the tab height through multiple methods, method 1 has the highest precedence and method 4 has the lowest.


      Note: In most cases when you display a vertical tab panel, you must explicitly set the height of the tab display area. As described above, the default tab display area height is determined by the tab label's font height rather than the width of the label. As a result, the tabs might not be large enough to display all of the label text.

Calculating total height of a tab

The total height of a tab, including decoration, is the sum of the following conditions:

    1. The height of tab display area as returned by tabHeight() plus
    2. The tab's top and bottom margin (determined by value of marginHeight resource of the tabLabel widget created by VkTabPanel) plus
    3. The value of the additionalMarginHeight resource of the VkTabPanel component.

      The total height of the VkTabPanel component (or width, if the tab panel is horizontal) is the total height of the tab as described in the preceding conditions, plus the value of the VkTabPanel component's "margin" resource.

      int tabHeight()

  • VkTabPanel::uniformTabs() returns TRUE if the tabs have a uniform width (or height, if the tab panel is vertical). By default, tabs take on the width necessary to display their label and pixmap. You can force all tabs to take the width of the largest tab in the group by setting the VkTabPanel component's "uniformTabs" resource to TRUE.

    The total width of a tab, including decoration, is: 1) the width of the tab label; plus 2) if the tab has a pixmap installed, the width of the pixmap plus the pixmap spacing, determined by the value of the VkTabPanel component's "pixmapSpacing" resource; plus 3) the tab's left and right margin, determined by the value of the "marginWidth" resource of the "tabLabel" widget created by VkTabPanel plus the value of the VkTabPanel component's "additionalMarginWidth" resource.

    Boolean uniformTabs()

  • VkTabPanel::lineThickness() returns the line thickness used when drawing the tab edges. The line thickness defaults to 1. You can set this value through the "lineThickness" resource of the VkTabPanel component, but a line thickness other than 1 might not render properly.
    int lineThickness()

  • VkTabPanel::tabBg() returns the color used for the background area around the tabs. This color is set by the "background" resource of the VkTabPanel component.
    Pixel tabBg()

  • VkTabPanel::labelFg() returns the color used for tab foregrounds (that is, the tab lettering and the foreground bits if the pixmap you supply is a bitmap). This color is set by the "foreground" resource for the "tabLabel" widget created by VkTabPanel.
    Pixel labelFg()

  • VkTabPanel::labelBg() returns the color used for tab backgrounds. This color is set by the "background" resource for the "tabLabel" widget created by VkTabPanel. When a bitmap is supplied as the pixmap, this color is used for the background bits.
    Pixel labelBg()

  • VkTabPanel::gc() returns X graphics context used for drawing the tabs. This might be useful if you create pixmaps and want to use the same foreground and background colors as the tabs.
    GC gc()

  • VkTabPanel::area1() returns work area widget to the left of the tab display (or top if the tab panel is vertical), and VkTabPanel::area2() returns the work area widget to the right of the tab display (or bottom if the tab panel is vertical). Both work areas are implemented as OSF/Motif Form widgets. By default, work areas are empty. Access work area widgets and implement additional displays as desired.
    Widget area1()

    Widget area2()

X Resources Associated with the Tab Panel Component

Determining component display characteristics

The VkTabPanel class provides X resources that determine the display characteristics of the component The following table lists and describes the available resources:

 

 

X Resource

Description

additionalMarginHeight

Additional height, expressed in pixels, added to margin between top and bottom of tab border and tab display area (default value 2).

additionalMarginWidth

Additional width, expressed in pixels, added to margin between sides of tab border and the tab display area (default value 4).

background

Background color of VkTabPanel component, shown in space around tabs.

endMultiplier

Number of overlapped tab symbols displayed as an "end indicator" when there are more tabs in panel than can be displayed at one time (default value 3).

endSpacing

Space, expressed in pixels, between overlapped tab symbols in the "end indicator" (default value 9).

lineThickness

Line thickness used when drawing the tab edges. Default value is 1. You can provide another value, but line thickness other than 1 might not render properly.

margin

Margin, expressed in pixels, between tab edges and component edge (default value 5).

margin1

Margin, expressed in pixels, between left or top work area widget and tabs (default value 5).

margin2

Margin, expressed in pixels, between right or bottom work area widget and tabs (default value 5).

pixmapSpacing

If tab contains a pixmap, the space, expressed in pixels, between the tab label and the pixmap (default value 3).

selectedTabBackground

Background color of the selected tab.

sideOffset

Amount of tab overlap, expressed in pixels (default value 17).

tabHeight

Height of tab display area determined by the following methods:

1. Value you specify in the VkTabPanel constructor

2. Value of the VkTabPanel component's "tabHeight" resource

3. Value of height" resource of the "tabLabel" widget created by VkTabPanel

4. Height of tab label's font as specified by the "fontList" resource of the "tabLabel" widget created by VkTabPanel.

If you attempt to set tab height via multiple methods, method 1 has highest precedence and method 4 the lowest. Default value of "tabHeight" is 0.

uniformTabs

Determines whether all tabs have the same width. The default value, FALSE, allows tabs to be wide enough to display their label and pixmap. You can force all tabs to take the width of the largest tab in the group by setting this resource to TRUE.

 

 

Determining tabLabel display resources

The VkTabPanel class creates a widget called "tabLabel" to manage the tabs in a tab panel. VkTabPanel provides X resources that determine display characteristics of the "tabLabel" widget. The following table lists and describes these resources:

 

 

X Resource

Description

tabLabel.background

Color used for tab backgrounds. When a bitmap is supplied as the pixmap, this color is used for background bits.

tabLabel.fontList

Font used for tab labels. If the values of the "tabLabel.height" and "tabHeight" resources are 0, and you do not specify a tab height in the VkTabPanel constructor, the height of the font is also used as the height of the tab display area.

tabLabel.foreground

Color used for tab foregrounds (tab lettering and foreground bits if pixmap a bitmap).

tabLabel.height

Height of tab display area determined by the following methods:

1. Value you specify in the VkTabPanel constructor

2. Value of the VkTabPanel component's "tabHeight" resource

3. Value of the "height" resource of the "tabLabel" widget created by VkTabPanel

4. Height of the tab label's font as specified by fontList" resource of tabLabel" widget created by VkTabPanel.

If you attempt to set tab height via multiple methods, method 1 has the highest precedence and method 4 the lowest. Default value of "tabLabel.height" is 0.

tabLabel.marginHeight

Margin, in pixels, between top and bottom of tab border and tab display area.

tabLabel.marginWidth

Margin, in pixels, between sides of tab border and tab display area.