package org.tessell.widgets;
import org.tessell.gwt.dom.client.IsElement;
import org.tessell.gwt.dom.client.IsStyle;
import org.tessell.gwt.user.client.ui.IsWidget;
import com.google.gwt.event.dom.client.DomEvent.Type;
import com.google.gwt.event.logical.shared.AttachEvent.Handler;
import com.google.gwt.event.shared.EventHandler;
import com.google.gwt.event.shared.GwtEvent;
import com.google.gwt.event.shared.HandlerRegistration;
import com.google.gwt.user.client.Event;
import com.google.gwt.user.client.ui.Widget;
/**
* Base class for making logical {@link IsWidget}s that can be unit tested.
*
* E.g.:
*
* <code>
* class MyWidget extends CompositeIsWidget {
* private final IsTextBox textBox = newTextBox();
*
* public MyWidget() {
* setWidget(textBox);
* }
*
* public void customLogic() {
* textBox.getStyle().setBackgroundColor("blue");
* }
* }
* </code>
*
* Note that only widgets that do not rely directly on the DOM
* can be built in this fashion. E.g. {@link #onBrowserEvent(Event)}
* is not implemented for stub/test widgets.
*
* If you do have a widget that needs direct DOM access, you'll
* have to make your own {@code IsMyWidget}, {@code GwtMyWidget},
* and {@code StubMyWidget} classes, so that {@code GwtMyWidget}
* can do whatever it wants with DOM/browser-coupled code, and
* {@code StubMyWidget} will pretend to do it for tests.
*/
public class CompositeIsWidget implements IsWidget {
protected IsWidget widget;
/** Sets our composite widgets, and returns it for fluent/inline assignments. */
protected <W extends IsWidget> W setWidget(final W widget) {
if (this.widget != null) {
throw new IllegalStateException("CompositeIsWidget.setWidget was already called");
}
this.widget = widget;
return widget;
}
@Override
public Widget asWidget() {
if (widget == null) {
throw new IllegalStateException("CompositeIsWidget.setWidget was not called");
}
return widget.asWidget();
}
@Override
public void ensureDebugId(final String id) {
widget.ensureDebugId(id);
// This is hacky way as it won't get compiled out like regular
// widget's onEnsureDebugId (which is called by GWT's DebugImpl)
onEnsureDebugId(id);
}
/** Method for subclasses to override to set debug ids on their children. */
protected void onEnsureDebugId(String id) {
// We're not actually called by GWT's DebugImpl, as it calls the
// widget's onEnsureDebugId, so we don't have to do anything.
}
@Override
public int getAbsoluteLeft() {
return widget.getAbsoluteLeft();
}
@Override
public int getAbsoluteTop() {
return widget.getAbsoluteTop();
}
@Override
public int getOffsetHeight() {
return widget.getOffsetHeight();
}
@Override
public int getOffsetWidth() {
return widget.getOffsetWidth();
}
@Override
public void onBrowserEvent(final Event event) {
widget.onBrowserEvent(event);
}
@Override
public void fireEvent(final GwtEvent<?> event) {
widget.fireEvent(event);
}
@Override
public void addStyleName(final String styleName) {
widget.addStyleName(styleName);
}
@Override
public IsStyle getStyle() {
return getIsElement().getStyle();
}
@Override
public String getStyleName() {
return widget.getStyleName();
}
@Override
public void setStyleName(String styleName) {
widget.setStyleName(styleName);
}
@Override
public void removeStyleName(final String styleName) {
widget.removeStyleName(styleName);
}
@Override
public IsElement getIsElement() {
return widget.getIsElement();
}
@Override
public HandlerRegistration addAttachHandler(Handler handler) {
return widget.addAttachHandler(handler);
}
@Override
public <H extends EventHandler> HandlerRegistration addDomHandler(H handler, Type<H> type) {
return widget.addDomHandler(handler, type);
}
@Override
public boolean isAttached() {
return widget.isAttached();
}
public IsWidget getIsWidget() {
return widget;
}
@Override
public IsWidget getIsParent() {
return widget.getIsParent();
}
}