eu.future.earth.gwt.client.TimeEditBox Maven / Gradle / Ivy
The newest version!
package eu.future.earth.gwt.client;
import java.util.Calendar;
import java.util.Date;
import java.util.GregorianCalendar;
import com.google.gwt.event.dom.client.FocusEvent;
import com.google.gwt.event.dom.client.FocusHandler;
import com.google.gwt.event.dom.client.KeyCodes;
import com.google.gwt.event.logical.shared.ValueChangeEvent;
import com.google.gwt.event.logical.shared.ValueChangeHandler;
import com.google.gwt.event.shared.HandlerRegistration;
import com.google.gwt.i18n.client.DateTimeFormat;
import com.google.gwt.user.client.DOM;
import com.google.gwt.user.client.Event;
import com.google.gwt.user.client.ui.TextBox;
import eu.future.earth.gwt.client.ui.events.enter.HasKeyEnterEventHandlers;
import eu.future.earth.gwt.client.ui.events.enter.KeyEnterEvent;
import eu.future.earth.gwt.client.ui.events.enter.KeyEnterHandler;
import eu.future.earth.gwt.client.ui.popup.PopupRenderer;
import eu.future.earth.gwt.client.ui.popup.SelectPopup;
/**
* Box for editing time entries
*/
public class TimeEditBox extends TextBox implements HasKeyEnterEventHandlers {
public final static String DEFAULT_TIME_FORMAT = "HH:mm";
private static int convert(int keyCode) {
// convert 0 - 9 keys on number pad down into normal 0 - 9 range
if (keyCode >= 96 && keyCode <= 105) {
return keyCode - 48;
}
return keyCode;
}
private static boolean isTimeKey(int keyCode) {
boolean result = false;
// 0 - 9 keys above qwerty
if (keyCode >= 48 && keyCode <= 57) {
result = true;
}
// 0 - 9 keys on number pad
if (keyCode >= 96 && keyCode <= 105) {
result = true;
}
// A, M, P keys
if (keyCode == 65 || keyCode == 77 || keyCode == 80) {
result = true;
}
if (keyCode == KeyCodes.KEY_BACKSPACE) {
result = true;
}
return result;
}
private String format = DEFAULT_TIME_FORMAT;
private DateTimeFormat date = null;
private final SelectPopup panel = new SelectPopup(new PopupRenderer() {
@Override
public String getId(String newRow) {
return newRow;
}
@Override
public String getLabel(String item) {
return item;
}
});
public TimeEditBox() {
this(DEFAULT_TIME_FORMAT);
}
public TimeEditBox(boolean showPopup) {
this(DEFAULT_TIME_FORMAT, showPopup);
}
public TimeEditBox(String format) {
this(format, false);
}
public TimeEditBox(String format, boolean showPopup) {
super.sinkEvents(Event.ONKEYDOWN);
setFormat(format);
addStyleName("ftr-time-box");
// getElement().getStyle().setWidth(50, Unit.PX);
for (int i = 0; i < 24; i++) {
if (i < 10) {
panel.addValue("0" + i + ":00");
panel.addValue("0" + i + ":30");
} else {
panel.addValue(i + ":00");
panel.addValue(i + ":30");
}
}
if (showPopup) {
super.addFocusHandler(new FocusHandler() {
@Override
public void onFocus(FocusEvent event) {
panel.showRelativeTo(TimeEditBox.this);
panel.setValue(getValue());
panel.scrollToValue();
}
});
}
panel.addValueChangeHandler(new ValueChangeHandler() {
@Override
public void onValueChange(ValueChangeEvent event) {
setText(event.getValue());
}
});
}
@Override
public HandlerRegistration addValueChangeHandler(ValueChangeHandler handler) {
return panel.addValueChangeHandler(handler);
}
@Override
public HandlerRegistration addKeyEnterHandler(KeyEnterHandler handler) {
return super.addHandler(handler, KeyEnterEvent.getType());
}
private void checkState() {
if (isValid()) {
super.removeStyleName("ftr-field-error");
} else {
super.addStyleName("ftr-field-error");
}
}
public String getFormat() {
return format;
}
public Date getValue(Date dateToAttachTo) {
Date result = null;
if (dateToAttachTo != null && getText() != null && getText().length() == format.length()) {
if (!getText().equals(format)) {
try {
final Date time = DateTimeFormat.getFormat(format).parse(getText());
final GregorianCalendar thelper = new GregorianCalendar();
thelper.setTime(time);
final GregorianCalendar helper = new GregorianCalendar();
setHelper(dateToAttachTo, thelper, helper);
return helper.getTime();
} catch (IllegalArgumentException ex) {
}
}
}
return result;
}
@SuppressWarnings("static-method")
private void setHelper(Date dateToAttachTo, final GregorianCalendar thelper, final GregorianCalendar helper) {
helper.setTime(dateToAttachTo);
helper.set(Calendar.HOUR_OF_DAY, thelper.get(Calendar.HOUR_OF_DAY));
helper.set(Calendar.MINUTE, thelper.get(Calendar.MINUTE));
helper.set(Calendar.SECOND, 0);
helper.set(Calendar.MILLISECOND, 0);
}
public boolean isValid() {
if (super.getText() == null || super.getText().isEmpty() || super.getText().equalsIgnoreCase(format)) {
return true;
}
return getValue(new Date()) != null;
}
@Override
public void onBrowserEvent(Event event) {
int eventType = DOM.eventGetType(event);
int keyCode = event.getKeyCode();
switch (eventType) {
case Event.ONKEYDOWN: {
if (KeyEnterEvent.isValidKeyCode(keyCode)) {
KeyEnterEvent.fire(this);
} else {
if (keyCode == KeyCodes.KEY_DOWN) {
panel.showRelativeTo(TimeEditBox.this);
panel.setValue(getValue());
panel.scrollToValue();
panel.focusSelected();
}
if (keyCode == KeyCodes.KEY_TAB) {
panel.hide();
}
if (keyCode == 37 || keyCode == 39 || keyCode == 18 || keyCode == 9) {
super.onBrowserEvent(event);
checkState();
return;
}
if (isTimeKey(keyCode)) {
final int cursor = super.getCursorPos();
if (cursor >= format.length() && keyCode != KeyCodes.KEY_BACKSPACE) {
// This block is empyt as intended.
} else {
final String temp = super.getText();
if (keyCode == KeyCodes.KEY_BACKSPACE) {
if (cursor < 1) {
return;
}
final char rep = format.charAt(cursor - 1);
final String newString = temp.substring(0, cursor - 1) + rep + temp.substring(cursor, format.length());
super.setText(newString);
checkState();
super.setCursorPos(cursor - 1);
} else {
final char rep = format.charAt(cursor);
if (rep == ':') {
super.setCursorPos(cursor + 1);
} else {
char next = (char) -1;
if (format.length() > cursor + 1) {
next = format.charAt(cursor + 1);
}
char newChar = (char) convert(keyCode);
boolean allow = false;
if (rep == 'H' && next == 'H') {
if (newChar == '0' || newChar == '1' || newChar == '2') {
allow = true;
}
} else {
if (rep == 'H') {
char prev = temp.charAt(cursor - 1);
if (prev == '2') {
if (newChar == '0' || newChar == '1' || newChar == '2' || newChar == '3') {
allow = true;
}
} else {
allow = true;
}
}
}
if (rep == 'h' && next == 'h') {
if (newChar == '0' || newChar == '1') {
allow = true;
}
} else {
if (rep == 'h') {
char prev = temp.charAt(cursor - 1);
if (prev == '1') {
if (newChar == '0' || newChar == '1' || newChar == '2') {
allow = true;
}
} else {
allow = true;
}
}
}
if (rep == 'm' && next == 'm') {
if (newChar == '0' || newChar == '1' || newChar == '2' || newChar == '3' || newChar == '4' || newChar == '5') {
allow = true;
}
} else {
if (rep == 'm') {
final char prev = temp.charAt(cursor - 1);
if (prev == '0' || prev == '1' || prev == '2' || prev == '3' || prev == '4' || prev == '5') {
allow = true;
} else {
if (newChar == '0') {
allow = true;
}
}
}
}
if (rep == 'a' && next == 'a') {
if (newChar == 'A' || newChar == 'a') {
newChar = 'A';
allow = true;
} else if (newChar == 'P' || newChar == 'p') {
newChar = 'P';
allow = true;
}
} else {
if (rep == 'a') {
if (newChar == 'M' || newChar == 'm') {
newChar = 'M';
allow = true;
}
}
}
if (allow) {
final String newString = temp.substring(0, cursor) + newChar + temp.substring(cursor + 1, format.length());
super.setText(newString);
checkState();
if (keyCode == KeyCodes.KEY_BACKSPACE) {
super.setCursorPos(cursor - 1);
} else {
if (next == ':') {
super.setCursorPos(cursor + 2);
} else {
super.setCursorPos(cursor + 1);
}
}
}
}
}
}
checkState();
event.preventDefault();
return;
}
checkState();
event.preventDefault();
return;
}
}
//$FALL-THROUGH$
default:
super.onBrowserEvent(event);
}
checkState();
}
public void setDate(Date newValue) {
if (newValue != null) {
super.setText(date.format(newValue));
} else {
super.setText(format);
}
checkState();
}
public void setFormat(String format) {
this.format = format;
date = DateTimeFormat.getFormat(format);
super.setText(format);
super.setMaxLength(format.length());
super.setVisibleLength(format.length());
checkState();
}
}