Jump to: navigation, search

GEMS Stylesheet Tutorial

GEMS Stylesheets Overview

GEMS stylesheets are intended to work similarly to Cascading Style Sheets (CSS) for HTML. The goal of stylesheets is to separate the visual presentation of the model from the structural representation and code. Stylesheets can be applied to individual models, all models in a directory, or entire modeling languages. You can also override stylesheets on a per model or per directory basis.

Creating a Stylesheet

GEMS uses specific naming convention for stylesheets. All stylsheets should either be named "dsml.css" or "<your_models_file_name_with_ext>.css". For example, if you have a model named "deployment.dmod" and you want to override the stylesheet for just that model, your stylesheet should be named "deployment.dmod.css".

Generally, when you want to create a stylesheet for your modeling language, you should create a "dsml.css" file an place it in the root directory of your modeling tool's project. By default, GEMS automatically generates a "dsml.css" file there for you. You can also scope your stylesheets in different ways to acheive different effects.

Where you place the stylesheet file determines the scope that it is applied to. When GEMS attempts to resolve stylesheets, it first starts with the directory containing the model. Let's assume that your model file is located at "/myworkspace/mymodels/deployment.dmod" and that your modeling tool plug-in is located in the jar file "/eclipse/plugins/org.gems.test.deployment.jar". GEMS will use the following lookup order to find a stylsheet for your model:

  1. "/myworkspace/mymodels/deployment.dmod.css"
  2. "/eclipse/plugins/org.gems.test.deployment.jar/deployment.dmod.css"
  3. "/myworkspace/mymodels/dsml.css"
  4. "/eclipse/plugins/org.gems.test.deployment.jar/org/gems/test/deployment/dsml.css"
  5. "/eclipse/plugins/org.gems.test.deployment.jar/dsml.css"

Updating a Model's Stylesheet Without Restarting Eclipse

The latest version of GEMS contains a "Reload Model" option that will automatically update the stylesheet, triggers, palette, menu, and constraint files. To reload a model and hence its stylesheet:

  1. Make changes to the stylesheet and save them
  2. Right-click, "Modeling", "Reload Model"

Any unsaved changes to the model will be lost. The model will be reset to its previously saved state and the stylesheet for it will be reloaded.

Stylesheet Syntax

GEMS stylsheets use a syntax similar to CSS stylsheets for HTML. First, each set of style directives is scoped by a "selector" that determines what model elements it gets applied to. For example:

Node {
  active-style:true;
  ....
}

This style would be applied to all elements of type "Node". The "Node" specification is the selection that determines which elements have the style applied. Selectors use inheritance, so any subclasses of Node would also have the Node style applied. The style attributes associated with the more specific selectors will take priority over the more general style selectors. For example:

Node {active-style:true; ContentLayout:FlowLayout; TitleTemplate:A Node;}

SomeNodeSubclass {active-style:true; ContentLayout:XYLayout;}

In this stylsheet, there are two styles, one for Nodes and one for SomeNodeSubclass. Each instance of a Node that is not an instanceof SomeNodeSubclass will have the style attributes:

ContentLayout:FlowLayout; 
TitleTemplate:A Node;

Nodes that are instances of SomeNodeSubclass, however, will have a different set of style attributes applied:

ContentLayout:XYLayout; 
TitleTemplate:A Node;

Thus, SomeNodeSubclass inherits the "TitleTemplate" style attribute but overrides the value for "ContentLayout".

As we have begun to show, each selector is followed by braces and then a series of style attributes in the form:

StyleAttributeName : StyleAttributeValue ;
StyleAttributeName1 : StyleAttributeValue1 ;

If we need to use ":", ";", or "{}" within an attribute value, we can escape them as follows:

StyleAttributeName : { StyleAttributeValue };

Everything between "{ }" will be escaped, allowing us to use the restricted characters. We can also place comments in stylesheets using "/** **/" syntax:

/** The style for all Nodes **/
Node {active-style:true; ContentLayout:FlowLayout; TitleTemplate:A Node;}

/** This style inherits from Node style **/
SomeNodeSubclass {active-style:true; ContentLayout:XYLayout;}

Style Attributes

GEMS supports a large number of style attributes. Generally, a small subset of them tend to be most useful. The following sections present some of the most useful attributes.

A very important note! All GEMS styles MUST have the following style attribute at the begining of them:

Node {
 active-style:true;
 ...
}

Originally, GEMS used another stylesheet language that provided much less functionality. In order to provide backwards compatibility, all new stylesheet styles must begin with the "active-style:true;" attribute.

Setting Icons

First, let's look at how we can change the icons used by a modeling element:

Node {
   active-style:true;

   /** The icon used for the element when
         it is not expanded. **/
   ExpansionPanel.ClosedImage:resources/icons/Node.gif;
}

The style attribute "ExpansionPanel.ClosedImage" sets the icon used by the modeling elements on the canvas when they are not expanded. We can also set the icon used by an element in the tree view:

Node {
   active-style:true;

   /** The icon used for the element when
         it is in the tree view. **/
   TreeImage:resources/icons/NodeTree.gif;
}

Icons can also be set for elements on the palette but this is accomplished through the "dsml.palette" file. Please see the documentation on palette customization for more information on this.

Setting the Title Label of an Element

The title label is the label that by default contains the name of the element and is displayed at the top of the element. The title label can be changed with the attribute "TitleTemplate":

Node { 
  active-style:true;
  TitleTemplate:I am a node!;
}

This is a simple static title that will display the text "I am a Node!" above all elements. Generally, however, we want the titles to be more dynamic and include the Name of the element or other attributes. The TitleTemplate can refer to the attributes of a modeling element in it as follows:

Node { 
  active-style:true;
  TitleTemplate:I am %Name% and my type is %Type%;
}

GEMS will attempt to resolve any names in %% with the value of that attribute on the modeling element. The identifier %Foo% would attempt to be resolved to the "Foo" attribute on the element.

The titles of the elements in the tree view can also be set. To set the tree view titles, use the "TreeTitleTemplate" attribute:

Node { 
  active-style:true;
  TitleTemplate:I am %Name% and my type is %Type%;
  TreeTitleTemplate:%Name% [%Type%];
}

If we prefer to remove the title label altogether, we can use the "ShowName" attribute:

Node { 
  active-style:true;
  ShowName:false;
}

This will completely remove the name label from the model element.

Changing Layouts

The way that the children of an element are laid out can be changed using the "ContentLayout" attribute. For example:

Node { 
  active-style:true;
  ContentLayout:FlowLayout[V];
}

This will change the layout so that all children are laid out in a single vertical column. GEMS supports three built in types of layouts:

  1. FreeFormLayout - all children can be dragged and arranged manually by the modeler. This is the same layout used by the main canvas.
  2. FlowLayout - all children are laid out in a vertical or horizontal row. To create a vertical row FlowLayout[V]. For a horizontal row FlowLayout[H]. To make the minor axis (e.g. everything the same width in a vertical row) consistent among the children FlowLayout[V, StretchMinorAxis].
  3. DirectedGraphLayout - uses a directed graph algorithm to attempt to minimize crossings among connections.

Changing Borders

Each model element has five panels that you can adjust the borders for:

  1. TopPanel
  2. BottomPanel
  3. LeftPanel
  4. RightPanel
  5. CenterPanel

Each panel has a number of options for setting the border. For example:

NodeResource {
    active-style:true;
    TopPanel.Border.Color:220,220,220;
    TopPanel.Border.DrawTop:false;
    TopPanel.Border.DrawLeft:false;
    TopPanel.Border.DrawRight:false;
    TopPanel.Border.DrawBottom:true;
    TopPanel.Border.Width:1;

We can also explicitly set the class used to draw the border:

NodeResource {
    active-style:true;
    TopPanel.Border:org.my.border.MyBorder;

If we want to remove a border completely:

NodeResource {
    active-style:true;
    TopPanel.Border:null;

Toggling the Attributes Panel on an Element

Each element has a small panel that can be expanded to see the attributes of the element. This panel is different from the properties view in Eclipse. To turn this panel on or off, we can use the "ShowAttributes" attribute:

NodeResource {
    active-style:true;
    ShowAttributes:false;

Applying Styles to Connections

Connections (lines drawn between elements) can also have styles applied to them. In the metamodel, the name you gave to a Connection declaration can be used in a selector. For example, in the deployment example, we created a Connection declaration called Deployment. We can apply a style to it:

Deployment {

    /** Line color in RGB **/
    line-color:(50,200,50);
  
    /** This is the line's style.
        Valid values are:
        solid,dash,dash-dot,
        dash-dash-dot **/
    line-style:dash;
  
    /** Line width **/
    line-width:2;
  
    /** The decoration for the
        end of the connection. 
        Valid values are arrow, diamond, butt. **/
    dst-decoration:arrow;
  
    /** This would set the source decoration:
    src-decoration:arrow;
    **/
  }

We can also add labels to the connection to display useful information, such as connection attributes:

Deployment {
 
 /** This would define a label to add to the connection.
        Any number of labels can be defined and added to
        each connection type. The first part of the
        definition is the template for the label's
        text. Attributes of the connection can be referred
        to just as they can with elements. The next parameter
        is where the label should appear. Valid values are
        (dst-top,dst-bottom,src-top,src-bottom,middle).
        The next parameter is the foreground for the
        label. The next parameter is the background for
        the label. Next, font and font-size. The
        final three parameters are not working at the
        moment and are for specifying italics, bold,
        etc. 
 **/

    @mylabel: A Connection Label With %SomeAttribute%, dst-top, (100,100,255), 
               (255,255,255), Verdana, 10, -15, false, false, false;
}

Dynamically Changing Styles when State Changes

Often, we want the way an element looks to change depending on its state. GEMS supports dynamically changing styles through the use of "tags". A tag is similar to a CSS class. A tag allows us to create a more refined selector. Whenever an element's currently applied set of tags changes, the styles for the element are automatically updated.

Let's say that we want to display Nodes that do and do not have Components hosted on them differently. We can create a "free" tag to indicate a Node with no Components hosted by it. The free tag is simply a text string that can be added to an element's list of tags with a call:

Node node = ...;
node.addTag("free");

Much more detail on adding/using tags is available in the documentation for GEMS event listeners or GEMS triggers. For now, let's assume that we have some Java code to add / remove the "free" tag as the model changes. We can create two different styles for Nodes:

Node {
  active-style:true;
  TitleTemplate:%Name% [hosts components];
}

Node[free] {
  active-style:true;
  TitleTemplate:%Name% [does not host any components];
}

When the "free" tag is not applied to a Node, the first style will be used and the Node's title will have the text "[hosts components]". When the "free" tag is applied, the second style will be applied to the node and its title text will now use the extra text string "[does not host any components]" instead.

GEMS automatically applies a number of useful tags to capture the current selection:

  1. selected - is applied when the element is selected
  2. sel-child - is applied when the element is a chlid element of the current selection
  3. sel-target - is applied when the element is a target of a connection originating at an element in the selection

Using these built-in styles, we can create a custom Node style for when an element is selected:

Node {
 active-style:true;
 TopPanel.Border.Color:200,200,0;
 BottomPanel.Border.Color:200,200,0;
 CenterPanel.Border.Color:200,200,0;
 RightPanel.Border.Color:200,200,0;
 LeftPanel.Border.Color:200,200,0;
}

All Known Style Attributes

A list of all known style attributes is automatically generated into the bottom of each new dsml.css file produced by GEMS.