package org.tessell.model.dsl;
import org.tessell.gwt.user.client.ui.HasCss;
import org.tessell.model.commands.HasActive;
import org.tessell.model.commands.UiCommand;
import org.tessell.model.properties.Property;
import org.tessell.util.OnEnterKeyHandler;
import org.tessell.widgets.IsTextList;
import com.google.gwt.event.dom.client.HasAllKeyHandlers;
import com.google.gwt.event.dom.client.HasClickHandlers;
import com.google.gwt.user.client.ui.HasEnabled;
/** Binds various things to a command. */
public class UiCommandBinder {
private final Binder b;
private final UiCommand command;
public UiCommandBinder(final Binder b, final UiCommand command) {
this.b = b;
this.command = command;
}
/** Binds clicks from {@code clickable} to our command, and our errors to {@code errors}. */
public UiCommandBinder to(final HasClickHandlers clickable, final IsTextList errors) {
return to(clickable).errorsTo(errors);
}
/** Binds "enter" from key down handlers to our command. */
public UiCommandBinder toEnterKey(final HasAllKeyHandlers... allKeys) {
OnEnterKeyHandler h = new OnEnterKeyHandler(() -> command.execute());
for (HasAllKeyHandlers allKey : allKeys) {
b.add(allKey.addKeyDownHandler(h));
}
return this;
}
/** Has our command execute only if {@code onlyIf} is true. */
public UiCommandBinder onlyIf(final Property<Boolean> onlyIf) {
command.addOnlyIf(onlyIf);
return this;
}
/** Binds clicks from {@code clickable} to our command. */
public UiCommandBinder to(final HasClickHandlers clickable) {
b.add(clickable.addClickHandler(e -> {
command.execute();
e.preventDefault();
}));
// Assume that if command.active() is available, and HasEnabled is available,
// it just makes sense to disable clickable while the command is active
if (command instanceof HasActive && clickable instanceof HasEnabled) {
Property<Boolean> active = ((HasActive) command).active();
b.when(active).is(true).disable((HasEnabled) clickable);
}
return this;
}
/** Shows {@code hasCss} only when the command is active. */
public UiCommandBinder spin(final HasCss hasCss) {
if (command instanceof HasActive) {
Property<Boolean> active = ((HasActive) command).active();
b.when(active).is(true).visible(hasCss);
} else {
throw new IllegalStateException("Not a command that has .active() available");
}
return this;
}
/** Binds errors for our command to {@code errors}. */
public UiCommandBinder errorsTo(IsTextList errors) {
final TextListOnError i = new TextListOnError(errors);
b.add(command.addRuleTriggeredHandler(i));
b.add(command.addRuleUntriggeredHandler(i));
return this;
}
}