DroidDiagram Programmer's Guide
Styles and Themes

The style and theme system provides a consistent way to customize the appearance of a Diagram and its items. By using styles and themes, it is easier to achieve coherent look and feel across the entire diagram. In addition, changing the look and feel can be achieved by simply replacing the current theme. New themes can be designed in the visual environment of the Theme Editor tool and subsequently used and distributed as XML files. Several pre-defined theme files are installed under the Themes subfolder of the control's root installation folder.

Styles

The style is a set of properties. Styles can be applied to diagrams and individual diagram items and this can potentially affect the values of some properties of the target object. More specifically, if the value of a style-affected property in the target object is null, then the value is obtained from the associated style. The style does not necessarily need to provide values for all of its properties. If a styled property is null and it is not defined in the associated style, the style system searches for a value in the current theme. A complete value precedence list can be found later in this topic.

The styles are represented by the Style class and its various subclasses. Styles can be applied to diagram objects through the Style property of the Diagram class and to diagram items through the Style property of the DiagramItem class. Styles can also participate in themes, in which case they affect all objects of specific type.

Themes

The theme is a set of styles, each associated with specific diagram or item type. When the theme is applied to a diagram, the styles registered in the theme affect all objects of their associated type.

Themes are represented by the Theme class and can be assigned to Diagram objects through the setTheme method. Styles are associated with types within the theme through the registerStyle method. The following code creates a new theme, with a single style for ShapeNode items and applies this theme to an existing diagram.

Java  Copy Code

Theme theme = new Theme();
ShapeNodeStyle style = new ShapeNodeStyle();
style.setFontFamily("Courier New");
theme.registerStyle(ShapeNode.class, style);
diagram.setTheme(theme);

Alternatively, themes can be loaded from XML files by calling the loadFromXml method. Such XML files can be produced by the Theme Editor tool, or by calling the saveToXml method of an existing theme.

Value Precedence

The style and theme system is hierarchical. This means that, when a value of a styled property is requested, the system starts searching for this value along a chain of defined styles. The system returns the first valid value encountered. If no valid value is encountered along the chain, the system returns a globally defined default value for the property. The following list explains the search order in more details:

  1. If the local value of the object is not null, the local value is returned.
  2. If the object has a style and the property in this style has value, this value is returned.
  3. If the object is an item, which is part of a diagram, the local style of the diagram is searched.
  4. If the object is an item, which is part of a diagram and the diagram has associated theme, the theme is searched for styles registered for the item's type or its base types. If a style with a defined property value is found, this value is returned.
  5. Similar search as the previous one is performed for a theme-registered style for the Diagram class.
  6. If the above steps do not produce value; the system returns a globally define default for the property.

For example, if the effective value of the text brush property of a ShapeNode is requested (through the getEffectiveTextBrush method), the style system performs the following search, according to the above rules:

  1. If the node's TextBrush property is not null, its value is returned.
  2. If the node's Style is set and the DiagramItemStyle.TextBrush property in this style has value, this value is returned.
  3. If the node is part of a diagram, the Diagram.Style is set, and the DiagramStyle.TextBrush property of this style has value, this value is returned.
  4. If the node is part of a diagram and the Diagram.Theme is set, the theme is searched for a style registered for the ShapeNode type. If there is such style and its DiagramItemStyle.TextBrush property has value, this value is returned.
  5. Similar search as the previous one is performed for a theme-registered style for the Diagram type.
  6. Finally, the system returns a globally-defined default value for the TextBrush property (which is a solid Black brush).

Theme Editor

The Theme Editor provides simple visual environment for theme creation and modification. The editor displays a sample diagram with items of various types and exposes a list of all possible built-in diagram and item styles through a property grid to the left. Any modification of the style properties in the grid is immediately reflected on the diagram to give a preview on what effect the change would have if the theme is applied to a diagram. The theme can be saved at any time through the Save menu. Existing themes can be opened and modified.

The following image illustrates the Theme Editor in action:

Custom Styles

The following section describes how to enable styling for properties of custom item classes. To enable styling, create a custom style class by deriving from the closest existing type. For example, for a custom ShapeNode (say, MyNode), the custom style needs to inherit from ShapeNodeStyle:

Java  Copy Code

public class MyNodeStyle extends ShapeNodeStyle
{
}

For each property in MyNode that needs to be styled, define a property with the same name and type in the MyNodeStyle class by following the pattern below. For example, if MyNode contains a property MyBrush of type Brush, the following code defines its corresponding style property:

Java  Copy Code

class MyNodeStyle extends ShapeNodeStyle
{
    public MyNodeStyle()
    {
        myBrushProperty = registerProperty("MyBrush");
    }

    public Brush getMyBrush()
    {
        return (Brush)getValue(myBrushProperty);
    }
   
    public void setMyBrush(Brush value)
    {
        setValue(myBrushProperty, value);
    }

    private Object myBrushProperty;
}

Now, in the custom MyNode class, define a new method, getEffectiveMyBrush, which will return the actual value of MyBrush:

Java  Copy Code

public Brush getEffectiveMyBrush()
{
    // Checking for local value
    Brush localValue = getBrush();
    if (localValue != null)
        return localValue;
    // Querying the property value through the style system
    return (Brush)getValue("MyBrush");
}

Remember to register the style class for serialization, along with the custom node class:

Java  Copy Code

Diagram.registerClass(MyNode.class, "MyNode", 1);
Diagram.registerClass(MyNodeStyle.class, "MyNodeStyle", 1);

Now you can style and theme your custom nodes. Here is a theme, which affects the MyBrush property of all MyNode items in a diagram:

Java  Copy Code

Theme theme = new Theme();
MyNodeStyle myNodeStyle = new MyNodeStyle();
myNodeStyle.setMyBrush(new SolidBrush(Color.lightGray));
theme.registerStyle(MyNode.class, myNodeStyle);
diagram.setTheme(theme);

It is important to remember that there are no global default values for custom properties. Therefore you should be prepare to handle null values from getValue or ensure that at least one of the five steps in the precedence list above produces a value.