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 Indigo Magic Desktop and other applications. “Schemes for Colors and Fonts” in Chapter 3 in Indigo Magic User Interface Guidelines describes the guidelines for using schemes in the Indigo Magic 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.
“Testing Your Application with Schemes” 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. Silicon Graphics 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 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 “Colors” 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 Indigo Magic 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 don't 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 might 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.)
This section describes how to write your application for use with schemes.
Silicon Graphics incorporates schemes in its implementation of Xt, so you don't 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 |
where AppClass is your application's class name. This activates all aspects of schemes.
![]() | Note: To ensure that users don't 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 can't be changed by users, call the function SgiUsesScheme():
void SgiUsesScheme(char *value) |
value can be either “all” or “none”. This function requires that you include the header file <X11/SGIScheme.h>.
The schemes map file automatically handles applying colors and fonts to most IRIS IM widgets based on the widgets' class names. Unfortunately, IRIS IM doesn't have unique class names for menu bars, menu panes, and option menus. To allow schemes to be applied to these elements, your application must follow some simple naming conventions for these widgets. Schemes expect applications to 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”. Don't hard code colors or fonts in your application because they might 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 might not be correct if a user changes the scheme.
There are obviously some cases for which this recommendation doesn't 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 aren't derived from schemes.
Fonts are usually less critical than colors, although the best visual effects will be produced if you use only the fonts defined in the schemes. You should be aware that on low-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 shouldn't 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 might 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 might 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 could 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 could 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 could set a label widget to be “red” as follows:
YourApp*label*background: SGI_DYNAMIC RedColor |
The exact shade of red will change from scheme to scheme, but will always be “reddish” and always fit with the other colors in the scheme.
If necessary, you can also use non-scheme colors and fonts, although Silicon Graphics strongly recommends that you don't do this. In particular, if you hard-code a color, the user might select a scheme in which that color doesn't provide the contrast you desire. The color could even be “lost” among the other scheme colors. Non-scheme fonts are less likely to cause problems, but your application will still 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 could 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 might need to access some of the scheme's colors or fonts directly from within a program. For example, you might 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 could 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'll use the color in.
![]() | Tip: There is a far simpler method for retrieving a resource value if you're using the IRIS ViewKit toolkit. Instead of writing the getColorResource() function listed in Example 3-1, you could simply call: |
Pixel color1 = (Pixel) VkGetResource( barChartWidget,
"drawingAreaContrastColor1",
XmCForeground, XmRPixel,
"Black" );
|
You must handle some resources programmatically. For example, the Indigo Magic 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 ReadOnlyColor, and can be retrieved by the resource readOnlyColor. Assuming that you've created the getColorResource() function listed in Example 3-1, the following code illustrates this process:
ro = getColorResource( textw, "readOnlyColor",
XmCForeground);
XtVaSetValues( textw, XmNeditable, FALSE,
XmNbackgroundColor, ro,
NULL);
|
![]() | Tip: The equivalent IRIS ViewKit code would be: |
Pixel ro = (Pixel) VkGetResource( textw, "readOnlyColor",
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 “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 | Indigo Magic toggle check mark color |
radioColor | RadioColor | Indigo Magic radio pip color |
indicatorBackground | IndicatorBackground | Indigo Magic 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 doesn't 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 will 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 |
For best results, you should be sure to test your application against all available schemes, and watch for any anomalies. As an added precaution, you might try using the Scheme Browser, schemebr, (available from the “Colors” option of the Customize menu in Desktop toolchest) to create some variations on existing schemes and see how your program will react. 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 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, but there are several things to be aware of. First, 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, you should still make sure your program looks good with the existing schemes. Second, if you install your scheme on a user's system, the user might apply that scheme to other applications. If you attempt to design a new scheme, you should attempt to 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 “Colors” 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 Silicon Graphics. Making only minor changes will reduce the chances that the new scheme will not work with other programs. Once you have created and saved your new scheme, you can retrieve the files from your $HOME/.desktop-<hostname>/scheme 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 will appear in the Scheme Browser as a local scheme. You can also include this scheme with your software distribution.
In some rare situations, you might want your application to use one particular scheme, not the one that the user selects. Silicon Graphics 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 |