Wednesday, July 22, 2009

DivPanel - Creating a new Widget

Create a composite or extend a widget ?

This question has many answers. In the end it all depends on what is your needs.

When you want to make many widgets work together, like the labeltextbox we created before it's better to create a composite. But when you need to create a new behavior for your widget, maybe it's better to extend a base widget.

As example we will extend the simplePanel, that supports only one widget inside it, to support as many widgets as we need.

Unlike the HorizontalPanel and the VerticalPanel, that uses tables to align the widgets inside it, the simplePanel uses a div to wrap its widget.

Here is the code:

public class DivPanel extends SimplePanel {


private WidgetCollection children = new WidgetCollection(this);


public DivPanel() {

super();

}


public Widget getWidget(int index) {

return getChildren().get(index);

}


public int getWidgetCount() {

return getChildren().size();

}


public int getWidgetIndex(Widget child) {

return getChildren().indexOf(child);

}


public Iterator iterator() {

return getChildren().iterator();

}


public boolean remove(int index) {

return remove(getWidget(index));

}


@Override

public boolean remove(Widget w) {

// Validate.

if (w.getParent() != this) {

return false;

}

// Orphan.

orphan(w);


// Physical detach.

Element elem = w.getElement();

DOM.removeChild(DOM.getParent(elem), elem);


// Logical detach.

getChildren().remove(w);

return true;

}

public void add(Widget child){

add(child,getElement());

}


protected void add(Widget child, Element container) {

// Detach new child.

child.removeFromParent();


// Logical attach.

getChildren().add(child);


// Physical attach.

DOM.appendChild(container, child.getElement());


// Adopt.

adopt(child);

}


protected WidgetCollection getChildren() {

return children;

}


}

First and most important we need to rewrite the add method (the simplePanel.add method verify if you already added a widget and throws an exception).
Second we need to create a WidgetCollection to hold all the widgets that will be accessed.
Let's take a look at the add(Container,widget).
If we use the DOM.appendChild method our page will look like we want, but we need also to call the adopt(widget) method, so the events and handlers already associated with the widget still works.

Also when extending an widget it's very important to know what will be your base class.
It could be the widget class, some Panel class, maybe a TextBox... and so on. Choosing the rigth base widget is a key factor.

Note that when extending the widget class you need also to create a DOM element and call the setElement method. This is the method responsable for binding your element to the page.

Here is another example:

public class DockDiv extends DivPanel{


public final static int NORTH = 0;

public final static int SOUTH = 1;

public final static int EAST = 2;

public final static int WEST = 3;

public final static int CENTER = 4;

private Element north = DOM.createDiv();

private Element south = DOM.createDiv();

private Element east = DOM.createDiv();

private Element west = DOM.createDiv();

private Element center = DOM.createDiv();

private Element row = DOM.createDiv();

private Element container = DOM.createDiv();

public DockDiv(){

container.appendChild(north);

container.appendChild(row);

container.appendChild(south);

row.appendChild(west);

row.appendChild(center);

row.appendChild(east);

getElement().appendChild(container);

east.getStyle().setProperty("float", "left");

west.getStyle().setProperty("float", "left");

center.getStyle().setProperty("float", "left");

}

public void add(Widget child){

add(child,center);

}

public void add(Widget child, int pos){

switch (pos) {

case NORTH:

add(child,north);

break;

case SOUTH:

add(child,south);

break;

case EAST:

add(child,east);

break;

case WEST:

add(child, west);

break;

default:

add(child, center);

break;

}

}

public Element getRegion(int region){

switch (region) {

case NORTH:

return north;

case SOUTH:

return south;

case EAST:

return east;

case WEST:

return west;

default:

return center;

}

}

@Override

public void setWidth(String width) {

super.setWidth(width);

north.getStyle().setProperty("width", width);

row.getStyle().setProperty("width", width);

south.getStyle().setProperty("width", width);

}

public void setCenterSize(String west, String center, String east){

if (west != null && !west.equals("")){

this.west.getStyle().setProperty("width", west);

}

if (center != null && !center.equals("")){

this.center.getStyle().setProperty("width", center);

}

if (east != null && !east.equals("")){

this.east.getStyle().setProperty("width", east);

}

}

}

as you see this DockDiv extends the divPanel (working with divs, not tables).
Also there is some DOM Elements and in the add method we decide what element will be the container of the widget. This shows that you may create as many elements you need.

No comments:

Post a Comment