GWT Button with image AND text

GWT just provides the basic widgets like check boxes, hyperlinks, buttons etc...and leave the more complex ones to the developer or to 3rd party providers. For instance they don't have lists. Another thing which quite surprised me, their implementation of a button doesn't allow to have images AND text at the same time although a lot of Google products have it (Wave, GDocs, Gmail...).

With GWT buttons you have mainly two possibilities, using Button or PushButton. The first is just the standard one while the latter allows to assign an image which is passed in its constructor. But also the PushButton doesn't allow to have both, image AND text visualized...which somehow seems to be a use case which is quite requested. A search on the web brought me to the GWT's JavaDoc describing a CustomButton widget which can be used like this:
<g:PushButton ui:field='pushButton' enabled='true'>
<g:upFace>
<b>click me</b>
</g:upFace>
<g:upHoveringFace>
<b>Click ME!</b>
</g:upHoveringFace>
<g:downFace image='{res.save}' />
</g:PushButton>

But also this kind of implementation doesn't allow you to have an image and text declaration...* uff *.

So after that, similar as for the Hyperlink, I decided to implement one by myself. The implementation wasn't that difficult after all. Here's the source code:
import com.google.gwt.resources.client.ImageResource;
import com.google.gwt.user.client.DOM;
import com.google.gwt.user.client.Element;
import com.google.gwt.user.client.ui.Button;
import com.google.gwt.user.client.ui.Image;

public class CustomButton extends Button {
private String text;

public CustomButton(){
super();
}

public void setResource(ImageResource imageResource){
Image img = new Image(imageResource);
String definedStyles = img.getElement().getAttribute("style");
img.getElement().setAttribute("style", definedStyles + "; vertical-align:middle;");
DOM.insertBefore(getElement(), img.getElement(), DOM.getFirstChild(getElement()));
}

@Override
public void setText(String text) {
this.text = text;
Element span = DOM.createElement("span");
span.setInnerText(text);
span.setAttribute("style", "padding-left:3px; vertical-align:middle;");

DOM.insertChild(getElement(), span, 0);
}

@Override
public String getText() {
return this.text;
}
}
The according usage with the GWT UiBinder is the following:
...
<!-- Declaration of your ImageBundle -->
<ui:with field="res" type="com.sample.client.IDevbookImageBundle" />
...
<d:CustomButton ui:field="buttonSave" text="Save" resource="{res.save}"></d:CustomButton>
Pretty simple, isn't it? And it doesn't alter the button's behavior rather than adding the image. Some explanations might be needed as for instance you may wonder why I've overridden the setText(String), getText() of the standard Button widget. This was needed in order to wrap the text inside a span element which I can then identify when adding the image in order to position the image before the text. This has the drawback that a definition like
...
<d:CustomButton ui:field="buttonSave"resource="{res.save}">Save</d:CustomButton>
...won't work.

Moreover this widget may be enhanced by making it more configurable like adding the image after the text etc. I've also hard-coded some styles as you see in order to make the widget easier to use. The final outcome:
Kindle

blog comments powered by Disqus

Your ad here?