On most of my customer projects that involved RAP, we had to adapt the look of the application to a Corporate Identity branding. In this blog I want to give a quick overview of the tools and options that we have in such situations. In addition, I want to add a few thoughts and comments on the patterns that we have used at EclipseSource on customer projects and mention potential drawbacks and other criteria that might help you select your best option.
The most obvious choice for adding simple custom styling effects (at least for me :-) since I programmed SWT before RAP appeared) is to use the RWT/SWT API to modify the widgets in my application. Setting the font, background color, company logo and other simple tricks can be easily achieved. To ensure that all widgets used in the project follow the same style guide, one could theoretically subclass the most common widgets (not a good practice though) or use a central factory (better choice) that adapts the widgets created. A very good example of such a factory is the FormToolkit from the org.eclipse.ui.form bundle.
But since RWT is not only an SWT implementation but also a web toolkit you can of course use CSS to customize the look of your application/widgets. You have three different layers of customization available:
- Theme – Your first option is to work with the Theme. Instead of using the RAP themes provided (default or business), you can create your own. You can basically take an existing theme.css as a template and change the CSS classes to meet your requirements. The names of the classes tell you where they are used. For more details on what you can define and how you can contribute your theme you can check the Eclipse RAP Toolkit help or the Developer’s Guide on eclipse.org/rap.
- Override Theme CSS classes – If you only want to change a few classes in an existing theme, you can contribute a custom CSS file that overrides the classes defined in the theme.css file. This can be very handy, especially because you do not need to change anything in your code. But be aware that all your widgets of the same class share the same CSS style. You can find a guide on how to do this here: Rap: adapt your style.
- Contribute new CSS classes – In situations where you would like to define a handful of styles for a single widget type (e.g. ‘normal’ label vs. ‘error message’ label), you can also add a CSS file that defines your own CSS classes, in the form of custom widget variants. The CSS file itself can be added just like in the previous scenario. However, in this case you need to change the CSS class definition in the RWT widget that you’ve created. Again, please refer to the RAP Toolkit help and the Developer’s Guide for details.
Tips & comments
- CSS – The use of CSS-based styling is of course much more powerful than the styling offered by the RWT/SWT API. A decent designer can implement a very sophisticated look using CSS. The SWT API on the other hand, was mainly targeted at widget toolkits provided by the classical operating systems like Linux and Windows. Clearly, certain things are only achievable with CSS.
- Theme – Creating your own theme is a nice option, but most of the time the ‘overwriting’ of existing theme CSS classes is enough and is easier to implement.
- Use of Web-Designer – If possible, it is always a good option to make use of a specialist in your organization. CSS-design can be delegated to a web designer. CSS definition is not part of my day-to-day job, so I am always happy to use this option whenever a designer is at hand :-).
- Pecking-Order – Remember however, that CSS definitions define the default look of your widget. Setting properties using the RWT API will overwrite the corresponding CSS setting – e.g. no matter what background color you defined in the CSS class for Text Widgets, if you set the property BackgroundColor on your instance, the instance will win.
- Single-Sourcing and the SWT API – The reuse of your code in an RCP and RAP application makes the use of the CSS-based styling less attractive. Most of the time it is not really an option. Especially if you want to keep the look of the RWT and the SWT versions the same, your job is much simpler if you stick with the SWT API option. In this case however, remember (in RAP 1.5) to switch to the business theme – see RAP 1.5: the Workbench and the New Default Theme.
- Single-Sourcing and CSS – Sometimes you may want to use a different styling in the RAP Version of your single-sourced application. Otherwise applications tend to just look ‘wrong’ in the web context. In this case the CSS-based styling is back in the game.
- Widget Sub-classing – Do not subclass widgets. It only creates problems!
- Widget-Factory – I personally really like the widget-factory pattern and use it whenever possible. Here is why:
- The single-sourcing strategy pattern is easily integrated and implemented – see http://www.eclipse.org/rap/singlesourcing.php for more info.
- Custom variant values can be easily set by creating, for example, a factory method for error message labels (with its own CSS class) .
- Reuse of code.
- It is a central place where new widget related features can be implemented, like a listener that changes the background color on the focused widget. This gives you great flexibility. Especially once your application has grown you will appreciate this!
- The Widget-Factory has only one disadvantage that I can think of: the use of a designer like WindowBuilder (see related post) is not compatible.
- Eclipse 4 – With e4 the SWT API has been enriched with CSS functionality. RAP is not yet e4 enabled (see related post). But once it is, this blog post will have to be reevaluated ;-).
RAP has more than one option for customizing the general look of your application. Especially with the use of the CSS customization, one can completely redesign an app without changing a single line of code. However if you single-source, avoid CSS customization to keep your code ‘single’. Either way, try to use a widget factory!
These tips are based on my personal experiences – please feel free to add your ‘penny’s worth’ or even to challenge my statements :-)