Adding gwt QR Code generator, and appspot configuration files.
[zxing.git] / zxing.appspot.com / generator / src / com / google / zxing / web / generator / client / CalendarEventGenerator.java
diff --git a/zxing.appspot.com/generator/src/com/google/zxing/web/generator/client/CalendarEventGenerator.java b/zxing.appspot.com/generator/src/com/google/zxing/web/generator/client/CalendarEventGenerator.java
new file mode 100644 (file)
index 0000000..ddd3b3b
--- /dev/null
@@ -0,0 +1,273 @@
+/*
+ * Copyright (C) 2008 ZXing authors
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.google.zxing.web.generator.client;
+
+import com.google.gwt.i18n.client.DateTimeFormat;
+import com.google.gwt.user.client.DOM;
+import com.google.gwt.user.client.Element;
+import com.google.gwt.user.client.ui.ChangeListener;
+import com.google.gwt.user.client.ui.CheckBox;
+import com.google.gwt.user.client.ui.ClickListener;
+import com.google.gwt.user.client.ui.Grid;
+import com.google.gwt.user.client.ui.ListBox;
+import com.google.gwt.user.client.ui.TextBox;
+import com.google.gwt.user.client.ui.Widget;
+import com.google.gwt.widgetideas.client.event.ChangeEvent;
+import com.google.gwt.widgetideas.client.event.ChangeHandler;
+import com.google.gwt.widgetideas.datepicker.client.DateBox;
+import com.google.gwt.widgetideas.datepicker.client.TimePicker;
+import com.google.zxing.web.generator.client.TimeZoneList.TimeZoneInfo;
+
+import java.util.Date;
+
+/**
+ * A Generator for calendar events. Output is in VCal format.
+ * 
+ * @author Yohann Coppel
+ */
+public class CalendarEventGenerator implements GeneratorSource {
+  public final static String[] FULL_DAY_ONLY_IDS = { "fullDayOnlyInfo1",
+      "fullDayOnlyInfo2", "fullDayOnlyInfo3", "fullDayOnlyInfo4" };
+  private final static long ONE_HOUR = 60 * 60 * 1000;
+
+  Grid table = null;
+  TextBox eventName = new TextBox();
+  CheckBox fullDay = new CheckBox();
+  DateBox datePicker1 = new DateBox();
+  DateBox datePicker2 = new DateBox();
+  TimePicker timePicker1 = new TimePicker(new Date(), DateTimeFormat
+      .getFormat("a"), DateTimeFormat.getFormat("hh"), DateTimeFormat
+      .getFormat("mm"), null);
+  TimePicker timePicker2 = new TimePicker(new Date(), DateTimeFormat
+      .getFormat("a"), DateTimeFormat.getFormat("hh"), DateTimeFormat
+      .getFormat("mm"), null);
+  CheckBox summerTime = new CheckBox();
+  ListBox timeZones = new ListBox();
+  Date timePicker1PreviousDate = null;
+
+  public CalendarEventGenerator(final ChangeListener listener) {
+    eventName.addStyleName(StylesDefs.INPUT_FIELD_REQUIRED);
+    eventName.addChangeListener(listener);
+    datePicker1.setAnimationEnabled(true);
+    datePicker2.setAnimationEnabled(true);
+    timePicker2
+        .setDateTime(addMilliseconds(timePicker1.getDateTime(), ONE_HOUR));
+    timePicker1PreviousDate = timePicker1.getDateTime();
+
+    buildTimeZoneList();
+    timeZones.setSelectedIndex(25);
+    timePicker1.addChangeHandler(new ChangeHandler<Date>() {
+      public void onChange(ChangeEvent<Date> event) {
+        Date time = timePicker1PreviousDate;
+        Date time1 = timePicker1.getDateTime();
+        Date time2 = timePicker2.getDateTime();
+        if (time2.after(time)) {
+          // keep the same time difference if the interval is valid.
+          long diff = timeDifference(time, time2);
+          timePicker2.setDateTime(addMilliseconds(time1, diff));
+        } else {
+          // otherwise erase the end date and set it to startdate + one hour.
+          timePicker2.setDateTime(addMilliseconds(time, ONE_HOUR));
+        }
+        // no need to call onChange for timePicker1, since it will be called
+        // for timePicker2 when changes are made.
+        // listener.onChange(timePicker1);
+        timePicker1PreviousDate = time1;
+      }
+    });
+    timePicker2.addChangeHandler(new ChangeHandler<Date>() {
+      public void onChange(ChangeEvent<Date> event) {
+        listener.onChange(timePicker2);
+      }
+    });
+  }
+
+  private void buildTimeZoneList() {
+    for (TimeZoneInfo info : TimeZoneList.TIMEZONES) {
+      timeZones.addItem(info.GMTRelative + " " + info.abreviation, ""
+          + info.gmtDiff);
+    }
+  }
+
+  public String getName() {
+    return "Calendar event";
+  }
+
+  public Grid getWidget() {
+    if (table != null) {
+      return table;
+    }
+    datePicker1.getDatePicker().setSelectedDate(new Date());
+    datePicker2.getDatePicker().setSelectedDate(new Date());
+    table = new Grid(8, 2);
+
+    table.setText(0, 0, "All day event");
+    table.setWidget(0, 1, fullDay);
+
+    table.setText(1, 0, "Event title");
+    table.setWidget(1, 1, eventName);
+
+    table.setText(2, 0, "Start date");
+    table.setWidget(2, 1, datePicker1);
+
+    table.setText(3, 0, "Time");
+    table.setWidget(3, 1, timePicker1);
+
+    table.setText(4, 0, "End date");
+    table.setWidget(4, 1, datePicker2);
+
+    table.setText(5, 0, "Time");
+    table.setWidget(5, 1, timePicker2);
+
+    table.setText(6, 0, "Time zone");
+    table.setWidget(6, 1, timeZones);
+
+    table.setText(7, 0, "Daylight savings");
+    table.setWidget(7, 1, summerTime);
+
+    table.getRowFormatter().getElement(3).setId(FULL_DAY_ONLY_IDS[0]);
+    table.getRowFormatter().getElement(5).setId(FULL_DAY_ONLY_IDS[1]);
+    table.getRowFormatter().getElement(6).setId(FULL_DAY_ONLY_IDS[2]);
+    table.getRowFormatter().getElement(7).setId(FULL_DAY_ONLY_IDS[3]);
+
+    fullDay.addClickListener(new ClickListener() {
+      public void onClick(Widget sender) {
+        CheckBox cb = (CheckBox) sender;
+        setFullDay(cb.isChecked());
+      }
+    });
+
+    return table;
+  }
+
+  private void setFullDay(boolean fullDay) {
+    for (String s : FULL_DAY_ONLY_IDS) {
+      Element element = DOM.getElementById(s);
+      String style = "";
+      if (fullDay) {
+        style = "none";
+      }
+      DOM.setStyleAttribute(element, "display", style);
+    }
+  }
+
+  public String getText() throws GeneratorException {
+    String eventName = getEventNameField();
+    String dates = getDateTimeFields();
+
+    String output = "";
+    output += "BEGIN:VEVENT\n";
+    output += eventName;
+    output += dates;
+    output += "END:VEVENT\n";
+    return output;
+  }
+
+  private String getEventNameField() throws GeneratorException {
+    String inputName = eventName.getText();
+    if (inputName.length() < 1) {
+      throw new GeneratorException("Event name must be at least 1 character.");
+    }
+    if (inputName.contains("\n")) {
+      throw new GeneratorException(
+          "Event name should not contain \\n characters.");
+    }
+    return "SUMMARY:" + inputName + "\n";
+  }
+
+  private String getDateTimeFields() throws GeneratorException {
+    if (fullDay.isChecked()) {
+      return getFullDayDateFields();
+    }
+    return getDateTimeValues();
+  }
+
+  private String getFullDayDateFields() throws GeneratorException {
+    Date date1 = datePicker1.getDatePicker().getSelectedDate();
+    Date date2 = datePicker2.getDatePicker().getSelectedDate();
+    if (null == date1 || null == date2) {
+      throw new GeneratorException("Start and end dates must be set.");
+    }
+    if (date1.after(date2)) {
+      throw new GeneratorException("Ending date is after starting date.");
+    }
+    DateTimeFormat isoFormatter = DateTimeFormat.getFormat("yyyyMMdd");
+    String output = "";
+    output += "DTSTART:" + isoFormatter.format(date1) + "\n";
+    output += "DTEND:" + isoFormatter.format(date2) + "\n";
+    return output;
+  }
+
+  private String getDateTimeValues() throws GeneratorException {
+    Date date1 = datePicker1.getDatePicker().getSelectedDate();
+    Date date2 = datePicker2.getDatePicker().getSelectedDate();
+    Date time1 = timePicker1.getDateTime();
+    Date time2 = timePicker2.getDateTime();
+    if (null == date1 || null == date2 || null == time1 || null == time2) {
+      throw new GeneratorException("Start and end dates/times must be set.");
+    }
+    String timezoneDelta = timeZones.getValue(timeZones.getSelectedIndex());
+    long diffTimeZone = Long.parseLong(timezoneDelta);
+    if (summerTime.isChecked()) {
+      diffTimeZone += ONE_HOUR;
+    }
+    Date dateTime1 = addMilliseconds(mergeDateAndTime(date1, time1),
+        -diffTimeZone);
+    Date dateTime2 = addMilliseconds(mergeDateAndTime(date2, time2),
+        -diffTimeZone);
+    if (dateTime1.after(dateTime2)) {
+      throw new GeneratorException("Ending date is after starting date.");
+    }
+    DateTimeFormat isoFormatter = DateTimeFormat
+        .getFormat("yyyyMMdd'T'kkmmss'Z'");
+    String output = "";
+    output += "DTSTART:" + isoFormatter.format(dateTime1) + "\n";
+    output += "DTEND:" + isoFormatter.format(dateTime2) + "\n";
+    return output;
+  }
+
+  private Date mergeDateAndTime(Date date, Date time) {
+    // Is that the only ugly way to do with GWT ? given that we don't
+    // have java.util.Calendar for instance
+    DateTimeFormat extractDate = DateTimeFormat.getFormat("yyyyMMdd");
+    DateTimeFormat extractTime = DateTimeFormat.getFormat("kkmm");
+    DateTimeFormat merger = DateTimeFormat.getFormat("yyyyMMddkkmmss");
+    String d = extractDate.format(date);
+    String t = extractTime.format(time) + "00";
+    return merger.parse(d + t);
+  }
+
+  public void validate(Widget widget) throws GeneratorException {
+    if (widget == eventName)
+      getEventNameField();
+    if (widget == datePicker1 || widget == timePicker1 || widget == datePicker2
+        || widget == timePicker2)
+      getDateTimeFields();
+  }
+
+  private static Date addMilliseconds(Date time1, long milliseconds) {
+    return new Date(time1.getTime() + milliseconds);
+  }
+
+  private static long timeDifference(Date time1, Date time2) {
+    return time2.getTime() - time1.getTime();
+  }
+
+  public void setFocus() {
+    eventName.setFocus(true);
+  }
+}