com.mecatran.otp.gwt.client.view.TimePicker.java Source code

Java tutorial

Introduction

Here is the source code for com.mecatran.otp.gwt.client.view.TimePicker.java

Source

/* -------------------------------------------------------------------------
OpenTripPlanner GWT Client
Copyright (C) 2015 Mecatran - info@mecatran.com
    
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2 of the License, or
(at your option) any later version.
    
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
GNU General Public License for more details.
    
You should have received a copy of the GNU General Public License along
with this program; if not, write to the Free Software Foundation, Inc.,
51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
   ------------------------------------------------------------------------- */
package com.mecatran.otp.gwt.client.view;

import java.util.Date;

import com.google.gwt.dom.client.Document;
import com.google.gwt.dom.client.NativeEvent;
import com.google.gwt.event.dom.client.BlurEvent;
import com.google.gwt.event.dom.client.BlurHandler;
import com.google.gwt.event.dom.client.FocusEvent;
import com.google.gwt.event.dom.client.FocusHandler;
import com.google.gwt.event.dom.client.HasBlurHandlers;
import com.google.gwt.event.dom.client.KeyCodes;
import com.google.gwt.event.dom.client.KeyUpEvent;
import com.google.gwt.event.dom.client.KeyUpHandler;
import com.google.gwt.event.dom.client.MouseWheelEvent;
import com.google.gwt.event.dom.client.MouseWheelHandler;
import com.google.gwt.event.logical.shared.HasValueChangeHandlers;
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.ui.Composite;
import com.google.gwt.user.client.ui.Focusable;
import com.google.gwt.user.client.ui.HasValue;
import com.google.gwt.user.client.ui.HasVerticalAlignment;
import com.google.gwt.user.client.ui.HorizontalPanel;
import com.google.gwt.user.client.ui.Label;
import com.google.gwt.user.client.ui.VerticalPanel;

/**
 * Input box that allows to type time values.
 * 
 * The box allows to type hours and minutes, both with am/pm format or 24h. As
 * an extra it allows to move block of 15 minutes, quite useful for scheduling
 * systems.
 * 
 * @author Carlos Tasada
 * 
 */
@SuppressWarnings("deprecation")
public class TimePicker extends Composite
        implements HasValueChangeHandlers<Long>, HasValue<Long>, HasBlurHandlers, Focusable {

    private static final String STYLE_TIMEPICKER = "timePicker";
    private static final String STYLE_TIMEPICKER_ENTRY = "timePickerEntry";
    private static final String STYLE_TIMEPICKER_READONLY = "timePickerReadOnly";

    /**
     * Defines the possible precisions when comparing hours.
     */
    public static enum TIME_PRECISION {
        MINUTE, QUARTER_HOUR
    };

    private final ValueTextBox hoursBox;
    private final ValueTextBox minutesBox;
    private final int minutesSteps;
    private boolean readOnly = false;
    private final VerticalPanel container;
    private final HorizontalPanel timePanel;
    private final Date timeValue;

    /**
     * Default Constructor.
     * 
     * @param time
     *            Hour that will show the widget
     */
    public TimePicker(Date time) {
        this(time, TIME_PRECISION.MINUTE);
    }

    /**
     * Default Constructor.
     * 
     * @param time
     *            Hour that will show the widget
     * @param precision
     *            Indicates if widget precision
     */
    public TimePicker(Date time, TIME_PRECISION precision) {
        timeValue = time;

        container = new VerticalPanel();

        int hour = time.getHours();
        int minutes = time.getMinutes();

        if (precision == TIME_PRECISION.QUARTER_HOUR) {
            minutesSteps = 15;
        } else {
            minutesSteps = 1;
        }

        hoursBox = new ValueTextBox(hour, 0, 24);
        hoursBox.setMinDigits(2);
        hoursBox.setSteps(0);

        minutesBox = new ValueTextBox(minutes, 0, 59);
        minutesBox.setMinDigits(2);
        minutesBox.setSteps(0);

        Label separator = new Label(":");

        hoursBox.setWidth("30px");
        minutesBox.setWidth("30px");

        hoursBox.setStyleName(getStyleTimePickerEntry());
        separator.setStyleName(getStyleTimePickerEntry());
        minutesBox.setStyleName(getStyleTimePickerEntry());

        timePanel = new HorizontalPanel();
        timePanel.setStyleName(getStyleTimePicker());

        timePanel.add(hoursBox);
        timePanel.add(separator);
        timePanel.add(minutesBox);

        setReadOnly(readOnly);

        timePanel.setCellVerticalAlignment(separator, HasVerticalAlignment.ALIGN_MIDDLE);

        container.add(timePanel);

        initWidget(container);

        hoursBox.addValueChangeHandler(new ValueChangeHandler<String>() {
            @Override
            public void onValueChange(ValueChangeEvent<String> event) {
                fireValueChange();
            }
        });
        hoursBox.addKeyUpHandler(new KeyUpHandler() {
            @Override
            public void onKeyUp(KeyUpEvent event) {
                if (isReadOnly()) {
                    return;
                }

                int keyCode = event.getNativeEvent().getKeyCode();

                int hour = Integer.parseInt(hoursBox.getValue());
                int oldHour = timeValue.getHours();
                boolean stepKey = false;

                switch (keyCode) {
                case KeyCodes.KEY_UP:
                    stepKey = true;
                    timeValue.setHours(timeValue.getHours() + 1);
                    break;
                case KeyCodes.KEY_DOWN:
                    stepKey = true;
                    timeValue.setHours(timeValue.getHours() - 1);
                    break;
                }
                updateTimeValue(stepKey, oldHour, hour);
            }
        });
        hoursBox.addMouseWheelHandler(new MouseWheelHandler() {
            public void onMouseWheel(MouseWheelEvent event) {
                int hour = Integer.parseInt(hoursBox.getValue());
                int oldHour = timeValue.getHours();
                if (event.isNorth()) {
                    timeValue.setHours(timeValue.getHours() + 1);
                } else {
                    timeValue.setHours(timeValue.getHours() - 1);
                }
                updateTimeValue(true, oldHour, hour);
            }
        });
        hoursBox.addBlurHandler(new BlurHandler() {
            @Override
            public void onBlur(BlurEvent event) {
                fireBlurEvent();
            }
        });

        minutesBox.addValueChangeHandler(new ValueChangeHandler<String>() {
            @Override
            public void onValueChange(ValueChangeEvent<String> event) {
                fireValueChange();
            }
        });
        minutesBox.addKeyUpHandler(new KeyUpHandler() {
            @Override
            public void onKeyUp(KeyUpEvent event) {
                if (isReadOnly()) {
                    return;
                }

                int keyCode = event.getNativeEvent().getKeyCode();

                int minutes = Integer.parseInt(minutesBox.getValue());
                boolean stepKey = false;

                int oldMinutes = timeValue.getMinutes();

                switch (keyCode) {
                case KeyCodes.KEY_UP:
                    stepKey = true;
                    increaseValue();
                    return;
                case KeyCodes.KEY_DOWN:
                    stepKey = true;
                    decreaseValue();
                    return;
                }

                if (!stepKey && (oldMinutes != minutes)) {

                    int hour = Integer.parseInt(hoursBox.getValue());

                    timeValue.setHours(hour);
                    timeValue.setMinutes(minutes);

                    fireValueChange();
                }
            }
        });
        minutesBox.addMouseWheelHandler(new MouseWheelHandler() {
            public void onMouseWheel(MouseWheelEvent event) {
                if (event.isNorth()) {
                    increaseValue();
                } else {
                    decreaseValue();
                }
            }
        });
        minutesBox.addBlurHandler(new BlurHandler() {
            @Override
            public void onBlur(BlurEvent event) {
                fireBlurEvent();
            }
        });

        // Trying to force that the whole value is selected when receiving the
        // focus
        hoursBox.addFocusHandler(new FocusHandler() {
            @Override
            public void onFocus(FocusEvent event) {
                hoursBox.setFocus(true);
                hoursBox.selectAll();
            }
        });
        minutesBox.addFocusHandler(new FocusHandler() {
            @Override
            public void onFocus(FocusEvent event) {
                minutesBox.setFocus(true);
                minutesBox.selectAll();
            }
        });
        // Making sure the cursor is always in the last position so the editing
        // works as expected
        hoursBox.addValueChangeHandler(new ValueChangeHandler<String>() {
            @Override
            public void onValueChange(ValueChangeEvent<String> event) {
                hoursBox.setCursorPos(hoursBox.getText().length());
            }
        });
        minutesBox.addValueChangeHandler(new ValueChangeHandler<String>() {
            @Override
            public void onValueChange(ValueChangeEvent<String> event) {
                minutesBox.setCursorPos(minutesBox.getText().length());
            }
        });
    }

    private void updateTimeValue(boolean stepKey, int oldHour, int hour) {
        if (stepKey || (oldHour != hour)) {
            if (stepKey) {
                hour = timeValue.getHours();
            }

            hoursBox.setValue(String.valueOf(hour), false);
            int minutes = Integer.parseInt(minutesBox.getValue());

            if (!stepKey) {
                timeValue.setHours(hour);
                timeValue.setMinutes(minutes);
            }

            fireValueChange();
        }
    }

    public void increaseValue() {
        increaseValue(true);
    }

    public void increaseValue(boolean fireEvents) {
        // if (timeValue < 24.0) {
        if (timeValue.getHours() < 24) {
            int hours = timeValue.getHours();
            int oldHours = hours;

            int minutes = timeValue.getMinutes();
            int oldMinutes = minutes;

            if (minutesSteps == 15) {
                if (minutes < 15) {
                    minutes = 15;
                } else if (minutes < 30) {
                    minutes = 30;
                } else if (minutes < 45) {
                    minutes = 45;
                } else {
                    minutes = 0;
                    hours++;
                    if (hours > 23) {
                        hours = 0;
                    }
                }
            } else {
                minutes++;
            }

            if ((oldMinutes != minutes) || (oldHours != hours)) {
                timeValue.setHours(hours);
                timeValue.setMinutes(minutes);
                setValue(timeValue.getTime(), fireEvents);
            }
        }
    }

    public void decreaseValue() {
        decreaseValue(true);
    }

    public void decreaseValue(boolean fireEvents) {
        if (timeValue.getHours() > 0.0) {
            int hours = timeValue.getHours();
            int oldHours = hours;

            int minutes = timeValue.getMinutes();
            int oldMinutes = minutes;

            if (minutesSteps == 15) {
                if (minutes >= 45) {
                    minutes = 30;
                } else if (minutes >= 30) {
                    minutes = 15;
                } else if (minutes >= 15) {
                    minutes = 0;
                } else {
                    minutes = 45;
                    hours--;
                    if (hours < 0) {
                        hours = 23;
                    }
                }
            } else {
                minutes--;
            }

            if ((oldMinutes != minutes) || (oldHours != hours)) {
                timeValue.setHours(hours);
                timeValue.setMinutes(minutes);
                setValue(timeValue.getTime(), fireEvents);
            }
        }
    }

    public long getTime() {
        return timeValue.getTime();
    }

    private void fireValueChange() {
        ValueChangeEvent.fire(this, getValue());
    }

    private void fireBlurEvent() {
        NativeEvent event = Document.get().createBlurEvent();
        BlurEvent.fireNativeEvent(event, this);
    }

    @Override
    public HandlerRegistration addValueChangeHandler(ValueChangeHandler<Long> handler) {
        return addHandler(handler, ValueChangeEvent.getType());
    }

    @Override
    public HandlerRegistration addBlurHandler(BlurHandler handler) {
        return addHandler(handler, BlurEvent.getType());
    }

    @Override
    public Long getValue() {
        return timeValue.getTime();
    }

    public String getValueAsString() {
        DateTimeFormat fmt;
        fmt = DateTimeFormat.getFormat("h:mm");
        return fmt.format(timeValue);
    }

    @Override
    public void setValue(Long value) {
        setValue(value, false);
    }

    @Override
    public void setValue(Long time, boolean fireEvents) {

        Date tmpValue = new Date(time);

        int hour = tmpValue.getHours();
        int minutes = tmpValue.getMinutes();

        hoursBox.setValue(String.valueOf(hour), false);
        minutesBox.setValue(String.valueOf(minutes), false);

        if (fireEvents) {
            ValueChangeEvent.fireIfNotEqual(this, timeValue.getTime(), time);
        }

        timeValue.setTime(time);
    }

    public void setReadOnly(boolean readOnly) {
        this.readOnly = readOnly;

        hoursBox.setReadOnly(readOnly);
        minutesBox.setReadOnly(readOnly);

        if (readOnly) {
            timePanel.setStyleName(getStyleTimePickerReadOnly());
        }
    }

    public boolean isReadOnly() {
        return readOnly;
    }

    @Override
    public int getTabIndex() {
        return hoursBox.getTabIndex();
    }

    @Override
    public void setAccessKey(char key) {
        hoursBox.setAccessKey(key);
    }

    @Override
    public void setFocus(boolean focused) {
        hoursBox.setFocus(focused);
        hoursBox.selectAll();
    }

    @Override
    public void setTabIndex(int index) {
        hoursBox.setTabIndex(index);
    }

    protected String getStyleTimePickerEntry() {
        return STYLE_TIMEPICKER_ENTRY;
    }

    protected String getStyleTimePicker() {
        return STYLE_TIMEPICKER;
    }

    protected String getStyleTimePickerReadOnly() {
        return STYLE_TIMEPICKER_READONLY;
    }
}