Thursday, April 29, 2010

Patch-extending an insider-traded UIBinder widget

This a continuation of the rant on insider-traded UIBinder widgets.

In this example, we wish to extend the behaviour of
com.google.gwt.user.client.ui.MenuBar. UIMenuBar is to be a patch-extension of MenuBar by retaining the package namespace com.google.gwt.user.client.ui.

MenuBar widget has an addSeparator() method. However, the addSeparator() can be used only in Java code but not in UIBinder becausee the insider-traders of UIBinder somehow left that out. Therefore, UIBinder does not have the feature to add a separator between MenuItems.

This tutorial illustrates extending MenuBar so that a separator could be added as a MenuItem of a MenuBar when using UIBinder.

package com.google.gwt.user.client.ui;

public class UIMenuBar
    extends MenuBar
{

    public UIMenuBar() {}

    public UIMenuBar(boolean vertical) {
        super(vertical);
    }

    public UIMenuBar(Resources resources) {
        super(resources);
    }

    public UIMenuBar(boolean vertical, Resources resources) {
        super(vertical, resources);
    }

    @Override
    public MenuItem addItem(MenuItem item) {
        if (item.getText().equals("!")){
            super.addSeparator();
            return null;
        }
           
        return super.addItem(item);
    }
}

Notice the package declaration of UIMenuBar masquerades as the same package as MenuBar's. This is because just as GWT compiler recognises UIMenuBar as MenuBar (due to inheritance), the GWT compiler would attempt to look for the MenuItem class within the same package.

Therefore, if we had extended UIMenuBar as
org.synthful.holymoly.UIMenuBar, the GWT compiler, due to insider-trading, would attempt to look for MenuItems class under the namespace org.synthful.holymoly rather than com.google.gwt.user.client.ui. Then we would have to extend the whole repertoire of classes associated with MenuBar, just to package them as org.synthful.holymoly. But, the shortcoming is only with MenuBar while its associated classes and widgets are rather well behaved, already UIBinder-friendly classes with which we don't wish to mess around.

Note the overridden addItem method. A separator is added instead, if the text of the MenuItem is "!".

Now you can use UIBinder to insert separators into your MenuBar:
<!DOCTYPE ui:UiBinder SYSTEM
  "http://dl.google.com/gwt/DTD/xhtml.ent">
<ui:UiBinder
  xmlns:ui="urn:ui:com.google.gwt.uibinder"
  xmlns:gz="urn:import:org.synthful.gwt.widgets.client.ui"
  xmlns:g="urn:import:com.google.gwt.user.client.ui">
  <ui:with field='mainMenu'
  type='holymoly.main.client.MainMenuBar'/>
  <g:UIMenuBar ui:field="menuBar">
   <g:MenuItem ui:field="edit">Edit
     <g:MenuBar ui:field="editMenu" vertical="true">
       <g:MenuItem ui:field="editFile"
         command="{mainMenu.getEditProfileCmd}">Edit File</g:MenuItem>
     </g:MenuBar>
   </g:MenuItem>
   <g:MenuItem>!</g:MenuItem>
   <g:MenuItem ui:field="exit"
     command="{mainMenu.getExitCmd}">Exit</g:MenuItem>
  </g:UIMenuBar>
</ui:UiBinder>

The listing for UIMenuBar is at http://code.google.com/p/synthfuljava/source/browse/#svn/trunk/gwt/widgets/com/google/gwt/user/client/ui.

No comments:

Post a Comment