779 строки
30 KiB
XML
779 строки
30 KiB
XML
<?xml version="1.0"?>
|
|
<!--
|
|
- ***** 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 Sun Microsystems code.
|
|
-
|
|
- The Initial Developer of the Original Code is Sun Microsystems.
|
|
- Portions created by the Initial Developer are Copyright (C) 2008
|
|
- the Initial Developer. All Rights Reserved.
|
|
-
|
|
- Contributor(s):
|
|
- Berend Cornelius <berend.cornelius@sun.com>
|
|
-
|
|
- 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 *****
|
|
-->
|
|
|
|
<bindings id="calendar-multiday-view-bindings"
|
|
xmlns="http://www.mozilla.org/xbl"
|
|
xmlns:html="http://www.w3.org/1999/xhtml"
|
|
xmlns:xul="http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul"
|
|
xmlns:xbl="http://www.mozilla.org/xbl">
|
|
|
|
<binding id="calendar-base-view">
|
|
<resources>
|
|
<stylesheet src="chrome://calendar/skin/calendar-alarms.css"/>
|
|
</resources>
|
|
<implementation>
|
|
<field name="mWeekStartOffset">0</field>
|
|
<field name="mRangeStartDate">null</field>;
|
|
<field name="mRangeEndDate">null</field>;
|
|
<field name="mWorkdaysOnly">false</field>
|
|
<field name="mRefreshQueue">[]</field>
|
|
<field name="mRefreshPending">null</field>
|
|
<field name="mCalendar">null</field>
|
|
<field name="mController">null</field>
|
|
<field name="mStartDate">null</field>
|
|
<field name="mEndDate">null</field>
|
|
<field name="mTasksInView">false</field>
|
|
<field name="mShowCompleted">false</field>
|
|
<field name="mDisplayDaysOff">true</field>
|
|
<field name="mDaysOffArray">[0,6]</field>
|
|
<field name="mTimezone">null</field>
|
|
<field name="mFlashingEvents">new Object()</field>
|
|
<field name="mSelectedItems">[]</field>
|
|
<field name="mBatchCount">0</field>
|
|
<field name="mLongWeekdayTotalPixels">-1</field>
|
|
<field name="mResizeHandler">null</field>
|
|
<field name="mPrefObserver"><![CDATA[
|
|
({ calView: this,
|
|
observe: function calViewPrefChange(subj, topic, pref) {
|
|
this.calView.handlePreference(subj, topic, pref);
|
|
return;
|
|
}
|
|
})
|
|
]]></field>
|
|
|
|
<field name="mOperationListener"><![CDATA[
|
|
({
|
|
calView: this,
|
|
|
|
onOperationComplete:
|
|
function onOperationComplete(aCalendar, aStatus, aOperationType,
|
|
aId, aDetail) {
|
|
// Fire event
|
|
this.calView.fireEvent('viewloaded', aOperationType);
|
|
|
|
// signal that the current operation finished.
|
|
this.calView.mRefreshPending = null;
|
|
|
|
// immediately start the next job on the queue.
|
|
this.calView.popRefreshQueue();
|
|
},
|
|
|
|
onGetResult:
|
|
function onGetResult(aCalendar, aStatus, aItemType, aDetail,
|
|
aCount, aItems) {
|
|
if (!Components.isSuccessCode(aStatus)) {
|
|
return;
|
|
}
|
|
let items = aItems.filter(function(x) !isToDo(x) ||
|
|
(x.entryDate && x.dueDate));
|
|
|
|
for each (let item in items) {
|
|
this.calView.doAddItem(item);
|
|
}
|
|
}
|
|
})
|
|
]]></field>
|
|
|
|
<field name="mObserver"><![CDATA[
|
|
// the calIObserver, calICompositeObserver, and calIAlarmServiceObserver
|
|
({
|
|
QueryInterface: function QueryInterface(aIID) {
|
|
return cal.doQueryInterface(this, null, aIID,
|
|
[Components.interfaces.calIObserver,
|
|
Components.interfaces.calIAlarmServiceObserver,
|
|
Components.interfaces.calICompositeObserver,
|
|
Components.interfaces.nsISupports]);
|
|
},
|
|
|
|
calView: this,
|
|
|
|
onStartBatch: function onStartBatch() {
|
|
this.calView.mBatchCount++;
|
|
},
|
|
onEndBatch: function onEndBatch() {
|
|
this.calView.mBatchCount--;
|
|
if (this.calView.mBatchCount == 0) {
|
|
this.calView.refresh();
|
|
}
|
|
},
|
|
|
|
onLoad: function onLoad() {
|
|
this.calView.refresh();
|
|
},
|
|
|
|
onAddItem: function onAddItem(aItem) {
|
|
if (this.calView.mBatchCount) {
|
|
return;
|
|
}
|
|
|
|
if (isToDo(aItem)) {
|
|
if (!aItem.entryDate || !aItem.dueDate) {
|
|
return;
|
|
}
|
|
if(!this.calView.mTasksInView){
|
|
return;
|
|
}
|
|
if (aItem.isCompleted && !this.calView.mShowCompleted) {
|
|
return;
|
|
}
|
|
}
|
|
|
|
let occs = aItem.getOccurrencesBetween(this.calView.startDate,
|
|
this.calView.queryEndDate,
|
|
{});
|
|
for each (let occ in occs) {
|
|
this.calView.doAddItem(occ);
|
|
}
|
|
return;
|
|
},
|
|
|
|
onModifyItem: function onModifyItem(aNewItem, aOldItem) {
|
|
if (this.calView.mBatchCount) {
|
|
return;
|
|
}
|
|
|
|
if (isToDo(aNewItem) && isToDo(aOldItem) &&
|
|
!this.calView.mTasksInView) {
|
|
return;
|
|
}
|
|
let occs;
|
|
|
|
if (!isToDo(aOldItem) ||
|
|
(aOldItem.entryDate && aOldItem.dueDate)) {
|
|
occs = aOldItem.getOccurrencesBetween(this.calView.startDate,
|
|
this.calView.queryEndDate,
|
|
{});
|
|
for each (let occ in occs) {
|
|
this.calView.doDeleteItem(occ);
|
|
}
|
|
}
|
|
if (isToDo(aNewItem)) {
|
|
if (!aNewItem.entryDate || !aNewItem.dueDate || !this.calView.mTasksInView) {
|
|
return;
|
|
}
|
|
if (aNewItem.isCompleted && !this.calView.mShowCompleted) {
|
|
return;
|
|
}
|
|
}
|
|
|
|
occs = aNewItem.getOccurrencesBetween(this.calView.startDate,
|
|
this.calView.queryEndDate,
|
|
{});
|
|
for each (let occ in occs) {
|
|
this.calView.doAddItem(occ);
|
|
}
|
|
},
|
|
|
|
onDeleteItem: function onDeleteItem(aItem) {
|
|
if (this.calView.mBatchCount) {
|
|
return;
|
|
}
|
|
|
|
if (isToDo(aItem)) {
|
|
if (!this.calView.mTasksInView) {
|
|
return;
|
|
}
|
|
if (!aItem.entryDate || !aItem.dueDate) {
|
|
return;
|
|
}
|
|
if (aItem.isCompleted && !this.calView.mShowCompleted) {
|
|
return;
|
|
}
|
|
}
|
|
|
|
let occs = aItem.getOccurrencesBetween(this.calView.startDate,
|
|
this.calView.queryEndDate,
|
|
{});
|
|
for each (let occ in occs) {
|
|
this.calView.doDeleteItem(occ);
|
|
}
|
|
},
|
|
|
|
onError: function onError(aCalendar, aErrNo, aMessage) { },
|
|
|
|
onPropertyChanged: function(aCalendar, aName, aValue, aOldValue) {
|
|
switch (aName) {
|
|
case "suppressAlarms":
|
|
if (!getPrefSafe("calendar.alarms.indicator.show", true) ||
|
|
aCalendar.getProperty("capabilities.alarms.popup.supported") === false ) {
|
|
break;
|
|
}
|
|
// else fall through
|
|
case "readOnly":
|
|
case "disabled":
|
|
// XXXvv we can be smarter about how we handle this stuff
|
|
this.calView.refresh();
|
|
break;
|
|
}
|
|
},
|
|
|
|
onPropertyDeleting: function(aCalendar, aName) {
|
|
// Values are not important here yet.
|
|
this.onPropertyChanged(aCalendar, aName, null, null);
|
|
},
|
|
|
|
//
|
|
// calIAlarmServiceObserver stuff
|
|
//
|
|
onAlarm: function onAlarm(aAlarmItem) {
|
|
this.calView.flashAlarm(aAlarmItem, false);
|
|
},
|
|
|
|
onRemoveAlarmsByItem: function onRemoveAlarmsByItem(aItem) {
|
|
// Stop the flashing for the item.
|
|
this.calView.flashAlarm(aItem, true);
|
|
},
|
|
|
|
onRemoveAlarmsByCalendar: function onRemoveAlarmsByCalendar(aCalendar) {
|
|
// Stop the flashing for all items of this calendar
|
|
for each (let item in this.calView.mFlashingEvents) {
|
|
if (item.calendar.id == aCalendar.id) {
|
|
this.calView.flashAlarm(item, true);
|
|
}
|
|
}
|
|
},
|
|
|
|
//
|
|
// calICompositeObserver stuff
|
|
// XXXvv we can be smarter about how we handle this stuff
|
|
//
|
|
onCalendarAdded: function onCalendarAdded(aCalendar) {
|
|
if (!aCalendar.getProperty("disabled")) {
|
|
this.calView.refresh();
|
|
}
|
|
},
|
|
|
|
onCalendarRemoved: function onCalendarRemoved(aCalendar) {
|
|
if (!aCalendar.getProperty("disabled")) {
|
|
this.calView.refresh();
|
|
}
|
|
},
|
|
|
|
onDefaultCalendarChanged:
|
|
function onDefaultCalendarChanged(aNewDefaultCalendar) {
|
|
// don't care, for now
|
|
}
|
|
})
|
|
]]></field>
|
|
|
|
<constructor><![CDATA[
|
|
const kWorkdaysCommand = "calendar_toggle_workdays_only_command";
|
|
const kTasksInViewCommand = "calendar_toggle_tasks_in_view_command";
|
|
const kShowCompleted = "calendar_toggle_show_completed_in_view_command";
|
|
const kOrientation = "calendar_toggle_orientation_command";
|
|
|
|
this.workdaysOnly = (document.getElementById(kWorkdaysCommand)
|
|
.getAttribute("checked") == "true");
|
|
this.tasksInView = (document.getElementById(kTasksInViewCommand)
|
|
.getAttribute("checked") == "true");
|
|
this.rotated = (document.getElementById(kOrientation)
|
|
.getAttribute("checked") == "true");
|
|
this.showCompleted = (document.getElementById(kShowCompleted)
|
|
.getAttribute("checked") == "true");
|
|
|
|
this.mTimezone = calendarDefaultTimezone();
|
|
let alarmService = Components.classes['@mozilla.org/calendar/alarm-service;1']
|
|
.getService(Components.interfaces.calIAlarmService);
|
|
alarmService.addObserver(this.mObserver);
|
|
let self = this;
|
|
this.setAttribute("type", this.type);
|
|
this.mResizeHandler = function resizeHandler() {
|
|
self.onResize(self); };
|
|
this.viewBroadcaster.addEventListener(this.getAttribute("type") + "viewresized", this.mResizeHandler, true);
|
|
// add a preference observer to monitor changes
|
|
let pb2 = Components.classes["@mozilla.org/preferences-service;1"].
|
|
getService(Components.interfaces.nsIPrefBranch2);
|
|
|
|
pb2.addObserver("calendar.", this.mPrefObserver, false);
|
|
this.weekStartOffset = getPrefSafe("calendar.week.start", 0);
|
|
this.updateDaysOffPrefs();
|
|
]]></constructor>
|
|
|
|
<destructor><![CDATA[
|
|
if (this.mCalendar) {
|
|
this.mCalendar.removeObserver(this.mObserver);
|
|
}
|
|
let alarmService = Components.classes['@mozilla.org/calendar/alarm-service;1']
|
|
.getService(Components.interfaces.calIAlarmService);
|
|
alarmService.removeObserver(this.mObserver);
|
|
this.viewBroadcaster.removeEventListener(this.getAttribute("type") + "viewresized", this.mResizeHandler, true);
|
|
let pb2 = Components.classes["@mozilla.org/preferences-service;1"].
|
|
getService(Components.interfaces.nsIPrefBranch2);
|
|
pb2.removeObserver("calendar.", this.mPrefObserver);
|
|
]]></destructor>
|
|
|
|
<property name="type" readonly="true">
|
|
<getter><![CDATA[
|
|
let typelist = this.id.split("-");
|
|
return typelist[0];
|
|
]]></getter>
|
|
</property>
|
|
|
|
<property name="viewBroadcaster" readonly="true"
|
|
onget="return document.getElementById('calendarviewBroadcaster')"/>
|
|
|
|
<property name="labeldaybox" readonly="true"
|
|
onget="return document.getAnonymousElementByAttribute(this, 'anonid', 'labeldaybox')"/>
|
|
|
|
<property name="rotated"
|
|
onget="return (this.orient == 'horizontal')"
|
|
onset="return (this.orient = (val ? 'horizontal' : 'vertical'))"/>
|
|
<property name="displayDaysOff"
|
|
onget="return this.mDisplayDaysOff;"
|
|
onset="return (this.mDisplayDaysOff = val);"/>
|
|
<property name="controller"
|
|
onget="return this.mController;"
|
|
onset="return (this.mController = val);"/>
|
|
<property name="daysOffArray"
|
|
onget="return this.mDaysOffArray;"
|
|
onset="return (this.mDaysOffArray = val);"/>
|
|
<property name="tasksInView"
|
|
onget="return this.mTasksInView;"
|
|
onset="return (this.mTasksInView = val);"/>
|
|
<property name="showCompleted"
|
|
onget="return this.mShowCompleted;"
|
|
onset="return (this.mShowCompleted = val);"/>
|
|
<property name="timezone"
|
|
onget="return this.mTimezone;"
|
|
onset="return (this.mTimezone = val);"/>
|
|
<property name="workdaysOnly"
|
|
onget="return this.mWorkdaysOnly;"
|
|
onset="return (this.mWorkdaysOnly = val);"/>
|
|
<property name="selectionObserver" readonly="true"
|
|
onget="return this.mSelectionObserver;"/>
|
|
<property name="startDay" readonly="true"
|
|
onget="return this.startDate;"/>
|
|
<property name="endDay" readonly="true"
|
|
onget="return this.endDate;"/>
|
|
<property name="rangeStartDate"
|
|
onget="return this.mRangeStartDate;"
|
|
onset="return (this.mRangeStartDate = val);"/>
|
|
<property name="rangeEndDate"
|
|
onget="return this.mRangeEndDate;"
|
|
onset="return (this.mRangeEndDate = val);"/>
|
|
<property name="observerID" readonly="true"
|
|
onget="return 'base-view-observer';"/>
|
|
|
|
<property name="weekStartOffset">
|
|
<getter><![CDATA[
|
|
return this.mWeekStartOffset;
|
|
]]></getter>
|
|
<setter><![CDATA[
|
|
this.mWeekStartOffset = val;
|
|
return val;
|
|
]]></setter>
|
|
</property>
|
|
|
|
<property name="displayCalendar">
|
|
<getter><![CDATA[
|
|
return this.mCalendar;
|
|
]]></getter>
|
|
<setter><![CDATA[
|
|
if (this.mCalendar)
|
|
this.mCalendar.removeObserver(this.mObserver);
|
|
this.mCalendar = val;
|
|
this.mCalendar.addObserver(this.mObserver);
|
|
this.refresh();
|
|
return val;
|
|
]]></setter>
|
|
</property>
|
|
|
|
<property name="initialized">
|
|
<getter><![CDATA[
|
|
let retval;
|
|
|
|
// Some views throw when accessing an uninitialized startDay
|
|
try {
|
|
retval = this.displayCalendar && this.startDay
|
|
&& this.endDay;
|
|
} catch(ex) {
|
|
return false;
|
|
}
|
|
return retval;
|
|
]]></getter>
|
|
</property>
|
|
|
|
<method name="goToDay">
|
|
<parameter name="aDate"/>
|
|
<body><![CDATA[
|
|
this.showDate(aDate);
|
|
]]></body>
|
|
</method>
|
|
|
|
<method name="getRangeDescription">
|
|
<body><![CDATA[
|
|
return getDateFormatter().formatInterval(this.rangeStartDate, this.rangeEndDate);
|
|
]]></body>
|
|
</method>
|
|
|
|
<method name="popRefreshQueue">
|
|
<body><![CDATA[
|
|
let pendingRefresh = this.mRefreshPending;
|
|
if (pendingRefresh) {
|
|
if (calInstanceOf(pendingRefresh, Components.interfaces.calIOperation)) {
|
|
this.mRefreshPending = null;
|
|
pendingRefresh.cancel(null);
|
|
} else {
|
|
if(this.mRefreshQueue.length > 0) {
|
|
this.relayout();
|
|
}
|
|
return;
|
|
}
|
|
}
|
|
|
|
let refreshJob = this.mRefreshQueue.pop();
|
|
if (!refreshJob) {
|
|
return;
|
|
}
|
|
|
|
if (!this.startDate || !this.endDate) {
|
|
return;
|
|
}
|
|
|
|
// recreate our columns
|
|
this.relayout();
|
|
|
|
if (!this.mCalendar) {
|
|
return;
|
|
}
|
|
|
|
// start our items query; for a disjoint date range
|
|
// we get all the items, and just filter out the ones we don't
|
|
// care about in addItem
|
|
|
|
let filter = this.mCalendar.ITEM_FILTER_CLASS_OCCURRENCES;
|
|
if (this.mShowCompleted) {
|
|
filter |= this.mCalendar.ITEM_FILTER_COMPLETED_ALL;
|
|
} else {
|
|
filter |= this.mCalendar.ITEM_FILTER_COMPLETED_NO;
|
|
}
|
|
|
|
if(this.mTasksInView) {
|
|
filter |= this.mCalendar.ITEM_FILTER_TYPE_ALL;
|
|
} else {
|
|
filter |= this.mCalendar.ITEM_FILTER_TYPE_EVENT;
|
|
}
|
|
|
|
this.mRefreshPending = true;
|
|
pendingRefresh = this.mCalendar.getItems(filter,
|
|
0,
|
|
this.startDate,
|
|
this.queryEndDate,
|
|
this.mOperationListener);
|
|
if (pendingRefresh && pendingRefresh.isPending) { // support for calIOperation
|
|
this.mRefreshPending = pendingRefresh;
|
|
}
|
|
]]></body>
|
|
</method>
|
|
|
|
<!-- This function guarantees that the
|
|
labels are clipped in the instance that the overflow occurrs,
|
|
avoiding horizontal scrollbars from showing up for a short period. -->
|
|
<method name="adjustWeekdayLength">
|
|
<parameter name="forceShortName"/>
|
|
<body><![CDATA[
|
|
let useShortNames = false;
|
|
let labeldayboxkids = this.labeldaybox.childNodes;
|
|
if (!labeldayboxkids || !labeldayboxkids[0]) {
|
|
useShortNames = true;
|
|
} else if (forceShortName && forceShortName === true) {
|
|
useShortNames = true;
|
|
} else {
|
|
let clientWidth = document.getAnonymousElementByAttribute(this, "anonid", "mainbox").clientWidth;
|
|
let timespacer = document.getAnonymousElementByAttribute(this, "anonid", "headertimespacer");
|
|
if (timespacer) {
|
|
clientWidth -= timespacer.clientWidth;
|
|
}
|
|
if (this.getLongWeekdayTotalPixels() > 0.95 * clientWidth) {
|
|
useShortNames = true;
|
|
}
|
|
}
|
|
for (let i = 0; i < labeldayboxkids.length; i++) {
|
|
labeldayboxkids[i].shortWeekNames = useShortNames;
|
|
}
|
|
]]></body>
|
|
</method>
|
|
|
|
<method name="today">
|
|
<body><![CDATA[
|
|
let date = createDateTime();
|
|
date.jsDate = new Date();
|
|
date = date.getInTimezone(this.mTimezone);
|
|
date.isDate = true;
|
|
return date;
|
|
]]></body>
|
|
</method>
|
|
|
|
<method name="isVisible">
|
|
<body><![CDATA[
|
|
return (this.nodeName == currentView().nodeName);
|
|
]]></body>
|
|
</method>
|
|
|
|
<method name="refresh">
|
|
<body><![CDATA[
|
|
if (this.mBatchCount == 0 && this.isVisible()) {
|
|
var refreshJob = {};
|
|
this.mRefreshQueue.push(refreshJob);
|
|
this.popRefreshQueue();
|
|
}
|
|
]]></body>
|
|
</method>
|
|
|
|
<!-- the end date that should be used for getItems and similar queries -->
|
|
<property name="queryEndDate" readonly="true">
|
|
<getter><![CDATA[
|
|
let end = this.endDate;
|
|
if (!end) {
|
|
return null;
|
|
}
|
|
end = end.clone();
|
|
end.day += 1;
|
|
end.isDate = true;
|
|
return end;
|
|
]]></getter>
|
|
</property>
|
|
|
|
<method name="fireEvent">
|
|
<parameter name="aEventName"/>
|
|
<parameter name="aEventDetail"/>
|
|
<body><![CDATA[
|
|
let event = document.createEvent('Events');
|
|
event.initEvent(aEventName, true, false);
|
|
event.detail = aEventDetail;
|
|
this.dispatchEvent(event);
|
|
]]></body>
|
|
</method>
|
|
|
|
<method name="removeDropShadows">
|
|
<body><![CDATA[
|
|
let dropbox = document.getAnonymousElementByAttribute(this, "dropbox", "true");
|
|
if (dropbox && dropbox !== undefined) {
|
|
dropbox.setAttribute("dropbox", "false");
|
|
}
|
|
]]></body>
|
|
</method>
|
|
|
|
<method name="getLongWeekdayTotalPixels">
|
|
<body><![CDATA[
|
|
if (this.mLongWeekdayTotalPixels <= 0) {
|
|
let maxDayWidth = 0;
|
|
for each(label in this.labeldaybox.childNodes) {
|
|
if (label.localName == "calendar-day-label") {
|
|
label.shortWeekNames = false;
|
|
let curPixelLength = label.getLongWeekdayPixels();
|
|
maxDayWidth = Math.max(maxDayWidth, curPixelLength);
|
|
}
|
|
}
|
|
this.mLongWeekdayTotalPixels = (maxDayWidth * this.labeldaybox.childNodes.length) + 10;
|
|
}
|
|
return this.mLongWeekdayTotalPixels;
|
|
]]></body>
|
|
</method>
|
|
|
|
<!-- A preference handler which is called by the preference observer.
|
|
Can be overwritten in derived bindings. -->
|
|
<method name="handleCommonPreference">
|
|
<parameter name="aSubject"/>
|
|
<parameter name="aTopic"/>
|
|
<parameter name="aPreference"/>
|
|
<body><![CDATA[
|
|
// refresh view if categories seem to have changed
|
|
if (aPreference.indexOf("calendar.category.color") == 0) {
|
|
this.refreshView();
|
|
return;
|
|
}
|
|
switch (aPreference) {
|
|
case "calendar.week.d0sundaysoff":
|
|
case "calendar.week.d1mondaysoff":
|
|
case "calendar.week.d2tuesdaysoff":
|
|
case "calendar.week.d3wednesdaysoff":
|
|
case "calendar.week.d4thursdaysoff":
|
|
case "calendar.week.d5fridaysoff":
|
|
case "calendar.week.d6saturdaysoff":
|
|
this.updateDaysOffPrefs();
|
|
break;
|
|
case "calendar.timezone.local":
|
|
this.timezone = calendarDefaultTimezone();
|
|
this.refreshView();
|
|
break;
|
|
case "calendar.alarms.indicator.show":
|
|
//Break here to ensure the view is refreshed
|
|
break;
|
|
case "calendar.week.start":
|
|
this.weekStartOffset = aSubject.getIntPref(aPreference);
|
|
break;
|
|
case "calendar.date.format":
|
|
this.refreshView();
|
|
break;
|
|
default:
|
|
return;
|
|
}
|
|
this.refreshView();
|
|
]]></body>
|
|
</method>
|
|
|
|
<method name="updateDaysOffPrefs">
|
|
<body><![CDATA[
|
|
const weekPrefix = "calendar.week.";
|
|
const prefNames = ["d0sundaysoff", "d1mondaysoff", "d2tuesdaysoff",
|
|
"d3wednesdaysoff", "d4thursdaysoff",
|
|
"d5fridaysoff", "d6saturdaysoff"];
|
|
const defaults = ["true", "false", "false", "false",
|
|
"false", "false", "true"];
|
|
let daysOff = new Array();
|
|
for (let i in prefNames) {
|
|
if (getPrefSafe(weekPrefix+prefNames[i])) {
|
|
daysOff.push(Number(i));
|
|
}
|
|
}
|
|
this.daysOffArray = daysOff;
|
|
]]></body>
|
|
</method>
|
|
|
|
<method name="refreshView">
|
|
<body><![CDATA[
|
|
if (!this.startDay || !this.endDay) {
|
|
// don't refresh if we're not initialized
|
|
return;
|
|
}
|
|
// Just refresh, the goToDay function will notice
|
|
this.goToDay(this.selectedDay);
|
|
]]></body>
|
|
</method>
|
|
|
|
</implementation>
|
|
<handlers>
|
|
<handler event="move">
|
|
<![CDATA[
|
|
this.moveView(event.detail);
|
|
]]>
|
|
</handler>
|
|
<handler event="keypress"><![CDATA[
|
|
const kKE = Components.interfaces.nsIDOMKeyEvent;
|
|
switch (event.keyCode) {
|
|
case kKE.DOM_VK_PAGE_UP:
|
|
this.moveView(-1);
|
|
break;
|
|
case kKE.DOM_VK_PAGE_DOWN:
|
|
this.moveView(1);
|
|
break;
|
|
}
|
|
]]></handler>
|
|
<handler event="DOMMouseScroll"><![CDATA[
|
|
if (event.shiftKey) {
|
|
this.moveView(event.detail < 0 ? -1 : 1);
|
|
}
|
|
|
|
// Prevent default scroll handling
|
|
event.preventDefault();
|
|
]]></handler>
|
|
</handlers>
|
|
</binding>
|
|
|
|
<binding id="calendar-day-label" extends="xul:box">
|
|
<content flex="1" pack="center">
|
|
<xul:label anonid="longWeekdayName" class="calendar-day-label-name" xbl:inherits="selected"/>
|
|
<xul:label anonid="shortWeekdayName" class="calendar-day-label-name" hidden="true" xbl:inherits="selected"/>
|
|
</content>
|
|
<implementation>
|
|
<field name="mWeekday">-1</field>
|
|
<field name="longWeekdayPixels">0</field>
|
|
<field name="mDate">null</field>
|
|
<property name="longName" readonly="true"
|
|
onget="return document.getAnonymousElementByAttribute(this, 'anonid', 'longWeekdayName');"/>
|
|
<property name="shortName" readonly="true"
|
|
onget="return document.getAnonymousElementByAttribute(this, 'anonid', 'shortWeekdayName');"/>
|
|
<property name="weekDay">
|
|
<getter>return this.mWeekday;</getter>
|
|
<setter><![CDATA[
|
|
this.mWeekday = val % 7;
|
|
this.longName.value = getDateFormatter().dayName(val);
|
|
this.shortName.value = getDateFormatter().shortDayName(val);
|
|
return this.mWeekday;
|
|
]]></setter>
|
|
</property>
|
|
|
|
<property name="date">
|
|
<getter><![CDATA[
|
|
return this.mDate;
|
|
]]></getter>
|
|
<setter><![CDATA[
|
|
this.mDate = val;
|
|
this.shortName.setAttribute("value", getDateFormatter().shortDayName(val.weekday) + " " +
|
|
getDateFormatter().formatDateWithoutYear(val));
|
|
this.longName.setAttribute("value", getDateFormatter().dayName(val.weekday) + " " +
|
|
getDateFormatter().formatDateWithoutYear(val));
|
|
return val;
|
|
]]></setter>
|
|
</property>
|
|
|
|
<property name="shortWeekNames">
|
|
<getter><![CDATA[
|
|
]]></getter>
|
|
<setter><![CDATA[
|
|
// cache before change, in case we are switching to short
|
|
this.getLongWeekdayPixels();
|
|
setBooleanAttribute(this.longName, "hidden", val);
|
|
setBooleanAttribute(this.shortName, "hidden", !val);
|
|
return val;
|
|
]]></setter>
|
|
</property>
|
|
|
|
<method name="getLongWeekdayPixels">
|
|
<body><![CDATA[
|
|
// Only do this if the long weekdays are visible and we haven't already cached.
|
|
let longNameWidth = this.longName.boxObject.width;
|
|
if (longNameWidth > 0) {
|
|
this.longWeekdayPixels = longNameWidth +
|
|
getSummarizedStyleValues(this.longName, ["margin-left", "margin-right"]);
|
|
this.longWeekdayPixels += getSummarizedStyleValues(this, ["border-left-width",
|
|
"padding-left", "padding-right"]);
|
|
return this.longWeekdayPixels;
|
|
} else {
|
|
// in this case the weekdaypixels have not yet been layouted;
|
|
// by definition 0 is returned
|
|
return 0;
|
|
}
|
|
]]></body>
|
|
</method>
|
|
</implementation>
|
|
</binding>
|
|
</bindings>
|