Style (tag)

From JAXXWiki

The <style> tag allows CSS stylesheets to be specified in a JAXX file. The CSS support provided by JAXX is similar in concept to HTML's CSS stylesheets, but there are a few important differences.

Contents

The <style> tag

The <style> tag accepts either an inline stylesheet, as in:

<style>
  JTextField {
    background: #ffffe0;
  }
</style>

Or a reference to an external stylesheet using the source property, as in:

<style source='main.css'/>

What stylesheets do

Stylesheets define sets of attributes that apply to certain components within an application. You can define attributes that apply to all components, a particular group of components, or even a single specific component.

The attributes you specify within a stylesheet rule are treated as if they had appeared as XML attributes within the component's tag. The following two JAXX files are exactly equivalent:

With a stylesheet:

<style>
  #styledLabel {
    foreground: red;
    font: {new Font('Verdana', 0, 14)};
  }
</style>
<JLabel id='styledLabel' text='Red 14-point Verdana'/>

With inline attributes:

<JLabel id='styledLabel' text='Red 14-point Verdana' 
    foreground='red' 
    font='{new Font("Verdana", 0, 14)}'/>

Any "ordinary" attribute of a component can be specified using CSS stylesheets. The only exceptions are id, constraints, constructorParams, and styleClass, which are all special attributes that wouldn't be useful in stylesheets anyway.

Note that you specify values exactly the way you would if the attribute appeared directly on a class tag. This even extends to data binding expressions, which are fully supported.

CSS selectors

A CSS selector is an expression that "selects" components to operate on. The example above uses the selector #styledLabel, which means "the component with the ID 'styledLabel'". There are four basic types of selectors, which may be combined into compound expressions:

  • Java Class: This is the simple (no package name) name of a Java class. All instances of like-named classes, or subclasses of like-named classes, are selected. The Java class comes at the beginning of the expression and does not have a prefix symbol. A star (*) may be used in place of a Java class; stars are wildcards which match all Java classes. It is generally better to omit the star unless it is the only thing in the selector -- there is no technical difference between *.bold and .bold.
  • ID: This is the JAXX id of a component. Only one component per JAXX file can possibly match, but across multiple files a single stylesheet could still affect multiple components.
  • Style Class: This is the CSS style class of a component, specified using the styleClass attribute. All components with matching styleClass attributes are selected. The style class follows the ID (if any) in the selector and is prefixed with a dot (.).
  • Pseudoclass: A pseudoclass is a group to which a component may belong at some times and not others, based on its current state. Examples of pseudoclasses are mouseover and disabled. See the page on CSS pseudoclasses for full documentation. Pseudoclasses appear that at the end of the selector and are prefixed with a colon (:).

The following expressions are all valid selectors:

JLabel Selects all classes named JLabel (in any package), and subclasses of classes named JLabel.
.bold Selects all components with the attribute styleClass='bold'.
#title Selects the component with the attribute id='title'.
JButton.flat Selects all JButtons with the attribute styleClass='flat'.
#leftSide.special Selects the component with the attributes id='leftSide' and styleClass='special'.
JTextComponent:focused Selects all subclasses of JTextComponent, but only when they are focused. The effect will be dynamically applied and removed as focus shifts.

It is not an error to specify rules that do not match anything. If there is no component with the id title, a rule with the selector #title simply has no effect.

Cascading

The 'C' in CSS stands for "cascading". Stylesheets cascade, so that their rules apply to subclasses as well as contained (descending) components. If a stylesheet rule applies to a component Foo, which is itself a JAXX component, then the rule also applies to all tags within Foo. Similarly, if Foo is subclassed, its subclasses will inherit all styles that apply to it. More-specific stylesheets (defined in a subclass of Foo) override properties set by less-specific stylesheets (set in Foo itself).

As JAXX is fully compiled and does not use reflection at runtime, stylesheets are fully applied at compile time. Components added dynamically using Java code are not visible at compile time and therefore will not be affected by any stylesheets. In other words, JAXX stylesheets affect all JAXX tags, but do not effect any components that do not directly correspond to JAXX tags.

Why use stylesheets?

Stylesheets are a very powerful mechanism for controlling an application's appearance.

  • You can style many components with a single stylesheet rule. This is much easier and more maintainable than manually adding the attributes to each element
  • Stylesheets separate appearance from content, similar to the way Swing models separate data from views
  • You can completely alter the appearance of an application simply by swapping in a new stylesheet, making for very easy customization (especially useful for branding the same application differently for different customers)

Ethan's blog has an entry on using CSS to control an application's appearance: Style Swing components using CSS

Differences from HTML

While similar in concept to the CSS stylesheets found in HTML, JAXX stylesheets are not the same. These are the major differences:

  • Different properties are supported. CSS names like color and padding do not work; you must instead use JAXX attribute names like foreground and border.
  • Selectors specify Java class names, not XML element names. The stylesheet <style>JButton { foreground: red; }</style> applies to classes with the simple name JButton (which includes javax.swing.JButton and com.foo.JButton), as well as their subclasses. If you need to tighten up the selection, the styleClass attribute allows you to directly control which components are selected.
  • Contextual selectors are not supported. These are selectors of the form H1 B, which means "<B> tags inside of <H1> tags".