Custom Widget and firing events to child widgets

107 views
Skip to first unread message

Sam

unread,
May 17, 2007, 5:15:55 AM5/17/07
to Google Web Toolkit
Hello all,

I'm trying to implement a custom widget by reusing an existing
JavaScript library (http://www.jswitch.com/scripts/show/1) a kind of
stackpanel with a fading effect.
The idea is to host any widget as a subMenu.

When I create any GWT hosted widget (let's say a TextBox) that contain
bound events (click, change, ...) in this way :

TextBox tb = new TextBox();
tb.addClickListener(....)
AddSubMenu("mainMenu","subMenu",tb)

My Textbox listeners are never called. Obviously, I understand why.
Because when we deal with AppendChild elements, GWT doesn't
necessarily know that this Widget is a child widget in the whole
widget hierarchy and onBrowserEvent() could only fire sunk events on
the host widget (in this case, xpmenu).

The question is : how can I create a kind of composite widget where I
could reuse an initial DOM layout (see the xpmenu DOM at the end) and
fire events to all my child components. I don't want to deal with
Composite/Panel and so on because they rely on a kind of user's layout
(flow, vertical, etc...) for which I don't have the hands on.
I know it is possible because Tree widget works this way.

Tell me if I'm not clear ....

Sam

--------------------------------------
My code looks like the following :

package com.mycompany.project.client;

import java.util.HashMap;

import com.google.gwt.user.client.DOM;
import com.google.gwt.user.client.Element;
import com.google.gwt.user.client.Event;
import com.google.gwt.user.client.ui.*;

public class XPMenu extends Widget implements SourcesClickEvents,
SourcesChangeEvents, SourcesKeyboardEvents {

java.util.HashMap menuEntries = new HashMap();

private ClickListenerCollection clickListeners;
private FocusListenerCollection focusListeners;
private KeyboardListenerCollection keyboardListeners;
private MouseListenerCollection mouseListeners;

public XPMenu() {
setElement(DOM.createDiv());
setStyleName(getElement(), "navbar",true);

Element scriptJS = DOM.createElement("script");
DOM.setAttribute(scriptJS, "type", "text/javascript");
DOM.setAttribute(scriptJS, "src", "xpmenuv21.js");
DOM.appendChild(getElement(), scriptJS);
DOM.setEventListener(getElement(), this);
sinkEvents(Event.MOUSEEVENTS | Event.ONCLICK | Event.KEYEVENTS);
}

public void addMenu(String name) {
Element mainDiv = DOM.createDiv();

setStyleName(mainDiv, "mainDiv",true);
DOM.insertChild(getElement(),
mainDiv,DOM.getChildCount(getElement())) ;

Element topItem = DOM.createDiv();

DOM.setAttribute(topItem, "id", name);
setStyleName(topItem, "topItem",true);
DOM.appendChild(mainDiv, topItem);
DOM.setInnerText(topItem, name);

Element dropMenu = DOM.createDiv();
setStyleName(dropMenu, "dropMenu",true);
DOM.appendChild(mainDiv, dropMenu);
Element subMenu = DOM.createDiv();

DOM.setAttribute(subMenu, "Style", "display:inline;");
setStyleName(subMenu, "subMenu",true);
DOM.appendChild(dropMenu, subMenu);

menuEntries.put(name,subMenu);
}

public void addSubMenu(String menu, String submenu, Widget w) {

Element subMenu = (Element) menuEntries.get(menu);
// menu doesn't exist
if (subMenu==null) return ;

Element subItem = DOM.createDiv();
DOM.appendChild(subMenu, subItem);

setStyleName(subItem, "subItem",true);
// by default, xpmenu hosts only href links
// DOM.setInnerHTML(subItem, "<a href=#>" + submenu +"</a>");

// but I want to host any widget
DOM.appendChild(subItem,w.getElement());

}

public void onBrowserEvent(Event event) {
switch (DOM.eventGetType(event)) {
case Event.ONCLICK:
if (clickListeners != null) {
clickListeners.fireClick(this);
}
break;

case Event.ONMOUSEDOWN:
case Event.ONMOUSEUP:
case Event.ONMOUSEMOVE:
case Event.ONMOUSEOVER:
case Event.ONMOUSEOUT:
if (mouseListeners != null) {
mouseListeners.fireMouseEvent(this, event);
}
break;

case Event.ONBLUR:

case Event.ONKEYDOWN:
case Event.ONKEYUP:
case Event.ONKEYPRESS:
if (keyboardListeners != null) {
keyboardListeners.fireKeyboardEvent(this, event);
}
break;
}
}

// Listeners
public void addClickListener(ClickListener listener) {
if (clickListeners == null) {
clickListeners = new ClickListenerCollection();
}
clickListeners.add(listener);
}

public void addFocusListener(FocusListener listener) {
if (focusListeners == null) {
focusListeners = new FocusListenerCollection();
}
focusListeners.add(listener);
}

public void addKeyboardListener(KeyboardListener listener) {
if (keyboardListeners == null) {
keyboardListeners = new KeyboardListenerCollection();
}
keyboardListeners.add(listener);
}

public void addMouseListener(MouseListener listener) {
if (mouseListeners == null) {
mouseListeners = new MouseListenerCollection();
}
mouseListeners.add(listener);
}

public void removeClickListener(ClickListener listener) {
// TODO Auto-generated method stub
}

public void addChangeListener(ChangeListener listener) {
// TODO Auto-generated method stub

}

public void removeChangeListener(ChangeListener listener) {
// TODO Auto-generated method stub
}

public void removeKeyboardListener(KeyboardListener listener) {
// TODO Auto-generated method stub
}
}

----------------------------------------------------------
The DOM I want to mimic :

<!-- *********************************Start
Menu****************************** -->
<div class="mainDiv" >
<div class="topItem" >Demo Menu 1</div>
<div class="dropMenu" ><!-- -->
<div class="subMenu" style="display:inline;">
<div class="subItem"><a href="#">Configuration</a></div>
<div class="subItem"><a href="#">Tool Box</a></div>
<div class="subItem"><a href="#">Contact Us</a></div>
<div class="subItem"><a href="#">Sub Menu 4</a></div>
<div class="subItem"><a href="#">Sub Menu 5</a></div>
</div>
</div>
</div>
<!-- *********************************End
Menu****************************** -->
<br>
<!-- *********************************Start
Menu****************************** -->
<div class="mainDiv" >
<div class="topItem" >Demo Menu 2</div>
<div class="dropMenu" ><!-- -->
<div class="subMenu" style="display:none;">
<div class="subItem"><a href="#">Configuration</a></div>
<div class="subItem"><a href="#">Sub Menu 2</a></div>
<div class="subItem"><a href="#">Sub Menu 3</a></div>
<div class="subItem"><a href="#">Sub Menu 4</a></div>
</div>
</div>
</div>
<!-- *********************************End
Menu****************************** -->
<script type="text/javascript" src="xpmenuv21.js"></script>
</div>

Sam

unread,
May 17, 2007, 5:57:02 AM5/17/07
to Google Web Toolkit
And I would like also to avoid a kind of recursive onBrowserEvent()
call in the main widget onBrowserEvent() like this

XPMenu.onBrowserEvent(Event event) {
// Event handling for the host widget
switch (event) (......)
// child widget propagation
for (int i=0;i<widgets.size();i++) ((Widget)
widgets.get(i)).onBrowserEvent(event);

Reply all
Reply to author
Forward
0 new messages