How to create a Google Web Toolkit widget using by loe13858

VIEWS: 224 PAGES: 34

									                                                   Objet Direct
                                                        Tatami
        How to create a Google Web Toolkit
          widget using the Dojo Framework
                                              Auteur : Henri Darmet, Vianney Grassaud
                                                                          Version : 1.1
                                                                       December 2007




               Objet Direct Lyon
     1 cours Albert Thomas 69003 Lyon
   Tél 04 72 33 78 30 Fax 04 72 33 68 67
             Objet Direct Grenoble
       Les Iles Cordées 38113 Veurey
   Tél 04 76 53 72 72 Fax 04 76 53 72 77
Siège : 39 rue des Peupliers 92100 Boulogne
   Tel 01 56 88 69 00 Fax 01 56 88 69 01
         SAS au capital de 160 000 €.
           Siret 433 914 322 722 Z
    www.objetdirect.com
                                                          Objet Direct
                                       How to create a Google Web Toolkit widget using the
                                                        Dojo Framework



1.       HOW TO CREATE A GOOGLE WEB TOOLKIT WIDGET USING THE DOJO FRAMEWORK .. 3
     1.1.     DOJO INTEGRATION .................................................................................................................. 3
     1.2.     INTERNALS OF TATAMI (GWT/DOJO) WIDGETS ........................................................................... 4
        1.2.1. Presentation ....................................................................................................................... 4
        1.2.2. Life cycle ............................................................................................................................ 5
        1.2.3. DOM shell element (and GWT events capture)................................................................. 5
        1.2.4. Be friendly with the Garbage Collector .............................................................................. 6
        1.2.5. Avoid memory leaks .......................................................................................................... 8
     1.3.     A COMMENTED EXAMPLE: THE FISHEYE ..................................................................................... 8
        1.3.1. To start ............................................................................................................................... 8
        1.3.2. Add active icons ............................................................................................................... 13
        1.3.3. Capturing selection events .............................................................................................. 16
        1.3.4. Some other little enhancements … ................................................................................. 17
     1.4.     AS A CONCLUSION: HOW TO CREATE A TATAMI WIDGET THAT WRAPS A DOJO WIDGET ................ 17
        1.4.1. Create a Tatami class ...................................................................................................... 18
        1.4.2. Ask for Dojo Script loading .............................................................................................. 18
        1.4.3. Define a constructor that partially build the widget .......................................................... 18
        1.4.4. Define simplified constructors .......................................................................................... 19
        1.4.5. Redefine “onAttach” and “onDetach” methods ................................................................ 20
2.       TOOLS TO WRAP DOJO WIDGETS. ......................................................................................... 21
     2.1.     THE INTERFACE « HASDOJO ». ............................................................................................... 22
     2.2.     AN « HELPER » : DOJOCONTROLLER ...................................................................................... 23
     2.3.     USE ABSTRACT CLASSES TO FACTORISE THE CODE OF TATAMI COMPONENTS. ........................... 26
        2.3.1. The abstract classes proposed by Tatami. ...................................................................... 26
        2.3.2. An example detailed. ....................................................................................................... 26
     2.4.     THE NEW FISHEYE CLASS. ...................................................................................................... 29




                                                Version 1.1                                                                          -2-
                                          Objet Direct
                       How to create a Google Web Toolkit widget using the
                                        Dojo Framework



1. How to create a Google Web Toolkit widget using the
   Dojo Framework
The goal of the Tatami project is to deliver a rich and amazing set of components for
the Google Web Toolkit, using well known JavaScript libraries. The most impressive
of these libraries is certainly the Dojo framework (www.dojotoolkit.org). Dojo contains
today a large set of resources which a great part can be reused in Google Web
Toolkit applications. And because direct use of Dojo (JavaScript programming) is
very hard, this solution is particularly interesting. Indeed, Dojo is a complicated
framework, poorly documented, and its APIs may change at any time! Tatami is a
good (if not the best) solution to hide this complexity and to protect projects against
Dojo unstable nature.


   1.1.       Dojo Integration

To integrate Dojo in the Google Web Toolkit, the following steps are required:

      First, GWT module is created,
      Second, Dojo is installed inside this module
      Eventually, Dojo is declared in the module configuration file

I don’t explain here how to create a GWT module. There are numerous tutorials,
documentation and books that explain this with great details, counting mine which is
accessible in Objet Direct Wiki (unfortunately, in French only)

The second task is the Dojo installation inside the module. This is done by copying
the “dojo.js” script file and the “src” folder, from the Dojo distribution to the “public”
folder of your GWT module (a GWT module is constituted by three folders : client,
server and public). The “src” folder contains numerous JavaScript file loaded when
necessary, by the Dojo bootstrap.

If the version of your GWT distribution is older than 1.4, you must append the
following line at the end of the “dojo.js” file :


function dojoIsOk() {}



This function is necessary for the Google Web Toolkit page loader to ensure that the
Dojo bootstrap file (i.e. “Dojo.js”) is completely loaded before your application is
started.
The last step is to declare Dojo in the module configuration file (the file within the
“public” folder and which extension is “.gwt.xml”). This is done by inserting the
following lines:


                            Version 1.1                                          -3-
                                         Objet Direct
                      How to create a Google Web Toolkit widget using the
                                       Dojo Framework



<script src="dojo.js"><![CDATA[
      if ($wnd.dojoIsOk)
            return true;
      else
            return false;
      ]]></script>



Note that if the GWT version is 1.4 or newer, only a shorter declaration is required:

<script src="dojo.js" />




   1.2.      Internals of Tatami (GWT/Dojo) widgets


      1.2.1. Presentation
A classical GWT widget is constituted by an envelope (the widget object itself) and a
DOM object. The DOM object is the only one recognized by the navigator. For GWT,
the DOM object is an opaque JavaScript object. This DOM object is handled using
helper methods declared in the DOM class (package com.google.gwt.user.client).
The envelope object is a Java Object and must be an instance of a sub class of
Widget (same package). This Java Object drives the DOM object.

This structure implies that GWT handles two component trees: one for GWT widget
and one for DOM objects. The two trees are related, and must remain consistent.
The widget tree is build programmatically (and this built is often the main part of a
GWT application). The DOM tree is constructed and maintained by the widgets.

When Dojo is used, this structure is a little bit more complicated, because Dojo needs
another component structure! Indeed, Dojo uses a principle similar to the one
described before: Dojo envelope objects are used to handle DOM objects. The
envelope objects are Dojo widgets. These widgets, like their GWT counterparts,
cannot render directly to the screen (Only DOM objects can). Theses widgets are
JavaScript objects, and cannot be used directly as GWT widgets. The internal Dojo
structure is not really a tree. It is more a registry, a kind of pool of widgets, not
necessarily linked together. The important point to remember is that when a widget is
not used any more, it must be explicitly destroyed, in order to be unregistered from
the Dojo and so, removed from memory.

The master object in this hybrid component structure is the GWT widget (called
thereafter the Tatami widget). It’s to this widget to create the Dojo widget which in
turn creates the DOM object. At last, the Tatami widget retrieves the DOM object
from the Dojo widget (and don’t create one like in the classical scheme). The Tatami
widget keeps a link to the Dojo widget, because it needs this widget in order to drives
safely the DOM object. Eventually, the Tatami widget must destroy the Dojo Widget.

                           Version 1.1                                      -4-
                                         Objet Direct
                      How to create a Google Web Toolkit widget using the
                                       Dojo Framework




      1.2.2. Life cycle

In fact, the Tatami widget and the Dojo widget are heavily coupled. The best solution
would have to synchronize their life cycles : when the Tatami widget is created, it
creates immediately the Dojo widget. When the Tatami widget is discarded, it
destroys the Dojo one.

But there is an issue : In JavaScript, the destruction of an object cannot be
intercepted like in Java using the finalize method. So, the destruction of a GWT
widget cannot be used to call the destruction of the Dojo one.

The only reliable events in the GWT/Tatami widget lifecycle which can be used are
the attachment and the detachment of the widget into (or from) the widget tree.
Tatami uses these events to manage the lifecycle of the Dojo widget (and associated
DOM elements).

The Tatami widget delays the construction of the Dojo widget until it is inserted in the
widget tree. This happens when the “onAttach” method is invoked on the Tatami
widget. Do the construction of the Dojo widget is done inside this method. Conversely
the Dojo widget is destroyed inside the “onDetach” method invocation.


      1.2.3. DOM shell element (and GWT events capture)

There is another issue, which can be transformed in an advantage: during GWT
widget creation (thus Tatami widget creation), a DOM element must be created and
associated to the widget. But at that moment, the Dojo widget doesn’t exist.
Unfortunately, the needed DOM element is not available so early because it’s to the
Dojo widget to create the DOM structure.

To solve this issue, the Tatami widget created a basic DOM element without any
rendering effect. Generally, this DOM element is a DIV one. The widget attaches the
element as its root DOM element. When the Tatami widget is “attached” (i.e. inserted
into the widget tree), it creates the Dojo widget as explained before. Then, it ask the
Dojo widget to get its “domNode”. This “domNode” refers the root DOM element
created by the Dojo widget. Eventually, this “domNode” element is inserted at the
bottom of the DIV element.




                           Version 1.1                                      -5-
                                        Objet Direct
                     How to create a Google Web Toolkit widget using the
                                      Dojo Framework




This craftiness has another advantage. It simplifies the standard management of
events. Tatami uses this shell element (i.e. the DIV element) to capture GWT UI
events (mouse event for example) and to send them to listeners in the usual way.
This makes the framework more robust. Indeed, it’s very difficult to inject directly
JavaScript into DOM elements created by Dojo. Using the shell element, this risky
task is not needed any more.


      1.2.4. Be friendly with the Garbage Collector

The Tatami Widget and its associated Dojo widget work together. The Tatami widget
requests the Dojo widget every time something must be updated in the DOM tree.
So, the Tatami widget holds a reference to the Dojo one.

But a reverse link, owned by the Dojo widget is also necessary. It’s used to call back
methods when a UI event occurs. DOM elements which interact with the user are
triggered to call Dojo widget methods, not Tatami widget methods. It’s to the Dojo

                          Version 1.1                                     -6-
                                        Objet Direct
                     How to create a Google Web Toolkit widget using the
                                      Dojo Framework


widget to forward these calls to the Tatami widget. So a reference to the Tatami
widget is also needed.




And, of course, there is an issue. In “hosted mode” (i.e. development mode),
Tatami widgets and Dojo widget live in different worlds. Tatami widgets are Java
objects managed by the JVM. Dojo widgets remain JavaScript objects and are
managed by the JavaScript runtime.

The border between these two worlds is JSNI, the JavaScript interface defined by
GWT, and based on JNI. And J(S)NI is not truly compatible with garbage collector of
each side. Even, if Java and JavaScript object pair constitutes a disconnected cycle,
they cannot be removed because references to each others, cross JSNI.


To avoid this problem, the reference pair must be broken. The best place to break it
is the “onDetach” method seen earlier. The method onDetach of the widget Tatami
sets to null its reference towards the widget Dojo after having asked for its
destruction. It also nullifies the gwtWidget attribute (of the Dojo widget). Resetting


                          Version 1.1                                     -7-
                                         Objet Direct
                      How to create a Google Web Toolkit widget using the
                                       Dojo Framework


these references is mandatory: asking for purely logical destruction of the Dojo
widget, is not enough to remove the JavaScript object from memory.

      1.2.5. Avoid memory leaks


But this is not sufficient to save us from JavaScript memory leaks. There are cases,
where JavaScript creates memory leaks. We must avoid them systematically. The
most common example is closure. Closures are often used to define methods that
trigger UI events. Tatami takes a great care to never use closure.

   1.3.      A commented example: the FishEye

FishEye is a command Dojo widget. It renders as a bar of icons. These icons
increase when the mouse approaches them. The closer the mouse is, the bigger the
size of the. As soon as an icon is clicked, the command associated with the icon is
executed.




The FishEye is one of the most popular Dojo component. It was the first component
which was integrated in Tatami.

      1.3.1. To start

The first thing to do is to create a Java class which extends the Widget class
(package com.google.gwt.user.client.ui). It’s also possible to extend from a derived
class like AbstractPanel. In our case this is not necessary, the Widget class is
enough. This class must declare as many attributes as there are parameters needed
by the Dojo widget construction. As the Dojo widget will be built after the construction
of the Tatami widget ended, it is necessary to keep the values of these parameters
inside the Tatami widget.


public class FishEye extends Widget {

      int itemWidth;
      int itemHeight;
      int itemMaxWidth;
      int itemMaxHeight;
      String orientation;
      int effectUnits;
      int itemPadding;
      String attachEdge;
      String labelEdge;
      boolean enableCrappySvgSupport;
      boolean conservativeTrigger;

                           Version 1.1                                      -8-
                                         Objet Direct
                      How to create a Google Web Toolkit widget using the
                                       Dojo Framework




I would not comment on the signification and utility of these attributes. It doesn’t
matter here. I guess you to read the user guide for a detailed description. It is enough
to know here that these values are the exact counterpart of the values given to the
FishEye when it is built.

The main Tatami Widget constructor just keeps the values in its internal state.


public FishEye(
            int itemWidth,
            int itemHeight,
            int itemMaxWidth ,
            int itemMaxHeight,
            String orientation,
            int effectUnits,
            int itemPadding,
            String attachEdge,
            String labelEdge,
            boolean enableCrappySvgSupport,
            boolean conservativeTrigger)
      {
            super();
            this.itemWidth = itemWidth;
            this.itemHeight = itemHeight;
            this.itemMaxWidth = itemMaxWidth;
            this.itemMaxHeight = itemMaxHeight;
            this.orientation = orientation;
            this.effectUnits = effectUnits;
            this.itemPadding = itemPadding;
            this.attachEdge = attachEdge;
            this.labelEdge = labelEdge;
            this.enableCrappySvgSupport = enableCrappySvgSupport;
            this.conservativeTrigger = conservativeTrigger;

              Element rootDiv = DOM.createDiv();
              DOM.sinkEvents(rootDiv, Event.ONMOUSEOVER);
              DOM.setEventListener(rootDiv, this);
              this.setElement(rootDiv);
              loadDojoFishEye();
       }



It also builds a basic DIV element. This element is attached to the Widget. The
reason why such element is built and attached to the widget is explained earlier.

Call to DOM.sinkEvents and DOM.setEventListener are necessary to fix a bug of the
Dojo FishEye implementation (unfortunately there are some). For other Dojo
Widget wraps, these calls should not be useful.

Look at the last line : there is a call to “loadDojoFishEye”. This call is needed. It must
be systematically done (just changing the method name for other wrappings). This

                           Version 1.1                                        -9-
                                          Objet Direct
                       How to create a Google Web Toolkit widget using the
                                        Dojo Framework


call asks for partial Dojo script (FishEye implementation only) loading. This operation
is implemented in two methods:

      A Java method verifies that theses scripts are not already loaded.
      A JavaScript method (i.e. a JSNI method to be precise), invoked by the
       previous Java method, really does the stuff.

The Java method is given here :


protected static void loadDojoFishEye() {
            if (!dojoFishEyeLoaded) {
                  doLoadFishEye();
                  dojoFishEyeLoaded = true;
            }
      }

       static boolean dojoFishEyeLoaded = false;



The JavaScript (JSNI) method is the following one :


protected static native void doLoadFishEye()
      /*-{
         $wnd.dojo.declare("dojox.widget.TatamiFisheyeItem",
                 $wnd.dojox.widget.FisheyeListItem, {
                        onClick:function (e) {

this.parent.gwtWidget.@com.objetdirect.tatami.client.FishEye::dispatchClick
(Ljava/lang/String;)(this.iconSrc);
       }});

        }-*/;




The Java method is trivial. It just calls the JavaScript method if it hasn’t do it before.

The content of the JavaScript method is more interesting. There are two parts: the
first one asks for a script loading. The second one creates a new Dojo Widget class.


Script loading deals with Dojo scripts which implements the FishEye (FisheyeList.js
file contained in the “widget” folder. This folder is included in the “src” folder of the
Dojo distribution).

With the creation of a new class of widget, we define once for all, how the Dojo
widget is wired to the Tatami widget. We will explain this feature later, with more
details.


                            Version 1.1                                       - 10 -
                                        Objet Direct
                     How to create a Google Web Toolkit widget using the
                                      Dojo Framework


Other constructors are defined in the Tatami FishEye class. There are specializations
and simplifications of the main constructor. They set some parameters to common
values. The simplest constructor is given here as an example:


public FishEye() {
            this(
                  50 ,50, 200, 200,
                  "horizontal",
                  2, 10,
                  "center", "bottom",
                  false, false);
      }



The real stuff (Dojo Widget construction) is not made during the Tatami widget
construction, but inside the “onAttach” method as explained in the previous part of
this document. This method is invoked by GWT just after the Tatami Widget is
inserted into the widget tree. At that moment, the DOM shell element (the DIV one) is
inserted into the DOM tree. But it still contains nothing.

Look at the “onAttach” method snippet :


protected void onAttach() {
            rootWidget = createFishEye(
                  itemWidth, itemHeight,
                  itemMaxWidth, itemMaxHeight,
                  orientation,
                  effectUnits, itemPadding,
                  attachEdge, labelEdge,
                  enableCrappySvgSupport,
                  conservativeTrigger);
            DOM.appendChild(getElement(), DojoUtil.getDomNode(rootWidget));
            DojoUtil.setGWTWidget(rootWidget, this);
            buildItems();
            super.onAttach();
      }

      JavaScriptObject rootWidget;



The method builds a Dojo widget and attaches it to the Tatami widget (using
“rootWidget” attribute). Then the method requests the Dojo widget to get the root
DOM subtree built by Dojo. The root element of this subtree is inserted within the
shell DOM element of the Tatami widget. It then establishes a reference that start
from the Dojo Widget and targets the Tatami widget (call of
“DojoUtil.setGWTWidget”). This reference will be used thereafter by Dojo to forward
events to Tatami.

“buildItems” is the name of the method that recreate Dojo subwidgets corresponding
to Fisheye icons.

                          Version 1.1                                   - 11 -
                                        Objet Direct
                     How to create a Google Web Toolkit widget using the
                                      Dojo Framework


“onDetach” do reverse operations :


protected void onDetach() {
            removeItems();
            DojoUtil.setGWTWidget(rootWidget, null);
            DOM.removeChild(getElement(), DojoUtil.getDomNode(rootWidget));
            DojoUtil.destroy(rootWidget);
            rootWidget = null;
            super.onDetach();



      A call to “removeItems” destroys the icon Dojo subwidgets.
      References between the Tatami widget and the Dojo widget are broken (to
       help Garbage collectors both in the Java area and in the JavaScript area.
      The Dojo root DOM element is removed from the Tatami shell DIV element.
      The “destroy” method of the Dojo widget is invoked in order to signal to Dojo,
       that this widget is not used any more.

Now, it’s time to see how the Dojo widget is built. This is done inside the
“createFishEye” JSNI method:


protected native JavaScriptObject createFishEye(
            int itemWidth,
            int itemHeight,
            int itemMaxWidth,
            int itemMaxHeight,
            String orientation,
            int effectUnits,
            int itemPadding,
            String attachEdge,
            String labelEdge,
            boolean enableCrappySvgSupport,
            boolean conservativeTrigger)
      /*-{
            var fisheye = new $wnd.dojox.widget.FisheyeList(
                  {
                        itemWidth: itemWidth,
                        itemHeight: itemHeight,
                        itemMaxWidth: itemMaxWidth,
                        itemMaxHeight:itemMaxHeight,
                        orientation: orientation,
                        effectUnits: effectUnits,
                        itemPadding: itemPadding,
                        attachEdge: attachEdge,
                        labelEdge: labelEdge,
                        enableCrappySvgSupport: enableCrappySvgSupport,
                        conservativeTrigger: conservativeTrigger
                  }
            );
            return fisheye;
      }-*/;



                          Version 1.1                                   - 12 -
                                         Objet Direct
                      How to create a Google Web Toolkit widget using the
                                       Dojo Framework



Let’s take a look on this snippet. The Dojo widget class is given using a string. The
parameters values are given as a JSON record. It’s possible to give only a subset of
the values understood by the FishEye.


       1.3.2. Add active icons

A FishEye component without any icon is useless ! Let’s see now how we can add
icons dynamically on it. The only point to take care of, is that icons may be inersterd
when the fisheye is active (inserted in the widget tree) or not. The processes of these
two cases are quite different:

      If Tatami widget is already attached to the widget tree, the Dojo subwidget that
       represents the icon is built. This subwidget build the icon DOM elements (an
       image). Then the subwidget is given to the FishEye Dojo widget. Updating the
       DOM tree is then driven by Dojo.
      If Tatami widget is not attached to the widget tree, the icon definition is kept by
       the Tatami widget. This information will be used during the next “onAttach”
       method invocation.

There is a golden rule : the Tatami widget must keep in its state all the information
needed by Dojo in order to give them during the next “onAttach” method invocation.

An active icon is described inside the Tatami widget using the following structure:


static class Item {
            Item(String icon, String caption, Command command) {
                  this.icon = icon;
                  this.caption = caption;
                  this.command = command;
            }

             String icon;
             String caption;
             Command command;
             JavaScriptObject child;
       }


       List items = new ArrayList();



This class is an inner class of the Tatami FishEye widget class. This structure keep
three important values:

      The URL of the image that is rendered by the icon
      The popup text shown near the icon
      The command object executed when the icon is clicked.

                           Version 1.1                                      - 13 -
                                          Objet Direct
                       How to create a Google Web Toolkit widget using the
                                        Dojo Framework



This record is also used to keep a reference to the Dojo subwidget. Indeed, for each
icon, a reference to its subwidget must be retained in order to eventually call its
“destroy” method.

To add a new icon, the “add” method is called:


public void add(String icon, String caption, Command command) {
            Item item = new Item(icon, caption, command);
            items.add(item);
            if (isAttached()) {
                  buildItem(item);
            }



Its principle is obvious: the data describing the icon is first registerd, and then, if the
FishEye widget is already attached to the widget tree, Dojo is requested in order to
create really the icon.

To remove an existing icon, the “remove” method is called:


public void remove(String icon) {
            for (int i=0; i<items.size(); i++) {
                  Item item = (Item)items.get(i);
                  if (item.icon.equals(icon)) {
                        items.remove(item);
                        if (isAttached()) {
                              removeItem(item);
                        }
                  }
            }
      }



Its principle is exactly the opposite. The icon record is looked for. Then the
corresponding Dojo subview is destroyed, if it exists, that is if the Tatami widget is
attached to the widget tree.

Icon construction and destruction are not only done in these two methods. During
attachment and detachment of the Tatami widget, Dojo subwidget are created or
removed. These operations are done by a pair of internal methods:


void buildItems() {
            for (int i=0; i<items.size(); i++) {
                  Item item = (Item)items.get(i);
                  buildItem(item);
            }
      }



                             Version 1.1                                        - 14 -
                                         Objet Direct
                      How to create a Google Web Toolkit widget using the
                                       Dojo Framework


      void removeItems() {
            for (int i=0; i<items.size(); i++) {
                  Item item = (Item)items.get(i);
                  removeItem(item);
            }
      }



What about the circumstances which provoke it, the construction of an icon is
eventually managed by the “buildItem” method (of the Tatami FishEye class). The
code of this method is given here :


void buildItem(Item item) {
            JavaScriptObject child =
                  createFishEyeItem(rootWidget, item.icon, item.caption);
            addChildWidget(rootWidget, child);
            item.child = child;
      }



This method starts with the Dojo subwidget creation. Then, it request the FishEye
Dojo widget to insert the subwidget on its internal sutrcutre. At last, the reference of
this subwidget is kept inside the Tatami widget state.

The JSNI method that build the subwidget looks like to the one building the Dojo
FishEye widget:


protected native JavaScriptObject createFishEyeItem(
            JavaScriptObject rootWidget, String icon, String caption)
      /*-{
            var child = new $wnd.dojox.widget.TatamiFisheyeItem(
                  {
                        parent: rootWidget,
                        iconSrc: icon,
                        caption: caption
                  }
            );
            return child;
      }-*/;



One may note that the JavaScript widget which is created is a Tatami widget, not a
pure Dojo one. Remember the code of the “doLoadFishEye” init method (or look at it
again). It contains a JavaScript class definition. It’s this class that is used here.

The “addChidWidget” JSNI method ask Dojo to include an icon subwidget in the
FishEye Dojo Widget. Here is the code:


protected native void addChildWidget(
            JavaScriptObject panel, JavaScriptObject child) /*-{

                           Version 1.1                                     - 15 -
                                         Objet Direct
                      How to create a Google Web Toolkit widget using the
                                       Dojo Framework


               panel.addChild(child);
              panel.startup() ;
      }-*/;



Removing an icon is eventually managed by the following method:


void removeItem(Item item) {
            removeChildWidget(rootWidget, item.child);
            DojoUtil.destroy(item.child);
            item.child = null;
      }



It is the opposite of the “addItem” one. It begins by detaching the icon Dojo subwidget
from the Dojo FishEye widget. Then it asks for the destruction of the icon subwidget.

To remove an icon subwidget from the Dojo FishEye widget, the following method is
used:


protected native void removeChildWidget(
            JavaScriptObject panel, JavaScriptObject child) /*-{
            panel.removeChild(child);
            panel._initializePositioning();
      }-*/;



The last line is a Dojo FishEye bug workaround. It requests Dojo to reset and
compute again the mouse event capture data (in order to allow the widget to enlarge
or reduce correctly the size of the icons).


      1.3.3. Capturing selection events

Now we have a functional FishEye component with active icons. But it is still useless
because, it cannot forward event selection to the Tatami widget. These event are
generated by Dojo when a user click on an icon.

Indeed, Dojo knows how to capture low level UI events. To do that, it have attached
JavaScript code to standard DOM event triggers. This code forward the events to the
Dojo widget.

It should be very insane to try to change this behaviour. Trying to re route events
needs deep changes inside Dojo code. A difficult, messy and risky task !

A far better solution is to ask the Dojo widget to forward the event to the Tatami
widget each time an icon is selected. Fortunately, there is a method, defined by the
Dojo FishEye widget class that is invoked every time such a selection is done by the

                           Version 1.1                                    - 16 -
                                         Objet Direct
                      How to create a Google Web Toolkit widget using the
                                       Dojo Framework


user. This JavaScript is named “onClick”. The default behaviour is to do nothing! So it
can be replaced easily.


onClick:function (e) {
this.parent.gwtWidget.@com.objetdirect.tatami.client.FishEye::
dispatchClick(Ljava/lang/String;)(this.iconSrc); }



This JavaScript snippet calls the “dispatchClick” method, witch is a Java method
defined in the Tatami FishEye class. Here is the code of this method:


protected void dispatchClick(String icon) {
            for (int i=0; i<items.size(); i++) {
                  Item item = (Item)items.get(i);
                  if (item.icon.equals(icon)) {
                        if (item.command!=null)
                              item.command.execute();
                  }
            }
      }



The behaviour of this method is easy to understand: it looks for the icon description
that corresponds to the image URL given in parameter. Then it executes the
associated command (if any).

An important point is to determine when the onclick method should be redefined.
There are two possibilities:

      Each time an icon must be build, an object of the FisheyeListeItem Dojo class
       is created and the onclick method is replaced by a customized one.
      A customized FisheyeListItem subclass is define when Dojo scripts are
       loaded. The onclick method is defined on it once for all. Each time an icon
       must be build, an object of this subclass is created. This second solution is
       retained for Tatami widgets.


       1.3.4. Some other little enhancements …

The Fisheye component contains other (very specific) methods. There is some code
that implements a workaround of an annoying bug. This very specialized code may
not be reproduced to wrap other Dojo widgets.


   1.4.    As a conclusion: How to create a Tatami widget that
       wraps a Dojo widget


                           Version 1.1                                    - 17 -
                                        Objet Direct
                     How to create a Google Web Toolkit widget using the
                                      Dojo Framework


If you want to create a Tatami widget, we recommend you to follow this blue print


      1.4.1. Create a Tatami class

The first task is to create a Java class. This class must extend the GWT Widget
(package com.google.gwt.user.client.ui) class or a (low level) subclass of it.
AbstractWidget, FocusWidget, SimplePanel or ComplexPanel are seldom used in the
actual code of Tatami.


      1.4.2. Ask for Dojo Script loading

The next step is to define methods which would load JavaScript code from Dojo. This
is done by creating a couple of methods: the first one is a pure Java method that
protects the second one. It ensures that the second method is called only once. The
second method is a JSNI method that really does the stuff.


protected static void loadDojoFooWidget() {
if (!dojoFooWidgetLoaded) {
            doLoadFooWidget();
            dojoFooWidgetLoaded = true;
      }
}

protected static native void doLoadFooWidget()
/*-{
      $wnd.dojo.require("dojox.widget.FooWidget");
}-*/;

static boolean dojoFooWidgetLoaded = false;



      1.4.3. Define a constructor that partially build the widget

The third step is to write a constructor for our Tatami Widget class. This constructor
must receive as parameter values all the data needed by the underlying Dojo widget.
But, the Dojo widget is not created by this constructor. The constructor just keep the
values in its internal state.

This constructor must also create a DOM element and attaches the element to its
GWT standard structure. Some derived class do it (SimplePanel for example). In this
case, a simple call to the super implementation of the constructor is sufficient.

Eventually, the constructor must call the method that manages Dojo script loading.


public FooWidget(
            int param1,

                          Version 1.1                                    - 18 -
                                         Objet Direct
                      How to create a Google Web Toolkit widget using the
                                       Dojo Framework


             String param2,
             Boolean param3)
      {
             super();
             this.param1 = param1;
             this.param2 = param2;
             this.param3 = param3;

             Element rootDiv = DOM.createDiv();
             this.setElement(rootDiv);
             loadDojoFooWidget();
      }

      int param1;
      String param2;
      boolean param3;




      1.4.4. Define simplified constructors

It is often necessary to define simplified constructors that define only a subset of the
parameter values. Other ones are set by values commonly used. These constructors
must call the main constructor.


public FooWidget()
      {
            this(0, null, true);
      }


      public FooWidget(
            int param1)
      {
            this(param1, null, true);
      }



Define the method that create the Dojo widget

The next step is to write the JSNI method that creates the Dojo widget. This method
generally contains only a unique statement, which is a complex call to the
“createWidget” Dojo method.


protected native JavaScriptObject createFooWidget(
      int param1,
      String param2,
      boolean param3)
/*-{
      var fooWidget = new $wnd.dojox.widget.FooWidget(
            {
                  param1: param1,

                           Version 1.1                                     - 19 -
                                         Objet Direct
                      How to create a Google Web Toolkit widget using the
                                       Dojo Framework


                    param2: param2,
                    param3: param3
              });
        return fooWidget;
}-*/;



        1.4.5. Redefine “onAttach” and “onDetach” methods

We are now ready to wire Dojo widget creation to our Tatami widget implementation.
This is done inside the “onAttach” and (for destruction) “onDetach” methods.

The following snippet is a good example of how to do this, and what are the points to
take care of:


protected void onAttach() {
            rootWidget = createFooWidget(
                  param1, param2, param3);
            DOM.appendChild(getElement(), DojoUtil.getDomNode(rootWidget));
            DojoUtil.setGWTWidget(rootWidget, this);
            super.onAttach();
      }



The stuff is made in three stages:

       The Dojo widget is created,
       The Dojo DOM root element is retrieved and then inserted below the DOM
        element already associated to the Tatami widget.
       A reference is defined in the Dojo widget that points to the Tatami widget.

The “onDetach” method do the opposite job, in the reverse order:


protected void onDetach() {
            DojoUtil.setGWTWidget(rootWidget, null);
            DOM.removeChild(getElement(), DojoUtil.getDomNode(rootWidget));
            DojoUtil.destroy(rootWidget);
            rootWidget = null;
            super.onDetach();
      }



Manage events sent by the Dojo Widget

An event triggered by Dojo is generally materialized by a JavaScript method inside
the Dojo widget. This method can be easily replaced. Tatami redefines it, by
subclassing the Dojo class. The new event method must call a “dispatchXXX”
method defined in the Tatami widget class.


                            Version 1.1                                 - 20 -
                                        Objet Direct
                     How to create a Google Web Toolkit widget using the
                                      Dojo Framework


The Dojo subclass is defined when scripts are loaded, that is inside the
“doLoadFooWidget” JSNI method introduced earlier:


protected static native void doLoadFooWidget()
/*-{

    $wnd.dojo.require("dojox.widget.FooWidget");
    $wnd.dojo.declare("dojox.widget.TatamiFooWidget",
    $wnd.dojox.widget.FooWidget, {
         onClick:function (e) {

this.parent.gwtWidget.@com.objetdirect.tatami.client.FooWidget::
dispatchFooEvent(Ljava/lang/String;)(this.param2);
;
       }});

}-*/;



In order to use this class as a replacement of the native Dojo Widget class, it is
necessary to change the name of the widget class inside the “createFooWidget” JSNI
method:


protected native JavaScriptObject createFooWidget(
      int param1,
      String param2,
      boolean param3)
/*-{
      var fooWidget = new $wnd.dojox.widget.TatamiFooWidget(
            {
                  param1: param1,
                  param2: param2,
                  param3: param3
            }
      );
      return fooWidget;
}-*/;

The last action is to define the “dispatchXXX” method, witch is a standard Java one.
This method process the event:


protected void dispatchFooEvent(String param) {
      …
}




2. Tools to wrap Dojo widgets.

                          Version 1.1                                  - 21 -
                                        Objet Direct
                     How to create a Google Web Toolkit widget using the
                                      Dojo Framework


From essential elements of the chapter 1, some tools were created to simplify the
wrapping and avoid any useless copying between components. In this chapter we
are going to present these tools to develop new components according to the good
practices quoted before. So a reading of the chapter 1 is advised to understand and
use the tools below.

   2.1.       The interface « HasDojo ».

First of all, we need to specify that our Google Web Toolkit (GWT) will wrap a Dojo
widget. To do that, the interface “HasDojo” was created. Below, the methods of the
interface that a developer will have to implement:


             Methods                                     Purpose
JavaScriptObject getDojoWidget()       Returns the Dojo widget.

void createDojoWidget() throws         Creates the Dojo widget using JSNI in most of
Exception                              the cases. This method is not directly
                                       executed by the GWT widget. It’s a controller
                                       which should execute it. An exception is
                                       thrown if the Dojo widget can’t be created. Be
                                       careful to well check the parameters and the
                                       type of them when you are writing JSNI code.

void onDojoLoad()                      This method executes Java code or JSNI
                                       code. This method is called when the
                                       JavaScript scripts which are necessaries for
                                       the Dojo widget had well been loaded.

String getDojoName()                   Returns the name of the Dojo widget,
                                       example : « FisheyeList »
                                       This method is called to load the JavaScript
                                       scripts of Dojo. See the Dojo documentation
                                       de Dojo to know the correct names.

void doAfterCreation()                 Executes some code after that the widget was
                                       created. Sometimes we need to do some
                                       others instructions, not only the instantiation.
                                       This method is called by a controller.

void doBeforeDestruction()             Executes some code before that the Dojo
                                       widget is destroyed. It’s useful to avoid some
                                       memory leak. This method is called by a
                                       controller.

void free()                            Frees some properties, object in the GWT
                                       widget after that the Dojo widget was
                         Version 1.1                                       - 22 -
                                        Objet Direct
                     How to create a Google Web Toolkit widget using the
                                      Dojo Framework


                                        destroyed. This method is called by a
                                        controller.



These methods should be called at specifics moments in your code and not if
possible directly by the GWT component to develop in order to avoid a hard
maintenance. We need a class which will be able to control the « HasDojo » interface
and call these methods in a specific order for a specific action in our GWT
component. This class is presented in the next section. By this way the developer
keeps his mind on implementation of his methods and not on how to call the method,
anyway it’s necessary to know when for a good understanding.


   2.2.      An « Helper » : DojoController

To simplify the wrapping and avoid some repeats of code, use the singleton
DojoController. This class aims to load JavaScript scripts of Dojo, create the Dojo
widgets, and free the memory taken by theses widgets… Below, the details of each
methods of this singleton:



                    Methods                                       Purpose


static DojoController getInstance()                  Returns the unique instance of
                                                     the singleton.


void destroy(JavaScriptObject)                       Destroys the Dojo widget.

                                                     Loads if it is necessary the
void loadDojoWidget(HasDojo)                         JavaScripts scripts of Dojo for a
                                                     GWT widget implementing the
                                                     interface HasDojo. This method
                                                     calls HasDojo#onDojoLoad()
                                                     And, the method uses
                                                     HasDojo#getDojoName() to
                                                     know the scripts to load.

                                                     Creates the Dojo widget from a
void constructDojoWidget(HasDojo, Widget)            HasDojo interface and links it to
                                                     the GWT widget.

                                                     Deletes the link between the
void destroyDojoWidget(HasDojo, Widget)              GWT widget and the Dojo
                          Version 1.1                                       - 23 -
                                         Objet Direct
                      How to create a Google Web Toolkit widget using the
                                       Dojo Framework


                                                  widget. The Dojo widget is also
                                                  destroyed.

                                                  Creates a link between a GWT
void link(JavaScriptObject, Widget)               widget and a Dojo widget.. Adds
                                                  also the DOM node of the Dojo
                                                  widget to the DOM node of the
                                                  GWT widget.

                                                  Deletes the link between the
void unLink(JavaScriptObject, Widget)             Dojo widget and the GWT
                                                  widget. The DOM node of the
                                                  Dojo widget is also removed from
                                                  the DOM node of the GWT
                                                  widget.

                                                  Returns the DOM element of the
Element getDomNode(HasDojo)                       Dojo widget.

                                                  Creates or deletes the link
void setGWTWidget(JavaScriptObject,Widget)        between the Dojo widget and the
                                                  GWT widget.


void alert(String object)                         Displays a dialog box of type
                                                  alert.
                                                  NB : if it’s to debug some code,
                                                  it’s recommended to use
                                                  GWT.log(String, Throwable)


static JavaScriptObject createArray(String[])     Creates a JavaScript array of
                                                  String object from a Java String
                                                  array.


static void startup(HasDojo)                      Calls the startup method on a
                                                  widget which contains a DOJO
                                                  widget


void addChild(HasDojo ,JavaScriptObject)          Adds a JavaScriptObject as a
                                                  child for the DOJO widget


void removeChild(HasDojo,JavaScriptObject)        Removes a JavaScriptObject
                                                  from the DOJO widget.

                            Version 1.1                                - 24 -
                   Objet Direct
How to create a Google Web Toolkit widget using the
                 Dojo Framework




    Version 1.1                                  - 25 -
                                         Objet Direct
                      How to create a Google Web Toolkit widget using the
                                       Dojo Framework



      2.3.   Use abstract classes to factorise the code of Tatami
          components.

We saw some tools to simplify the wrapping of a dojo component in a GWT
component. However, we can still reduce the cost of this wrapping using some
abstract classes. Indeed, suppose that we want wrap several Dojo components in
several GWT components of type “Widget”. It will be a bad practice to rewrite the
same code several times for each component, because we know that there will be
some resemblances. So, we want to create an abstract class which will extend the
class Widget and implement the interface HasDojo. Each component to wrap will
have to extend this abstract class. The code which will be factorised is the code
permitting the creation, destruction of the Dojo widgets during the attachment and
detachment of the GWT widget to the browser. This practice, can be reiterate for
each type of GWT widgets that we need for the wrapping, for example: FocusWidget.


        2.3.1. The abstract classes proposed by Tatami.

Tatami wraps some Dojo components; it’s evidence that some abstract classes was
created. The use of these classes is recommended for futures components for
Tatami in order to keep some homogeneity and improve the maintenance. The
abstract classes are: (the super classes are on the right)


AbstractDojo                   com.google.gwt.user.client.ui.Widget


AbstractDojoComplexPane        com.google.gwt.user.client.ui.ComplexPane


AbstractDojoFocus              com.google.gwt.user.client.ui.FocusWidget




        2.3.2. An example detailed.

The class AbstractDojo :

First of all the class must to have as super class at the top of its hierarchy the class
com.google.gwt.user.client.ui.Widget.
And implement the interface HasDojo.



/**



                            Version 1.1                                      - 26 -
                                        Objet Direct
                     How to create a Google Web Toolkit widget using the
                                      Dojo Framework


 This abstract class aims to d'implement the necessaries method to
integrate easily a Dojo widget in a GWT <code>Widget</code>. To do this,
the class implements the interface <code>HasDojo</code>
There are 3 points to know for implementing correctly this class : <br>
 <ul>
  <li> How to create the Dojo widget ? </li>
  <li> Do we do something after that the scripts JavaScript are loaded for
the Dojo widget ? </li>
 <li> Know the name of the Dojo widget to create.</li>
 </ul>

   This abstract class permits to call methods at " the good times" in order
to avoid some memory leak problems and assume that scripts JavaScript Dojo
are well loaded by the browser and they are load only once.
*/
public abstract class AbstractDojo extends Widget implements HasDojo



L’interface HasDojo implique que l’on retourne un objet de type JavaScriptObjet,
pour cela nous allons déclarer l’attribut de classe : dojoWidget de ce même type.

/**
 The Widget DOJO advocated by the interface */
protected JavaScriptObject dojoWidget;



Occupons nous maintenant d’implémenter les méthodes recommandées par
l’interface HasDojo. Il parait évident que les méthodes getDojoName() et
createDojoWidget() ne peuvent pas être implémentées car elles sont trop spécifiques
au stade où on est dans l’intégration. Ci-dessous les méthodes en allant vers les
besoins les plus basiques :

/**
  Returns the DOJO widget.
  @return the JavaScriptObject corresponding to the Dojo widget.
  */
public JavaScriptObject getDojoWidget() {
             return this.dojoWidget;
}

/**
  Frees the widget Dojo.
  */
public void free() {
       this.dojoWidget = null;
}

/** Do nothing, override this method if it’s necessary */
  public void doBeforeDestruction() { }

/** Do nothing, override this method if it’s necessary */
  public void doAfterCreation() { }

/** Do nothing, override this method if it’s necessary */
  public void onDojoLoad() {}

                         Version 1.1                                   - 27 -
                                         Objet Direct
                      How to create a Google Web Toolkit widget using the
                                       Dojo Framework




Keep an eye on the constructor of the class. Several constructors can be
necessaries, in ou case only one is necessary. We have to add the DOM element
corresponding to the Dojo widget to the DOM element of the GWT widget during the
creation of the Dojo widget. The DOM element of the GWT widget will be created in
the constructor of the class. It’s also in the constructor that we have to load the
JavaScript scripts. See below :


/**
   Loads scripts JavaScript that are necessaries for the dojo widget to
integrate.
@param element an <code>Element</code> for the DOM tree to associate as an
element DOM to the GWT widget.
  @see DojoController#loadDojoWidget(HasDojo)
  */
protected AbstractDojo(Element element) {
       super();
       DojoController.getInstance().loadDojoWidget(this);
       this.setElement(element);
}

At this step, we have implemented the methods of the HasDojo interface, and have
created the constructor to load the JavaScript scripts and initialise the DOM element
of the GWT widget. A last step is necessary to finish the wrapping: the creation of the
Dojo widget during the attachment to the browser and the destruction of the Dojo
widget during the detachment. To do that, we will override the methods onAttach()
and onDetach() from the class Widget.


/**
 When the GWT widget is detached from the browser, the link between it and
the Dojo widget is drawn. The Dojo widget is also destroy. The DOM element
fulfilling the Dojo widget is also destroy.
@see DojoController#destroyDojoWidget(HasDojo,
com.google.gwt.user.client.Element)
@see #doBeforeDestruction()
*/
 protected void onDetach() {
    DojoController.getInstance().destroyDojoWidget(this, this);
    super.onDetach();
 }

 /**
When the widget GWT is attached on the browser, the Dojo widget is created
and link with the GWT widget. If the creation of the Dojo widget fails then
an alert will be display on the screen (problem under IE). A log is also
written. This methode can be overrided to add some other dependencies
between the dojo widget to create and the GWT widget.
@see Widget#onLoad()
@see #doAfterCreation()
*/

                          Version 1.1                                     - 28 -
                                        Objet Direct
                     How to create a Google Web Toolkit widget using the
                                      Dojo Framework


protected void onAttach() {
      DojoController.getInstance().constructDojoWidget(this,this);
      super.onAttach();
}



To finish, the code of this abstract class is not complex. When a object extends this
class, the developer will only keep an eye on the problem: « How to create the Dojo
widget? » in implementing the method createDojoWidget() recommended by the
interface HasDojo. He will also have to add the specifics methods of the Dojo widget.


   2.4.      The new FishEye class.

Below the FishEye class revisited in using the tools presented.


public class FishEye extends AbstractDojo {

                                    ...
/**
 Creates a FishEye menu with no icons
*/

public FishEye(int itemWidth,
               int itemHeight,
               int itemMaxWidth,
               int itemMaxHeight,
               String orientation,
               int effectUnits,
               int itemPadding,
               String attachEdge,
               String labelEdge,
               boolean conservativeTrigger) {
      super();
      this.itemWidth = itemWidth;
      this.itemHeight = itemHeight;
      this.itemMaxWidth = itemMaxWidth;
      this.itemMaxHeight = itemMaxHeight;
      this.orientation = orientation;
      this.effectUnits = effectUnits;
      this.itemPadding = itemPadding;
      this.attachEdge = attachEdge;
      this.labelEdge = labelEdge;
      this.conservativeTrigger = conservativeTrigger;
      DOM.sinkEvents(getElement(), Event.ONMOUSEOVER);
      DOM.setEventListener(getElement(), this);
}

                                         ...

/**
Overrides the method in order to catch if the mouse cross over the widget.
In this case, the event mouse structure of the DOJO widget is updated if
the widget was moved.

                          Version 1.1                                   - 29 -
                                      Objet Direct
                   How to create a Google Web Toolkit widget using the
                                    Dojo Framework


*/
public void onBrowserEvent(Event event) {
   if (DOM.eventGetType(event) == Event.ONMOUSEOVER) {
       if (getAbsoluteLeft() != x || getAbsoluteTop() != y) {
             x = getAbsoluteLeft();
             y = getAbsoluteTop();
             resetLocation(getDojoWidget());
       }
   }
   // by default the method onBrowserEvent does nothing
   super.onBrowserEvent(event);
 }

/**
  Creates the Dojo widget FishEyeList
  */
public void createDojoWidget() throws Exception {
   this.dojoWidget = createFishEye(
       itemWidth,
       itemHeight,
       itemMaxWidth,
       itemMaxHeight,
       orientation,
       effectUnits,
       itemPadding,
       attachEdge,
       labelEdge,
       enableCrappySvgSupport,
       conservativeTrigger);
}

/**
Adds a new icon to the fisheye menu
@param icon URL of the image, must be unique for the fisheye
@param caption title associated to this icon.
@param command command which will be executed when a icon is selected (can
be null )
*/
public void add(String icon, String caption, Command command) {
   Item item = new Item(icon, caption, command);
   items.add(item);
   // If the widget is attached to the browser
   // we create a new Item.
   if (isAttached()) {
      buildItem(item);
    }
}


/**
  Constructs all the items */
private void buildItems() {
    for (int i = 0; i < items.size(); i++) {
          Item item = (Item) items.get(i);
           buildItem(item);
       }
}


                        Version 1.1                                 - 30 -
                                      Objet Direct
                   How to create a Google Web Toolkit widget using the
                                    Dojo Framework


/**
Constructs a FishEyeItem and ad dit to the list
@param item Item to add
*/
void buildItem(Item item) {
  JavaScriptObject child = createFishEyeItem(getDojoWidget(),
item.icon,item.caption);
  addChildWidget(getDojoWidget(), child);
  item.child = child;
}


/**
Removes a item form the FishEye (Dojo) et destroy this item.
@param item Item to remove
*/
private void removeItem(Item item) {
   removeChildWidget(getDojoWidget(), item.child);
   DojoController.getInstance().destroy(item.child);
   item.child = null;
}

/**
Supprime tous item "Dojo" rajoutés à la barre d'icone.
Ne pas utiliser cette méthode, elle est appelée par un contrôleur quand la
widget GWT est détachée du navigateur.
*/
public void doBeforeDestruction() {
      removeItems();
}

                                     ...

private native JavaScriptObject createFishEye(
      int itemWidth,
      int itemHeight,
      int itemMaxWidth,
      int itemMaxHeight,
      String orientation,
      int effectUnits,
      int itemPadding,
      String attachEdge,
      String labelEdge,
      boolean enableCrappySvgSupport,
      boolean conservativeTrigger)
/*-{
       var fisheye = new $wnd.dojox.widget.FisheyeList(
             {
       itemWidth: itemWidth,
       itemHeight: itemHeight,
       itemMaxWidth: itemMaxWidth,
       itemMaxHeight:itemMaxHeight,
       orientation: orientation,
       effectUnits: effectUnits,
       itemPadding: itemPadding,
       attachEdge: attachEdge,
       labelEdge: labelEdge,
       isFixed: true,

                       Version 1.1                                  - 31 -
                                      Objet Direct
                   How to create a Google Web Toolkit widget using the
                                    Dojo Framework


      enableCrappySvgSupport: enableCrappySvgSupport,
      conservativeTrigger: conservativeTrigger
      }
      );

      return fisheye;
      }-*/;
/**
Adds an item to the DOJO widget FishEye menu.
@param dojoWidget the Dojo Fisheye
@param child the new item
*/
private native void addChildWidget(JavaScriptObject dojoWidget,
JavaScriptObject child) /*-{
    dojoWidget.addChild(child);
    dojoWidget.startup();
    child.startup();
 }-*/;

/**
Removes an item from the DOJO widget FishEye menu. Re-initializes also the
position of the FishEye menu.
@param dojoWidget the DOJO widget
@param child the item to remove
*/
 private native void removeChildWidget(JavaScriptObject dojoWidget,
                                       JavaScriptObject child)
/*-{
   dojoWidget.removeChild(child);
   dojoWidget._initializePositioning();
 }-*/;

/**
 Creates the DOJO widget which fulfilling an <code>Item</code>.
Warning this method doesn't add the item to the FishEye menu.
@param dojoWidget the DOJO widget FishEye
@param icon URL of the icon
@param caption title for the item
@return the item created
*/
 private native JavaScriptObject createFishEyeItem(
      JavaScriptObject dojoWidget,
      String icon,
      String caption)    /*-{
 /*-{
        var child = new $wnd.dojox.widget.TatamiFisheyeItem(
                 {
                   parent: dojoWidget,
                   iconSrc: icon,
                   label: caption
                 }
       );
       return child;
       }-*/;


/**


                        Version 1.1                                 - 32 -
                                      Objet Direct
                   How to create a Google Web Toolkit widget using the
                                    Dojo Framework


Creates the DOJO items for the FishEye menu when GWT widget is attached on
the browser. Don't use this method directly the <code>DojoController</code>
call the method.
        */
  public void doAfterCreation() {
   buildItems();
}


public String getDojoName() {
      return "dojox.widget.FisheyeList";
}

/**
Defines the DOJO widget Item (not create one). The name of the widget is
TatamiFisheyeItem. Arms also the callback to catch the mouse event or these
items.
*/
  public void onDojoLoad() {
       defineTatamiItem();
}

/**
Defines the DOJO widget Item (not create one). The name of the widget is
TatamiFisheyeItem. Arms also the callback to catch the mouse event or these
items.
*/
private native void defineTatamiItem()/*-{
       $wnd.dojo.declare("dojox.widget.TatamiFisheyeItem",
$wnd.dojox.widget.FisheyeListItem, {
       onClick:function (e) {

this.parent.gwtWidget.@com.objetdirect.tatami.client.FishEye::dispatchClick
(Ljava/lang/String;)(this.iconSrc);
       }});

      }-*/;

/**
Method invoked by the DOJO widget when a item is selected. This method
execute the command associated to the item.
@param icon the URL of the icon corresponding to the item.
*/
protected void dispatchClick(String icon) {
   for (int i = 0; i < items.size(); i++) {
       Item item = (Item) items.get(i);
             if (item.icon.equals(icon)) {
                 if (item.command != null) {
                         item.command.execute();
                  }
             }
        }
   }

                                     ...
}//end of class




                       Version 1.1                                  - 33 -
                   Objet Direct
How to create a Google Web Toolkit widget using the
                 Dojo Framework




    Version 1.1                                  - 34 -

								
To top