5

Imagine you created the following simple widget with UiBinder:

<!DOCTYPE ui:UiBinder SYSTEM "http://dl.google.com/gwt/DTD/xhtml.ent">
<ui:UiBinder xmlns:ui="urn:ui:com.google.gwt.uibinder"
    xmlns:g="urn:import:com.google.gwt.user.client.ui">

    <ui:style type="my.package.Widget1.Widget1Style">
        .childWidgetStyle {
            border-width: 1px;
            border-style: dotted;
        }
    </ui:style>

    <g:TextArea styleName="{style.childWidgetStyle}"/>
</ui:UiBinder>

package my.package;
// some imports here

public class Widget1 extends Composite {
    private static Widget1UiBinder uiBinder = GWT.create(Widget1UiBinder.class);

    interface Widget1UiBinder extends UiBinder<Widget, Widget1> {
    }

    public interface Widget1Style extends CssResource {
        String childWidgetStyle();
    }

    @UiField
    TextArea textArea;

    public Widget1(String text) {
        initWidget(uiBinder.createAndBindUi(this));
        textArea.setText(text);
    }
}

Than you use this simple widget in another (parent) widget you created:

<!DOCTYPE ui:UiBinder SYSTEM "http://dl.google.com/gwt/DTD/xhtml.ent">
<ui:UiBinder xmlns:ui="urn:ui:com.google.gwt.uibinder"
    xmlns:g="urn:import:com.google.gwt.user.client.ui">

    <ui:style>
        .parentWidgetStyle .childWidgetStyle {
            margin-bottom: 10px;
        }
    </ui:style>
    <g:VerticalPanel ui:field="listPanel" addStyleNames="{style.parentWidgetStyle}" />
</ui:UiBinder>

package my.package;
// imports go here
public class ParentWidget extends Composite {
    private static ParentWidgetUiBinder uiBinder = GWT.create(ParentWidgetUiBinder.class);

    interface ParentWidgetUiBinder extends UiBinder<Widget, ParentWidget> {
    }

    @UiField
    VerticalPanel listPanel;

    public ParentWidget(final String... texts) {
        initWidget(uiBinder.createAndBindUi(this));
        for (final String text : texts) {
            final Widget1 entry = new Widget1(text);
            listPanel.add(entry);
        }
    }
}

What you want to achieve is to get some margin between the Widget1 entries in the list using css. But this won't work. Because GWT will obfuscate the css names. And the obfuscated name for .childWidgetStyle in ParentWidget will be different from the .childWidgetStyle in Widget1. The resulting css will look similar to this:

.G1unc9fbE {
    border-style:dotted;
    border-width:1px;
}
.G1unc9fbBB .G1unc9fDa {
    margin-bottom:10px;
}

So the margin setting wont apply. How do I do this correctly?

Eduard Wirch
  • 9,785
  • 9
  • 61
  • 73
  • For another take on this, see [the posting I created after a long, frustrating bout with the available online resources](http://www.steveclaflin.com/blog-stuff/gwt/CssResourceImports.html) – stevec Jan 30 '13 at 15:15

1 Answers1

4

The trick is to import the css class name into ParentWidget:

<!DOCTYPE ui:UiBinder SYSTEM "http://dl.google.com/gwt/DTD/xhtml.ent">
<ui:UiBinder xmlns:ui="urn:ui:com.google.gwt.uibinder"
    xmlns:g="urn:import:com.google.gwt.user.client.ui">

    <ui:style import="my.widget.Widget1.Widget1Style">
        .parentWidgetStyle .Widget1Style-childWidgetStyle {
            margin-bottom: 10px;
        }
    </ui:style>
    <g:VerticalPanel addStyleNames="{style.parentWidgetStyle}" />
</ui:UiBinder>

The important part is, if you don't use ImportedWithPrefix annotation GWT will prefix the imported style names with the class name of the resource the css class is in. So childWidgetStyle becomes .Widget1Style-childWidgetStyle.

(edit: removed part about @Shared following comments and documentation.)

Rade_303
  • 905
  • 11
  • 28
Eduard Wirch
  • 9,785
  • 9
  • 61
  • 73
  • Eduard - Why is the @Shared annotation required? According to the docs, it is not required: http://code.google.com/webtoolkit/doc/latest/DevGuideClientBundle.html#Shared_scopes – logan Nov 12 '11 at 02:46
  • @logan - That link seems to specify that the common superclass must have the Shared annotation: "The short version is that if distinct CSS types need to share obfuscated class names, the CssResource subtypes to which they are attached must share a common supertype that defines accessors for those names and has the Shared annotation." – David Mann Jun 18 '12 at 15:19
  • @Stembrain - I agree, a shared superclass must have the `@Shared` annotation. That said, in this answer there is no shared superclass. This an example of "Imported scopes" not "Shared Scopes", and is a mis-use of the annotation in my opinion. – logan Jun 19 '12 at 23:13