You can create a new folder in the theme path to hold your own custom themes. It is recommended that you directly make a copy of an existing system theme folder and then make changes to the copy.
Note
If you directly make changes to the system theme, your changes may be lost after you re-install or upgrade PowerBuilder.
Always create a copy from the system theme, by following steps below.
To create custom themes:
-
Open the "%AppeonInstallPath%\PowerBuilder [version]\IDE\theme" directory, make a copy of any existing system theme folder, and rename the copy.
For example, you can duplicate the "Flat Design Blue" folder and name it "Custom Blue".
Make sure the copied folder contains the theme.json file, so the folder name (in this example "Custom Blue") will be automatically recognized as the theme name and listed for selection in the Themes tab or called by the
ApplyThememethod.Note
When creating the application's executable file, make sure to manually deploy the "theme" folder with the application executable. For more details, refer to Packaging the theme runtime files.
-
In the copied folder, add one or more custom theme definition files.
It is recommended to make a copy of the theme.json file and rename and change the file, by following instructions below.
-
The custom theme file must be named in this format: theme-[xxxx].json.
The file name must start with "theme-".
[xxxx] can be any text.
The file extension must be .json, for example, theme-control.json, theme-dw.json, etc.
-
The settings in the file can be a subset or all of the theme.json file (see Understanding the theme.json file for more about the theme.json file).
The nodes that host theme settings are the system object or control name (such as "checkbox", "commandbutton" etc.) in theme.json; but the nodes that host theme settings in the custom theme file must be the name that points to the specific object or control (such as "w_main.uo_1.cb_1", "w_main$commandbutton" etc.) that will apply the settings. For example,
{ "meta-info": { "version":"190" }, "w_main.uo_1.cb_1": { ... //Copy the settings from the "commandbutton" node //of the "theme.json" file and then modify. } "w_main$commandbutton": { ... //Copy the settings from the "commandbutton" node //of the "theme.json" file and then modify. } "w_main": { ... //Copy the settings from the "window" node //of the "theme.json" file and then modify. } }
-
-
In the custom theme file, configure the theme settings for a window, a custom visual user object, a standard visual user object, a control/object, or controls/objects of the same type in the window or user object.
For detailed information and examples, refer to the next section Configuring the custom theme.
Each individual control or object can have its own theme settings, for example, one button can have theme settings different from the other buttons. And controls of the same type in the same window/user object can have their own theme settings, for example, all group boxes in one window can have theme settings different from the group boxes in the other window.
Therefore you can configure theme settings for a specific control or object, or controls or objects of a specific type.
Unsupported
The dynamically created DataWindow is unsupported to have custom theme settings.
The dynamically created user object is unsupported to have custom theme settings.
Similar to PowerScript, you write dot donation in the theme file to qualify a reference to a control/object in a container. But pay attention to the following:
-
You can customize theme settings for controls and objects (except DropDownDataWindows) in both the window container and user object container.
-
The user object container must be a custom visual user object (not external visual user object or standard visual user object).
-
Different containers use different rules when customizing the theme settings. If a user object container is placed in a window container, then it should use rules of the window container, instead of rules of the user object container.
-
To reference to controls (or objects) in a window container, you could write dot notation in the theme file.
Controls (or objects) of the same type in the window or user object must be referenced by qualifier of the current window or current user object only: [window]$[controltype] or [userobject]$[controltype]. You must reference by only one level of window or user object (even if there are more). For example, [w_1].[uo1]$[controltype] will NOT take effect, and must be changed to [w_1]$[controltype] (which affects controls contained in w_1) or [uo1]$[controltype] (which affects controls contained in uo1).
-
To reference to controls (or objects) in a user object container, you could write dot notation in the theme file.
A control (or object) in the user object must be referenced by qualifier of the current user object only: [userobject].[control-or-object]. You must reference by only one level of user object (even if there are more). For example, [uo1].[uo2].[control-or-object] will NOT take effect, and must be changed to [uo1].[control-or-object] (which affects the control contained in uo1) or [uo2].[control-or-object] (which affects the control contained in uo2).
In the user object container, controls (or objects) of the same type in the user object must be referenced by qualifier of the current user object only: [userobject]$[controltype]. You must reference by only one level of user object (even if there are more). For example, [uo1].[uo2]$[controltype] will NOT take effect, and must be changed to [uo1]$[controltype] (which affects controls contained in uo1) or [uo2]$[controltype] (which affects controls contained in uo2).
-
-
You can customize theme settings for standard visual user objects. Note that the theme settings are not these types of standard visual user objects: Picture, PictureHyperLink, or Animation.
-
The user object which is dynamically created via OpenTab or OpenUserObject method is unsupported to have their own theme settings.
-
A window must be referenced in this format: [windowname]
For example, to configure the theme settings for w_main:
"w_main": { ... //Copy "window" node from "theme.json" and customize. }For another example, to configure the theme settings for w_descendant (which is inherited from another window):
"w_descendant": { ... //Copy "window" node from "theme.json" and customize. } -
A control or object in the window must be referenced in this format: [windowname].[control-or-object].
-
A control in a window
Supposing the w_main window contains the cb_1 button, you can customize cb_1 like below:
"w_main.cb_1": { ... //Copy "commandbutton" node from "theme.json" and customize. } -
A userobject in a window
Supposing the w_main window contains the uo_1 user object, you can customize uo_1 like below:
"w_main.uo_1": { ... //Copy "userobject" node from "theme.json" and customize. } -
An embedded userobject in a window
Supposing the w_main window contains the uo_1 user object and uo_1 contains an embedded userobject uo_custom, you can customize uo_custom like below:
"w_main.uo_1.uo_custom": { ... //Copy "userobject" node from "theme.json" and customize. } -
A control in a userobject in a window
Supposing the w_main window contains the uo_1 user object and uo_1 contains the cb_1 button, you can customize cb_1 like below:
"w_main.uo_1.cb_1": { ... //Copy "commandbutton" node from "theme.json" and customize. } -
A control in an embedded userobject in a window
Supposing the w_main window contains the uo_1 user object, uo_1 contains an embedded userobject uo_custom, and uo_custom contains the cb_1 button, you can customize cb_1 like below:
"w_main.uo_1.uo_custom.cb_1": { ... //Copy "commandbutton" node from "theme.json" and customize. } -
A tab in a window
Supposing the w_main window contains the tab_1 tab control, you can customize tab_1 like below:
"w_main.tab_1": { ... //Copy "tab" node from "theme.json" and customize. } -
A tab in a userobject in a window
Supposing the w_main window contains the uo_1 user object and uo_1 contains the tab_1 tab control, you can customize tab_1 like below:
"w_main.uo_1.tab_1": { ... //Copy "tab" node from "theme.json" and customize. } -
A tab in an embedded userobject in a window
Supposing the w_main window contains the uo_1 user object, uo_1 contains an embedded userobject uo_custom, and uo_custom contains the tab_1 tab control, you can customize tab_1 like below:
"w_main.uo_1.uo_custom.tab_1": { ... //Copy "tab" node from "theme.json" and customize. } -
A control in a tabpage in a window
Supposing the w_main window contains the tab_1 tab control and tab_1's tab page 1 contains the cb_1 button, you can customize cb_1 like below:
"w_main.tab_1.tabpage_1.cb_1": { ... //Copy "commandbutton" node from "theme.json" and customize. } -
A control in a tabpage in a userobject in a window
Supposing the w_main window contains the uo_1 user object, uo_1 contains the tab_1 tab control, and tab_1's tab page 1 contains the cb_1 button, you can customize cb_1 like below:
"w_main.uo_1.tab_1.tabpage_1.cb_1": { ... //Copy "commandbutton" node from "theme.json" and customize. } -
A control in a tabpage in an embedded userobject in a window
Supposing the w_main window contains the uo_1 user object, uo_1 contains an embedded userobject uo_custom, uo_custom contains the tab_1 tab control, and tab_1's tab page 1 contains the cb_1 button, you can customize cb_1 like below:
"w_main.uo_1.uo_custom.tab_1.tabpage_1.cb_1": { ... //Copy "commandbutton" node from "theme.json" and customize. } -
A control in a userobject in a tabpage in a window
Supposing the w_main window contains the tab_1 tab control, tab_1's tab page 1 contains the uo_1 user object, and uo_1 contains the cb_1 button, you can customize cb_1 like below:
"w_main.tab_1.tabpage_1.uo_1.cb_1": { ... //Copy "commandbutton" node from "theme.json" and customize. } -
A control in an embedded userobject in a tabpage in a window
Supposing the w_main window contains the tab_1 tab control, tab_1's tab page 1 contains the uo_1 user object, uo_1 contains an embedded user object uo_custom, and uo_custom contains the cb_1 button, you can customize cb_1 like below:
"w_main.tab_1.tabpage_1.uo_1.uo_custom.cb_1": { ... //Copy "commandbutton" node from "theme.json" and customize. } -
A userobject in a tabpage in a window
Supposing the w_main window contains the tab_1 tab control and tab_1's tab page 1 contains the uo_1 user object, you can customize uo_1 like below:
"w_main.tab_1.tabpage_1.uo_1": { ... //Copy "userobject" node from "theme.json" and customize. } -
An embedded userobject in a tabpage in a window
Supposing the w_main window contains the tab_1 tab control, tab_1's tab page 1 contains the uo_1 user object, uo_1 contains an embedded user object uo_custom, you can customize uo_custom like below:
"w_main.tab_1.tabpage_1.uo_1.uo_custom": { ... //Copy "userobject" node from "theme.json" and customize. }
-
-
A control or object in the descendant window (a descendant window is a window inherited from another window) must be referenced in this format: [descendantwindow].[control-or-object].
If the control or object in the descendant window has no custom theme settings, it will inherit the theme settings from the control or object in the ancestor window. If the control or object in the descendant window has custom theme settings, its custom theme settings will take effect.
-
A control in the descendant window
Supposing the w_descendant window (inherited from another window) contains the cb_1 button, you can customize cb_1 like below:
"w_descendant.cb_1": { ... //Copy "commandbutton" node from "theme.json" and customize. } -
A tab in the descendant window
Supposing the w_descendant window (inherited from another window) contains the tab_1 tab control, you can customize tab_1 like below:
"w_descendant.tab_1": { ... //Copy "tab" node from "theme.json" and customize. } -
A control in a tabpage in the descendant window:
Supposing the w_w_descendant window (inherited from another window) contains the tab_1 tab control, and tab_1's tab page 1 contains cb_1 button, you can customize cb_1 like below:
"w_descendant.tab_1.tabpage_1.cb_1": { ... //Copy "commandbutton" node from "theme.json" and customize. }
-
-
Controls of the same type in the window must be referenced in this format: [windowname]$[controltype]
[controltype] must be the same values as those in theme.json, for example, checkbox, commandbutton, datawindow, groupbox, ribbonbar, tab, userobject etc.
You must reference by only one level of window or object (even if there are more). For example, [w_1].[uo1]$[controltype] will NOT take effect, and must be changed to [w_1]$[controltype] or [uo1]$[controltype].
For example, to configure the theme settings for all command buttons in w_main window:
"w_main$commandbutton": { ... //Copy "commandbutton" node from "theme.json" and customize. }For another example, supposing the w_main window contains the uo_base1 user object and cb_1 button, and uo_base1 contains cb_2; to configure the theme settings for these command buttons, you cannot use "w_main.uo_base1$commandbutton" and will have to use "w_main$commandbutton" (which affects all buttons including cb_1 and cb_2) or "uo_base1$commandbutton" (which affects cb_2 only).
"w_main$commandbutton": { ... //affects all buttons including cb_1 and cb_2 }"uo_base1$commandbutton": { ... //affects cb_2 only }
-
Controls of the same type in the descendant window (a descendant window is a window inherited from another window) must be referenced in this format: [descendantwindow]$[controltype]
[controltype] must be the same values as those in theme.json, for example, checkbox, commandbutton, datawindow, groupbox, ribbonbar, tab, userobject etc.
For example, to customize the theme settings for all command buttons in w_descendant window (inherited from another window):
"w_descendant$commandbutton": { ... //Copy "commandbutton" node from "theme.json" and customize. }
-
A user object must be referenced in this format: [userobjectname].
For example, to configure the theme settings for uo_base1:
"uo_base1": { ... //Copy "userobject" node from "theme.json" and customize. }You must reference by only one level of user object. For example, suppose uo_base2 is placed in uo_base1. To configure the theme settings for uo_base2, you should not include the qualifier of uo_base1 (uo_base1.uo_base2 will NOT take effect).
"uo_base2": { ... //Copy "userobject" node from "theme.json" and customize. } -
A control or object in the user object must be referenced in this format: [userobjectname].[control-or-object].
-
A control in a userobject
Supposing the uo_base1 user object contains the cb_1 button, you can customize cb_1 like below:
"uo_base1.cb_1": { ... //Copy "commandbutton" node from "theme.json" and customize. } -
An embedded userobject in a userobject
Supposing the uo_base2 user object is placed (and named as uo_1) in the uo_base1 user object, you can customize uo_base2 like below:
"uo_base2": { ... //Copy "userobject" node from "theme.json" and customize. } -
A tab in a userobject
Supposing the uo_base1 user object contains the tab_1 tab control, you can customize tab_1 like below:
"uo_base1.tab_1": { ... //Copy "tab" node from "theme.json" and customize. } -
A control in a tabpage
Supposing the uo_base1 user object contains the tab_1 tab control and tab_1's tab page 1 contains the cb_1 button, you can customize cb_1 like below:
"uo_base1.tab_1.tabpage_1.cb_1": { ... //Copy "commandbutton" node from "theme.json" and customize. }
-
-
A control or object in the embedded user object (an embedded user object is a user object placed into another user object) must be referenced in this format: [embeddeduserobject].[control-or-object].
You must reference by only one level of user object (even if there are more). For example, [uo1].[uo2].[control-or-object] will NOT take effect, and must be changed to [uo1].[control-or-object] (which affects the control contained in uo1) or [uo2].[control-or-object] (which affects the control contained in uo2).
-
A control in an embedded userobject
Supposing the uo_base2 user object contains the cb_1 button, and uo_base2 is placed and named as uo_1 in uo_base1, you can customize cb_1 like below:
Incorrect: uo_base1.uo_base2.cb_1 or uo_base1.uo_1.cb_1
Correct:
"uo_base2.cb_1": { ... //Copy "commandbutton" node from "theme.json" and customize. } -
A tab in an embedded userobject
Supposing the uo_base2 user object contains the tab_1 tab control, and uo_base2 is placed and named as uo_1 in uo_base1, you can customize tab_1 like below:
Incorrect: uo_base1.uo_base2.tab_1 or uo_base1.uo_1.tab_1
Correct:
"uo_base2.tab_1": { ... //Copy "tab" node from "theme.json" and customize. } -
A control in a tabpage in an embedded userobject:
Supposing the uo_base2 user object contains the tab_1 tab control, tab_1's tab page 1 contains the cb_1 button, and uo_base2 is placed and named as uo_1 in uo_base1, you can customize cb_1 like below:
Incorrect: uo_base1.uo_base2.tab_1.tabpage_1.cb_1 or uo_base1.uo_1.tab_1.tabpage_1.cb_1
Correct:
"uo_base2.tab_1.tabpage_1.cb_1": { ... //Copy "commandbutton" node from "theme.json" and customize. }
-
-
Controls of the same type in the user object must be referenced in this format: [userobjectname]$[controltype]
[controltype] must be the same values as those in theme.json, for example, checkbox, commandbutton, datawindow, groupbox, ribbonbar, tab, userobject etc.
For example, to configure the theme settings for all command buttons in uo_base1 user object:
"uo_base1$commandbutton": { ... //Copy "commandbutton" node from "theme.json" and customize. } -
Controls of the same type in the embedded user object (an embedded user object is a user object placed into another user object) must be referenced in this format: [embeddeduserobject]$[controltype]
[controltype] must be the same values as those in theme.json, for example, checkbox, commandbutton, datawindow, groupbox, ribbonbar, tab, userobject etc.
You must reference by only one level of user object (even if there are more). For example, [uo1].[uo2]$[controltype] will NOT take effect, and must be changed to [uo1]$[controltype] or [uo2]$[controltype].
For example, to configure the theme settings for all command buttons in uo_base2 user object (uo_base2 is placed into uo_base1):
"uo_base2$commandbutton": { ... //Copy "commandbutton" node from "theme.json" and customize. }For another example, supposing the uo_base1 user object contains the uo_base2 user object and cb_1 button, and uo_base2 contains cb_2; to configure the theme settings for these command buttons, you cannot use "uo_base1.uo_base2$commandbutton" and will have to use "uo_base1$commandbutton" (which affects cb_1 only) or "uo_base2$commandbutton" (which affects cb_2 only).
"uo_base1$commandbutton": { ... //affects cb_1 }"uo_base2$commandbutton: { ... //affects cb_2 }
-
A standard visual user object must be referenced in this format: [userobjectname]. The custom theme settings apply to both the standard visual user object and its descendants.
For example, to configure the theme settings for sv_multilineedit and its descendant:
"sv_multilineedit": { ... //Copy the corresponding "control" node from "theme.json" and customize. }To configure the theme settings for one of the descendant user object only, sv_multilineedit1:
"sv_multilineedit1": { ... //Copy the corresponding "control" node from "theme.json" and customize. }
Precedence of theme files:
If there are multiple theme-[xxxx].json files, the settings in the last file in alphabetical order will be applied first.
Precedence of theme settings for control/object in the window (container):
If there are multiple settings defined for the same object/control in the window container, the settings will be applied in this order:
-
setting for a specific control in the window ([windowname].[controlname] in theme-[xxxx].json)
-
setting for controls of the same type in the window ([windowname]$[controltype] in theme-[xxxx].json)
-
generic setting for controls of the same type ([controltype] in theme.json)
Precedence of theme settings for control/object in the user object (container):
If there are multiple settings defined for the same object/control in the user object container, the settings will be applied in this order:
-
setting for a specific control in the user object ([userobject].[controlname] in theme-[xxxx].json)
-
setting for controls of the same type in the user object ([userobject]$[controltype] in theme-[xxxx].json)
-
generic setting for controls of the same type ([controltype] in theme.json)
Precedence of theme settings for control/object in the descendant window (container):
If the control/object in the descendant window has custom theme settings, its custom theme settings will take effect.
If the control/object in the descendant window has no custom theme settings, it will inherit the theme settings from the control/object in the ancestor window.
For example, if w_ancestor contains cb_1, and w_descendant inherits from w_ancestor and adds another button cb_2, and if settings are defined for w_descendant$commandbutton, then settings under w_descendant$commandbutton will be effective to cb_2, and if no settings are defined for w_descendant$commandbutton, then settings under w_ancestor$commandbutton will be effective to both cb_1 and cb_2.
If there are multiple settings defined for the same object/control in the descendant window, the settings will be applied in this order:
-
setting for a specific control in the descendant window ([descendantwindow].[controlname] in theme-[xxxx].json)
-
setting for a specific control in the ancestor window ([ancestorwindow].[controlname] in theme-[xxxx].json)
-
setting for controls of the same type in the descendant window ([descendantwindow]$[controltype] in theme-[xxxx].json)
-
setting for controls of the same type in the ancestor window ([ancestorwindow]$[controltype] in theme-[xxxx].json)
-
generic setting for controls of the same type ([controltype] in theme.json)
Precedence of theme settings for control/object in the descendant user object (container):
If the control/object in the descendant user object has custom theme settings, its custom theme settings will take effect.
If the control/object in the descendant user object has no custom theme settings, it will inherit the theme settings from the control/object in the ancestor user object.
For example, if uo_ancestor contains cb_1, and uo_descendant inherits from uo_ancestor and adds another button cb_2, and if settings are defined for uo_descendant$commandbutton, then settings under uo_descendant$commandbutton will be effective to cb_2, and if no settings are defined for uo_descendant$commandbutton, then settings under uo_ancestor$commandbutton will be effective to both cb_1 and cb_2.
If there are multiple settings defined for the same object/control in the descendant user object, the settings will be applied in this order:
-
setting for a specific control in the descendant user object ([descendantuserobject].[controlname] in theme-[xxxx].json)
-
setting for a specific control in the ancestor user object ([ancestoruserobject].[controlname] in theme-[xxxx].json)
-
setting for controls of the same type in the descendant user object ([descendantuserobject]$[controltype] in theme-[xxxx].json)
-
setting for controls of the same type in the ancestor user object ([ancestoruserobject]$[controltype] in theme-[xxxx].json)
-
generic setting for controls of the same type ([controltype] in theme.json)
Precedence of theme settings for control/object in the user object in the window (user object is contained by the window):
If there are multiple settings defined for the same object/control in the user object in the window, the settings will be applied in this order:
-
setting for a specific control in the user object in the window ([windowname].[userobjectname].[controlname] in theme-[xxxx].json)
-
setting for a specific control in the user object ([userobjectname].[controlname] in theme-[xxxx].json)
-
setting for controls of the same type in the user object ([userobjectname]$[controltype] in theme-[xxxx].json)
-
setting for controls of the same type in the window ([windowname]$[controltype] in theme-[xxxx].json)
-
generic setting for controls of the same type ([controltype] in theme.json)
Precedence of theme settings for control/object in the descendant user object in the descendant window (user object is contained by the window):
If there are multiple settings defined for the same object/control in the descendant user object in the descendant window, the settings will be applied in this order:
-
setting for a specific control in the descendant user object in the descendant window ([descendantwindow].[userobjectname].[controlname] in theme-[xxxx].json)
-
setting for a specific control in the descendant user object in the ancestor window ([ancestorwindow].[userobjectname].[controlname] in theme-[xxxx].json)
-
setting for a specific control in the descendant user object ([descendantuserobject].[controlname] in theme-[xxxx].json)
-
setting for a specific control in the ancestor user object ([ancestoruserobject].[controlname] in theme-[xxxx].json)
-
setting for controls of the same type in the descendant user object ([descendantuserobject]$[controltype] in theme-[xxxx].json)
-
setting for controls of the same type in the ancestor user object ([ancestoruserobject]$[controltype] in theme-[xxxx].json)
-
setting for controls of the same type in the descendant window ([descendantwindow]$[controltype] in theme-[xxxx].json)
-
setting for controls of the same type in the ancestor window ([ancestorwindow]$[controltype] in theme-[xxxx].json)
-
generic setting for controls of the same type ([controltype] in theme.json)


