Friday, March 28, 2014

GWT - ClientBundle in Action

ClientBundle is the GWT's way to organize the non-js resources, such as css codes, images.
Getting resources into client bundle is simple as declaring a method with some annotations. 
public interface AppBundle extends ClientBundle {

    interface Style extends CssResource {

        String appleBackground();

        String orangeBackground();
    }

    @Source({"App.gwtcss", "App.css"})
    Style style();

    @Source("orange.html")
    TextResource orangeDescription();

    @Source("apple.html")
    TextResource appleDescription();

    @Source("apple.jpg")
    ImageResource appleImage();

    @Source("orange.jpg")
    ImageResource orangeImage();
}
As shown above we have 2 html files included as text, 2 jpg images and 2 css files mashed into a single Style interface.
The tricky part is how do we reference the images inside the css code.
@url appleUrl appleImage;
@url orangeUrl orangeImage;
these two lines instruct the GWT compiler to create two variable appleUrl and ornageUrl out of the images we included, then we can write out css codes as
.appleBackground {
    background-repeat: no-repeat;
    background-image: appleUrl;
    background-position: right center;
}

.orangeBackground {
    background-repeat: no-repeat;
    background-image: orangeUrl;
    background-position: right center;
}
there is one caveat about this @url codes, netbeans is not happy with non standard css codes, if we keep the codes inside the App.css, we will have a red face netbeans like this

so i decided to move the @url codes into a special App.gwtcss file.
The .ensureInjected method of the generated Style must be called, otherwise we will have the correct class name but the css content will NOT be injected into the page.
Pulling resources out of the ResouceBundle is straight forward
FlowPanel panel = new FlowPanel();
panel.setStyleName(bundle.style().appleBackground());
panel.add(new Image(bundle.appleImage()));
panel.add(new HTML(bundle.appleDescription().getText()));
RootPanel.get().add(panel);
here is the final result, we have a FlowPanel with a "right center" positioned background apple image, also containing an apple image tag and some random html codes from the apple.html.
There are more black magics to discover from the CssResource doc.
Code is available here https://github.com/verydapeng/gwt-tutorials, under ClientBundle folder.
Happy Coding