Working with RibbonBar

A RibbonBar control enables you to create ribbons which are a modern way of organizing user commands in user interfaces. A ribbon can replace the traditional menu bar and toolbars with tabbed pages (called Category); and each Category splits into Panels that contain individual or groups of LargeButton (with or without RibbonMenu), SmallButton (with or without RibbonMenu), CheckBox, ComboBox, TabButton (with or without RibbonMenu), and Spin (currently unsupported).

Introduction to RibbonBar items

A RibbonBar control is composed of the following items. It is recommended that you use the RibbonBar Builder to create the RibbonBar control (see the next section Creating a RibbonBar using RibbonBar Builder for details). You can also write scripts to create the RibbonBar control and the items that composes the control. For details, refer to the section called “RibbonBar control” in Objects and Controls.

Category

The category is a tab page that organize the functions of the application.

A RibbonBar control can contain one or more categories; a category can contain one or more panels:

RibbonBar > Category > Panel > ... (view ribbon hierarchy)

The following image shows that the RibbonBar control contains three categories: Home, Workspaces, and View.


For properties/functions of the Category, see the section called “RibbonCategoryItem control” in Objects and Controls. This control has no events or user events.

Panel

The panel is used to split the commands in a category into different groups.

A panel must be placed in a category; and a panel can contain individual or groups of CheckBox, ComboBox, LargeButton, and SmallButton:

RibbonBar > Category > Panel > [Group >] CheckBox/ComboBox/LargeButton/SmallButton (view ribbon hierarchy)

The following image shows that the Home category contains four panels: Tabs, Boards, Actions, and Print.


A panel is collapsed automatically (with a drop-down arrow) if there is not enough space to completely display all of the items in the panel, for example when the user shrinks the width of the window. You cannot control when the panel should be collapsed (there is no property or function to set the collapsed mode for a panel). But you can specify which picture will display (using the PictureName property of the panel) when the panel is collapsed.


For properties/functions of the Panel, see the section called “RibbonPanelItem control” in Objects and Controls. This control has no events or user events.

Group

The group organizes related commands and controls within the same area.

A group must be placed in a panel, and a group can contain one or more CheckBox, ComboBox, and SmallButton, but cannot contain LargeButton:

RibbonBar > Category > Panel > Group > CheckBox/ComboBox/SmallButton (view ribbon hierarchy)


For properties/functions of the Group, see the section called “RibbonGroupItem control” in Objects and Controls. This control has no events or user events.

ComboBox

The combo box contains a list box that displays available choices.

A ComboBox can be placed in a group or panel: RibbonBar > Category > Panel [> Group] > ComboBox (view ribbon hierarchy)


For properties/functions of the ComboBox, see the section called “RibbonComboBoxItem control” in Objects and Controls. The Ribbon ComboBox control has no events. But you can create the Modified user event, the Selected user event, and the SelectionChanged user event and bind them with this control. For details, see Modified in PowerScript Reference, Selected in PowerScript Reference, and SelectionChanged in PowerScript Reference.

CheckBox

The check box provides a toggle state of an option.

A CheckBox can be placed in a group or panel: RibbonBar > Category > Panel [> Group] > CheckBox (view ribbon hierarchy)


For properties/functions of the CheckBox, see the section called “RibbonCheckBoxItem control” in Objects and Controls. The Ribbon CheckBox control has no events. But you can create the Clicked user event and the Selected user event and bind them with this control. For details, see Clicked in PowerScript Reference and Selected in PowerScript Reference.

LargeButton

A large button displays an image of 32 * 32 pixels.

A LargeButton can be placed in the panel only; and it can be associated with a ribbon menu:

RibbonBar > Category > Panel > LargeButton [> RibbonMenu > RibbonMenuItem] (view ribbon hierarchy)


For properties/functions of the LargeButton, see the section called “RibbonLargeButtonItem control” in Objects and Controls. The Ribbon LargeButton control has no events. But you can create the Clicked user event and the Selected user event and bind them with this control. For details, see Clicked in PowerScript Reference and Selected in PowerScript Reference.

SmallButton

A small button displays an image of 16 * 16 pixels.

A SmallButton can be placed in a group or panel; and it can be associated with a ribbon menu:

RibbonBar > Category > Panel [> Group] > SmallButton [> RibbonMenu > RibbonMenuItem] (view ribbon hierarchy)


For properties/functions of the SmallButton, see the section called “RibbonSmallButtonItem control” in Objects and Controls. The Ribbon SmallButton control has no events. But you can create the Clicked user event and the Selected user event and bind them with this control. For details, see Clicked in PowerScript Reference and Selected in PowerScript Reference.

RibbonMenu

A ribbon menu is a drop-down list of related commands for a button. A ribbon menu can be associated with the large button, the small button, or the tab button:

RibbonBar > Category > Panel > [Group >] LargeButton/SmallButton > RibbonMenu > RibbonMenuItem (view ribbon hierarchy)

RibbonBar > TabButton > RibbonMenu > RibbonMenuItem (view ribbon hierarchy)

The menu item with the "Normal" or "Separator" type (that is RibbonMenuItem with ItemType 0 or 1) can be added to RibbonMenu. A "Separator" menu item is a horizontal line used to visually distinguish between groups of menu items. RibbonMenu can contain menu items in no more than two levels. If a RibbonMenu contains menu items in more than two levels, the ribbon XML editor will display an error message similar to: "The element cannot contain text. Content model is empty."

The following image shows that the History large button is associated with a menu.


For properties/functions of the RibbonMenu, see the section called “RibbonMenu control” in Objects and Controls. This control has no events or user events.

For properties/functions of the RibbonMenuItem, see the section called “RibbonMenuItem control” in Objects and Controls. The RibbonMenuItem control has no events. But you can create the Clicked user event and the Selected user event and bind them with this control. For details, see Clicked in PowerScript Reference and Selected in PowerScript Reference.

TabButton

The tab button is normally displayed at the top right corner of the RibbonBar control which provides access to the application-level settings such as minimize, help, etc. A tab button can show text if you specify no picture for it.

A RibbonBar control can contain one or more tab buttons; and a tab button can be associated with a ribbon menu:

RibbonBar > TabButton [> RibbonMenu > RibbonMenuItem] (view ribbon hierarchy)


For properties/functions of the TabButton, see the section called “RibbonTabButtonItem control” in Objects and Controls. The Ribbon TabButton control has no events. But you can create the Clicked user event and the Selected user event and bind them with this control. For details, see Clicked in PowerScript Reference and Selected in PowerScript Reference.

ApplicationButton

The application button is normally displayed at the top left corner of the RibbonBar control which provides end users with easy access to the main menu of your application.

Only one application button is allowed in a ribbon bar, therefore, you can get, set, or remove the application button without needing to insert the application button first or identify the application button by its handle. The application button must be associated with an application menu.

RibbonBar > ApplicationButton > ... (view ribbon hierarchy)

The following image shows that the RibbonBar control contains a "MyApp" application button.


For properties/functions of the ApplicationButton, see the section called “RibbonApplicationButtonItem control” in Objects and Controls. This control has no events or user events.

ApplicationMenu

The application menu is the main menu of your application; it usually contains two menus: a master menu on the left and a recent menu on the right. The application menu is associated with the application button.

RibbonBar > ApplicationButton > ApplicationMenu > RibbonMenuItem (view ribbon hierarchy)

  • Master menu -- The master menu is a pane in the application menu that displays the main menu items for an application. The menu item with the "Normal" or "Separator" type (that is RibbonMenuItem with ItemType 0 or 1) can be added as a master menu item. A "Separator" menu item is a horizontal line used to visually distinguish between groups of menu items.

    The master menu can have no more than two levels. If the master contains menu items in more than two levels, the ribbon XML editor will display an error message similar to: "The element cannot contain text. Content model is empty."

  • Recent menu -- The recent menu is a pane in the application menu that displays the most recently used items for an application. You can specify a text title for the recent menu (using the SetRecentTitle function), for example, "Recent Items", "Recently Opened Windows" etc.

    The menu item with the "Recent" type (that is RibbonMenuItem with ItemType 2) can be added as a recent menu item. The recent menu item will not show picture even if you have specified a picture for it (using the PictureName property of RibbonMenuItem). No separator line can be added to the recent menu.

    The recent menu can have only one level; and can contain no more than 9 items.


For properties/functions of the ApplicationMenu, see the section called “RibbonApplicationMenu control” in Objects and Controls. This control has no events or user events.

For properties/functions of the RibbonMenuItem, see the section called “RibbonMenuItem control” in Objects and Controls. The RibbonMenuItem control has no events. But you can create the Clicked user event and the Selected user event and bind them with this control. For details, see Clicked in PowerScript Reference and Selected in PowerScript Reference.

RibbonBar Header

The RibbonBar header is not an individual control; it is the area composed of the application button title, the category title, and the tab header on the same horizontal level.

The header can be set to invisible (by using the HideTabHeader property), and the RibbonBar can be minimized to display the header only (by using the SetMinimized function). When the RibbonBar is minimized, the HideTabHeader property cannot be set to TRUE. When the HideTabHeader property is set to TRUE, the SetMinimized function will not take effect.

For more, see the section called “SetMinimized” in PowerScript Reference and the section called “HideTabHeader” in Objects and Controls.


Creating a RibbonBar using RibbonBar Builder

It is recommended that you use RibbonBar Builder to create the source of a RibbonBar control and then use the source to create the RibbonBar control in the application.

RibbonBar Builder provides a graphical UI of the RibbonBar control template and the corresponding XML scripts in an editor, to help you quickly create your own source of a ribbon bar.

To launch the RibbonBar Builder, select Tools > RibbonBar Builder from the menu bar in the PowerBuilder IDE.

To open the RibbonBar control template in the RibbonBar Builder, click the Open Template button on the toolbar of the RibbonBar Builder.



Using the RibbonBar Builder

You can directly adjust the scripts in the XML editor to design your own RibbonBar control and preview the UI on the fly. Every change you make to the XML script is immediately reflected in the Preview pane. The RibbonBar Builder allows you to:

  • Create or open the XML or JSON scripts of a RibbonBar control

    To create a new XML file, click New File.

    To open an existing XML file, click Open File.

    To open the default XML template of RibbonBar, click Open Template.

    To import XML scripts from a JSON file and display the XML scripts in the XML editor, click Import from JSON.

  • Save the current RibbonBar as an XML or JSON file, or as a PowerBuilder string.

    To save the XML scripts to an XML file, click the Save File or Save As button.

    To save the XML scripts to a JSON file, click the Export to JSON button.

    To save the XML scripts to a PowerBuilder string, click the Copy as a PB String button.

  • Search or replace text for the ribbon bar controls in the XML editor

    Click the Search button from the toolbar or directly press Ctrl+F to display the search box. You can search for or replace text in the search box.

  • Set property values in the XML editor

    Select to modify the property value, or input "=" after a property, the editor aromatically displays a list of values for the property.

  • Insert images

    Method 1: Place the cursor in the value of the PictureName property, or double click to select the value of the PictureName property, and then click the Select Image button from the toolbar.

    Method 2: In the Select Image dialog, select to use a custom image or a built-in image. The selected image name will be inserted into the value of the PictureName property.

  • Edit the ribbon bar controls

    To insert a control, right click where you want to insert the control in the XML editor; the editor will display a list of controls that can be inserted in the current position. As shown in the following figure, if you right click after <RibbonItems>, you will be prompted to select from the following options: ApplicationButton, Categories, and TabButtons.


    You can also copy/paste the corresponding XML node to reuse the XML scripts for a control.

    To remove a control, simply remove the corresponding XML node.

  • Customize the RibbonBar Builder

    The Option button on the toolbar provides a number of settings for you to customize the RibbonBar Builder.

    • Images Directory -- This directory will be ignored if a built-in image is selected. For a custom image, you can specify a relative path of the custom image in the XML scripts according to the directory specified here; or specify an absolute path if the custom image is in a different directory.

    • Enable word wrap -- Whether to break a long line into multiple lines based on the XML editor view area.

    • Show line numbers -- Whether to show line numbers on the left hand side of the XML editor.

    • Place the preview pane on the top -- Whether to place the preview pane on the top of the XML editor.

    • Dynamically refresh the preview -- Whether to dynamically refresh the preview pane to reflect the changes made to the RibbonBar control. If this option is not selected, a refresh icon will appear on the top right corner of the preview pane and you can click this icon (or press Ctrl + R) to refresh the preview pane manually.

    • Refresh interval -- When "Dynamically refresh the preview" option is selected, you can determine how frequently should the preview pane be refreshed after a change is made.


The XML editor also provides auto-completion to help you write XML elements, properties, and property values easily.

  • When you input "<", the editor automatically displays a list of possible elements

  • When you enter a space in an element, the editor automatically displays a list of properties for the current element.

  • When you input "=" after a property, the editor aromatically displays a list of values for the property.

The scripts will be validated against XML 1.0 Specification immediately after input. The syntax error, if any, will be displayed in Error List pane at the bottom of the RibbonBar Builder.

Creating a valid structure

You can right-click in the XML editor to add the nodes, and use the Error List pane to analyze and fix any syntax error.

Here is a brief description to the main XML nodes of a RibbonBar control which can help you understand what a valid structure looks like:

  • <RibbonBar> -- This is the root node. It provides property values for the RibbonBar controls.

    • <RibbonItems> -- This is the only-one second-level node. Only one <RibbonItems> is allowed here.

      • <ApplicationButton> -- Only one <ApplicationButton> is allowed here. It provides property values for the application button.

        • <ApplicationMenu> -- Only one <ApplicationMenu> is allowed here. <ApplicationMenu> can contain only one <Master> and only one <Recent>; and <Master> and <Recent> can contain multiple <Item>.

      • <Categories> -- This is the only-one node for all of the categories.

        • <Category> -- Multiple <Category> are allowed.

          • <Panel> -- Multiple <Panel> are allowed. <Panel> can contain multiple <LargeButton>, <SmallButton>, <CheckBox>, <ComboBox>, and <Group>.

            • <Group> -- Multiple <Group> are allowed. <Group> can contain multiple <SmallButton>, <CheckBox>, and <ComboBox>, but cannot contain any <LargeButton>.

            • <SmallButton> -- Multiple <SmallButton> are allowed. <SmallButton> can contain only one <Menu>; <Menu> can have multiple <Item>.

            • <LargeButton> -- Multiple <LargeButton> are allowed. <LargeButton> can contain only one <Menu>; <Menu> can have multiple <Item>.

            • <CheckBox> -- Multiple <CheckBox> are allowed.

            • <ComboBox> -- Multiple <ComboBox> are allowed. <ComboBox> can contain multiple <Item>.

      • <TabButtons> -- This is the only-one node for all of the tab buttons.

        • <TabButton> -- Multiple <TabButton> are allowed. <TabButton> can contain only one <Menu>; <Menu> can have multiple <Item>.

After you finalize the design, you can save the XML scripts of the RibbonBar control to an XML or JSON file or as a string, and then load the file or string to create the RibbonBar in the application.

  • To load the XML file to create the RibbonBar, call the ImportFromXMLFile function

    Lnv_RibbonBar1.ImportFromXMLFile ("D:\RibbonBarXML\RibbonBar.xml")
  • To load the JSON file to create the RibbonBar, call the ImportFromJSONFile function

    Lnv_RibbonBar1.ImportFromJSONFile ("D:\RibbonBarXML\RibbonBar.json")
  • To load the XML string to create the RibbonBar, call the ImportXML function

    Lnv_RibbonBar1.ImportXML (XMLData)
  • To load the JSON string to create the RibbonBar, call the ImportJSON function

    Lnv_RibbonBar1.ImportJSON (JSONData)

Accessing the RibbonBar items in the hierarchy

The RibbonBar control is a container. The RibbonBar control as well as the item controls it contains have a hierarchical relationship. The item controls cannot exist independently and must be placed on top of the parent object; therefore, to get an item control, you need to search from the top level (RibbonBar control), or to search by tag. The control you get is a copy (not a reference), and after the copy is modified, it needs to be set back to the parent object, and then to the RibbonBar control, for the change to take effect.

To access a ribbon item, you need to understand the hierarchical structure of the RibbonBar control and its item controls.

To get a copy of a ribbon item control, use the following two ways:

  1. (Recommended) You can get a copy of a ribbon item through its tag value.

    For example, suppose RibbonBar rbb_1 contains a Category and the Category contains a Panel and the Panel contains a CheckBox (its Tag value is CheckBoxTag1). You can access the CheckBox with the following scripts.

    RibbonCheckBoxItem lr_CheckBox1
    if rbb_1.GetItemByTag ("CheckBoxTag1", lr_CheckBox1) = 1 Then
       lr_CheckBox1.enabled = False
       ...
    End If
    
  2. You can get a copy of a ribbon item according to its hierarchical level:

    RibbonBar > Category > Panel [> Group] > CheckBox/ComboBox

    RibbonBar > Category > Panel [> Group] > LargeButton/SmallButton [> RibbonMenu > MenuItem]

    RibbonBar > TabButton [> RibbonMenu > MenuItem]

    RibbonBar > ApplicationButton > ApplicationMenu > MenuItem (Master and/or Recent)

    Panel can directly contain CheckBox, ComboBox, LargeButton, and SmallButton. Group cannot contain LargeButton. ApplicationMenu can contain a list of master menu items and a list of recent menu items. For more, see Introduction to RibbonBar items.

    For example, suppose RibbonBar rbb_1 contains a Category and the Category contains a Panel and the Panel contains a CheckBox. You first get a copy of the Category from RibbonBar rbb_1, and then get a copy of the Panel from the copy of the Category, finally get a copy of the CheckBox from the copy of the Panel. The code will look like this:

    RibbonCategoryItem lr_Category
    RibbonPanelItem lr_Panel
    RibbonCheckBoxItem lr_CheckBox
    
    If rbb_1.GetcategoryByIndex (1, lr_Category) = 1 Then
       If rbb_1.GetChildItemByIndex (lr_Category.itemhandle, 1, lr_panel) = 1 Then
          If rbb_1.GetChildItemByIndex (lr_panel.itemhandle, 1, lr_CheckBox) = 1 Then
             lr_CheckBox.enabled = False
             ...
          End If
       End If
    End If
    

To set changes for a ribbon item control, use different ways according to different item controls:

  • For items in the Generic Controls category in the chart, including ApplicationButton, TabButton, Category, Panel, Group, CheckBox, ComboBox, LargeButton, and SmallButton, you can directly apply changes to the RibbonBar.

    For example, if you have changed the property of the CheckBox lr_CheckBox, to apply this change to the RibbonBar rbb_1, you write scripts like this:

    …
    rbb_1.SetItem (lr_CheckBox)
    …

    Or

    …
    rbb_1.SetCheckBox (lr_CheckBox.ItemHandle, lr_CheckBox)
    …

    For differences between SetItem and SetCheckBox, refer to SetItem in PowerScript Reference.

  • For ApplicationMenu (its parent object is ApplicationButton) and RibbonMenu (its parent object can be TabButton, LargeButton, or SmallButton) in the Menu Controls category in the chart, you must first apply changes to the parent object and then to the RibbonBar.

    For example, if you have changed the text of the application menu lr_ApplicationMenu, to apply this change to the RibbonBar rbb_1, you write scripts like this:

    …
    ApplicationButton1.SetMenu (lr_ApplicationMenu)
    rbb_1.SetItem (ApplicationButton1) //or rbb_1.SetApplicationButton (ApplicationButton1)
    …
  • For MenuItem (its parent object can be ApplicationMenu or RibbonMenu) in the Menu Controls category in the chart, you must first apply changes to the parent object, then to the parent object at one level higher, and finally to the RibbonBar.

    For example, if you have changed the text of the menu lr_MenuItem which is a dropdown of a large button, to apply this change to the RibbonBar rbb_1, you write scripts like this:

    …
    Menu1.SetItem (lr_MenuItem)
    LargeButton1.SetMenu (Menu1)
    rbb_1.SetItem (LargeButton1) //or rbb_1.SetLargeButton (LargeButton1.itemhandle, LargeButton1)
    …

Example 1:

Suppose RibbonBar rbb_1 contains a Category and the Category contains a Panel and the Panel contains a CheckBox (its Tag value is CheckBoxTag1). The following code gets the CheckBox by tag and then changes its Enabled property:

RibbonCheckBoxItem lr_CheckBox1
if rbb_1.GetItemByTag ("CheckBoxTag1", lr_CheckBox1) = 1 Then
   //Changes the Enabled property of CheckBox
   lr_CheckBox1.enabled = False
   //For the change to take effect, sets the change to the RibbonBar control
   rbb_1.SetItem (lr_CheckBox1) //or rbb_1.SetCheckBox (lr_CheckBox1.itemhandle, lr_CheckBox1) 
End If

Example 2:

Unlike the PowerBuilder traditional menu, to add/delete/modify a ribbon menu item, you need to first get a copy of the menu item and its parent object, make changes to the menu item, then set changes back to its parent object, and finally to the RibbonBar control.

The following code example changes the text of a menu item dynamically.

//Gets a copy of ApplicationButton from RibbonBar control rbb_1
rbb_1.GetApplicationButton(buttonitem)
//Gets a copy of ApplicationMenu from the copy of ApplicationButton
li_rc = buttonitem.getMenu( appmenu ) 
li_count = appmenu.GetMasterItemCount ()
FOR li_index = 1 TO li_count
    //Gets a copy of MenuItem from the copy of ApplicationMenu
    li_rc = appmenu.GetMasterItem( li_index, item )
    IF item.tag = 'Tools' THEN
       //Changes the text of a menu item
       item.Text = 'Tools Test'                      
       //For the change to take effect, sets the copy of MenuItem back to the copy of ApplicationMenu
       li_rc = appmenu.SetMasterItem( li_index, item )
       //Then sets the copy of ApplicationMenu back to the copy of ApplicationButton
       li_rc = buttonitem.Setmenu( appmenu )
       //Finally sets the copy of ApplicationButton back to the RibbonBar control
       li_rc = rbb_1.SetApplicationbutton( buttonitem )
    END IF
NEXT

Tutorial: How to Replace an Application Menu with a RibbonBar

Overview

The new RibbonBar control allows you to organize the navigation of your application in a simple, structured way, and gives the application the look and feel of modern applications. Because RibbonBar is provided in PowerBuilder as a control while Menu is a system object, the way that a RibbonBar works in an application is different from the application menu. This tutorial uses a demo application to walk you through the steps of replacing an application menu with a RibbonBar.

The figure below shows what the menu looks like in the original demo application.

The figure below shows what the RibbonBar control looks like after you use it to replace the menu in the application.


This tutorial contains the following sections:

Prerequisites

Step 1: Install PowerBuilder 2019 R3.

Step 2: Download the RibbonBar demo application from here.

Step 3: Set up the sample database.

  1. Get the database file "AppeonSample.db" from the downloaded demo application.

  2. Set up the ODBC database connection.

    1. Open Control Panel > System and Security > Administrative Tools > ODBC Data Sources.

    2. Create a new Data Source in SQL Anywhere 17.

    3. Fill in the following data source configurations. Note that username and password for data source connection is “dba” and "sql".

    4. In PowerBuilder, setup and connect to the created ODBC data source.

Design and create a RibbonBar

As the first step, you shall design the RibbonBar, that is, deciding what items to contain in the RibbonBar, what modern-looking image to use for each item, and how to group the items, etc.

Once you know clearly how you want the RibbonBar to look like, you can start to create it. We recommend you use the RibbonBar Builder tool to create the RibbonBar XML/JSON file. Alternatively, you can choose to directly create a RibbonBar via PowerScript.

For detailed instructions on how to create a RibbonBar, refer to PowerBuilder Help > RibbonBar control. In the Sales Demo application, for better illustration purpose, you will see both the XML file and PowerScript code are provided for creating the RibbonBar. When the application initiates the RibbonBar, it uses an argument in the wf_init_ribbonbar function to decide which way (XML or PowerScript) to use for creating the RibbonBar (see Initiate the RibbonBar).

Creating the XML for the RibbonBar in this demo (Recommended):

A dedicated tool, RibbonBar Builder, is available in PowerBuilder to assist you to create the RibbonBar XML (or JSON). In the tool, you can use a template (RibbonBar.xml) to create your own XML, and preview the RibbonBar UI while you work. This is the recommended approach.

In the Sales Demo application:

  1. Open Tools > RibbonBar Builder in PowerBuilder IDE, and open and edit the file created for the RibbonBar: SalesApplicationDemo_RibbonBar.xml.

Creating the PowerScript for the RibbonBar in this demo:

In the Sales Demo application:

  1. Open the function w_mdi.wf_init_ribbonbar, and you will see the PowerScript for the RibbonBar in the function. The script is different from XML, but shall still be easy to understand.

    For example, the following script inserts File as a RibbonBar category, adds an orderview panel in this category, and then adds buttons inside the panel.

    //File menu
    long ll_handle, ll_category, ll_panel, ll_group
    RibbonSmallButtonItem lrs_item
    Ribbonmenu lrm_menu
    ribbonLargeButtonItem lrl_item
    ribbongroupitem lrg_item
    long ll_return, ll_tmp, ll_tmp2
    ll_category = arbb.insertcategoryfirst ("File") //Insert a category
    //orderview
    ll_panel = arbb.insertpanellast (ll_category, "OrderView", "orderview.png") //Insert a panel
    arbb.insertLargebuttonlast (ll_panel, "Orders", "orderview.png", "ue_orderview") //Insert button
    arbb.insertLargebuttonLast (ll_panel, "Print", "printbig.png", "ue_orderview_print")
    

Add the RibbonBar to the application

Replacing the existing menu with an empty one

After the RibbonBar is applied, the previous menu will no longer be used in the application. You can create an empty menu and assign it to the MDI window, as a menu is required for all MDI frame windows (the MenuName property for the MDI window must be set).

  1. Use New > PB Object > Menu to create a new menu object. It is unnecessary to define any menu item for the menu or attach any script to it. If you do add a menu item, make sure the item shall be set to invisible.

  2. Assign the empty menu to the MDI window.

In the Sales Demo application, we created the menu object m_mdi_none and assigned it to the MDI window. The menu object contains one main menu and one submenu. Note that the submenu item is set to invisible.

Inserting a RibbonBar control to the MDI window

Insert the RibbonBar control into the MDI window. Note that you must resize the width and height for RibbonBar area in correspondence with the MDI client area to make sure the RibbonBar fits well in the MDI window.

In the Sales Demo application:

  1. Insert the RibbonBar control into the MDI window (from menu: Insert > Control > RibbonBar in PowerBuilder IDE).

  2. Add the following code to the Resize event of the MDI window:

    //resize RibbonBar
    rbb_1.move(0, newheight - this.workspaceheight())
    rbb_1.width = newwidth
    //resize mdi_1 based on RibbonBar
    mdi_1.move (0, rbb_1.height + newheight - this.workspaceheight())
    mdi_1.resize (newwidth, newheight - rbb_1.height - ( newheight - this.workspaceheight()))
    
Disabling ControlMenu in sheet windows

Because the RibbonBar control applies to the whole application, and the RibbonBar control usually contains a tab button to close the sheet window, it is no longer necessary to provide the Control Menu in the sheet windows. Make sure to design the new RibbonBar to contain a Close/Exit tab button so that the sheet window can be closed after the Control Menu is disabled.

In the Sales Demo application:

  1. Open every sheet window (for example, w_sheet), and uncheck the ControlMenu property in the General tab of the Properties window.

  2. Add the close/exit tab button to the RibbonBar top-right corner when we design and create the RibbonBar.

Initiate the RibbonBar

In the Design and create a RibbonBar section, we create the RibbonBar for the application in two ways: by XML/JSON or by PowerScript. We can initiate the RibbonBar created in either way.

Initiating the RibbonBar created by XML

In the Sales Demo Application:

  1. Add an instance variable in the MDI window.

    String is_Ribbonbar_XML_Name = "SalesApplicationDemo_RibbonBar.xml"

    Note

    Make sure this XML file exists in the specified location at the client when the PowerBuilder executable application is deployed and run at the client.

  2. Initiate the RibbonBar control in the open() event of the MDI window. The second argument must be True, indicating that the RibbonBar will be initiated using XML.

    wf_init_ribbonbar (rbb_1, True)
  3. In the wf_init_ribbonbar function of the MDI window, load the RibbonBar from the XML file.

    If ab_LoadXML Then
     arbb.ImportFromXMLFile(is_Ribbonbar_XML_Name)
     return
    End If
    
Initiating the RibbonBar created by PowerScript

In the Sales Demo Application:

  1. Initiate RibbonBar menu in the open() event of the MDI window. The second argument must be False, indicating that the RibbonBar will be initiated using PowerScript.

    wf_init_ribbonbar(rbb_1,False)

Define and bind user events with RibbonBar items

The ribbon item controls have no events, you should define a number of user events accordingly, move the scripts from the original menu events to the user events, and then bind the user events with the corresponding ribbon item control.

The ribbon item controls support the following user events:

  • RibbonCheckBoxItem, RibbonLargeButtonItem, RibbonMenuItem, RibbonSmallButtonItem and RibbonTabButtonItem: You can create and bind the clicked and selected user events with them.

  • RibbonComboBoxItem: You can create and bind the modified, selected, and selection changed user events with it.

When defining a user event for the ribbon control, make sure the argument (quantities and types) of the event is properly defined according to the requirement of the ribbon control. If the number of arguments or the argument type does not match with the requirement of the ribbon control, the event will not be triggered.

For example, in the Sales Demo Application, we want to create and bind the clicked user event with the Order View large button. The RibbonLargeButtonItem control requires that the clicked user event have a long-type argument and return no value. Therefore, in the rbb_1 RibbonBar control, we create an event with its name as ue_orderview, argument name as al_handle, argument type as long, and the following script:

// ue_orderview (long al_handle) returns (none)
opensheet (w_order_viewer, parent, 0, Original!)

And then we bind the ue_orderview user event with the clicked event of the Order View large button using this script:

arbb.InsertLargeButtonFirst (ll_Itemhandle_Panel, wf_SetLargetButtonItem_Pro ("Order View", "OrderView", ".\picture\orderview.png", "ue_orderview", True, "", "", "ctrl+shift+O"))

You can also bind the ue_orderview user event with the clicked event of the Order View large button using the XML file:

...
   <LargeButton Text="Order View" Tag="OrderView" PictureName=".\picture\orderview.png" Clicked="ue_orderview" Shortcut="ctrl+shift+O" />
...

Different ribbon controls require different arguments and types for the user event. For details, see the corresponding user events:

Clicked in PowerScript Reference

Selected in PowerScript Reference

Modified in PowerScript Reference

SelectionChanged in PowerScript Reference

Associate functions with RibbonBar items

Previously the application functions are all associated with menu items. You need to decide which function to associate with which RibbonBar item now. In the Sales Demo application, you can see clearly how a function that is previously associated with a menu item is now associated with a RibbonBar item. In this tutorial, let’s explain two examples.

Example 1: Opening the “By Order Type” report

In the original application, the “By Order Type” report is opened from Report > Sales Reports > By Order Type menu item.

The new application uses the Report > Sales Reports > By Order Type RibbonBar item to open the report.

PowerScript in the previous menu item m_report1.m_salesreports.m_byordertype:

str_rptparm lstr_parm

lstr_parm.ftitle = 'Sales Report by Order Type'
lstr_parm.fdataobject = ""
opensheetWithParm (w_rpt_order_type, lstr_parm, parentwindow, 0, Original!)

PowerScript in the event ue_rep_ordertype of the RibbonBar:

str_rptparm lstr_parm

lstr_parm.ftitle = 'Sales Report by Order Type'
lstr_parm.fdataobject = ""
opensheetWithParm (w_rpt_order_type, lstr_parm, parent, 0, Original!)

iw_tmp = w_rpt_order_type
wf_setstyle("2D BarStacked")

Key points covered in the PowerScript change:

  • opensheetWithParm (w_rpt_order_type, lstr_parm, parent, 0, Original!)

    As the report item is placed in the RibbonBar panel, the parent object for this item is changed; therefore, the mdiframe argument of OpenSheetWithParm must be changed from parentwindow to parent. The Tag value is migrated into this RibbonBar item. You can find more information for Tag migration in the next example.

  • iw_tmp = w_rpt_order_type

    The original toolbar items are migrated as RibbonBar items (small buttons), e.g. 2D Pie, 3D Column, 2D BarStacked/Line and Grid Data items. The items may be enabled or disabled depending on the activation of the sheet window. Here we add each opened window into a buffer to track the activation status, so that it can control the status for the RibbonBar items.

  • wf_setstyle("2D BarStacked")

    Identify if the report supports 2D BarStacked or 2D Line style. In this example, the small button “2D Bar” is displayed when this report is actively opened.

Example 2: Opening the “2D BarStacked” report

In the original application, the “2D BarStacked” report is opened from the “2D BarStacked” toolbar item.

The new application uses the Report > 2D Bar RibbonBar item to open the “2D Bar” report, and then provides the 2D BarStacked option in the report for users to view the 2D Bar Stacked report.

PowerScript in the previous toolbar item m_report.m_settings.m_defaultsettings.m_reportstyle.m_item1:

ParentWindow.Dynamic Event ue_Settings(This.Tag)
If This.Checked Then Return
This.Checked = True
m_item2.Checked = False
m_item3.Checked = False
m_item4.Checked = False
m_item5.Checked = False

PowerScript in the event ue_report_style of the RibbonBar:

ribbonsmallbuttonitem lrs_item
this.getsmallbutton (al_handle, lrs_item)
string ls_tag
ls_tag = lrs_item.tag
if isvalid (iw_tmp) then
 iw_tmp.dynamic event ue_Settings(lrs_item.tag)
end if

Key points covered in the PowerScript change:

  • The Checked status for the toolbar item is no longer applicable for RibbonBar item.

  • ribbonsmallbuttonitem lrs_item
    this.getsmallbutton (al_handle, lrs_item)
    string ls_tag
    ls_tag = lrs_item.tag
    

    The Tag property is used as the identifier for some business logic of toolbar items. The Tag value needs to be migrated into the RibbonBar item. In this example, we use handle to obtain the Tag value from a RibbonBar item. The report style will be switched based on the Tag value.

  • if isvalid (iw_tmp) then
     iw_tmp.dynamic event ue_Settings(lrs_item.tag)
    end if
    

    The ParentWindow is not applicable for RibbonBar items. And the parent object is not applicable for RibbonBar either, because the parent window is an MDI window instead of a sheet window. The actual parent object will be the tracked sheet window in the buffer. The buffer is maintained in the iw_tmp object.

Example 3: Replacing the Close/Exit in sheet windows

In the original MDI window application, the control menu provides the Close button to close the sheet window, and the Exit button to close the application.

When using the RibbonBar, the open, close and refresh functions are now provided in the RibbonBar, and the ControlMenu property should be disabled in the sheet windows.

PowerScript in the previous w_sheet object close() event:

parentwindow().post dynamic event ue_closesheet(this.classname())

PowerScript in the w_sheet object close() event of the RibbonBar:

parentwindow().post dynamic event ue_closesheet(this.classname())
if isvalid(w_mdi) then
 w_mdi.post function wf_refresh_ribbon()
end if
parentwindow().post function Arrangesheets(Layer!)

Key points covered in the PowerScript change:

  • w_mdi.post function wf_refresh_ribbon()

    In the Close event of the sheet window, call the wf_refresh_ribbon function to refresh the RibbonBar buttons and controls in the MDI window at the closing of the sheet window w_mdi function. For example, if the 2D BarStacked report window is closed, the current active report supports 2D Line style. The style button in the RibbonBar is refreshed to display the 2D Line button.

  • parentwindow().post function Arrangesheets(Layer!)

    In the Close event of the sheet window, call the ArrangeSheets function to re-arrange all the remaining sheet windows via the Layer parameter.

Example 4: Adding the Application Menu category

The Application Menu category contains the generic application functions, including:

  • Recent Windows, listing the recently opened windows;

  • User, providing the user/group management, password setting, and sign out functions;

Example 5: Including special RibbonBar widgets

There are some special RibbonBar widgets that can further enhance user experience in the application.

For example, the standard RibbonBar buttons for collapsing and expanding, help, and closing functions, as shown below:

Summary notes

  • The RibbonBar can be constructed by a standard XML/JSON file. PowerBuilder provides RibbonBar Builder with preview functionality to assist you to create the XML/JSON file.

  • When you apply a RibbonBar to an application, the previous menu in the application shall be removed. It is recommended that you create an empty menu and assign it to the MenuName property of the MDI window of the application.

  • The ControlMenu property must be disabled for all windows in the application, so that the Control Menu titlebar will not display when a sheet window is maximized.

  • Remember to resize the width and height for RibbonBar area and the MDI client area after the RibbonBar is added to the MDI window. This is to make sure the sheet windows opened in the MDI window will display properly together with the RibbonBar.

  • If some windows are inherited from an ancient window, you can follow the same way to associate functions with the child windows as with the ancient window.

    If previously some menu items with the same functionality are placed in different sheet windows and you plan to put the menu items in the same panel in the RibbonBar, you can consider to control the enable/disable statuses of the RibbonBar items depending on the active status of the sheet windows.

  • The window (including MDI window) that contains the RibbonBar control will have the Deactivate event triggered 1) when you click the drop-down arrow to show the Ribbon menu items, or 2) when you click the drop-down arrow to show the Ribbon panel items (the drop-down arrow appears when the panel is resized to only show the panel title). When the Window Deactivate event is triggered, the control within the window will lose focus.

  • The ribbon item controls have no events and must be bound with user events. For more, see the section called “Clicked” in Objects and Controls, the section called “Selected” in Objects and Controls, the section called “Modified” in Objects and Controls, and the section called “SelectionChanged” in Objects and Controls.

  • If the RibbonBar is created by XML (or JSON), make sure 1) this XML (or JSON) exists in the specified location at the client when the PowerBuilder executable application is deployed and run at the client; and 2) this XML (or JSON) is selected as "Files preloaded in uncompressed format" when the application is deployed with the PowerClient method.

  • You can create a PBR (PowerBuilder resource) file to list the resource names (such as BMP, PNG etc.) used by the RibbonBar control and compile the PBR file with the application executable.