Creating and processing composite windows

This topic includes the following sections:

 

UI Toolkit enables you to combine multiple windows and/or lists into a single window, called a composite window. For example, you could create a composite window that includes an input window, a table, an ActiveX control, and buttons. To the user, a composite window looks and functions as a single window.

A composite window consists of a parent window (called the composite container window) and child windows or lists. A child can be any type of UI Toolkit window or list, including an ActiveX window, a tab set window, an ActiveX Toolkit list, or another composite window. The composite window routines and methods enable you to create and process composite windows. Note the following:

A composite window not only appears to users as a single, unified window, it is also treated in many ways as a single window by the application. Code that affects the container affects the composite window as a whole:

Composite window development steps

The following steps include example code to illustrate composite window development. For a more complete code example, see %C_CONTAINER.

1. Create the composite container window

Start by using the DC_CREATE subfunction for %C_CONTAINER to create the composite container window. The example below creates a composite container window that

Additionally, this example returns the ID of the new composite container window in the id_contain variable.

id_contain = %c_container(DC_CREATE, "", g_bdysiz, %w_info(WIF_SCOLS))
2. Add child windows and/or lists

To add child windows and lists to the composite window, use the DC_ADD subfunction for %C_CONTAINER. In this call, you specify the ID of the container window as well as the ID of the window or list you want to add as a child. Additionally, you can set properties for the child, including placement, tabbing position, and a menu column to be loaded when the child is processed. For example, the following adds a list that starts on the first column of the first row of the composite window and loads a menu column with the ID id_selcol:

xcall c_container(DC_ADD, id_contain, DC_LIST, id_list, 1, 1,,,,id_selcol)
3. Place the composite window

To place a composite window, place its container window. For example, the following call places the composite window whose container window has the window ID id_contain.

xcall u_window(D_PLACE, id_contain, 1, 1)

When a container window is placed, only child windows and lists that have been placed are displayed in the window. Unplaced child windows and lists remain invisible. Additionally, when you place a child, it remains invisible until its container window is placed. See Placing, removing, and deleting windows below for more information.

4. Process the composite window

To process a composite window, call C_PROCESS. This routine calls the method for the active child. Toolkit includes default composite window processing methods, but you can create your own methods and specify one in the DC_ADD call for a child. The following processing loop example tests for menu entries and calls C_PROCESS, which passes the variables chan_icontacts, chan_contacts, list_contact, and inp_contact to the method for the active child.

;
; do_process - run input loop for composite window
do_process,
    xcall c_process(id_contain, chan_icontacts, chan_contacts,
  &                 list_contact, inp_contact)
    if (g_select)
      begin
        using g_entnam select
("O_ADD "),     call add
("O_DEL "),     call delete
("O_SEL "),     call select
("O_EXIT "),    call update     ;Leaves g_select == TRUE
        endusing
      end
    return
5. Remove and delete windows

To remove a composite window, remove the composite container window with the D_REMOVE operation for U_WINDOW. Use D_REMOVE to remove child windows as well. For a child list, use L_REMOVE. See Placing, removing, and deleting windows below for more information.

Placing, removing, and deleting windows

When you place a child, the child remains invisible until the composite container window is placed. When you place a composite window (by placing its container), only child windows and lists that have already been placed will appear on the window. Note that a container and its child windows and lists don’t have to be logged in the same environment. When a container is placed, placed windows and lists will be displayed, even if they are logged in different environments.

To instruct Toolkit to remove a child from the screen, use the D_REMOVE operation for U_WINDOW or use L_REMOVE. Note the following:

To remove a child from the display and from the container, use the DC_REMOVE subfunction for %C_CONTAINER.

To remove a composite window from the screen, pass the composite container window ID to the D_REMOVE operation for U_WINDOW. Removing the composite container window makes all child windows and lists invisible, no matter which environments they are logged in.

To delete a composite window, delete its composite container window. To delete a composite container window or a child, leave the environment in which it was logged or use the D_DELETE operation for U_WINDOW. Note, however, that deleting the container removes all child windows and lists but does not delete them.

Processing composite windows

Once you have created and placed a composite window, you can process it by calling C_PROCESS, which in turn calls methods that process the child windows and lists. Toolkit includes default processing methods, but you can instruct C_PROCESS to call your own custom methods instead. See C_PROCESS and The composite window processing methods for more information.

Controlling tabbing, focus, and input context

When a composite window is being processed, tabbing moves through placed child windows and lists according to the composite window’s tabbing order, which by default is the order they were added to the composite window. Then, after child windows and lists, tabbing moves through any enabled buttons added to the composite container window.

Note

Every child window and list for a composite window has a tabbing index. This number specifies the child’s position in the tabbing order. Tabbing indices are base 1, so the first child for a composite window has a tabbing index of 1. (To get the tabbing index of a child, use the DC_CHILDINDEX subfunction for %C_CONTAINER.)

Buttons on the composite container window also have tabbing indices, which are also base 1.

You can do the following to control the tabbing order or activate a specific child or button:

Tabbing within child windows and lists

When processing a child window or list with L_INPUT, L_INPFLD, S_SELECT, T_EDIT, T_VIEW, or U_CHR, pressing Tab (or otherwise signaling the C_NEXT menu entry) moves focus to the first button for the window. Subsequent tabbing advances through remaining buttons for the window and then, if the window is on a tab, advances through buttons on the tab set. Finally, tabbing causes the input routine to return with g_select set to true and g_entnam set to “C_NEXT”, which instructs C_PROCESS to move focus to the next child window. Shift+Tab works the same way, but in reverse. It returns g_select set to true, but it sets g_entnam to “C_PREV” to move to the preceding child.

The above also applies to I_INPUT and I_INPFLD, except that

In any case, users will not be able to tab out of a window or list if the child processing method changes the value of g_entnamtab or g_entnamstab (defined in tkctl.def) and if the ActiveX control for a child ActiveX window processes Tab and Shift+Tab as an accelerator without returning it as a keystroke (see ActiveX controls and tabbing below).

Additionally, Toolkit includes several routines that enable you to control the context of a child window or list. All the following except I_NEXT and L_NEXT determine context based on the reason the child received focus. This enables child processing methods (the default methods and any methods you create) to provide an interface where users can smoothly tab through and click into composite windows.

Note that when processing tab sets, Ctrl+Tab and Ctrl+Shift+Tab apply to the innermost tab set. For example, if a tab set contains a composite window, and that composite window in turn contains a tab set, these key combinations apply to the inner tab set when the inner tab is being processed. When Toolkit is processing any other window in the composite window on the tab, they apply to the outer tab set. See %TS_TABSET for more information on navigating tab sets.

For Windows, note the following:

ActiveX controls and tabbing

There are a couple of situations in which tabbing may not automatically work seamlessly when a composite window includes an ActiveX control. The mechanisms for working around these issues are illustrated in ActiveX_Child_Tabbing, available from Synergy CodeExchange in the Synergex Resource Center.

Buttons in composite windows

To add buttons to a composite window, you can use B_BUTTON to add buttons to the container, and you can use B_BUTTON or L_BUTTON to add buttons to a child window or list. Note the following:

The default button

The following rules determine which button is the default for a composite window as a whole. Note that for usability and aesthetics, we recommend that you specify only one default button anywhere within a composite window — in other words, only one child window or list should have a default button (unless a default button is set for the composite container window). This prevents Toolkit from switching the default as context changes.

1. If the window being processed specifies a default button, and that button is enabled, that button becomes the default button for the composite window.
2. Otherwise, if the container for the active window specifies an enabled default button, that button becomes the default. If the container doesn’t specify an enabled default button, but is itself contained, the default button for its container shall be the default, and so forth.
3. If no default button can be determined by the above, the default for another descendant window of a common container may become the default for the composite window. This, of course, will only come into play if there are several layers of containment (composite windows within composite windows). In this case, Toolkit starts with the innermost child and, if it is unable to establish a default from that, moves to its container, its container’s container, and so forth.
4. If none of the above results in a default (i.e., if no default button is specified on any window with a common ancestor), the first button for the composite window becomes the default. The first button is determined according to the same hierarchy discussed in the previous rules. If the active window has a button, the first button on that window will be the default. If the active window doesn’t have a button, the first button on the active window’s container will be the default. If the parent has no button, the first button on the grandparent becomes the default, and so on. If none of these have buttons, the first button on a window that shares a common ancestor to the current window will be the default.

See the BUTTON_SET Discussion for more information on default buttons.

Alt+key button activation

The following rules determine which button, if any, will be activated by an Alt+key combination.

Tip

For usability and aesthetics, we recommend that only one button for each Alt+key combination be specified anywhere within a container. This prevents Toolkit from switching key associations as context changes.

1. If the window being processed contains an enabled button that specifies the entered key combination, Toolkit activates that button.
2. Otherwise, if the container for the active window has an enabled button that specifies the entered combination, Toolkit activates that button. If the container doesn’t have an enabled button for the key combination, but is itself contained, Toolkit uses the enabled button for the key combination on the container’s container, and so forth.
3. If no button is activated as a result of the above, Toolkit may activate a button that specifies the key combination in another descendant window of a common container. In this case, Toolkit starts with the innermost child and, if no button specifies the key combination in that window, moves to its container, its container’s container, and so forth.

Positioning composite windows, child windows, and lists

To position a composite window (as a whole), position the composite container window by using one of the following:

To control the placement of a child window or list, use one of the following. In all cases, settings are relative to the client area of the immediate parent.

Getting composite window information

The %C_CONTAINER function includes several subfunctions that enable you to get child and composite container window information. With %C_CONTAINER you can

Additionally, you can

Event methods

When a window or list is added to a composite window (even if it is part of tab set), its %UWNDEVENTS_METHOD set is replaced by one that handles mouse clicks in composite windows. The previously registered method set, however, is registered as a set of extensions to the new method set if there is a difference between the two. You can use the DC_EVENT subfunction for %C_CONTAINER to replace these extensions. (See the DC_EVENT Discussion for information on the default behavior and how to replace it.)

To determine if a method set has been registered for a UI Toolkit window and, if it has, what the ID for the method is, use the D_GETEVENTS subfunction for %U_WNDEVENTS.

To retrieve the address of a method routine for the specified event in the specified method set, use the DC_GETEVENT subfunction for %U_WNDEVENTS.

When a child is removed from its container, the %UWNDEVENTS_METHOD set for the child will remain as it was before the DC_REMOVE call, but the click event will no longer alter the container’s context.