Package tsd.client

Source Code of tsd.client.DateTimeBox$DateTimePicker

// This file is part of OpenTSDB.
// Copyright (C) 2010-2012  The OpenTSDB Authors.
//
// This program is free software: you can redistribute it and/or modify it
// under the terms of the GNU Lesser General Public License as published by
// the Free Software Foundation, either version 2.1 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 Lesser
// General Public License for more details.  You should have received a copy
// of the GNU Lesser General Public License along with this program.  If not,
// see <http://www.gnu.org/licenses/>.
package tsd.client;

import java.util.Date;

import com.google.gwt.event.dom.client.ClickEvent;
import com.google.gwt.event.dom.client.ClickHandler;
import com.google.gwt.event.dom.client.DomEvent;
import com.google.gwt.event.shared.EventHandler;
import com.google.gwt.i18n.client.DateTimeFormat;
import com.google.gwt.user.client.ui.Grid;
import com.google.gwt.user.client.ui.HTMLTable.CellFormatter;
import com.google.gwt.user.client.ui.HorizontalPanel;
import com.google.gwt.user.client.ui.InlineHTML;
import com.google.gwt.user.client.ui.InlineLabel;
import com.google.gwt.user.client.ui.PushButton;
import com.google.gwt.user.client.ui.TextBox;
import com.google.gwt.user.client.ui.VerticalPanel;
import com.google.gwt.user.datepicker.client.DateBox;
import com.google.gwt.user.datepicker.client.DatePicker;

/**
* A {@link DateBox} with support for time.
* <p>
* This class is unnecessarily complicated because {@link DateBox} wasn't
* designed in an extensible way (semi-purposefully).  A thread gwt-contrib
* titled "DatePicker DatePickerComponent protected ?" from 2008 shows that
* back then they were working on an extensible {@link DateBox} and
* {@link DatePicker} for GWT 2, but as of Sep 2010 this hasn't happened.
* Their suggestion to copy-paste-hack the code is unacceptable so instead
* we go through a few hoops to make this work.
*/
final class DateTimeBox extends DateBox {

  private static final DateTimeFormat HHMM_FORMAT =
    DateTimeFormat.getFormat("HH:mm");

  private static final DefaultFormat DATE_FORMAT =
    new DefaultFormat(DateTimeFormat.getFormat("yyyy/MM/dd-HH:mm:ss")) {
      /** Adds support for some human readable dates ("1d ago", "10:30").  */
      @Override
      public Date parse(final DateBox box,
                        final String text,
                        final boolean report_error) {
        if (text.endsWith(" ago") || text.endsWith("-ago")) { // e.g. "1d ago".
          long interval;
          final int lastchar = text.length() - 5;
          try {
            interval = Integer.parseInt(text.substring(0, lastchar));
          } catch (NumberFormatException e) {
            setError(box);
            return null;
          }
          if (interval <= 0) {
            setError(box);
            return null;
          }
          switch (text.charAt(lastchar)) {
            case 's': break;                               // seconds
            case 'm': interval *= 60; break;               // minutes
            case 'h': interval *= 3600; break;             // hours
            case 'd': interval *= 3600 * 24; break;        // days
            case 'w': interval *= 3600 * 24 * 7; break;    // weeks
            case 'y': interval *= 3600 * 24 * 365; break// years
          }
          final Date d = new Date();
          d.setTime(d.getTime() - interval * 1000L);
          return d;
        } else if (text.length() == 5) {  // "HH:MM"
          try {
            return HHMM_FORMAT.parse(text);
          } catch (IllegalArgumentException ignored) {
            setError(box);
            return null;
          }
        }
        return super.parse(box, text, report_error);
      }

      private void setError(final DateBox box) {
        box.addStyleName("dateBoxFormatError");
      }
    };

  public DateTimeBox() {
    super(new DateTimePicker(), null, DATE_FORMAT);
    ((DateTimePicker) getDatePicker()).setDateTimeBox(this);
    final TextBox textbox = getTextBox();
    // Chrome 7.0.5xx versions, Safari 5.0.x and similar render a text box
    // that's too small for 19 characters (WTF?).  So we ask for space for
    // an extra 2 characters.  On Firefox the text box's width is computed
    // properly, so it simply appears slightly wider than necessary.
    textbox.setVisibleLength(19 + 2);
    textbox.setMaxLength(19);
  }

  /**
   * A {@link DatePicker} with a customized UI for time support.
   */
  private static final class DateTimePicker extends DatePicker {

    /** DateTimeBox this picker belongs to.  */
    private DateTimeBox box;
    /** A grid in which we put some buttons we may need to update.  */
    private Grid hours_minutes;

    public DateTimePicker() {
    }

    /**
     * Sets the {@link DateTimeBox} this {@link DateTimePicker} belongs to.
     * This <b>must</b> be called before using this object.
     */
    void setDateTimeBox(final DateTimeBox box) {
      this.box = box;
    }

    /**
     * Sets the date of the {@link DateBox} to the given {@link Date}.
     */
    private void setDate(final Date d) {
      refreshAll();
      box.setValue(d);
      // Put the focus back on the text box to make it easier for the
      // user to manually edit the field.
      box.getTextBox().setFocus(true);
    }

    /**
     * Returns a new button that shifts the date when clicked.
     * @param seconds How many seconds to shift.
     * @param label The label to put on the button.
     */
    private PushButton newShiftDateButton(final int seconds,
                                          final String label) {
      final PushButton button = new PushButton(label);
      button.setStyleName(seconds < 0 ? "datePickerPreviousButton"
                          : "datePickerNextButton");
      button.addClickHandler(new ClickHandler() {
        public void onClick(final ClickEvent event) {
          Date d = box.getValue();
          if (d == null) {
            if (seconds >= 0) {
              return;
            }
            d = new Date();
          }
          d.setTime(d.getTime() + seconds * 1000L);
          d.setSeconds(0);
          setDate(d);
        }
      });
      return button;
    }

    /**
     * Returns a new button that sets the hours when clicked.
     * @param hours An hour of the day (0-23).
     * @param label The label to put on the button.
     */
    private PushButton newSetHoursButton(final int hours) {
      final PushButton button = new PushButton(Integer.toString(hours));
      button.addClickHandler(new ClickHandler() {
        public void onClick(final ClickEvent event) {
          @SuppressWarnings(/* GWT requires us to use Date */{"deprecation"})
          Date d = box.getValue();
          if (d == null) {
            d = new Date();
            d.setMinutes(0);
          }
          d.setHours(hours);
          d.setSeconds(0);
          setDate(d);
        }
      });
      return button;
    }

    /**
     * Returns a new button that sets the minutes when clicked.
     * @param minutes A value for minutes (0-59).
     * @param label The label to put on the button.
     */
    private PushButton newSetMinutesButton(final int minutes,
                                           final String label) {
      final PushButton button = new PushButton(label);
      button.addClickHandler(new ClickHandler() {
        public void onClick(final ClickEvent event) {
          @SuppressWarnings(/* GWT requires us to use Date */{"deprecation"})
          Date d = box.getValue();
          if (d == null) {
            d = new Date();
          }
          d.setMinutes(minutes);
          d.setSeconds(0);
          setDate(d);
        }
      });
      return button;
    }

    /** Rebuilds parts of the UI with buttons to set AM hours.  */
    private void setupAmUI() {
      hours_minutes.setWidget(0, 1, newSetHoursButton(0));
      hours_minutes.setWidget(0, 2, newSetHoursButton(1));
      hours_minutes.setWidget(0, 3, newSetHoursButton(2));
      hours_minutes.setWidget(0, 4, newSetHoursButton(3));
      hours_minutes.setWidget(0, 5, newSetHoursButton(4));
      hours_minutes.setWidget(0, 6, newSetHoursButton(5));
      hours_minutes.setWidget(1, 1, newSetHoursButton(6));
      hours_minutes.setWidget(1, 2, newSetHoursButton(7));
      hours_minutes.setWidget(1, 3, newSetHoursButton(8));
      hours_minutes.setWidget(1, 4, newSetHoursButton(9));
      hours_minutes.setWidget(1, 5, newSetHoursButton(10));
      hours_minutes.setWidget(1, 6, newSetHoursButton(11));
    }

    /** Rebuilds parts of the UI with buttons to set PM hours.  */
    private void setupPmUI() {
      hours_minutes.setWidget(0, 1, newSetHoursButton(12));
      hours_minutes.setWidget(0, 2, newSetHoursButton(13));
      hours_minutes.setWidget(0, 3, newSetHoursButton(14));
      hours_minutes.setWidget(0, 4, newSetHoursButton(15));
      hours_minutes.setWidget(0, 5, newSetHoursButton(16));
      hours_minutes.setWidget(0, 6, newSetHoursButton(17));
      hours_minutes.setWidget(1, 1, newSetHoursButton(18));
      hours_minutes.setWidget(1, 2, newSetHoursButton(19));
      hours_minutes.setWidget(1, 3, newSetHoursButton(20));
      hours_minutes.setWidget(1, 4, newSetHoursButton(21));
      hours_minutes.setWidget(1, 5, newSetHoursButton(22));
      hours_minutes.setWidget(1, 6, newSetHoursButton(23));
    }

    /** Sets up the custom UI of the date picker.  */
    @Override
    protected void setup() {
      final HorizontalPanel panel = new HorizontalPanel();
      initWidget(panel);
      setStyleName(panel.getElement(), "gwt-DatePicker");

      {
        final VerticalPanel vbox = new VerticalPanel();
        setStyleName("gwt-DatePicker");
        vbox.add(super.getMonthSelector());
        vbox.add(super.getView());

        panel.add(vbox);
      }

      {
        // This vbox contains all of the "extra" panel on the side
        // of the calendar view.
        final VerticalPanel vbox = new VerticalPanel();
        setStyleName(vbox.getElement(), "datePickerMonthSelector");

        final PushButton now = new PushButton("now");
        now.setStyleName("datePickerNextButton");
        now.addClickHandler(new ClickHandler() {
          public void onClick(final ClickEvent event) {
            box.setValue(new Date());
          }
        });

        {
          final Grid grid = new Grid(2, 9);
          grid.setWidget(0, 0, newShiftDateButton(-3600, "1h"));
          grid.setWidget(0, 1, newShiftDateButton(-600, "10m"));
          grid.setWidget(0, 2, newShiftDateButton(-60, "1m"));
          grid.setWidget(0, 3, new InlineHTML("&lsaquo;"));
          grid.setWidget(0, 4, now);
          grid.setWidget(0, 5, new InlineHTML("&rsaquo;"));
          grid.setWidget(0, 6, newShiftDateButton(+60, "1m"));
          grid.setWidget(0, 7, newShiftDateButton(+600, "10m"));
          grid.setWidget(0, 8, newShiftDateButton(+3600, "1h"));
          grid.setWidget(1, 0, newShiftDateButton(-86400 * 30, "30d"));
          grid.setWidget(1, 1, newShiftDateButton(-86400 * 7, "1w"));
          grid.setWidget(1, 2, newShiftDateButton(-86400, "1d"));
          grid.setWidget(1, 3, new InlineHTML("&laquo;"));
          grid.setWidget(1, 4, new InlineHTML("&nbsp;"));
          grid.setWidget(1, 5, new InlineHTML("&raquo;"));
          grid.setWidget(1, 6, newShiftDateButton(+86400, "1d"));
          grid.setWidget(1, 7, newShiftDateButton(+86400 * 7, "1w"));
          grid.setWidget(1, 8, newShiftDateButton(+86400 * 30, "30d"));
          final CellFormatter formatter = grid.getCellFormatter();
          formatter.setWidth(0, 4, "100%");
          formatter.setWidth(1, 4, "100%");
          vbox.add(grid);
        }

        {
          hours_minutes = new Grid(4, 8);
          setupAmUI();
          hours_minutes.setWidget(0, 0, new InlineLabel("HH"));
          final PushButton set_am = new PushButton("AM");
          set_am.addClickHandler(new ClickHandler() {
            public void onClick(final ClickEvent event) {
              setupAmUI();
            }
          });
          hours_minutes.setWidget(0, 7, set_am);

          final PushButton set_pm = new PushButton("PM");
          set_pm.addClickHandler(new ClickHandler() {
            public void onClick(final ClickEvent event) {
              setupPmUI();
            }
          });
          hours_minutes.setWidget(1, 7, set_pm);

          hours_minutes.setWidget(2, 0, new InlineLabel("MM"));
          hours_minutes.setWidget(2, 1, newSetMinutesButton(0, "00"));
          hours_minutes.setWidget(2, 2, newSetMinutesButton(10, "10"));
          hours_minutes.setWidget(2, 3, newSetMinutesButton(20, "20"));
          hours_minutes.setWidget(2, 4, newSetMinutesButton(30, "30"));
          hours_minutes.setWidget(2, 5, newSetMinutesButton(40, "40"));
          hours_minutes.setWidget(2, 6, newSetMinutesButton(50, "50"));
          vbox.add(hours_minutes);
        }

        {
          final HorizontalPanel hbox = new HorizontalPanel();
          hbox.add(new InlineLabel("UNIX timestamp:"));
          final ValidatedTextBox ts = new ValidatedTextBox();
          ts.setValidationRegexp("^(|[1-9][0-9]{0,9})$");
          ts.setVisibleLength(10);
          ts.setMaxLength(10);
          final EventsHandler handler = new EventsHandler() {
            protected <H extends EventHandler> void onEvent(final DomEvent<H> event) {
              final Date d = new Date(Integer.parseInt(ts.getValue()) * 1000L);
              box.setValue(d, true);
            }
          };
          ts.addBlurHandler(handler);
          ts.addKeyPressHandler(handler);
          hbox.add(ts);
          vbox.add(hbox);
        }
        vbox.setHeight("100%");
        panel.add(vbox);
        panel.setCellHeight(vbox, "100%");
      }
    }

  }

}
TOP

Related Classes of tsd.client.DateTimeBox$DateTimePicker

TOP
Copyright © 2018 www.massapi.com. All rights reserved.
All source code are property of their respective owners. Java is a trademark of Sun Microsystems, Inc and owned by ORACLE Inc. Contact coftware#gmail.com.