package org.tessell.widgets;
import java.util.Iterator;
import org.tessell.gwt.dom.client.StubElement;
import org.tessell.gwt.dom.client.StubStyle;
import org.tessell.gwt.user.client.ui.IsWidget;
import com.google.gwt.event.dom.client.DomEvent;
import com.google.gwt.event.logical.shared.AttachEvent;
import com.google.gwt.event.logical.shared.AttachEvent.Handler;
import com.google.gwt.event.shared.*;
import com.google.gwt.user.client.Event;
import com.google.gwt.user.client.ui.Widget;
public class StubWidget implements IsWidget, IsStubWidget {
// Prefer SimpleEventBus because it matches browser semantics better; specifically
// if we're reacting to, say, a click event, and cause a focus event to fire, it
// fires right away instead of queueing it for later like SimplerEventBus does.
protected final EventBus handlers = new SimpleEventBus();
private final StubElement element;
private IsWidget parent;
private boolean attached = false;
public int absoluteTop;
public int absoluteLeft;
public int offsetWidth;
public int offsetHeight;
public StubWidget() {
this(new StubElement());
}
public StubWidget(StubElement element) {
this.element = element;
element.setWidget(this);
}
/** @return the widget for {@code id} or {@code null} */
public IsWidget findById(String id) {
if (element.getId() != null && element.getId().equals(id)) {
return this;
}
return findInChildren(id);
}
public void fireAttached() {
attached = true;
AttachEvent.fire(this, true);
}
public void fireDetached() {
attached = false;
AttachEvent.fire(this, false);
}
@Override
public void onBrowserEvent(final Event event) {
throw new UnsupportedOperationException("This is a stub.");
}
@Override
public IsWidget getIsParent() {
return parent;
}
public void setIsParent(IsWidget parent) {
this.parent = parent;
}
@Override
public void fireEvent(final GwtEvent<?> event) {
handlers.fireEvent(event);
}
@Override
public void addStyleName(final String style) {
element.addStyleName(style);
}
@Override
public void removeStyleName(final String style) {
element.removeStyleName(style);
}
@Override
public int getAbsoluteTop() {
return absoluteTop;
}
@Override
public int getAbsoluteLeft() {
return absoluteLeft;
}
@Override
public StubStyle getStyle() {
return element.getStyle();
}
@Override
public int getOffsetWidth() {
return offsetWidth;
}
@Override
public int getOffsetHeight() {
return offsetHeight;
}
@Override
public void ensureDebugId(final String debugId) {
element.setId(debugId);
onEnsureDebugId(debugId);
}
@Override
public String toString() {
return getClass().getSimpleName() + "[" + element.getId() + "]";
}
@Override
public String getStyleName() {
return element.getStyleName();
}
@Override
public void setStyleName(String styleName) {
element.setStyleName(styleName);
}
@Override
public Widget asWidget() {
throw new UnsupportedOperationException("This is a stub");
}
@Override
public StubElement getIsElement() {
return element;
}
@Override
public HandlerRegistration addAttachHandler(Handler handler) {
return handlers.addHandler(AttachEvent.getType(), handler);
}
@Override
public boolean isAttached() {
return attached;
}
@Override
public <H extends EventHandler> HandlerRegistration addDomHandler(final H handler, DomEvent.Type<H> type) {
return handlers.addHandler(type, handler);
}
// for subclasses to override
protected void onEnsureDebugId(String baseDebugId) {
}
// for subclasses that contain children to override
protected IsWidget findInChildren(String id) {
return null;
}
/** Looks recursively into {@code widgets} for one with {@code id}. */
protected static IsWidget findInChildren(Iterator<IsWidget> widgets, String id) {
while (widgets.hasNext()) {
IsWidget next = widgets.next();
final StubWidget stub;
if (next instanceof CompositeIsWidget) {
// assume the CompositeIsWidget is wrapping a stub widget
stub = (StubWidget) ((CompositeIsWidget) next).getIsWidget();
} else {
stub = (StubWidget) next;
}
IsWidget found = stub.findById(id);
if (found != null) {
return found;
}
}
return null;
}
}