Using Tab controls in scripts

This section provides examples of tabs in scripts:

Referring to tab pages in scripts

Dot notation allows you to refer to individual tab pages and controls on those tab pages:

  • The window or user object containing the Tab control is its parent:

    window.tabcontrol
  • The Tab control is the parent of the tab pages contained in it:

    window.tabcontrol.tabpageuo
  • The tab page is the parent of the control contained in it:

    window.tabcontrol.tabpageuo.controlonpage

For example, this statement refers to the PowerTips property of the Tab control tab_1 within the window w_display:

w_display.tab_1.PowerTips = TRUE

This example sets the PowerTipText property of tab page tabpage_1:

w_display.tab_1.tabpage_1.PowerTipText = &
   "Font settings"

This example enables the CommandButton cb_OK on the tab page tabpage_doit:

w_display.tab_1.tabpage_doit.cb_OK.Enabled = TRUE

Generic coding

You can use the Parent pronoun and GetParent function to make a script more general.

Parent pronoun

In a script for any tab page, you can use the Parent pronoun to refer to the Tab control:

Parent.SelectTab(This)

GetParent function

If you are in an event script for a tab page, you can call the GetParent function to get a reference to the tab page's parent, which is the Tab control, and assign the reference to a variable of type Tab.

In an event script for a user object that is used as a tab page, you can use code like the following to save a reference to the parent Tab control in an instance variable.

This is the declaration of the instance variable. It can hold a reference to any Tab control:

tab itab_settings

This code saves a reference to the tab page's parent in the instance variable:

// Get a reference to the Tab control
// "This" refers to the tab page user object
itab_settings = This.GetParent()

In event scripts for controls on the tab page, you can use GetParent twice to refer to the tab page user object and its Tab control:

tab tab_mytab
userobject tabpage_generic

tabpage_generic = This.GetParent()
tab_mytab = tabpage_generic.GetParent()

tabpage_generic.PowerTipText = &
   "Important property page"
tab_mytab.PowerTips = TRUE

tab_mytab.SelectTab(tabpage_generic)

Generic variables for controls have limitations

The type of these variables is the basic PowerBuilder object type -- a variable of type Tab has no knowledge of the tab pages in a specific Tab control and a variable of type UserObject has no knowledge of the controls on the tab page.

In this script for a tab page event, a local variable is assigned a reference to the parent Tab control. You cannot refer to specific pages in the Tab control because tab_settings does not know about them. You can call Tab control functions and refer to Tab control properties:

tab tab_settings
tab_settings = This.GetParent()
tab_settings.SelectTab(This)

User object variables

If the tab page is an independent user object, you can define a variable whose type is that specific user object. You can now refer to controls defined on the user object, which is the ancestor of the tab page in the control.

In this script for a Tab control's event, the index argument refers to a tab page and is used to get a reference to a user object from the Control property array. The example assumes that all the tab pages are derived from the same user object uo_emprpt_page:

uo_emprpt_page tabpage_current
tabpage_current = This.Control[index]
tabpage_current.dw_emp.Retrieve &
   (tabpage_current.st_name.Text)

The Tab control's Control property

The Control property array contains references to all the tab pages in the control, including both embedded and independent user objects. New tab pages are added to the array when you insert them in the painter and when you open them in a script.

Referring to controls on tab pages

If you are referring to a control on a tab page in another window, you must fully qualify the control's name up to the window level.

The following example shows a fully qualified reference to a static text control:

w_activity_manager.tab_fyi.tabpage_today. &
   st_currlogon_time.Text = ls_current_logon_time

This example from the PowerBuilder Code Examples sets the size of a DataWindow control on the tab page to match the size of another DataWindow control in the window. Because all the tab pages were inserted in the painter, the Control property array corresponds with the tab page index. All the pages are based on the same user object u_tab_dir:

u_tab_dir luo_Tab
luo_Tab = This.Control[newindex]
luo_Tab.dw_dir.Height = dw_list.Height
luo_Tab.dw_dir.Width = dw_list.Width

In scripts and functions for the tab page user object, the user object knows about its own controls. You do not need to qualify references to the controls. This example in a function for the u_tab_dir user object retrieves data for the dw_dir DataWindow control:

IF NOT ib_Retrieved THEN
   dw_dir.SetTransObject(SQLCA)
   dw_dir.Retrieve(as_Parm)
   ib_Retrieved = TRUE
END IF

RETURN dw_dir.RowCount()

Opening, closing, and hiding tab pages

You can open tab pages in a script. You can close tab pages that you opened, but you cannot close tab pages that were inserted in the painter. You can hide any tab page.

This example opens a tab page of type tabpage_listbox and stores the object reference in an instance variable i_tabpage. The value 0 specifies that the tab page becomes the last page in the Tab control. You need to save the reference for closing the tab later.

This is the instance variable declaration for the tab page's object reference:

userobject i_tabpage

This code opens the tab page:

li_rtn = tab_1.OpenTab &
   (i_tabpage, "tabpage_listbox", 0)

This statement closes the tab page:

tab_1.CloseTab(i_tabpage)

Keeping track of tab pages

To refer to the controls on a tab page, you need the user object reference, not just the index of the tab page. You can use the tab page's Control property array to get references to all your tab pages.

Control property for tab pages

The Control property of the Tab control is an array with a reference to each tab page defined in the painter and each tab page added in a script. The index values that are passed to events match the array elements of the Control property.

You can get an object reference for the selected tab using the SelectedTab property:

userobject luo_tabpage
luo_tabpage = tab_1.Control[tab_1.SelectedTab]

In an event for the Tab control, like SelectionChanged, you can use the index value passed to the event to get a reference from the Control property array:

userobject tabpage_generic
tabpage_generic = This.Control[newindex]

Adding a new tab page

When you call OpenTab, the control property array grows by one element. The new element is a reference to the newly opened tab page. For example, the following statement adds a new tab in the second position in the Tab control:

tab_1.OpenTab(uo_newtab, 2)

The second element in the control array for tab_1 now refers to uo_newtab, and the index into the control array for all subsequent tab pages becomes one greater.

Closing a tab page

When you call CloseTab, the size of the array is reduced by one and the reference to the user object or page is destroyed. If the closed tab was not the last element in the array, the index for all subsequent tab pages is reduced by one.

Moving a tab page

The MoveTab function changes the order of the pages in a Tab control and also reorders the elements in the control array to match the new tab order.

Control property array for user objects

The Control property array for controls in a user object works in the same way.

Creating tab pages only when needed

The user might never look at all the tab pages in your Tab control. You can avoid the overhead of creating graphical representations of the controls on all the tab pages by checking Create on Demand on the Tab control's General property page or setting the CreateOnDemand property to TRUE.

The controls on all the tab pages in a Tab control are always instantiated when the Tab control is created. However, when Create on Demand is checked, the Constructor event for controls on tab pages is not triggered and graphical representations of the controls are not created until the user views the tab page.

Constructor events on the selected tab page

Constructor events for controls on the selected tab page are always triggered when the Tab control is created.

Tradeoffs for Create on Demand

A window will open more quickly if the creation of graphical representations is delayed for tab pages with many controls. However, scripts cannot refer to a control on a tab page until the control's Constructor event has run and a graphical representation of the control has been created. When Create on Demand is checked, scripts cannot reference controls on tab pages that the user has not viewed.

Whether a tab page has been created

You can check whether a tab page has been created with the PageCreated function. Then, if it has not been created, you can trigger the constructor event for the tab page using the CreatePage function:

IF tab_1.tabpage_3.PageCreated() = FALSE THEN
      tab_1.tabpage_3.CreatePage()
END IF

You can check whether a control on a tab page has been created by checking whether the control's handle is nonzero. If so, the control has been created.

IF Handle(tab_1.tabpage_3.dw_list) > 0 THEN ...

Changing CreateOnDemand during execution

If you change the CreateOnDemand property to FALSE in a script, graphical representations of any tab pages that have not been created are created immediately.

It does not do any good to change CreateOnDemand to TRUE during execution, because graphical representations of all the tab pages have already been created.

Creating tab pages dynamically

If CreateOnDemand is FALSE, you can set the label for a dynamically created tab page in its Constructor event, using the argument to OpenTabWithParm that is passed to the Message object. If CreateOnDemand is TRUE, you need to set the label when the tab page is instantiated, because the Constructor event is not triggered until the tab is selected. The following script in a user event that is posted from a window's open event opens five tab pages and sets the label for each tab as it is instantiated:

int li_ctr
string is_title
THIS.setredraw(false)

FOR li_ctr = 1 to 5
   is_title = "Tab#" + string(li_ctr)
   tab_test.opentabwithparm(iuo_tabpage[li_ctr], &
      is_title, 0)
iuo_tabpage[li_ctr].text = is_title //set tab label
NEXT

THIS.setredraw(true)
RETURN 1

Events for the parts of the Tab control

With so many overlapping pieces in a Tab control, you need to know where to code scripts for events.

To respond to actions in the

Write a script for events belonging to

Tab area of the Tab control, including clicks or drag actions on tabs

The Tab control

Tab page (but not the tab)

The tab page (for embedded tab pages) or the user object (for independent tab pages)

Control on a tab page

That control


For example, if the user drags to a tab and you want to do something to the tab page associated with the tab, you need to code the DragDrop event for the Tab control, not the tab page.

Examples

This code in the DragDrop event of the tab_1 control selects the tab page when the user drops something onto its tab. The index of the tab that is the drop target is an argument for the DragDrop event:

This.SelectTab( index )

The following code in the DragDrop event for the Tab control lets the user drag DataWindow information to a tab and then inserts the dragged information in a list on the tab page associated with the tab.

A user object of type tabpage_listbox that contains a ListBox control, lb_list, has been defined in the User Object painter. The Tab control contains several independent tab pages of type tabpage_listbox.

You can use the index argument for the DragDrop event to get a tab page reference from the Tab control's Control property array. The user object reference lets the script access the controls on the tab page.

The Parent pronoun in this script for the Tab control refers to the window:

long ll_row
string ls_name
tabpage_listbox luo_tabpage

IF TypeOf(source) = DataWindow! THEN
   l_row = Parent.dw_2.GetRow()
   ls_name = Parent.dw_2.Object.lname.Primary[ll_row]

   // Get a reference from the Control property array
   luo_tabpage = This.Control[index]

   // Make the tab page the selected tab page
   This.SelectTab(index)

   // Insert the dragged information
   luo_tabpage.lb_list.InsertItem(ls_name, 0)

END IF

If the tab page has not been created

If the CreateOnDemand property for the Tab control is TRUE, the Constructor events for a tab page and its controls are not triggered until the tab page is selected. In the previous example, making the tab page the selected tab page triggers the Constructor events. You could also use the CreatePage function to trigger them:

IF luo_tabpage.PageCreated() = FALSE THEN &
luo_tabpage.CreatePage()