Schemes provide an easy way to apply a collection of resources to your application. The scheme mechanism allows your users to select from pre-packaged collections of colors and fonts that are designed to integrate visually with the IRIX Interactive Desktop and other applications. “Schemes for Colors and Fonts” in Chapter 3 in IRIX Interactive User Interface Guidelines describes the guidelines for using schemes in the IRIX Interactive Desktop environment.
This chapter contains the following sections:
“Schemes Overview” provides an overview to schemes.
“Using Schemes in Your Application” describes what you need to do to use schemes in your application.
“Extending a Scheme to Support New Colors” provides tips for testing how your application responds to different schemes.
“Creating New Schemes” describes how to create new schemes.
“Hard-Coding a Scheme for an Application” describes how to force your application to use one specific scheme.
Schemes allow you to provide default colors and fonts for your application, while also ensuring that users can easily select other color and font collections according to their individual needs and preferences. SGI includes some standard system schemes with the X execution environment, but end users can modify existing schemes or create new ones, and you can create new schemes or extend existing ones for use with your application.
This section provides an overview of schemes and explains why you should use schemes in your application.
As a developer, it is impossible for you to choose colors and fonts for your application that satisfy all users. Aside from the consideration of individual taste, display characteristics vary and some users have various degrees of colorblindness. Schemes allow users to select colors and fonts according to their preferences and needs.
Although users can already use the X resource mechanism to customize colors and fonts, it is very difficult and time-consuming for most end users to do so, because the task requires knowledge of the internal structure of the program. On the other hand, if your application supports schemes, users can use the graphical Schemes Browser, schemebr (available from the “Color Schemes” option of the Customize menu in Desktop toolchest), to change colors and fonts.
Using schemes also reduces the time and effort required to develop your application. Instead of choosing your own colors and fonts and coding them into your application, you can simply set a resource value to activate schemes and get the distinctive IRIX Interactive Desktop appearance.
A scheme simply maps specific colors and fonts to abstract resource names according to the functions they serve in an application. So instead of using specific colors like “blue” or “#123456” and specific fonts like “-*-screen-medium-r-normal--13-*-*-*-*-*-iso8859-1,” your application can use symbolic values like TextForeground, TextSelectedColor, and FixedWidthFont. The exact definition of these symbolic values depends on the scheme the user chooses to apply to your application. As long as your application uses the symbolic color and font names for the purposes for which they were intended, users or graphic designers can design a new palette (a binding of the symbolic values to specific colors) and the result should look good with your application.
Often, you do not even need to deal with the symbolic colors and fonts yourself. The schemes mechanism includes a map file that automatically binds the symbolic values to the various IRIS IM widgets and widget resources. One case where you may need to set a color or font explicitly is if you need to highlight a component (for example, in a chart). The schemes mechanism defines special symbolic values such as HighlightColor1 through HighlightColor8 for these purposes. (See “Directly Accessing Colors and Fonts” for more information on the symbolic values.) Another case where you need to be aware of the symbolic values is if you need to extend a scheme for your application. (See “Extending a Scheme to Support New Colors” for more information on extending a scheme.)
This section describes how to write your application for use with schemes and includes:
SGI incorporates schemes in its implementation of Xt, so you do not need to link to a separate schemes library or call a special function to use schemes. All you need to do to enable schemes is to include in your application's app-defaults file (in the /usr/lib/X11/app-defaults directory) the line:
AppClass*useSchemes: all |
AppClass is your application's class name. This activates all aspects of schemes.
![]() | Note: To ensure that users do not accidently override your settings, be sure to prefix the useSchemes resource with your application's class name. |
To deactivate schemes, you can set:
AppClass*useSchemes: none |
If you wish to activate schemes without using an app-defaults file, or if you want to guarantee that the schemes setting cannot be changed by users, call the function SgiUseScheme():
void SgiUseScheme(char *value) |
value can be either “all” or “none.” This function requires that you include the header file <X11/SGIScheme.h>.
For example:
/* schemes.c */ /* cc -o schemes schemes.c -lXm -lXt */ #include <Xm/Label.h> #include <X11/SGIScheme.h> void main(int argc, char** argv) { Widget toplevel, label; XtAppContext app_context; SgiUseSchemes(“all”); toplevel = XtAppInitialize(&app_context, “Hello”, NULL, 0, &argc, argv, NULL, NULL, 0); label = XmCreateLabel(toplevel, “hello”, NULL, 0); XtManageChild(label); XtRealizeWidget(toplevel); XtAppMainLoop(app_context); } |
The schemes map file automatically handles applying colors and fonts to most IRIS IM widgets based on the widgets' class names. Unfortunately, IRIS IM does not have unique class names for menu bars, menu panes, and option menus. To allow schemes to be applied to these elements, your application should use some simple naming conventions for these widgets. Name all menu bars “menuBar,” all option menus “optionMenu,” and the pane of all option menus “optionPane.” Schemes also recognize some other variations of these names, including “menu_bar,” “menubar,” “menu_Bar,” and so on.
If you need to set a color or a font in your application, use the procedures described in “Assigning Non-Default Colors and Fonts to Widgets” and “Directly Accessing Colors and Fonts”. Do not hard code colors or fonts in your application because they may not work with the scheme that a user selects. For example, if you programmatically set a text color to black and a user chooses a scheme that has a very dark background, your text is unreadable. Also avoid setting colors that IRIS IM normally computes. For example, if you hard code the top or bottom shadow colors used by IRIS IM controls, these colors may not be correct if a user changes the scheme.
There are obviously some cases for which this recommendation does not apply. The most common are windows in which you are rendering images. For example, if your application uses OpenGL or some other library to render an image in a window, the colors used in this window are not derived from schemes.
Fonts are usually less critical than colors, although the best visual effects are produced if you use only the fonts defined in the schemes. You should be aware that on high-resolution screens, the sizes of the fonts defined by schemes can change. Therefore, you should design the layout of your application to handle variable-sized fonts. This means you should not hard-code x, y locations or fixed widths or heights for widgets in your application. Instead use IRIS IM manager widgets such as the Form to achieve a flexible layout that can respond to changes in font sizes.
Sometimes, you may want to override the default color or font assigned to a widget by a scheme. For example, all labels are set by default to use a bold font (BoldLabelFont); however you may decide that a regular font (PlainLabelFont) is more appropriate for some of your application's labels.
To assign a non-default font or color to a widget, include a line in your application's app-defaults file mapping a different symbolic scheme resource to that widget. For example, the following line assigns a regular label font (rather than the default bold font) to a label in your application named “simpleLabel”:
YourApp*simpleLabel*fontList: SGI_DYNAMIC PlainLabelFont
|
The symbol SGI_DYNAMIC identifies this resource as a dynamically changeable scheme resource. The actual font assigned to PlainLabelFont can potentially be different in each scheme. As the user changes schemes, the correct resource is applied to your program.
![]() | Note: Remember to prefix the widget hierarchy with your application's class name to prevent users from accidentally overriding your setting. |
You can use the same technique with colors. For example, suppose you have two types of label widgets positioned on an IRIS IM XmDrawingArea widget and you want to use color to give some significance to different labels. Perhaps the application is some type of a flowchart and some of the labels represent tasks in progress, while other represent tasks that have been completed. The schemes map file already maps the symbolic scheme resource DrawingAreaColor to the XmDrawingArea widget. The scheme palette also provides colors that both provide a nice contrast against the DrawingAreaColor and allow the current TextForeground color to be readable. These colors are DrawingAreaContrast1, DrawingAreaContrast2, DrawingAreaContrast3, and DrawingAreaContrast4. To specify the colors of each label widget in your application, you can set the following resources:
YourApp*label1*background: SGI_DYNAMIC DrawingAreaContrast1 YourApp*label2*background: SGI_DYNAMIC DrawingAreaContrast1 YourApp*label3*background: SGI_DYNAMIC DrawingAreaContrast2 ... |
Each scheme also contains a set of basic colors that you can use for simple graphics, icons, and so on. These colors maintain their basic characteristics, but change slightly from scheme to scheme to blend with the general flavor of the scheme. For example, you can set a label widget to be “red” as follows:
YourApp*label*background: SGI_DYNAMIC RedColor
|
The exact shade of red changes from scheme to scheme, but always is “reddish” and always fits with the other colors in the scheme.
If necessary, you can also use non-scheme colors and fonts, although SGI strongly recommends that you do not do this. If you hard-code a color, the user may select a scheme in which that color does not provide the contrast you desire. The color can even be “lost” among the other scheme colors. Non-scheme fonts are less likely to cause problems, but your application will have an inconsistent appearance if it uses them.
You use the same methods to assign a non-scheme color or font that you normally would in an X program. For example, you can set a font for a label named “simpleLabel” in your app-defaults file as follows:
YourApp*simpleLabel*fontList: 6x12
|
When your application uses widgets only, the schemes map file automatically retrieves all colors and fonts from the current scheme and assigns them to your application's widgets. However, you may need to access some of the scheme's colors or fonts directly from within a program. For example, you may want to draw a bar chart or other display using colors that look good no matter what scheme the user has selected.
Example 3-1 shows an example of a function that retrieves a color value given a widget, the color resource name, and the color resource class.
Example 3-1. Retrieving a Scheme Color Value
Pixel getColorResource(Widget w, char *name, char *classname) { XtResource request_resources; Display *dpy = XtDisplay ( w ); int scr = DefaultScreen ( dpy ); Colormap cmap = DefaultColormap ( dpy, scr ); XColor color, ignore; char *colorname; request_resources.resource_name = (char *) name; request_resources.resource_class = (char *) className; request_resources.resource_type = XmRString; request_resources.resource_size = sizeof (char *); request_resources.default_type = XmRImmediate; request_resources.resource_offset = 0; request_resources.default_addr = (XtPointer) NULL; XtGetSubresources(w, (XtPointer) &colorname, NULL, NULL, &requested_resources, 1, NULL, 0); if ( colorname && XAllocNamedColor ( dpy, cmap, colorname, &color, &ignore ) ) return ( color.pixel ); else return ( BlackPixel ( dpy, scr ) ); } |
You can then retrieve the color defined by the scheme resource drawingAreaContrastColor1 using getColorResource() as follows:
color1 = getColorResource(barChartWidget, "drawingAreaContrastColor1", XmCForeground); |
where barChartWidget is the widget that you will use the color in.
![]() | Tip: There is a simple method for retrieving a resource value if you are using the IRIS ViewKit toolkit. Instead of writing the getColorResource() function listed in Example 3-1, you can call: |
Pixel color1 = (Pixel) VkGetResource( barChartWidget, "drawingAreaContrastColor1", XmCForeground, XmRPixel, "Black" ); |
You must handle some resources programmatically. For example, the IRIX Interactive User Interface Guidelines suggests that your application use a different color for text fields that are not editable than it uses for editable text fields. The IRIS IM text widget currently does not change colors automatically when set to read only mode; so your application must handle this itself. The correct color is provided by schemes as the symbolic name ReadOnlyBackground, and can be retrieved by the resource readOnlyBackground. Assuming that you've created the getColorResource() function listed in Example 3-1, the following code illustrates this process:
ro = getColorResource( textw, "readOnlyBackground", XmCForeground); XtVaSetValues( textw, XmNeditable, FALSE, XmNbackgroundColor, ro, NULL); |
![]() | Tip: The equivalent IRIS ViewKit code would be: |
Pixel ro = (Pixel) VkGetResource( textw, "readOnlyBackground", XmCForeground, XmRPixel, "White" ); XtVaSetValues( textw, XmNeditable, FALSE, XmNbackgroundColor, ro, NULL); |
Table 3-1 lists the pre-defined scheme resources and symbolic values. You can use the resources to retrieve color and font values from within your application as described in “Directly Accessing Colors and Fonts”. You can use the symbolic values to assign colors and fonts to widgets in resource files as explained in “Assigning Non-Default Colors and Fonts to Widgets”.
Table 3-1. Pre-Defined Scheme Resources and Symbolic Values
Resource | Symbolic Value | Intended Use |
---|---|---|
basicBackground | BasicBackground | Background of application |
textForeground | TextForeground | Color of text characters |
textBackground | TextBackground | Background of multi-line text widgets |
textFieldBackground | TextFieldBackground | Background of single-line text field widgets |
readOnlyBackground | ReadOnlyBackground | Background of read-only text and text field widgets |
textSelectedBackground | TextSelectedBackground | Background when text is selected with the mouse |
textSelectedForeground | TextSelectedForeground | Color of text characters when text is selected with the mouse |
disabledTextForeground | DisabledTextForeground | For future use, this color will indicate disabled text instead of stippling. |
scrolledListBackground | ScrolledListBackground | Background of scrolled list widgets |
scrollBarTroughColor | ScrollBarTroughColor | Trough of scrollbar |
scrollBarControlBackground | ScrollBarControlBackground | Scrollbar controls (thumb, searchbutton) |
buttonBackground | ButtonBackground | Background of push buttons |
selectFillColor | SelectFillColor | Fill color for standard IRIS IM radio and toggle buttons |
selectColor | SelectFillColor | IRIS IM toggle and check fill color |
checkColor | CheckColor | IRIX Interactive Desktop toggle check mark color |
radioColor | RadioColor | IRIX Interactive Desktop radio pip color |
indicatorBackground | IndicatorBackground | IRIX Interactive Desktop background color for toggles and radios |
warningColor | WarningColor | Background color for icons in warning dialogs |
errorColor | ErrorColor | Background color for icons in error dialogs |
informationColor | InformationColor | Background color for icons in information dialogs |
wMBackground | WMBackground | Window manager colors. Note that 4Dwm currently does not pick up foreground. “Active” colors are used for window manager borders with mouse focus. |
wMActiveBackground | WMActiveBackground |
|
wMForeground | WMForeground |
|
wMActiveForeground | WMActiveForeground |
|
alternateBackground1 | AlternateBackground1 | Can be used as background color for widgets or text areas. Guaranteed to be different from one another, contrast with basic background and text background, and can have text drawn on them. |
alternateBackground2 | AlternateBackground2 |
|
alternateBackground3 | AlternateBackground3 |
|
alternateBackground4 | AlternateBackground4 |
|
alternateBackground5 | AlternateBackground5 |
|
alternateBackground6 | AlternateBackground6 |
|
drawingAreaBackground | DrawingAreaBackground | Background of drawing area widgets (typically used for graphs) |
drawingAreaContrastColor1 | DrawingAreaContrastColor1 | Contrast colors for drawing areas (typically used for graphs and trees). These colors are guaranteed to be different from one another, different from the drawing area background, and can have text drawn on them |
drawingAreaContrastColor2 | DrawingAreaContrastColor2 |
|
drawingAreaContrastColor3 | DrawingAreaContrastColor3 |
|
drawingAreaContrastColor4 | DrawingAreaContrastColor4 |
|
highlightColor1 | HighlightColor1 | Bright highlights suitable for small color spots. The first four are supposed to be in the same hue family as the corresponding DrawingAreaContrast colors so that the pair may be used for doing highlights in an annotated scrollbar. These colors are typically used for outlining and drawing graphs, wherever a small amount of color needs to be highly visible. |
highlightColor2 | HighlightColor2 |
|
highlightColor3 | HighlightColor3 |
|
highlightColor4 | HighlightColor4 |
|
highlightColor5 | HighlightColor5 |
|
highlightColor6 | HighlightColor6 |
|
highlightColor7 | HighlightColor7 |
|
highlightColor8 | HighlightColor8 |
|
redColor | RedColor | Colors that can be used for various graphics purposes. These colors always approximate their names, but may be slightly adjusted to blend with each scheme. Typically used in graphs and charts. |
orangeColor | OrangeColor |
|
yellowColor | YellowColor |
|
greenColor | GreenColor |
|
blueColor | BlueColor |
|
brownColor | BrownColor |
|
purpleColor | PurpleColor |
|
boldLabelFont | BoldLabelFont | Bold labels, such as column headings |
smallBoldLabelFont | SmallBoldLabelFont | Labels for tight packing situations |
tinyBoldLabelFont | TinyBoldLabelFont | Labels where space is at a premium |
plainLabelFont | PlainLabelFont | Button labels, also can be used for values in “Name: Value” pairs |
smallPlainLabelFont | SmallPlainLabelFont | Small buttons |
obliqueLabelFont | ObliqueLabelFont | Menus |
smallObliqueLabelFont | SmallObliqueLabelFont | Small menus |
fixedWidthFont | FixedWidthFont | Text areas where fixed width is mandatory, for example where it's important that columns line up |
smallFixedWidthFont | SmallFixedWidthFont | Text where a fixed-width font is appropriate but space is at a premium |
SGI strongly recommends that you use existing scheme colors for your application. Using the existing scheme colors ensures that your application will work with all schemes. However, you may need to add colors in some basic cases.This section explains how to extend Schemes to support new colors when necessary.
To extend a scheme, you create new symbolic values for the resources you need and then define bindings between these values and resources that your application can retrieve. This section describes the internal organization of scheme files and then describes how to define these symbolic values and mappings.
All system scheme files are kept in the directory /usr/lib/X11/schemes by default. This directory contains several subdirectories, one for each scheme. The directory Base serves as the basis of all schemes, although it is not a user-identifiable scheme itself. Base contains at least three files: Base, BaseColorPalette, and FontPalette. You may see other files as well.
Each of the palette files (BaseColorPalette and FontPalette) contain cpp-style definitions of symbolic names that represent colors and fonts. The Base file (referred to as a map file) contains the default mappings between these symbolic names and specific resources, using the same format as all X resource files.
For example, the Base file contains a line like:
*XmText*foreground: TextForeground |
This says that all Text widgets should use the color represented by TextForeground as their foreground color. By default, all schemes share the mappings specified in this Base file. However, the value assigned to each symbolic name can vary from scheme to scheme. For example the Mendocino scheme defines TextForeground to be #fffffe (white) whereas the Milan scheme defines TextForeground to be #000000 (black). The scheme mechanism evaluates these specifications at run time, based on the scheme specified by the user.
By default, all applications pick up the definitions in the Base file and the palette files from the selected scheme. However, applications can load additional scheme files as well.
There are two methods for extending a scheme. The first is to add additional mappings between existing colors and widgets in your application. This may be necessary if you want to bind colors of fonts to your widgets in a different way, or if you are using custom widgets that are not handled by the basic scheme mappings. You should do this by adding resources to your application's app-defaults file, using the SGI_DYNAMIC mechanism described earlier.
The second situation occurs when you would like to use colors or fonts that are not provided as a part of the existing schemes. Your should try to avoid this situation when at all possible, because users can use the scheme editor to create new schemes, and there is no current mechanism for using the scheme editor to adjust any additional colors your application may define. The standard scheme palettes contain over 40 colors, which should be enough for most situations.
To add new colors to the existing schemes, you need to create a new palette file that contains cpp-style definitions of those colors. To get your application to load this new palette, you then need to set a resource, paletteFileList, in your application's app-defaults files that specifies as a comma-separated list all custom palette files to be loaded.
For example, assume you have an application whose class name is Calendar and that you need two colors that you refer to in your program symbolically as brightColor and darkColor. If no color in the exiting schemes satisfies your requirements for this color, you will need to extend a scheme. Here are the steps you'd follow:
Define the colors in a palette file. By convention, you should name this file <AppClass>Palette, where <AppClass> is the application class of your application. In this case, you would name the palette CalendarPalette. It would contain the lines:
#define BrightColor red #define DarkColor MidnightBlue |
You can use any color names available on your target systems, as well as RGB specifications. If the resources you are using are dependent on the gamma setting, you should account for this in the palette file. You can handle the commonly used gamma settings like this:
#ifdef GAMMA_1_0 #define BrightColor <color that looks right on 1.0 gamma> #define DarkColor <color that looks right on 1.0 gamma> #endif #ifdef GAMMA_1_7 #define BrightColor <color that looks right on 1.7 gamma> #define DarkColor <color that looks right on 1.7 gamma> #endif #ifdef GAMMA_2_4 #define BrightColor <color that looks right on 2.4 gamma> #define DarkColor <color that looks right on 2.4 gamma> #endif |
The scheme mechanism handles gamma other than those listed here by finding the closest match.
Create additional palette files as needed. If your new resources need to change values when a scheme changes, create a file named CalendarPalette for each scheme you want to support. For each scheme, choose the colors that look right for that scheme. Note that if you do not support all existing schemes, the values of your new scheme resources defaults to the values in Base; so your application may not look right when a user selects that scheme.
Set your application's paletteFileList resource to load the new palettes. In this example, you would add the following line to your app-defaults file:
Calendar*schemeFilePaletteList: CalendarPalette |
When you install your software on a user's machine, you need to install the executable, the app-defaults file, and any other files specific to your application. You must also install your palette files into the directory of each scheme you support. You should, at a minimum, support the schemes found in /usr/lib/X11/schemes. You may also want to support schemes you find installed in /usr/local/schemes.
For best results, be sure to test your application against all available schemes, and watch for any anomalies. As an added precaution, you can try using the Scheme Browser, schemebr (available from the “Color Schemes” option of the Customize menu in Desktop toolchest), to create some variations on existing schemes and see how your program reacts. If you have not added any resources and are not setting any colors or fonts in your program or app-defaults files, any scheme should be reasonable. If you have extended the schemes or set colors directly in your application, you should watch carefully to see how your application reacts as colors change. It is always possible to use the scheme editor to create a very bad scheme, but if your program seems more sensitive than others to changes, you should think more carefully about your use of color.
You can also include your own new schemes in your software distribution; however, be aware of the following concerns:
The largest benefit of schemes is the users' ability to change to schemes of their choice; so even if you create a scheme that you prefer for your application, make sure your program looks good with the existing schemes.
If you install your scheme on a user's system, the user may apply that scheme to other applications. If you attempt to design a new scheme, make sure the scheme works reasonably with other applications on the desktop.
The easiest way to design a new scheme is to use the Scheme Browser, schemebr, available from the “Color Schemes” option of the Customize menu in Desktop toolchest. For best results, you should base your scheme on an existing scheme, preferably one of the standard ones supported by SGI. If you make only minor changes, your new scheme should work with other programs. Once you have created and saved your new scheme, you can retrieve the files from your $HOME/.desktop-<hostname>/schemes directory, where <hostname> is the name of your system. You can install your scheme in /usr/local/schemes/<SchemeName>, where <SchemeName> is the name you have chosen for your scheme. Once installed, this scheme appears in the Scheme Browser as a local scheme. You can also include this scheme with your software distribution.
In some rare situations, you may want your application to use one particular scheme, not the one that the user selects. SGI strongly recommends that you not use this approach, but if your application has special needs, the process is simple to do. Specify the value of the scheme resource in your application's app-defaults file using a complete path name. For example:
YourApp*scheme: /usr/lib/X11/schemes/Milan
|
When using this approach, the location of the scheme directory is unimportant. For example, if you've designed a custom scheme for your application, you can place the scheme directory in special configuration directory for your application. For example:
YourApp*scheme: /usr/lib/YourApp.config/YourAppScheme
|
This setting implies that /usr/lib/YourApp.config/YourAppScheme is a scheme directory. This means that the directory YourAppScheme would need to contain the files BaseColorPalette (containing the color palette you have defined), a file whose name is the same as the scheme that contains mappings, and a file named FontPalette. Normally, the FontPalette file would be a copy of the file in /usr/lib/X11/schemes/Base, and the map file would be the same as /usr/lib/X11/schemes/Base/Base, but renamed to have the same name as your scheme.