diff --git a/calendar/import-export/Makefile.in b/calendar/import-export/Makefile.in
index cd36a3e3701..bf0b13530a3 100644
--- a/calendar/import-export/Makefile.in
+++ b/calendar/import-export/Makefile.in
@@ -52,6 +52,7 @@ EXTRA_SCRIPTS = \
calListFormatter.js \
calMonthGridPrinter.js \
calOutlookCSVImportExport.js \
+ calWeekPrinter.js \
$(NULL)
# Use NSINSTALL to make the directory, as there's no mtime to preserve.
diff --git a/calendar/import-export/calImportExportModule.js b/calendar/import-export/calImportExportModule.js
index d2fdfb76fa7..ca1bd5be871 100644
--- a/calendar/import-export/calImportExportModule.js
+++ b/calendar/import-export/calImportExportModule.js
@@ -75,6 +75,13 @@ const componentData =
category: "cal-print-formatters",
categoryEntry: "cal-month-printer",
service: false},
+ {cid: Components.ID("{2d6ec97b-9109-4b92-89c5-d4b4806619ce}"),
+ contractid: "@mozilla.org/calendar/printformatter;1?type=weekplan",
+ script: "calWeekPrinter.js",
+ constructor: "calWeekPrinter",
+ category: "cal-print-formatters",
+ categoryEntry: "cal-week-planner-printer",
+ service: false},
{cid: Components.ID("{64a5d17a-0497-48c5-b54f-72b15c9e9a14}"),
contractid: "@mozilla.org/calendar/import;1?type=csv",
diff --git a/calendar/import-export/calWeekPrinter.js b/calendar/import-export/calWeekPrinter.js
new file mode 100644
index 00000000000..c648491d3df
--- /dev/null
+++ b/calendar/import-export/calWeekPrinter.js
@@ -0,0 +1,293 @@
+/* -*- Mode: javascript; tab-width: 20; indent-tabs-mode: nil; c-basic-offset: 4 -*-
+ * ***** BEGIN LICENSE BLOCK *****
+ * Version: MPL 1.1/GPL 2.0/LGPL 2.1
+ *
+ * The contents of this file are subject to the Mozilla Public License Version
+ * 1.1 (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.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the
+ * License.
+ *
+ * The Original Code is Mozilla Calendar code.
+ *
+ * The Initial Developer of the Original Code is
+ * Joey Minta
+ * Portions created by the Initial Developer are Copyright (C) 2006
+ * the Initial Developer. All Rights Reserved.
+ *
+ * Contributor(s):
+ * Matthew Willis
+ *
+ * Alternatively, the contents of this file may be used under the terms of
+ * either the GNU General Public License Version 2 or later (the "GPL"), or
+ * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
+ * in which case the provisions of the GPL or the LGPL are applicable instead
+ * of those above. If you wish to allow use of your version of this file only
+ * under the terms of either the GPL or the LGPL, and not to allow others to
+ * use your version of this file under the terms of the MPL, indicate your
+ * decision by deleting the provisions above and replace them with the notice
+ * and other provisions required by the GPL or the LGPL. If you do not delete
+ * the provisions above, a recipient may use your version of this file under
+ * the terms of any one of the MPL, the GPL or the LGPL.
+ *
+ * ***** END LICENSE BLOCK ***** */
+
+/**
+ * Prints a two column view of a week of events, much like a paper day-planner
+ */
+
+function calWeekPrinter() {
+ this.wrappedJSObject = this;
+}
+
+calWeekPrinter.prototype.QueryInterface =
+function QueryInterface(aIID) {
+ if (!aIID.equals(Components.interfaces.nsISupports) &&
+ !aIID.equals(Components.interfaces.calIPrintFormatter)) {
+ throw Components.results.NS_ERROR_NO_INTERFACE;
+ }
+
+ return this;
+};
+
+calWeekPrinter.prototype.getName =
+function weekPrint_getName() {
+ return calGetString("calendar", "weekPrinterName");
+};
+calWeekPrinter.prototype.__defineGetter__("name", calWeekPrinter.prototype.getName);
+
+calWeekPrinter.prototype.formatToHtml =
+function weekPrint_format(aStream, aStart, aEnd, aCount, aItems, aTitle) {
+ // Create the e4x framework of the HTML document
+ var html = ;
+ html.appendChild(
+
+ {aTitle}
+
+
+ );
+ html.head.style = ".main-table { font-size: 26px; font-weight:bold; }\n";
+ html.head.style += ".day-name { border: 1px solid #000; background-color: #e0e0e0; font-size: 12px; font-weight: bold; }\n";
+
+ var body = ;
+
+ // helper: returns the passed item's startDate, entryDate or dueDate, in
+ // that order. If the item doesn't have one of those dates, this
+ // doesn't return.
+ function hasUsableDate(item) {
+ return item.startDate || item.entryDate || item.dueDate;
+ }
+
+ // Clean out the item list so it only contains items we will want to
+ // include in the printout.
+ var filteredItems = aItems.filter(hasUsableDate);
+
+ var calIEvent = Components.interfaces.calIEvent;
+ var calITodo = Components.interfaces.calITodo
+ function compareItems(a, b) {
+ // Sort tasks before events
+ if (a instanceof calIEvent && b instanceof calITodo) {
+ return 1;
+ }
+ if (a instanceof calITodo && b instanceof calIEvent) {
+ return -1;
+ }
+ if (a instanceof calIEvent) {
+ var startCompare = a.startDate.compare(b.startDate);
+ if (startCompare != 0) {
+ return startCompare;
+ }
+ return a.endDate.compare(b.endDate);
+ }
+ var dateA = a.entryDate || a.dueDate;
+ var dateB = b.entryDate || b.dueDate;
+ return dateA.compare(dateB);
+ }
+ var sortedList = filteredItems.sort(compareItems);
+
+ var sbs = Components.classes["@mozilla.org/intl/stringbundle;1"]
+ .getService(Components.interfaces.nsIStringBundleService);
+ var props = sbs.createBundle("chrome://calendar/locale/calendar.properties");
+
+ var weekFormatter = Components.classes["@mozilla.org/calendar/weektitle-service;1"]
+ .getService(Components.interfaces.calIWeekTitleService);
+
+ // A place to cache the string for "All Day" events later if we need it.
+ var mAllDayString = null;
+
+ // Start at the beginning of the week that aStart is in, and loop until
+ // we're at aEnd. In the loop we build the HTML table for each day, and
+ // get the day's items using getDayTd().
+ var date = aStart.startOfWeek;
+ while(date.compare(aEnd) == -1) {
+ var weekno = weekFormatter.getWeekTitle(date);
+ var weekTitle = props.formatStringFromName('WeekTitle', [weekno], 1);
+ body.appendChild(
+
);
+ var mainWeek =
+
+ // Create the for each day, and put it into an array.
+ date.day -= 1; // Compensate for the increment in the loop.
+ date.normalize();
+ var dayTds = new Array();
+ for (var i = 0; i < 7 ; i++) {
+ date.day += 1;
+ date.normalize();
+ dayTds[i] = this.getDayTd(date, sortedList);
+ }
+
+ var monRow = |
;
+ monRow.appendChild(dayTds[1]); // Monday
+ monRow.appendChild(dayTds[4]); // Thursday
+ mainWeek.appendChild(monRow);
+
+ var tueRow =
;
+ tueRow.appendChild(dayTds[2]); // Tuesday
+ tueRow.appendChild(dayTds[5]); // Friday
+ mainWeek.appendChild(tueRow);
+
+ var wedRow =
;
+ wedRow.appendChild(dayTds[3]); // Wednesday
+
+ // Saturday and Sunday are half-size
+ var satSunTd = | ;
+ var weekendTable = ;
+
+ var satRow =
;
+ satRow.appendChild(dayTds[6]); // Saturday
+ weekendTable.appendChild(satRow);
+
+ var sunRow =
;
+ sunRow.appendChild(dayTds[0]); // Sunday
+ weekendTable.appendChild(sunRow);
+
+ satSunTd.appendChild(weekendTable);
+ wedRow.appendChild(satSunTd);
+ mainWeek.appendChild(wedRow);
+
+ body.appendChild(mainWeek);
+ // Make sure each month gets put on its own page
+ body.appendChild(
);
+
+ // Move to the next Sunday
+ date.day += 7;
+ date.normalize();
+ }
+ html.appendChild(body);
+
+ // Stream out the resulting HTML
+ var convStream = Components.classes["@mozilla.org/intl/converter-output-stream;1"]
+ .getService(Components.interfaces.nsIConverterOutputStream);
+ convStream.init(aStream, 'UTF-8', 0, 0x0000);
+ convStream.writeString(html.toXMLString());
+};
+
+calWeekPrinter.prototype.getDayTd =
+/**
+ * Given a calIDateTime and an array of items, this function creates an HTML
+ * table containing the items, using the appropriate formatting and colours.
+ */
+function weekPrint_getDayTable(aDate, aItems) {
+ // mainTd is the element from the parent HTML table that will hold
+ // the child HTML tables containing the date string and this day's items.
+ var mainTd = | |
+ var dateFormatter = Components.classes["@mozilla.org/calendar/datetime-formatter;1"]
+ .getService(Components.interfaces.calIDateTimeFormatter);
+ var dateString = dateFormatter.formatDateLong(aDate);
+
+ // Add the formatted date string (in its own child HTML table)
+ mainTd.appendChild(
+ );
+
+ // Add the formatted items (in their child HTML table)
+ var innerTable = ;
+ for each (var item in aItems) {
+ var sDate = item.startDate || item.entryDate || item.dueDate;
+ var eDate = item.endDate || item.dueDate || item.entryDate;
+
+ // End dates are exclusive. Adjust the eDate accordingly.
+ if (sDate && sDate.isDate && eDate) {
+ eDate = eDate.clone();
+ eDate.day -= 1;
+ eDate.normalize();
+ }
+
+ // If the item has no end date, or if the item's end date is aDate or
+ // is before aDate, skip to the next item.
+ if (!eDate || (eDate.compare(aDate) < 0)) {
+ continue;
+ }
+
+ // No start date or a start date that's after the date we want is bad.
+ if (!sDate || (sDate.compare(aDate) > 0)) {
+ break;
+ }
+
+ function getStringForDate(aDate) {
+ if (!aDate.isDate) {
+ return dateFormatter.formatTime(aDate);
+ }
+
+ // We cache the string for "All Day" 'cause we're good like that.
+ if (this.mAllDayString == null) {
+ var sbs = Components.classes["@mozilla.org/intl/stringbundle;1"]
+ .getService(Components.interfaces.nsIStringBundleService);
+ var props = sbs.createBundle("chrome://calendar/locale/dateFormat.properties");
+ this.mAllDayString = props.GetStringFromName("AllDay");
+ }
+ return this.mAllDayString;
+ }
+
+ var time;
+ if (sDate && eDate) {
+ if (!sDate.isDate) {
+ time = getStringForDate(sDate) + '-' + getStringForDate(eDate);
+ } else {
+ time = getStringForDate(sDate);
+ }
+ } else if (sDate) {
+ time = getStringForDate(sDate);
+ } else if (eDate) {
+ time = getStringForDate(eDate);
+ }
+
+ // Get calendar and category colours and apply them to the item's
+ // table cell.
+ var calMgr = Components.classes["@mozilla.org/calendar/manager;1"]
+ .getService(Components.interfaces.calICalendarManager);
+ var calColor = calMgr.getCalendarPref(item.calendar, 'color');
+ if (!calColor) {
+ calColor = "#A8C2E1";
+ }
+ var pb2 = Components.classes["@mozilla.org/preferences-service;1"]
+ .getService(Components.interfaces.nsIPrefBranch2);
+ var catColor;
+ try {
+ catColor = pb2.getCharPref("calendar.category.color."+item.getProperty("CATEGORIES").toLowerCase());
+ } catch(ex) {}
+
+ var style = 'font-size: 11px; background-color: ' + calColor + ';';
+ if (catColor) {
+ style += ' border: solid ' + catColor + ' 2px;';
+ }
+ var item =
+ {time} {item.title} |
+
;
+ innerTable.appendChild(item);
+ }
+ innerTable.appendChild(
);
+ mainTd.appendChild(innerTable);
+ return mainTd;
+};
diff --git a/calendar/locales/en-US/chrome/calendar/calendar.properties b/calendar/locales/en-US/chrome/calendar/calendar.properties
index 54f4f4c6067..29d5218e14d 100644
--- a/calendar/locales/en-US/chrome/calendar/calendar.properties
+++ b/calendar/locales/en-US/chrome/calendar/calendar.properties
@@ -226,6 +226,7 @@ likelyTimezone=America/New_York
# Print Layout
formatListName = List
+weekPrinterName = Weekly Planner
monthPrinterName = Monthly Grid
rotate=Rotate