Fix bug 689130 - Enabling timezone support in the event dialog should be more visible. r=decathlon,a=philipp BETA_BASE_20120313
authorPhilipp Kewisch <mozilla@kewis.ch>
Tue, 13 Mar 2012 10:56:26 +0100
changeset 10641 9420ad8a9c7f57fd709618faaabdfb5fcc4787ed
parent 10640 8deff9ff0b8928c8f5ef0f7a13b5727d6c944fb3
child 10642 72b7adf2c1460aa5a03aa01a4c844dab1992e29f
push idunknown
push userunknown
push dateunknown
reviewersdecathlon, philipp
bugs689130
Fix bug 689130 - Enabling timezone support in the event dialog should be more visible. r=decathlon,a=philipp
calendar/base/content/dialogs/calendar-event-dialog.js
calendar/base/content/dialogs/calendar-event-dialog.xul
calendar/base/src/calUtils.js
calendar/lightning/content/lightning.js
calendar/sunbird/app/profile/sunbird.js
--- a/calendar/base/content/dialogs/calendar-event-dialog.js
+++ b/calendar/base/content/dialogs/calendar-event-dialog.js
@@ -2535,45 +2535,108 @@ function onCommandCustomize() {
                           "dialog");                   // name of this mode
     }
 }
 
 /**
  * Prompts the user to change the start timezone.
  */
 function editStartTimezone() {
-    editTimezone(
-        "timezone-starttime",
-        gStartTime.getInTimezone(gStartTimezone),
-        function(datetime) {
-            var equalTimezones = false;
-            if (gStartTimezone && gEndTimezone) {
-                if (gStartTimezone == gEndTimezone) {
-                    equalTimezones = true;
-                }
-            }
-            gStartTimezone = datetime.timezone;
-            if (equalTimezones) {
-              gEndTimezone = datetime.timezone;
-            }
-            updateDateTime();
-        });
+    editTimezone("timezone-starttime",
+                 gStartTime.getInTimezone(gStartTimezone),
+                 editStartTimezone.complete);
 }
+editStartTimezone.complete = function(datetime) {
+    var equalTimezones = false;
+    if (gStartTimezone && gEndTimezone) {
+        if (gStartTimezone == gEndTimezone) {
+            equalTimezones = true;
+        }
+    }
+    gStartTimezone = datetime.timezone;
+    if (equalTimezones) {
+      gEndTimezone = datetime.timezone;
+    }
+    updateDateTime();
+};
 
 /**
  * Prompts the user to change the end timezone.
  */
 function editEndTimezone() {
-    editTimezone(
-        "timezone-endtime",
-        gEndTime.getInTimezone(gEndTimezone),
-        function(datetime) {
-            gEndTimezone = datetime.timezone;
-            updateDateTime();
-        });
+    editTimezone("timezone-endtime",
+                 gEndTime.getInTimezone(gEndTimezone),
+                 editEndTimezone.complete);
+}
+editEndTimezone.complete = function(datetime) {
+    gEndTimezone = datetime.timezone;
+    updateDateTime();
+};
+
+/**
+ * Called to choose a recent timezone from the timezone popup.
+ *
+ * @param event     The event with a target that holds the timezone id value.
+ */
+function chooseRecentTimezone(event) {
+    let tzid = event.target.value;
+    let timezonePopup = document.getElementById("timezone-popup");
+    let tzProvider = getCurrentCalendar().getProperty("timezones.provider") ||
+                     cal.getTimezoneService();
+
+    if (tzid != "custom") {
+        let zone = tzProvider.getTimezone(tzid);
+        let datetime = timezonePopup.dateTime.getInTimezone(zone);
+        timezonePopup.editTimezone.complete(datetime);
+    }
+}
+
+/**
+ * Opens the timezone popup on the node the event target points at.
+ *
+ * @param event     The event causing the popup to open
+ * @param dateTime  The datetime for which the timezone should be modified
+ * @param editFunc  The function to be called when the custom menuitem is clicked.
+ */
+function showTimezonePopup(event, dateTime, editFunc) {
+    // Don't do anything for right/middle-clicks. Also, don't show the popup if
+    // the opening node is disabled.
+    if (event.button != 0 || event.target.disabled) {
+        return;
+    }
+
+    let timezonePopup = document.getElementById("timezone-popup");
+    let timezoneDefaultItem = document.getElementById("timezone-popup-defaulttz");
+    let timezoneSeparator = document.getElementById("timezone-popup-menuseparator");
+    let defaultTimezone = cal.calendarDefaultTimezone();
+    let recentTimezones = cal.getRecentTimezones(true);
+
+    // Set up the right editTimezone function, so the custom item can use it.
+    timezonePopup.editTimezone = editFunc;
+    timezonePopup.dateTime = dateTime;
+
+    // Set up the default timezone item
+    timezoneDefaultItem.value = defaultTimezone.tzid;
+    timezoneDefaultItem.label = defaultTimezone.displayName;
+
+    // Clear out any old recent timezones
+    while (timezoneDefaultItem.nextSibling != timezoneSeparator) {
+        timezonePopup.removeChild(timezoneDefaultItem.nextSibling);
+    }
+
+    // Fill in the new recent timezones
+    for each (let tz in recentTimezones) {
+        let menuItem = createXULElement("menuitem");
+        menuItem.setAttribute("value", tz.tzid);
+        menuItem.setAttribute("label", tz.displayName);
+        timezonePopup.insertBefore(menuItem, timezoneDefaultItem.nextSibling);
+    }
+
+    // Show the popup
+    timezonePopup.openPopup(event.target, "after_start", 0, 0, true);
 }
 
 /**
  * Common function of edit(Start|End)Timezone() to prompt the user for a
  * timezone change.
  *
  * @param aElementId        The XUL element id of the timezone label.
  * @param aDateTime         The Date/Time of the time to change zone on.
@@ -2584,17 +2647,20 @@ function editTimezone(aElementId,aDateTi
         .hasAttribute("disabled")) {
         return;
     }
 
     // prepare the arguments that will be passed to the dialog
     var args = new Object();
     args.time = aDateTime;
     args.calendar = getCurrentCalendar();
-    args.onOk = aCallback;
+    args.onOk = function(datetime) {
+        cal.saveRecentTimezone(datetime.timezone.tzid);
+        return aCallback(datetime);
+    };
 
     // open the dialog modally
     openDialog(
         "chrome://calendar/content/calendar-event-dialog-timezone.xul",
         "_blank",
         "chrome,titlebar,modal,resizable",
         args);
 }
--- a/calendar/base/content/dialogs/calendar-event-dialog.xul
+++ b/calendar/base/content/dialogs/calendar-event-dialog.xul
@@ -456,18 +456,18 @@
                             accesskey="&event.menu.options.attendees.accesskey;"
                             command="cmd_attendees"
                             disable-on-readonly="true"/>
                   <menuitem id="options-attachments-menuitem"
                             label="&event.menu.options.attachments.label;"
                             accesskey="&event.menu.options.attachments.accesskey;"
                             command="cmd_attach_url"/>
                   <menuitem id="options-timezone-menuitem"
-                            label="&event.menu.options.timezone.label;"
-                            accesskey="&event.menu.options.timezone.accesskey;"
+                            label="&event.menu.options.timezone2.label;"
+                            accesskey="&event.menu.options.timezone2.accesskey;"
                             checked="false"
                             type="checkbox"
                             persist="checked"
                             command="cmd_timezone"
                             disable-on-readonly="true"/>
                   <menuseparator id="options-menuseparator1"/>
                   <menu id="options-priority-menu"
                         label="&event.menu.options.priority2.label;"
@@ -780,17 +780,17 @@
                     <hbox align="center">
                         <label id="timezone-starttime"
                                class="text-link"
                                collapsed="true"
                                crop="end"
                                disable-on-readonly="true"
                                flex="1"
                                hyperlink="true"
-                               onclick="editStartTimezone()"/>
+                               onclick="showTimezonePopup(event, gStartTime.getInTimezone(gStartTimezone), editStartTimezone)"/>
                     </hbox>
                 </hbox>
             </row>
 
             <!-- EndDate -->
             <row id="event-grid-enddate-row">
                 <hbox id="event-grid-enddate-label-box"
                       align="center">
@@ -825,17 +825,17 @@
                         <hbox align="center">
                             <label id="timezone-endtime"
                                    class="text-link"
                                    collapsed="true"
                                    crop="end"
                                    disable-on-readonly="true"
                                    flex="1"
                                    hyperlink="true"
-                                   onclick="editEndTimezone()"/>
+                                   onclick="showTimezonePopup(event, gEndTime.getInTimezone(gEndTimezone), editEndTimezone)"/>
                         </hbox>
                     </hbox>
                 </vbox>
             </row>
 
             <row id="event-grid-todo-status-row"
                  class="todo-only"
                  align="center">
@@ -1180,10 +1180,18 @@
                       accesskey="&event.attachments.popup.removeAll.accesskey;"
                       command="cmd_deleteAllAttachments"/>
             <menuseparator/>
             <menuitem id="attachment-popup-attachPage"
                       label="&event.attachments.popup.attachPage.label;"
                       accesskey="&event.attachments.popup.attachPage.accesskey;"
                       command="cmd_attach_url"/>
       </menupopup>
+      <menupopup id="timezone-popup" position="after_start" oncommand="chooseRecentTimezone(event)">
+        <menuitem id="timezone-popup-defaulttz"/>
+        <menuseparator id="timezone-popup-menuseparator"/>
+        <menuitem id="timezone-custom-menuitem"
+                  label="&event.repeat.custom.label;"
+                  value="custom"
+                  oncommand="this.parentNode.editTimezone()"/>
+      </menupopup>
     </popupset>
 </dialog>
--- a/calendar/base/src/calUtils.js
+++ b/calendar/base/src/calUtils.js
@@ -217,16 +217,71 @@ function floating() {
  *
  * @return user's default timezone.
  */
 function calendarDefaultTimezone() {
     return getTimezoneService().defaultTimezone;
 }
 
 /**
+ * Makes sure the given timezone id is part of the list of recent timezones.
+ *
+ * @param aTzid     The timezone id to add
+ */
+function saveRecentTimezone(aTzid) {
+    let recentTimezones = getRecentTimezones();
+    const MAX_RECENT_TIMEZONES = 5; // We don't need a pref for *everything*.
+
+    if (aTzid != calendarDefaultTimezone().tzid &&
+        recentTimezones.indexOf(aTzid) < 0) {
+        // Add the timezone if its not already the default timezone
+        recentTimezones.unshift(aTzid);
+        recentTimezones.splice(MAX_RECENT_TIMEZONES);
+        cal.setPref("calendar.timezone.recent", JSON.stringify(recentTimezones));
+    }
+}
+
+/**
+ * Gets the list of recent timezones. Optionally retuns the list as
+ * calITimezones.
+ *
+ * @param aConvertZones     (optional) If true, return calITimezones instead
+ * @return                  An array of timezone ids or calITimezones.
+ */
+function getRecentTimezones(aConvertZones) {
+    let recentTimezones = JSON.parse(cal.getPrefSafe("calendar.timezone.recent", "[]") || "[]");
+    if (!Array.isArray(recentTimezones)) {
+        recentTimezones = [];
+    }
+
+    let tzService = cal.getTimezoneService();
+    if (aConvertZones) {
+        let oldZonesLength = recentTimezones.length;
+        for (let i = 0; i < recentTimezones.length; i++) {
+            let tz = tzService.getTimezone(recentTimezones[i]);
+            if (!tz) {
+                // Looks like the timezone doesn't longer exist, remove it
+                recentTimezones.splice(i, 1);
+                i--;
+            } else {
+                // Replace id with found timezone
+                recentTimezones[i] = tz;
+            }
+        }
+
+        if (oldZonesLength != recentTimezones.length) {
+            // Looks like the one or other timezone dropped out. Go ahead and
+            // modify the pref.
+            cal.setPref("calendar.timezone.recent", JSON.stringify(recentTimezones));
+        }
+    }
+    return recentTimezones;
+}
+
+/**
  * Format the given string to work inside a CSS rule selector
  * (and as part of a non-unicode preference key).
  *
  * Replaces each space ' ' char with '_'.
  * Replaces each char other than ascii digits and letters, with '-uxHHH-'
  * where HHH is unicode in hexadecimal (variable length, terminated by the '-').
  *
  * Ensures: result only contains ascii digits, letters,'-', and '_'.
--- a/calendar/lightning/content/lightning.js
+++ b/calendar/lightning/content/lightning.js
@@ -126,16 +126,19 @@ pref("calendar.view.visiblehours", 9);
 pref("calendar.view.timeIndicatorInterval", 15);
 
 // If true, mouse scrolling via shift+wheel will be enabled
 pref("calendar.view.mousescroll", true);
 
 // Do not set this!  If it's not there, then we guess the system timezone
 //pref("calendar.timezone.local", "");
 
+// Recent timezone list
+pref("calendar.timezone.recent", "[]");
+
 // categories settings
 // XXX One day we might want to move this to a locale specific file
 //     and include a list of locale specific default categories
 pref("calendar.categories.names", "");
 
 // Make sure mouse wheel shift and no key actions to scroll lines.
 pref("mousewheel.withnokey.action", 0);
 pref("mousewheel.withshiftkey.action", 0);
--- a/calendar/sunbird/app/profile/sunbird.js
+++ b/calendar/sunbird/app/profile/sunbird.js
@@ -59,16 +59,19 @@ pref("calendar.alarms.todoalarmunit", "m
 pref("calendar.alarms.defaultsnoozelength", 5);
 pref("calendar.alarms.indicator.show", true);
 pref("calendar.alarms.indicator.totaltime", 3600);
 pref("calendar.date.format", 0);
 pref("calendar.event.defaultlength", 60);
 // Do NOT set this.  If it is unset, we guess the timezone from the system
 //pref("calendar.timezone.local", "America/New_York);
 
+// Recent timezone list
+pref("calendar.timezone.recent", "[]");
+
 // start and end work hour for day and week views
 pref("calendar.view.daystarthour", 8);
 pref("calendar.view.dayendhour", 17);
 
 // number of visible hours for day and week views
 pref("calendar.view.visiblehours", 9);
 
 // If true, mouse scrolling via shift+wheel will be enabled