Managing your CSS (GSS) files with variables and a theme

Managing your CSS (GSS) files with variables and a theme

My previous article showed you how to use CSS inside your GWT application. Today, we will introduce the concept of variables, and show you how to manage them effectively using theme files.

Variables

Post_GSS_Howto2_v1-03-white

One of the best examples of variable use in CSS is probably color management. If your application has a default blue color, let’s say #2054e8, and it is used in multiple places, you will need to remember this particular color code every time you specify that color. Then if you decide to make your default color the lovely #f31ae5 shade of pink, you will need to do a find and replace across your whole project, and hope that everything went well.

All these hassles can be avoided if you use variables for your colors, so let’s do that!

Creating the Colors file

We will create Colors.java in src/main/java/com/company/project/client/resources.

package com.company.project.client.resources;

public class Colors {
    /* -> App colors -- */
    public static final String C_PRIMARY = "#2054e8";
    public static final String C_SECONDARY = "#bea885";
    /* -> Default colors -- */
    public static final String C_BACKGROUND = "#f0efef";
    public static final String C_TEXT = "#323232";
    public static final String C_TEXT_LIGHT = "#a1a1a1";
}

We will discuss variable naming conventions later. Right now, you only need to understand that we can define a variable, like C_PRIMARY, and assign it a value, such as our initial shade of blue #2054e8.

The main purpose of this file is to contain all color values in the same place. It will then be easy to replace them later, and create different themes for our app.

Creating the associated GSS file

This is where we start to feel the real power of GSS over regular CSS files. After compilation, GSS files output basic CSS, transforming variables into the values associated with them.

In order to easily use our variables, we need to define them in a file. We will name that file colors.gss and put it into src/main/resources/com/company/project/client/resources/css.

@provide 'colors';

@def C_PRIMARY        eval("com.company.project.client.resources.Colors.C_PRIMARY");
@def C_SECONDARY      eval("com.company.project.client.resources.Colors.C_SECONDARY");
@def C_BACKGROUND     eval("com.company.project.client.resources.Colors.C_BACKGROUND");
@def C_TEXT           eval("com.company.project.client.resources.Colors.C_TEXT");
@def C_TEXT_LIGHT     eval("com.company.project.client.resources.Colors.C_TEXT_LIGHT");

We define variable names, and point them to the associated variables inside Colors.java.

The most important part is the very first line:

@provide 'colors';

We are providing this file with a name that we will be able to import later on, making the variables defined in this file accessible in other contexts.

Binding it with your default resources style file

Before we can use this file, we need to supply it to our style’s resource file. My default style file is named style.gss and it uses the AppResources.java resource file, located in src/main/java/com/company/project/client/resources.

You can probably guess what you’ll find in this file:

package com.company.project.client.resources;

import com.google.gwt.resources.client.ClientBundle;
import com.google.gwt.resources.client.CssResource;

public interface AppResources extends ClientBundle {
    interface Style extends CssResource {
        // Your classes here
    }

    @Source("css/style.gss")
    Style style();
}

We can see that we are using style() with the file located at css/style.gss. We need to add the color.gss to @Source, so it’s accessible. Instead of a string, we need to pass an array of strings, pointing to the desired files.

    @Source({"css/colors.gss", "css/style.gss"})
    Style style();
}

Note that we need to declare colors.gss before style.gss. Otherwise, style.gss will try to load the colors.gss file, but it will not yet be defined, causing an error.

Using variables inside of the style file

Remember when we defined @provide 'colors'? It is now required inside style.gss. Once that’s done, you will have access to your variables!

@require "colors";

body {
    background-color: C_BACKGROUND;
    color: C_TEXT;
    font-size: 1.5rem;
}

Structure

You can define variables for a lot of things beside colors, like sizes and fonts. You could decide to create a variables.gss file and add all your variables there, but this can pose a problem as your application grows. I prefer to structure my files by what they do, giving each set of variables their own file:

// src/main/java/com/company/project/client/resources/variables
    -> Colors.java
    -> Fonts.java
    -> Sizes.java

// src/main/resources/com/company/project/client/resources/variables
    -> colors.gss
    -> fonts.gss
    -> sizes.gss

This way, if you only need to use Colors inside of a specific style sheet, you can import them alone. Variable types become more modular.

Naming Conventions

As variables are not prefixed with any symbols, it helps to write them in uppercase. That way it’s easy to spot them in your CSS.

I also like to prefix them with a single letter that represents the type of variable that it is.

- Colors.java   -> C_VARIABLE_NAME (C_PRIMARY, C_BACKGROUND, C_TEXT ...)
- Fonts.java    -> F_VARIABLE_NAME (F_PRIMARY, F_SECONDARY_BOLD ...)
- Sizes.java    -> S_VARIABLE_NAME (S_SECTION_PADDING, S_LINE_HEIGHT ...)

Give your variables meaningful names, something that you will be able to remember and understand upon reading. Describe the purpose of the variable, not its value.

For example, F_PRIMARY is the primary font used inside the app, the most common one that will be almost everywhere. I find the use of primary / secondary easy to remember. It has a strong meaning, and it’s about what the variable is used for, and not about the value held by the variable. A bad example would be F_ARIAL for the same variable with the same purpose. It’s bad because if, in the middle of the project, you decide to change the main font from Arial to Helvetica, you will need to refactor the name of your variable. This is what we are trying to avoid.

Instead of C_RED for an error message color, go for C_ERROR. Or even better : C_STATE_ERROR. You will be able to manage your state colors easily, like C_STATE_SUCCESS and C_STATE_DEFAULT without worrying about the color it is.

Theme

Post_GSS_Howto2_v1-04-white

The problem

If you create different variable files, you gain the ability to only load the ones you want. This is both good and bad. If you need several variable types, you have to specify each one of them inside of your resource loader, and then require them in your GSS file. This can quickly become annoying, and it makes your code harder to maintain.

// src/main/java/com/company/project/client/resources/AppResources.java

package com.company.project.client.resources;

import com.google.gwt.resources.client.ClientBundle;
import com.google.gwt.resources.client.CssResource;

public interface AppResources extends ClientBundle {
    interface Style extends CssResource {
        // Your classes here
    }

    @Source({"css/variables/colors.gss",
             "css/variables/fonts.gss",
             "css/variables/sizes.gss",
             "css/style.gss"})
    Style style();
}
/* src/main/resources/com/company/project/client/resources/css/style.gss */

@require "colors";
@require "fonts";
@require "sizes";

body {
    background-color: C_BACKGROUND;
    color: C_TEXT;
    font-family: F_PRIMARY;
    line-height: S_LINE_HEIGHT;
}

As you can see, if you have multiple GSS files, you need to include required variables inside each of those files. And if you need to add another variable set, or remove one, you will need to go inside each of your Resource and GSS files and adapt them accordingly. And that sucks.

The solution

Faced with the above problem, you might think going back to having just one Variables.java file and a variables.gss file is not a bad idea after all. But we can have our cake and eat it too. We can keep the separation in our Java files and have only one GSS to rule them all. This way, variable files will remain modular, and yet we will still have only one file to require in each GSS file that need to access variables. If we need to change the structure, like adding a new subset of variables, we will only need to update one file, and that’s all!

I call this super GSS file theme.gss because it will be used to produce different themes, but you could name it variables.gss and it would still be totally accurate.

// src/main/resources/com/company/project/client/resources/css/theme.gss

@provide 'theme';

/**
 * Colors
 */

@def C_PRIMARY                  eval("com.company.project.client.resources.theme.Colors.C_PRIMARY");
@def C_PRIMARY_BACKGROUND       eval("com.company.project.client.resources.theme.Colors.C_BACKGROUND");
@def C_TEXT                     eval("com.company.project.client.resources.theme.Colors.C_TEXT");
/* ... */

/**
 * Fonts
 */

@def F_PRIMARY                  eval("com.company.project.client.resources.theme.Fonts.F_PRIMARY");
@def F_PRIMARY_BOLD             eval("com.company.project.client.resources.theme.Fonts.F_PRIMARY_BOLD");
/* ... */

/**
 * Sizes
 */

@def S_LINE_HEIGHT              eval("com.company.project.client.resources.theme.Sizes.S_LINE_HEIGHT");
@def S_SECTION_PADDING          eval("com.company.project.client.resources.theme.Sizes.S_SECTION_PADDING");
/* ... */

With this new method, things are now easier to maintain:

// src/main/java/com/company/project/client/resources/AppResources.java

package com.company.project.client.resources;

import com.google.gwt.resources.client.ClientBundle;
import com.google.gwt.resources.client.CssResource;

public interface AppResources extends ClientBundle {
    interface Style extends CssResource {
        // Your classes here
    }

    // We only need to source the theme file
    @Source({"css/theme.gss",
             "css/style.gss"})
    Style style();
}
/* src/main/resources/com/company/project/client/resources/css/style.gss */

/* And we only have one file to require */
@require "theme";

body {
    /* All variables are still accessibles */
    background-color: C_BACKGROUND;
    color: C_TEXT;
    font-family: F_PRIMARY;
    line-height: S_LINE_HEIGHT;
}

As the constants’ values are stocked in Java files, these constants can be modified easily. With this technique, it is now super easy to create different themes that can be user-based or changed at compile time.

Updated Structure

Using a theme file, my structure now looks like this:

src/main/java/com/company/project/client/resources/
    -> elements/
    -> pages/
    -> theme/
        -> Colors.java
        -> Fonts.java
        -> Sizes.java
    -> AppResources.java
    -> ResourcesLoader.java

src/main/resources/com/company/project/client/resources/css
    -> elements/
    -> pages/
    -> style.gss
    -> theme.gss

Tips

A variable will output the string of text inside of it into your CSS. Sometimes, you will need a variable to output more then one set of properties. You can do so this way:

// src/main/java/com/company/project/client/resources/theme/Fonts.java
public class Fonts {
    public static final String F_PRIMARY = "'My Cool Typo', sans-serif";
    public static final String F_PRIMARY_BOLD = "'My Cool Typo', sans-serif; font-weight: 700";
}

Can you spot the trick in F_PRIMARY_BOLD? The variable is defining the font-family, closed with the semicolon ;, then define the font-weight, without a closing semicolon ; because the closure will be handled in the CSS.

/* src/main/resources/com/company/project/client/resources/css/theme.gss */
body {
    font-family: F_PRIMARY;
    /* will output : */
    font-family: 'My Cool Typo', sans-serif;
}

h1 {
    font-family: F_PRIMARY_BOLD;
    /* will output : */
    font-family: 'My Cool Typo', sans-serif;
    font-weight: 700;
}

Conclusion

You now understand the true power of variables. When used with a theme file, the management of your application becomes a breeze. Things can be made even easier, using a tool to manage the generation of your theme and the associated files. But that, my friends, is a topic for another blog post.

Post_GSS_Howto_v2-03

Post_Arcbees_Survey_v1-02 (1)

Open letter to our community

Hello friend,

This letter is going out to everyone in our network, but especially to you in our open source development community. Many of you have been involved with us since the very beginning, when Philippe and I were working on GWTP as part of puzzlebazar. As we became Arcbees and continued to develop tools and best practices for ourselves, we have continued to share and develop them with you. We are proud of what this community has accomplished, and we are grateful for everything we have learned from you in the process.

We are enjoying our business adventure so far, and wish to do even more in the future. Our open source initiatives have always been our top priority, but we do face a challenge faced by many other open source startups. We need to move from a service business to a product business and we want to dedicate a team to work on our open source projects, to improve our tools faster, offer commercial clients the best support experience and continue our involvement with our community.

Post_Arcbees_Survey_v1-04 (1)

This is why I want to reach out to ask for your help! We’ve put together a brief survey asking critical questions that we hope will help us improve our support offering. I also welcome you to contact me directly if you want to share feedback without feeling constrained by the survey. I’d be very happy to speak with anybody who has ideas they want to share with me!

Please fill out the survey and/or contact me directly.

Thank you for your help!

Post_Arcbees_Survey_v1-03 (1)

Getting started with CSS (GSS) and GWT

Getting started with CSS (GSS) in GWT

GWT can be hard to tackle at first, especially if your experience is entirely in front-end web development. You may be an HTML and CSS ninja, but not much of a Java wizard. This tutorial introduces how style sheets are used in GWT. I will not explain how to create a new GWT project, and will assume that you have an application you can run. That will let us focus on style sheets in GWT.

Once completed, don’t forget to have a look at the second part : Managing your CSS (GSS) files with variables and a theme.

From the beginning

If there is no style sheet inside of your application, or if you want a rough understanding of how it works, here’s a small step-by-step guide to add your default CSS file. Note that your application might be using a different folder structure than my example program, and that you will have to replace com/company/project to match your project.

The CSS file

Post_GSS_Howto_v2-01

We will create our initial CSS file into src/main/resources/com/company/project/client/resources/css and will name it style.gss. That’s right, .gss and not .css, as GSS files are like CSS files, but with more power. And we always want more power, don’t we?

We should add at least one line in our file, so we know that it’s working. Let’s use :

body { background-color: pink; }

At this point, it should not be working yet.

The Resource file

Post_GSS_Howto_v2-04

We then need to create the resource file that will be the bridge between your GSS file and your Java classes. This is because GWT will obfuscate class names on compliation, so this file will handle the links between the obfuscated names and classes inside of your GSS file.

Let’s create AppResources.java inside of src/main/java/com/company/project/client/resources

The code inside of it goes like this:

package com.company.project.client.resources;

import com.google.gwt.resources.client.ClientBundle;
import com.google.gwt.resources.client.CssResource;

public interface AppResources extends ClientBundle {
    interface Style extends CssResource {
    }

    @Source("css/style.gss")
    Style style();
}

The Resource Loader file

Post_GSS_Howto_v2-06

We now need to setup the loader file to, well, to load everything inside the application.

Once again inside src/main/java/com/company/project/client/resources, create a file named ResourceLoader.java, containing :

package com.company.project.client.resources;

import javax.inject.Inject;

public class ResourceLoader {
    @Inject
    ResourceLoader(
            AppResources appResources) {
        appResources.style().ensureInjected();
    }
}

The ensureInjected() is the important part here, as it will inject your CSS into the DOM.

Don’t forget to bind this file inside your ClientModule, probably located at src/main/java/com/company/project/client/gin/ClientModule.java

package com.company.project.client.gin;

// [your imports]

public class ClientModule extends AbstractPresenterModule {
    @Override
    protected void configure() {
        // [your code]
        bind(ResourceLoader.class).asEagerSingleton();
    }

    // [you might have code here too]
}

Activate GSS

Post_GSS_Howto_v2-07

GSS has been included in GWT since version 2.7, but is not enabled by default. To enable it, you need to add one line of code inside your GWT module. Mine is located at src/main/java/com/company/project/AppModule.gwt.xml and looks like this:

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE module PUBLIC "-//Google Inc.//DTD Google Web Toolkit 2.7.0//EN"
        "http://gwtproject.org/doctype/2.7.0/gwt-module.dtd">
<module rename-to="AppModule">
   // [Inheriting some stuff]
   // [Source some stuff]

   // The line that you need to add
   <set-configuration-property name="CssResource.enableGss" value="true">

   // [Some more code extending ... thing?]
</module>

Voilà! If things went well, your application should build and run, loading your style.gss file in the process. Don’t worry if it fails, as you might have your application structured in a different way than shown in this tutorial. If you take time to read compile errors, you should manage to make it right. If you don’t, but have a backend dev near you, it’s always good to ask for help.

Using classes

One of the most confusing thing at first while working on GSS files in GWT is that you will need to declare your classes inside of your resource file to be able to access them.

Let’s add some classes into our style.gss file :

body {
    background-color: pink;
    padding: 2em 0;
}

.my_first_class {
    color: red;
}

.my_second_class {
    color: blue;
}

We then need to adapt the resource file accordingly:

package com.company.project.client.resources;

import com.google.gwt.resources.client.ClientBundle;
import com.google.gwt.resources.client.CssResource;

public interface AppResources extends ClientBundle {
    interface Style extends CssResource {
        String my_first_class();

        String my_second_class();
    }

    @Source("css/style.gss")
    Style style();
}

Congratulations! You can now use you classes inside your views (you know, the files ending with .ui.xml) and even with your Java files.

We will first need a view. The file that we will be working on, aka ApplicationView.ui.xml, looks like this:

<ui:UiBinder xmlns:ui='urn:ui:com.google.gwt.uibinder'>
    <div>
        <h1>Hello World!</h1>

        <p>This is my first paragraph.</p>
        <p>This is my second paragraph.</p>
    </div>
</ui:UiBinder>

In order to use our classes, we will need to import the desired resource into the view :

<ui:with field="resources" type="com.company.project.client.resources.AppResources"/>

We can now call the required classes using resources.style.name_of_my_class

In the precedent view, the final code would be :

<ui:UiBinder xmlns:ui='urn:ui:com.google.gwt.uibinder'>

    <ui:with field="resources" type="com.company.project.client.resources.AppResources"/>

    <div>
        <h1>Hello World!</h1>

        <p class="{resources.style.my_first_class}">This is my first paragraph.</p>
        <p class="{resources.style.my_second_class}">This is my second paragraph.</p>
    </div>
</ui:UiBinder>

You should know that Java uses the CamelCase naming convention, and that hyphenated class names using “-" will not compile. In order to make it work, you will need to use @ClassName inside of your CssResource:

@ClassName("my-class-name")
String myClassName();

Structure

Post_GSS_Howto_v2-09

It’s good to split your CSS into multiple files. It will be easier to maintain and understand, and will help you think in blocks and structure your classes accordingly; rather than having only one CSS file that does everything, but where you are not sure what that everything is.

A structure that I like, (but feel free to adapt it), is this one:

/resources
    /css
        /elements               // -> Elements that you reuse here and there
            section.gss
            form.gss
            anyElement.gss
        /pages                  // -> Pages related style
            login.gss
            contact.gss
        style.gss               // -> Your main style

Working with multiple GSS files

Post_GSS_Howto_v2-08

While working with multiple GSS files, you have two options: you can create a resource file for that GSS and include it only in views that will need it, or you can declare multiple GSS files into the same resource.

One resource file per GSS

It might sound easier to stack everything into the same resource file, but as with CSS files, it’s always better to break your code in blocks. If you have a contact.gss file that will only be used inside of your contact.ui.xml, you should create a dedicated resource for that. And I’d guess that you would also need your default style inside that view.

// src/main/resources/com/company/project/client/resources/css/pages/contact.gss

.contact {
    background-color: orange;
    padding: 4em;
}

.contact_form {
    width: 100%;
    border: 1px solid #00f;
}
// src/main/java/com/company/project/client/resources/pages/ContactResources.java

package com.company.project.client.resources.pages;

import com.google.gwt.resources.client.ClientBundle;
import com.google.gwt.resources.client.CssResource;

public interface AppResources extends ClientBundle {
    interface Style extends CssResource {
        String contact();

        String contact_form();
    }

    @Source("com/company/project/client/resources/css/pages/contact.gss")
    Style style();
}
// src/main/java/com/company/project/client/application/contact/ContactView.ui.xml

<ui:UiBinder xmlns:ui='urn:ui:com.google.gwt.uibinder'>

    <ui:with field="resources" type="com.company.project.client.resources.AppResources"/>
    <ui:with field="pageResources" type="com.company.project.client.resources.pages.ContactResources"/>

    <div class="{pageResources.style.contact}">
        <h1>My contact page!</h1>

        <p class="{resources.style.class_from_style_gss}">
            This is a beautiful contact form.
        </p>

        <form class="{pageResources.style.contact_form}">
            <input type="email" placeholder="your email please" />
            <input type="submit" value="Go!" />
        </form>
    </div>
</ui:UiBinder>

Multiple GSS files in the same resource

Let’s say you have a small application with only 3 pages: homepage, services and contact. For each page, you created a corresponding GSS file (homepage.gss, services.gss and contact.gss).

You could create one resource file for each, like in the previous example. You could also create one resource file to rule them all, named PageResources.java.

// src/main/java/com/company/project/client/resources/PageResources.java

package com.company.project.client.resources;

import com.google.gwt.resources.client.ClientBundle;
import com.google.gwt.resources.client.CssResource;

public interface AppResources extends ClientBundle {
    interface Homepage extends CssResource {
        String homepage();

        String homepage_big_title();

        [other cool classes related to homepage only]
    }

    interface Services extends CssResource {
        String services();

        [other cool classes related to services only]
    }

    interface Contact extends CssResource {
        String contact();

        String contact_form();

        [other cool classes related to contact only]
    }

    @Source("com/company/project/client/resources/css/pages/homepage.gss")
    Homepage homepage();

    @Source("com/company/project/client/resources/css/pages/services.gss")
    Services services();

    @Source("com/company/project/client/resources/css/pages/contact.gss")
    Contact contact();
}

You will need to update your ResourceLoader.java accordingly:

package com.company.project.client.resources;

import javax.inject.Inject;

public class ResourceLoader {
    @Inject
    ResourceLoader(
            AppResources appResources) {
        appResources.homepage().ensureInjected();
        appResources.services().ensureInjected();
        appResources.contact().ensureInjected();
    }
}

Now, you can include the PageResources in each of your pages. It will give you access to every interfaces in it (homepage, services, contact).

// src/main/java/com/company/project/client/application/contact/ContactView.ui.xml

<ui:UiBinder xmlns:ui='urn:ui:com.google.gwt.uibinder'>

    <ui:with field="resources" type="com.company.project.client.resources.AppResources"/>
    <ui:with field="pageResources" type="com.company.project.client.resources.PageResources"/>

    <div class="{pageResources.contact.contact}">
        <h1>My contact page!</h1>

        <p class="{resources.style.class_from_style_gss}">
            This is a beautiful contact form.
        </p>

        <p class="{pageResources.homepage.homepage_big_title}">
            Hey look, I can also use a class from the homepage, even though I should probably don't do this, right?
        </p>

        <form class="{pageResources.contact.contact_form}">
            <input type="email" placeholder="your email please" />
            <input type="submit" value="Go!" />
        </form>
    </div>
</ui:UiBinder>

Using images

Post_GSS_Howto_v2-05

If you want to use images inside of your GSS file, you will need to declare them as an ImageResource. Your image will need to be inside your resources folder, and like your GSS files, it’s always a good thing to create a proper folder structure in order to maintain control.

// src/main/java/com/company/project/client/resources/pages/ContactResources.java

package com.company.project.client.resources.pages;

import com.google.gwt.resources.client.ClientBundle;
import com.google.gwt.resources.client.CssResource;
import com.google.gwt.resources.client.ImageResource;
// ^ don't forget to import the ImageResource package

public interface AppResources extends ClientBundle {
    interface Style extends CssResource {
        String contact();

        String contact_form();
    }

    @Source("images/contact/background.jpg")
    ImageResource background();

    @Source("com/company/project/client/resources/css/pages/contact.gss")
    Style style();
}
// src/main/resources/com/company/project/client/resources/css/pages/contact.gss

@def BACKGROUND resourceUrl("background");

.contact {
    background: BACKGROUND no-repeat center center;
    padding: 4em;
}

.contact_form {
    width: 100%;
    border: 1px solid #00f;
}

Conclusion

CSS with GWT is not an easy task at first, but after mastering the basics, you can regain your status as a front end ninja in GWT-land. Find the workflow that suits your need, structure your files and don’t forget to have fun!

In my next post, I will teach you how to leverage the real power behind GSS and simplify your life, using variables and a theme file. Stay tuned!

Post_GSS_Howto_v2-03

Post_gwtp_Howto_v1-01

Gwt-Platform event best practices (revisited)

Not too long ago, I started using GWT and GWTP and found it pretty hard to understand its event system.

I still can’t find much recent information about it, so I am writing this post to hopefully help others. Disclaimer: There many ways to achieve what I do in this post, but this is the way I prefer.

All right! Let’s demonstrate how events and the event bus work by creating a CSI-Hacking Dashboard. You can get the code on GitHub.

Post_gwtp_Howto_v1-03

We have ComputerPresenter, a HackerPresenter and a root Presenter that holds/creates other widgets. We also have a ComputerHackedEvent and ComputerHackedHandler. The event will be raised to signal that the computers got hacked, and the handler code will be executed after that.

Here’s the classic implementation of a GWT event. Our event will only carry the hacker’s name.

public class ComputerHackedEvent extends GwtEvent<ComputerHackedEvent.ComputerHackedHandler> {
    public interface ComputerHackedHandler extends EventHandler {
        void onSystemHacked(ComputerHackedEvent event);
    }

    public static final Type<ComputerHackedHandler> TYPE = new Type<>();

    private final String hackerName;

    public ComputerHackedEvent(String hackerName) {
        this.hackerName = hackerName;
    }

    public static void fire(String hackerName, HasHandlers source) {
        source.fireEvent(new ComputerHackedEvent(hackerName));
    }

    public String getHackerName() {
        return hackerName;
    }

    @Override
    public Type<ComputerHackedHandler> getAssociatedType() {
        return TYPE;
    }

    @Override
    protected void dispatch(ComputerHackedHandler handler) {
        handler.onSystemHacked(this);
    }
}

I usually declare my handler as a nested interface in the event declaration. That’s only a matter of personal preference though.

Next we have to raise the event. That will be done by our HackerPresenter. A really simple way of becoming a computer hacker, is by adding a button to the screen and pressing it, right CSI?

Here’s the code of the view and the presenter.

public class HackerView extends ViewWithUiHandlers<HackerUiHandlers>
        implements HackerPresenter.MyView {
    interface Binder extends UiBinder<Widget, HackerView> {
    }

    @UiField
    Button hackThePlanet;

    @Inject
    HackerView(Binder binder) {
        initWidget(binder.createAndBindUi(this));
    }

    @UiHandler("hackThePlanet")
    public void initiateHacking(ClickEvent event) {
        getUiHandlers().onInitiateHacking();
    }
}
public class HackerPresenter extends PresenterWidget<MyView>
        implements HackerUiHandlers {
    public interface MyView extends View, HasUiHandlers<HackerUiHandlers> {
    }

    private final String hackerName;

    @Inject
    HackerPresenter(
            EventBus eventBus,
            MyView view,
            @Assisted String hackerName) {
        super(eventBus, view);

        this.hackerName = hackerName;

        getView().setUiHandlers(this);
    }

    @Override
    public void onInitiateHacking() {
        ComputerHackedEvent.fire(hackerName, this);
    }
}

So we have a button, and when we click on it, it raises an event. There are a couple of ways to raise an event, but the one I usually use, is the static fire() method on the event. (I’ll talk about the other ways of firing an event later on.)

Now we have to handle the event somewhere. We want to know when the computers get hacked, so we’ll represent the computers with the ComputerPresenter. Its role will be to print in the console when it gets hacked, and by which hacker. Here’s the presenter code:

public class ComputerPresenter extends PresenterWidget<MyView>
        implements ComputerHackedEvent.ComputerHackedHandler {
    public interface MyView extends View {
        void setComputerName(String computerName);

        void displayStatus(String computerName, String hackerName);
    }

    private final String computerName;

    @Inject
    ComputerPresenter(
            EventBus eventBus,
            MyView view,
            @Assisted String computerName) {
        super(eventBus, view);

        this.computerName = computerName;

        view.setComputerName(computerName);
    }

    @Override
    protected void onBind() {
        super.onBind();

        addRegisteredHandler(ComputerHackedEvent.TYPE, this);
    }

    @Override
    public void onSystemHacked(ComputerHackedEvent event) {
        getView().displayStatus(computerName, event.getHackerName());
    }
}

This way, when a hacker clicks on the “start hacking” button, all the computers that are listening to the event will print something. As you can see, the ComputerPresenter registers itself as a handler for the ComputerHackedEvent through the addRegisteredHandler method.

This is a convenience method provided by GWTP. Using this method instead of registering directly on the EventBus will make the event registration part of GWTP’s lifecycle and unbind the event handler when the presenter is unbound. That means that if the presenter is unbound and rebound, you’ll have to re-register event handlers. This is why the onBind method is a good place to register handlers.

Here’s the code of the root presenter:

public class RootPresenter extends Presenter<RootPresenter.MyView, RootPresenter.MyProxy> {
    interface MyView extends View {
    }

    @ProxyStandard
    @NameToken(NameTokens.home)
    interface MyProxy extends ProxyPlace<RootPresenter> {
    }

    public static final Object SLOT_COMPUTERS = new Object();
    public static final Object SLOT_HACKERS = new Object();

    private final WidgetsFactory widgetsFactory;

    @Inject
    RootPresenter(
            EventBus eventBus,
            MyView view,
            MyProxy proxy,
            WidgetsFactory widgetsFactory) {
        super(eventBus, view, proxy, ApplicationPresenter.SLOT_SetMainContent);

        this.widgetsFactory = widgetsFactory;
    }

    @Override
    protected void onBind() {
        super.onBind();

        HackerPresenter zeroCool = widgetsFactory.createHacker("Zer0C00L");
        HackerPresenter acidBurn = widgetsFactory.createHacker("AcidBurn");

        addToSlot(SLOT_HACKERS, zeroCool);
        addToSlot(SLOT_HACKERS, acidBurn);

        ComputerPresenter computerA = widgetsFactory.createComputer("A");
        ComputerPresenter computerB = widgetsFactory.createComputer("B");

        addToSlot(SLOT_COMPUTERS, computerA);
        addToSlot(SLOT_COMPUTERS, computerB);
    }
}

We just create one hacker named Zer0C00L and 2 computers to hack. And now the view:

public class RootView extends ViewImpl
        implements RootPresenter.MyView {
    interface Binder extends UiBinder<Widget, RootView> {
    }

    @UiField
    HTMLPanel computers;
    @UiField
    HTMLPanel hackers;

    @Inject
    RootView(Binder uiBinder) {
        initWidget(uiBinder.createAndBindUi(this));
    }

    @Override
    public void addToSlot(Object slot, IsWidget content) {
        super.addToSlot(slot, content);

        if (slot == RootPresenter.SLOT_COMPUTERS) {
            computers.add(content);
        } else if (slot == RootPresenter.SLOT_HACKERS) {
            hackers.add(content);
        }
    }

    @Override
    public void removeFromSlot(Object slot, IsWidget content) {
        super.removeFromSlot(slot, content);

        if (slot == RootPresenter.SLOT_COMPUTERS) {
            computers.remove(content);
        } else if (slot == RootPresenter.SLOT_HACKERS) {
            hackers.remove(content);
        }
    }
}

Post_gwtp_Howto_v1-04

Nice! When I click on “Hack the planet!” I see the following result in the Javascript console:

I got hacked. (A) by Zer0C00L
I got hacked. (B) by Zer0C00L

I should start writing in l33tsp33k now.

Now what if you remove one of the ComputerWidgets from the DOM by calling removeFromSlot(SLOT_COMPUTERS, computerB); and still try to hack the planet?

If you read the output of the console you will see:

I got hacked. (A) by Zer0C00L
I got hacked. (B) by Zer0C00L

Wait… What? The handler for the computer B is still registered, the presenter wasn’t unbound, it was only removed from the DOM.

What if we want computer B to stop listening to the events when it’s not present in the DOM? Well that’s a job for addVisibleHandler. So instead of registering the handler using addRegisteredHandler we’ll use addVisibleHandler that will handle this for us. This way, when a presenter is considered “not visible” in GWTP’s lifecycle perspective (read: not visible as in “visible in the DOM”), the event will not reach the handler. The new output should now be:

I got hacked. (A) by Zer0C00L

There’s still a problem though. What if there were too many computers for a single hacker? I think at some point we’ll have to add someone to the team. Let’s do it!

// in the RootPresenter's OnBind method
HackerPresenter acidBurn = widgetsFactory.createHacker("AcidBurn");
addToSlot(SLOT_HACKERS, acidBurn);

You should see 2 buttons saying “Hack the planet!” and when you click them both, the output is:

I got hacked. (A) by Zer0C00L
I got hacked. (B) by Zer0C00L
I got hacked. (A) by AcidBurn
I got hacked. (B) by AcidBurn

All computers are reacting to every hacker, which is not what we want. This is happening because of the way we registered the handlers earlier. What we want is for the computers to react a specific hacker’s ComputerHackedEvent.

Since we can have a reference to the said hacker, that is pretty easy to accomplish. We have to delegate the handler registration to the concerned presenter. From the RootPresenter we’ll delegate the task, but first let’s create an interface :

import com.google.web.bindery.event.shared.HandlerRegistration;

public interface HasComputerHackedHandlers {
    HandlerRegistration addComputerHackedHandler(ComputerHackedEvent.ComputerHackedHandler handler, Object source);
}

We can then let ComputerPresenter implement it.

public HandlerRegistration addComputerHackedHandler(ComputerHackedEvent.ComputerHackedHandler handler, Object source) {
    HandlerRegistration hr = getEventBus().addHandlerToSource(ComputerHackedEvent.TYPE, source, handler);
    registerHandler(hr);
    return hr;
}

Note that instead of registerHandler() you can also use registerVisibleHandler().

And finally, when you click on both buttons, the output should be:

I got hacked. (A) by Zer0C00L
I got hacked. (B) by AcidBurn

All right! We’re ready to hack the planet! Are we?

Post_gwtp_Howto_v1-02

Remember when I said I would talk about the ways of firing events? If you are new to GWT and GWTP, you might have noticed that there are multiple methods available to fire events and register handlers.

// GWT
eventBus.addHandler(eventType, handler)
eventBus.addHandlerToSource(eventType, source, handler)

eventBus.fireEvent(event)
eventBus.fireEventFromSource(event, source)

// GWTP
presenterWidget.addHandler(eventType, handler) // deprecated
presenterWidget.addRegisteredHandler(eventType, handler)
presenterWidget.addVisibleHandler(eventType, handler)
presenterWidget.registerHandler(handlerRegistration)
presenterWidget.registerVisibleHandler(handlerRegistration)

presenterWidget.fireEvent(event)

Confused yet? I can say I was after seeing this. If you dig down you can see that a presenter widget gets an event bus injected and delegates most of its job to it. The only difference is that GWTP manages the handler registrations with its lifecycle (i.e: when a presenter gets unbound, the registered handlers get cleared). Also, if you dig for the fireEvent method, you’ll see GWTP delegates to eventBus.fireEventFromSource(). You may want to call the original fireEvent() if you want to match the following case (taken from the javadoc) “Fires the event from no source. Only unfiltered handlers will receive it”. Honestly, I’ve never faced that situation.

Here’s my cheat sheet of events in GWTP:

– Do I need to fire an event globally on the event bus? (i.e: everything registered to the event will handle it)
Y: presenterWidget.addRegisteredHandler() + SomeEvent.fire()
N: Go next

– Do I need to filter the handlers by the visibility of the handler?
Y: presenterWidget.addVisibleHandler() + SomeEvent.fire()
N: Go next

– Do I need specific handlers to handle events from a specific source?
Y: Create an interface called HasXXXHandlers and make your handling presenter implement it. GWTP gives PresenterWidget the capability to register handlers via registerHandler() and registerVisibleHandler(). Finally, fire the event with SomeEvent.fire()
N: That’s it. I usually don’t need more options, so the decision tree ends here. If you have another situation that doesn’t fit, let me know!

Post_gwtp_Howto_v1-05