views:

500

answers:

2

I'm developing some widgets into a library for internal use at the company I work for.

I don't know what's the recommended way to style the widgets.

There are at least these ways:

  • use Widget.setPrimaryStyleName and let the user provide an external css. We use maven archetypes to build applications so we can provide default styles. Anyway I don't like it very much.

  • use the GWT 2.0 CssResourceBundle. So we can compile the CSS into the module and it will be optimized (and it can be browser-dependant too).

  • provide a module with the styling. Something like the default GWT themes. But I don't know how exactly this works.

I want to:

  • make the components as cohesive as I can (don't depend on externally included css's)
  • leave open the door to modify styles (if I want to change the way some widget looks in a concrete application).

What's your experience in this subject?

Note: if you are looking for a definitive answer look through all the answers and the comments. There are different ideas and all good ones. Then choose what is best for you :)

+3  A: 

I think the best way would be to provide styles in a module. This way you will be able to easily restyle, or add "themes" for your controls.

I'm doing a similar project which is hosted on github (http://github.com/markovuksanovic/gwt-styles), so you might want to check that out. You can download the jar file, include it in your project and specify in your module xml that you wanna use that style.. sth like

<inherits name='gwt.theme.flick.Flick'/>

I would suggest you to use new module for your styles so that you can easily switch among styles... (just change the inherits tag). So, for example, if one of your widgets used css class "my-widget", you would have a "style" module (or multiple modules) which would define that css class (in the css file) - this way you could have multiple modules that implement that css class and switching amongst them would be as easy as changing the module name in the inherits tag. This way you would a nicely decoupled code - styles will be independent of the technical implementation of the widgets. If you have some more questions, feel free to ask.

P.S. I forgot to mention above - pay close attention on how the style module is built (build.xml), it's a little tricky. You can find some more information about creating modules at the following lication http://developerlife.com/tutorials/?p=229

markovuksanovic
I like the module approach. When I make a library I provide a style-module too to style the widgets inside that library. But the approach I saw in your project is the used for standard widgets in GWT. A css that's copied into the public webdir and injected in the page. I guess that I can use the obfuscating way even with modules. I mean: using UIBinder (or using CssResource/@Source) and referring to a css inside the style-module. I think it could work. Providing modularity and CSS style name obfuscation... I'll try! :) thanks!
helios
Ups! I'm confusing modules with jars... I'll have to review my idea :)
helios
Yeah, I also think that should work. I just didn't use this CssResource/Source approach because you need to be able to apply my styles to the existing GWT widgets - and, in the end, they don't use CssResources.
markovuksanovic
Well, basically, module can be in the same or different jar....
markovuksanovic
Yep. But if I want to use one module to define the styles to use... that module has to include the style implementation (the css file). My current idea is to let the "style-module" xml define the source directory. So if you include one style-module or another it will have different source paths and use (in css compilation) different css source files. I promess to try it before midnight! :)
helios
I'm not sure why you need a module to decide which module to use... maybe an acceptable solution is that you decide (by specifying in the module's xml) which style you want to use... I'm not sure if you need to change style during runtime or just at compile time.
markovuksanovic
After reading your last comment a few more times - I think that we're basically talking about the same thing. My suggestion would be to implement multiple modules so that each module corresponds to a style. This way you just specify in your application's gwt.xml file which style to use (by specifying the correct value in the inherits xml tag). I guess you could dynamically specify the source paths and you would achieve the same functionality but, in my opinion, having multiple modules makes your code more readable and the only duplicate code you get is the "style" modules' gwt.xml file.
markovuksanovic
By the way, gwt.xml for the modules which define styles is sooo small. If I were you I would go for paying the price of having a little duplicate code for the sake of readability.
markovuksanovic
Found two ways: I wanted to use CssResources (GWT2.0) so it will be compiled. First test: separate jar for style including only the css. My app simply requires that jar and the css will be there for GWT to compile it. Second test: same jar with one main module and a style module. In this case, as I use @Source("mystyle.css") in the main code and I can't choose a file or path depending on the module, I used <super-source> in the style-module to achieve including an arbitrary file tree. That way I can include (if I want different style-modules inside the same jar). [complex comment huh]
helios
Its documentation is in http://code.google.com/intl/es-ES/webtoolkit/doc/latest/DevGuideOrganizingProjects.html#DevGuidePathFiltering With it you can declare a different root path to include java source (or css files!).
helios
This looks interesting... Will have a look at it...
markovuksanovic
Hey, if we merge the module-idea and the answerfrom @Chung Hu then we can do this: 1) the library declares a "css-factory"interface, it has a method createBundle() 2) the library uses cssresources from this bundle 3) we use deferred binding to give an implementation for this interface (look for "deffered binding" and "replace-with" in GWT docs) 4) put the factory implementation and the deferred binding in a separate module. This will be the style-module we want. [then we don't have to use the "super-source" tag I mentioned before... it's kinda ugly]
helios
Yeah, I just wanted to point deferred binding to you... But then I thought that this wouldn't suite your need because deferred binding chooses which implementation to use at compile time. This would allow you to have different implementations for different browsers... I'm not sure if differed binding offers some other features as well.
markovuksanovic
+1  A: 

If you're just writing a new widget and want people to be able to customize its css, then one pattern I've used is this:

public class MyWidget extends Composite {
  public interface MyCss extends CssResource {
    ...
  }

  private static MyCss defaultStyle;
  private static MyCss ensureDefaultStyle() {
    if (defaultStyle == null) {
      defaultStyle = GWT.create(DefaultResourceBundle.class).css();
    }
    return defaultStyle;
  }

  /** If you want to use default style, call this */
  public MyWidget() {
    this(ensureDefaultStyle());
  }

  /** If you want to use your custom style, call this */
  public MyWidget(MyCss css) {
    ...
  }
}

So your widget library can provide a CSS interface, and provide a default implementation for it. If your user wants to customize it, he can bind the CSS interface to a css file of his own choosing in his own resource bundle, and use the second constructor instead.

Chung Wu
Nice. Anyway I think it can be modified for making a global style change (like themes). Maybe asigning a "global" cssresource (or bundle)... LibraryUtilityClass.setCssBundle(mybundle)...
helios