package com.yoghurt.crypto.transactions.client.widget;
import com.google.gwt.core.client.GWT;
import com.google.gwt.dom.client.Style.Unit;
import com.google.gwt.event.dom.client.ClickEvent;
import com.google.gwt.event.dom.client.ClickHandler;
import com.google.gwt.event.dom.client.HasClickHandlers;
import com.google.gwt.event.dom.client.HasMouseOutHandlers;
import com.google.gwt.event.dom.client.HasMouseOverHandlers;
import com.google.gwt.event.dom.client.MouseOutEvent;
import com.google.gwt.event.dom.client.MouseOutHandler;
import com.google.gwt.event.dom.client.MouseOverEvent;
import com.google.gwt.event.dom.client.MouseOverHandler;
import com.google.gwt.event.shared.HandlerRegistration;
import com.google.gwt.resources.client.CssResource;
import com.google.gwt.uibinder.client.UiBinder;
import com.google.gwt.uibinder.client.UiField;
import com.google.gwt.user.client.Timer;
import com.google.gwt.user.client.ui.Composite;
import com.google.gwt.user.client.ui.FlowPanel;
import com.google.gwt.user.client.ui.Label;
import com.google.gwt.user.client.ui.Widget;
import com.yoghurt.crypto.transactions.client.util.ComputedStyle;
import com.yoghurt.crypto.transactions.client.util.misc.Color;
public class ContextField<T> extends Composite implements HasMouseOutHandlers, HasMouseOverHandlers, HasClickHandlers {
private static final int FIELD_HEIGHT = 24;
interface ContextFieldUiBinder extends UiBinder<Widget, ContextField<?>> {}
private static final ContextFieldUiBinder UI_BINDER = GWT.create(ContextFieldUiBinder.class);
/**
* Needs to correspond to the same value in the UiBinder
*/
private static final int ANIMATION_TIME = 200;
private static final int CLEAN_UP_DELAY = 5 + ANIMATION_TIME;
@UiField CustomStyle style;
@UiField FlowPanel container;
private T value;
private String currentText;
private final Timer cleanupTimer = new Timer() {
@Override
public void run() {
// Make sure we're not animating
container.addStyleName(style.noAnimation());
// Remove all but the last widget
while(container.getWidgetCount() > 1) {
container.remove(0);
}
// Reset the 'top' attribute to 0, and enforce the DOM change
container.getElement().getStyle().setTop(0, Unit.PX);
ComputedStyle.getStyleProperty(container.getElement(), "top");
// Re-enable animation
container.removeStyleName(style.noAnimation());
}
};
public interface CustomStyle extends CssResource {
String fieldSelected();
String fieldActive();
String noAnimation();
}
public ContextField(final T value, final Color color, final String text) {
this.value = value;
initWidget(UI_BINDER.createAndBindUi(this));
setColor(color);
setContent(text, false);
}
public void setColor(final Color color) {
final Color backgroundColor = color.copy();
backgroundColor.setA(0.2);
getElement().getStyle().setBorderColor(color.getValue());
getElement().getStyle().setBackgroundColor(backgroundColor.getValue());
}
public void setContent(final String text) {
setContent(text, true);
}
public void setContent(final String text, final boolean animate) {
// Bug out if the text to display is the same as the current text
if (text != null && text.equals(currentText)) {
return;
}
if(!animate) {
container.clear();
}
final Label lbl = new Label(text);
container.add(lbl);
if(animate) {
container.getElement().getStyle().setTop(- (container.getWidgetCount() - 1) * FIELD_HEIGHT, Unit.PX);
// This is gonna suck if there's more than a couple of these running, so thank god Mr Moore invented that law of his
cleanupTimer.cancel();
cleanupTimer.schedule(CLEAN_UP_DELAY);
} else {
container.getElement().getStyle().setTop(0, Unit.PX);
}
currentText = text;
}
public T getValue() {
return value;
}
public void setValue(final T value) {
this.value = value;
}
public void setSelected(final boolean selected) {
setStyleName(style.fieldSelected(), selected);
}
public void setActive(final boolean active) {
setStyleName(style.fieldActive(), active);
}
@Override
public HandlerRegistration addClickHandler(final ClickHandler handler) {
return addDomHandler(handler, ClickEvent.getType());
}
@Override
public HandlerRegistration addMouseOverHandler(final MouseOverHandler handler) {
return addDomHandler(handler, MouseOverEvent.getType());
}
@Override
public HandlerRegistration addMouseOutHandler(final MouseOutHandler handler) {
return addDomHandler(handler, MouseOutEvent.getType());
}
}