package org.tessell.model.dsl; import org.tessell.gwt.animation.client.IsAnimation; import org.tessell.gwt.user.client.ui.HasCss; import org.tessell.gwt.user.client.ui.IsWidget; import org.tessell.model.commands.UiCommand; import org.tessell.model.properties.Property; import org.tessell.model.validation.events.RuleTriggeredEvent; import org.tessell.model.validation.events.RuleUntriggeredEvent; import org.tessell.util.WidgetUtils; import com.google.gwt.dom.client.Style.Display; import com.google.gwt.dom.client.Style.Visibility; import com.google.gwt.user.client.TakesValue; import com.google.gwt.user.client.ui.HasEnabled; public class WhenIsBinder<P> { private final Binder b; private final Property<P> property; private final WhenCondition<P> condition; private boolean trigged = false; public WhenIsBinder(final Binder b, final Property<P> property, final WhenCondition<P> condition) { this.b = b; this.property = property; this.condition = condition; } public WhenIsSetStyleBinder<P> set(final String style) { return new WhenIsSetStyleBinder<P>(b, property, condition, style); } public WhenIsSetOrElseStyleBinder<P> setOrElse(final String ifTrueStyle, final String ifFalseStyle) { return new WhenIsSetOrElseStyleBinder<P>(b, property, condition, ifTrueStyle, ifFalseStyle); } /** @return a fluent {@link SetPropertyBinder} to set a value on {@code other} when this condition is true. */ public <Q> WhenIsSetValueBinder<P, Q> set(final TakesValue<Q> value) { return new WhenIsSetValueBinder<P, Q>(b, property, condition, value); } public <V> WhenIsRemoveBinder<P, V> remove(final V newValue) { return new WhenIsRemoveBinder<P, V>(b, property, condition, newValue); } public <V> WhenIsAddBinder<P, V> add(final V newValue) { return new WhenIsAddBinder<P, V>(b, property, condition, newValue); } public WhenIsAttachBinder<P> attach(final IsWidget widget) { return new WhenIsAttachBinder<P>(b, property, condition, widget); } public void run(final Runnable... runnables) { b.add(property.addPropertyChangedHandler(e -> runIfCondition(runnables))); runIfCondition(runnables); // run initial } // UiCommands are Runnables (now), but execute is still a nice alias public void execute(final UiCommand command) { run(command); } public void show(final HasCss... csses) { b.add(property.addPropertyChangedHandler(e -> showIfCondition(csses))); showIfCondition(csses); // set initial } public void hide(final HasCss... csses) { b.add(property.addPropertyChangedHandler(e -> hideIfCondition(csses))); hideIfCondition(csses); // set initial } public void visible(final HasCss... css) { b.add(property.addPropertyChangedHandler(e -> visibleIfCondition(css))); visibleIfCondition(css); // set initial } public void error(final String message) { b.add(property.addPropertyChangedHandler(e -> errorIfCondition(message))); errorIfCondition(message); } public void enable(final HasEnabled... enabled) { b.add(property.addPropertyChangedHandler(e -> updateEnabled(enabled, true))); updateEnabled(enabled, true); // set initial value } public void disable(final HasEnabled... enabled) { b.add(property.addPropertyChangedHandler(e -> updateEnabled(enabled, false))); updateEnabled(enabled, false); // set initial value } public void fadeIn(final HasCss widget) { final IsAnimation[] lastAnimation = { null }; b.add(property.addPropertyChangedHandler(e -> { if (lastAnimation[0] != null) { lastAnimation[0].cancel(); } if (condition.evaluate(property)) { lastAnimation[0] = WidgetUtils.fadeIn(widget); } else { lastAnimation[0] = WidgetUtils.fadeOut(widget); } })); // set initial value if (condition.evaluate(property)) { lastAnimation[0] = WidgetUtils.fadeIn(widget); } else { // assume we want to hide right away WidgetUtils.hide(widget); } } private void updateEnabled(final HasEnabled[] enabled, final boolean valueIfTrue) { final boolean valueToSet = condition.evaluate(property) ? valueIfTrue : !valueIfTrue; for (final HasEnabled e : enabled) { e.setEnabled(valueToSet); } } private void runIfCondition(Runnable... runnables) { if (condition.evaluate(property)) { for (Runnable runnable : runnables) { runnable.run(); } } } private void errorIfCondition(final String message) { if (condition.evaluate(property)) { property.fireEvent(new RuleTriggeredEvent(this, message, new Boolean[] { false })); trigged = true; } else if (trigged) { property.fireEvent(new RuleUntriggeredEvent(this, message)); trigged = false; } } private void showIfCondition(final HasCss... csses) { for (final HasCss css : csses) { if (condition.evaluate(property)) { css.getStyle().clearDisplay(); } else { css.getStyle().setDisplay(Display.NONE); } } } private void hideIfCondition(final HasCss... csses) { for (final HasCss css : csses) { if (condition.evaluate(property)) { css.getStyle().setDisplay(Display.NONE); } else { css.getStyle().clearDisplay(); } } } private void visibleIfCondition(final HasCss... csses) { for (final HasCss css : csses) { if (condition.evaluate(property)) { css.getStyle().clearVisibility(); } else { css.getStyle().setVisibility(Visibility.HIDDEN); } } } }