package org.tessell.model.dsl;
import static java.lang.Boolean.TRUE;
import java.util.Comparator;
import java.util.List;
import org.tessell.model.commands.UiCommand;
import org.tessell.model.properties.ListProperty;
import org.tessell.model.properties.Property;
import org.tessell.place.PlaceRequest;
import org.tessell.place.events.PlaceRequestEvent;
import com.google.gwt.event.dom.client.DomEvent;
import com.google.gwt.event.shared.HandlerRegistration;
import com.google.gwt.user.client.ui.Focusable;
import com.google.web.bindery.event.shared.EventBus;
public abstract class EventBinder {
private final Binder b;
protected EventBinder(final Binder b) {
this.b = b;
}
/** @return a fluent builder to set {@code property} when triggered. */
public <P> SetPropertyBinder<P> set(Property<P> property) {
return new SetPropertyBinder<P>(b, property, new SetPropertyBinder.Setup() {
public HandlerRegistration setup(final Runnable runnable) {
return hookUpRunnable(runnable);
}
});
}
/** Toggles {@code property} each time the event is triggered. */
public void toggle(final Property<Boolean> property) {
b.add(hookUpEventRunnable(new DomEventRunnable() {
public void run(DomEvent<?> event) {
property.set(TRUE.equals(property.get()) ? false : true);
if (event != null) {
event.preventDefault();
}
}
}));
}
/** Focuses on {@code focusable} when triggered. */
public void focus(final Focusable focusable) {
b.add(hookUpEventRunnable(new DomEventRunnable() {
public void run(DomEvent<?> event) {
focusable.setFocus(true);
if (event != null) {
event.preventDefault();
}
}
}));
}
/** Cancels the event's default action. */
public void preventDefault() {
b.add(hookUpEventRunnable(new DomEventRunnable() {
public void run(DomEvent<?> event) {
event.preventDefault();
}
}));
}
/** Executes {@code command} when triggered. */
public void execute(final UiCommand command) {
b.add(hookUpRunnable(new Runnable() {
public void run() {
command.execute();
}
}));
}
/** Executes {@code runnable} when triggered. */
public void execute(final Runnable runnable) {
b.add(hookUpRunnable(runnable));
}
/** Fires a {@link PlaceRequestEvent} for {@code request} when triggered. */
public void goTo(final EventBus bus, final PlaceRequest request) {
b.add(hookUpRunnable(new Runnable() {
public void run() {
bus.fireEvent(request.asEvent());
}
}));
}
/** @return a fluent binder to add {@code value} to a list when triggered. */
public <P> AddBinder<P> add(P value) {
return new AddBinder<P>(value);
}
/** @return a fluent binder to remove {@code value} remove a list when triggered. */
public <P> RemoveBinder<P> remove(P value) {
return new RemoveBinder<P>(value);
}
/** @return a fluent binder to move up {@code value} in a list when triggered. */
public <P> MoveBinder<P> moveUp(P value) {
return new MoveBinder<P>(value, true);
}
/** @return a fluent binder to move down {@code value} in a list when triggered. */
public <P> MoveBinder<P> moveDown(P value) {
return new MoveBinder<P>(value, false);
}
public <P> SortBinder<P> sort(ListProperty<P> list) {
return new SortBinder<P>(list);
}
protected abstract HandlerRegistration hookUpRunnable(Runnable runnable);
protected abstract HandlerRegistration hookUpEventRunnable(DomEventRunnable runnable);
protected interface DomEventRunnable {
public void run(DomEvent<?> event);
}
public class AddBinder<P> {
private final P value;
private AddBinder(P value) {
this.value = value;
}
public void to(final List<P> values) {
b.add(hookUpRunnable(new Runnable() {
public void run() {
values.add(value);
}
}));
}
public void to(final ListProperty<P> values) {
b.add(hookUpRunnable(new Runnable() {
public void run() {
values.add(value);
}
}));
}
}
public class RemoveBinder<P> {
private final P value;
private RemoveBinder(P value) {
this.value = value;
}
public void from(final List<P> values) {
b.add(hookUpRunnable(new Runnable() {
public void run() {
values.remove(value);
}
}));
}
public void from(final ListProperty<P> values) {
b.add(hookUpRunnable(new Runnable() {
public void run() {
values.remove(value);
}
}));
}
}
public class MoveBinder<P> {
private final P value;
private final boolean up;
private MoveBinder(P value, boolean up) {
this.value = value;
this.up = up;
}
public void in(final ListProperty<P> values) {
b.add(hookUpRunnable(new Runnable() {
public void run() {
if (up) {
values.moveUp(value);
} else {
values.moveDown(value);
}
}
}));
}
}
public class SortBinder<P> {
private final ListProperty<P> list;
private SortBinder(ListProperty<P> list) {
this.list = list;
}
public void by(final Comparator<P> comparator) {
b.add(hookUpRunnable(new Runnable() {
public void run() {
list.sort(comparator);
}
}));
}
}
}