1 <?xml version="1.0"?>
2 <!--
3 - ***** BEGIN LICENSE BLOCK *****
4 - Version: MPL 1.1/GPL 2.0/LGPL 2.1
5 -
6 - The contents of this file are subject to the Mozilla Public License Version
7 - 1.1 (the "License"); you may not use this file except in compliance with
8 - the License. You may obtain a copy of the License at
9 - http://www.mozilla.org/MPL/
10 -
11 - Software distributed under the License is distributed on an "AS IS" basis,
12 - WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
13 - for the specific language governing rights and limitations under the
14 - License.
15 -
16 - The Original Code is Calendar view code.
17 -
18 - The Initial Developer of the Original Code is
19 - Joey Minta <jminta@gmail.com>
20 - Portions created by the Initial Developer are Copyright (C) 2005
21 - the Initial Developer. All Rights Reserved.
22 -
23 - Contributor(s):
24 - Philipp Kewisch <mozilla@kewis.ch>
25 -
26 - Alternatively, the contents of this file may be used under the terms of
27 - either the GNU General Public License Version 2 or later (the "GPL"), or
28 - the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
29 - in which case the provisions of the GPL or the LGPL are applicable instead
30 - of those above. If you wish to allow use of your version of this file only
31 - under the terms of either the GPL or the LGPL, and not to allow others to
32 - use your version of this file under the terms of the MPL, indicate your
33 - decision by deleting the provisions above and replace them with the notice
34 - and other provisions required by the GPL or the LGPL. If you do not delete
35 - the provisions above, a recipient may use your version of this file under
36 - the terms of any one of the MPL, the GPL or the LGPL.
37 -
38 - ***** END LICENSE BLOCK *****
39 -->
40
41 <!-- Note that this file depends on helper functions in calUtils.js-->
42
43 <bindings id="calendar-specific-view-bindings"
44 xmlns="http://www.mozilla.org/xbl"
45 xmlns:html="http://www.w3.org/1999/xhtml"
46 xmlns:xul="http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul"
47 xmlns:xbl="http://www.mozilla.org/xbl">
48
49 <binding id="calendar-decorated-multiweek-view" extends="chrome://calendar/content/calendar-decorated-base.xml#calendar-decorated-base-view">
50 <content>
51 <xul:vbox anonid="main-box" flex="1">
52 <xul:calendar-navigation-buttons anonid="nav-control"/>
53 <xul:box style="overflow: auto;" flex="1">
54 <xul:calendar-month-view anonid="view-element" flex="1" xbl:inherits="context,item-context"/>
55 </xul:box>
56 </xul:vbox>
57 </content>
58
59 <implementation implements="calIDecoratedView">
60 <constructor><![CDATA[
61 // Set the preference for the default start of the week
62 this.viewElem.weekStartOffset = getPrefSafe("calendar.week.start", 0);
63
64 this.mWeeksInView = getPrefSafe("calendar.weeks.inview", 4);
65
66 this.updateDaysOffPrefs();
67
68 // add a preference observer to monitor changes
69 var pb2 = Components.classes["@mozilla.org/preferences-service;1"].
70 getService(Components.interfaces.nsIPrefBranch2);
71 pb2.addObserver("calendar.", this.mPrefObserver, false);
72 return;
73 ]]></constructor>
74
75 <destructor><![CDATA[
76 var pb2 = Components.classes["@mozilla.org/preferences-service;1"].
77 getService(Components.interfaces.nsIPrefBranch2);
78 pb2.removeObserver("calendar.", this.mPrefObserver);
79 return;
80 ]]></destructor>
81
82 <field name="mPrefObserver"><![CDATA[
83 ({ calView: this,
84 observe: function calDecWeekViewPrefChange(subj, topic, pref) {
85
86 subj.QueryInterface(Components.interfaces.nsIPrefBranch2);
87
88 // refresh view if categories seem to have changed
89 if (pref.indexOf("calendar.category.color") == 0) {
90 if (!this.calView.startDay || !this.calView.endDay) {
91 // Don't refresh if we're not initialized
92 return;
93 }
94 // Refresh the view to recreate the event boxes
95 this.calView.goToDay(this.calView.selectedDay);
96 }
97
98 switch (pref) {
99
100 case "calendar.previousweeks.inview":
101 case "calendar.week.d0sundaysoff":
102 case "calendar.week.d1mondaysoff":
103 case "calendar.week.d2tuesdaysoff":
104 case "calendar.week.d3wednesdaysoff":
105 case "calendar.week.d4thursdaysoff":
106 case "calendar.week.d5fridaysoff":
107 case "calendar.week.d6saturdaysoff":
108 this.calView.updateDaysOffPrefs();
109 if (this.calView.selectedDay) {
110 this.calView.goToDay(this.calView.selectedDay);
111 }
112 break;
113
114 case "calendar.week.start":
115 this.calView.viewElem.weekStartOffset = subj.getIntPref(pref);
116
117 if (!this.calView.startDay || !this.calView.endDay) {
118 // Don't refresh if we're not initialized
119 return;
120 }
121
122 // Refresh the view so the settings take effect
123 this.calView.goToDay(this.calView.selectedDay);
124 break;
125
126 case "calendar.weeks.inview":
127 this.calView.weeksInView = subj.getIntPref(pref);
128 break;
129
130 case "calendar.previousweeks.inview":
131 // Just refresh, the goToDay function will notice
132 this.calView.goToDay(this.calView.selectedDay);
133 break;
134 case "calendar.timezone.local":
135 this.calView.viewElem.timezone = calendarDefaultTimezone();
136 if (!this.calView.startDay || !this.calView.endDay) {
137 // Don't refresh if we're not initialized
138 return;
139 }
140 this.calView.goToDay(this.calView.selectedDay);
141 break;
142
143 case "calendar.alarms.indicator.show":
144 if (this.calView.startDay && this.calView.endDay) {
145 // Refresh the view, the view core takes care of
146 // resetting the alarm image.
147 this.calView.goToDay(this.calView.selectedDay);
148 }
149 break;
150
151 default:
152 break;
153 }
154 return;
155 }
156 })
157 ]]></field>
158
159 <field name="mWeeksInView">4</field>
160
161 <property name="weeksInView">
162 <getter><![CDATA[
163 return this.mWeeksInView;
164 ]]></getter>
165 <setter><![CDATA[
166 this.mWeeksInView = val;
167 if (this.selectedDay) {
168 this.goToDay(this.selectedDay);
169 }
170 return val;
171 ]]></setter>
172 </property>
173
174 <property name="observerID">
175 <getter><![CDATA[
176 return "multiweek-view-observer";
177 ]]></getter>
178 </property>
179
180 <!--Public methods-->
181 <method name="goToDay">
182 <parameter name="aDate"/>
183 <body><![CDATA[
184 var viewElement = this.viewElem;
185 viewElement.showFullMonth = false;
186 viewElement.tasksInView = this.mTasksInView;
187 viewElement.showCompleted = this.mShowCompleted;
188 viewElement.displayDaysOff = !this.mWorkdaysOnly;
189
190 aDate = aDate.getInTimezone(viewElement.timezone);
191
192 // Get the first date that should be shown. This is the
193 // start of the week of the day that we're centering around
194 // adjusted for the day the week starts on and the number
195 // of previous weeks we're supposed to display.
196 var d1 = aDate.startOfWeek.clone();
197 d1.day -= 7*getPrefSafe("calendar.previousweeks.inview", 4);
198 if (aDate.weekday < viewElement.weekStartOffset) {
199 d1.day -= 7;
200 }
201
202 // The variable firstWeekDate is a definitely showed date
203 // in the first week of the view (needed for setNavLabels).
204 var firstWeekDate = aDate.clone();
205 firstWeekDate.day -= 7*getPrefSafe("calendar.previousweeks.inview");
206
207 // The last day we're supposed to show
208 var d2 = d1.endOfWeek.clone();
209 d2.day += 7*(this.mWeeksInView-1);
210
211 viewElement.setDateRange(d1,d2);
212
213 viewElement.selectedDay = aDate;
214 this.setNavLabels(firstWeekDate);
215 ]]></body>
216 </method>
217 <method name="moveView">
218 <parameter name="aNumber"/>
219 <body><![CDATA[
220 var d1 = this.startDay.clone();
221 var savedSelectedDay = this.selectedDay.clone();
222 // aNumber only corresponds to the number of weeks to move
223 // make sure to compensate for previous weeks in view too
224 d1.day += 7 * (aNumber + getPrefSafe("calendar.previousweeks.inview", 4));
225 this.goToDay(d1);
226 savedSelectedDay.day += 7*aNumber;
227 this.viewElem.selectedDay = savedSelectedDay;
228 ]]></body>
229 </method>
230 <method name="setNavLabels">
231 <parameter name="aDate"/>
232 <body><![CDATA[
233 var nameArray = new Array();
234 var sbs = Components.classes["@mozilla.org/intl/stringbundle;1"]
235 .getService(Components.interfaces.nsIStringBundleService);
236 var props = sbs.createBundle("chrome://calendar/locale/calendar.properties");
237
238 const weekFormatter = Components.classes["@mozilla.org/calendar/weektitle-service;1"]
239 .getService(Components.interfaces.calIWeekTitleService);
240
241 for (var i = -2; i < 3; i++) {
242 var date = aDate.clone();
243 // Add/subtract number of weeks
244 date.day = aDate.day + i*7;
245
246 var weekno1 = weekFormatter.getWeekTitle(date);
247
248 // We'd show several weeks. Now get the week-number of the
249 // last week that would be shown if the user clicked the label
250 date.day += 7*(this.mWeeksInView-1);
251 var weekno2 = weekFormatter.getWeekTitle(date);
252
253 // If only one week is in the view, we use "Week X"
254 // instead of "Weeks X-Y".
255 var weekTitle;
256 if (this.mWeeksInView > 1) {
257 weekTitle = props.formatStringFromName('WeeksTitle', [weekno1, weekno2], 2);
258 } else {
259 weekTitle = props.formatStringFromName('WeekTitle', [weekno1], 1);
260 }
261 nameArray.push(weekTitle);
262 }
263 document.getAnonymousElementByAttribute(this, "anonid", "nav-control").setNames(nameArray);
264 ]]></body>
265 </method>
266
267 <method name="updateDaysOffPrefs">
268 <body><![CDATA[
269 const weekPrefix = "calendar.week.";
270 const prefNames = ["d0sundaysoff", "d1mondaysoff", "d2tuesdaysoff",
271 "d3wednesdaysoff", "d4thursdaysoff",
272 "d5fridaysoff", "d6saturdaysoff"];
273 const defaults = ["true", "false", "false", "false",
274 "false", "false", "true"];
275 var daysOff = new Array();
276 for (var i in prefNames) {
277 if (getPrefSafe(weekPrefix+prefNames[i], defaults[i])) {
278 daysOff.push(Number(i));
279 }
280 }
281 this.viewElem.daysOffArray = daysOff;
282 ]]></body>
283 </method>
284 </implementation>
285 <handlers>
286 <handler event="DOMMouseScroll"><![CDATA[
287 if (!event.ctrlKey &&
288 !event.shiftKey &&
289 !event.altKey &&
290 !event.metaKey) {
291 // In multiweek views, the only thing that can be scrolled
292 // is the week the user is in. decorated-base takes care
293 // of the shift key, so only move the view when no modifier
294 // is pressed.
295 this.moveView(event.detail < 0 ? -1 : 1);
296 }
297 ]]></handler>
298 </handlers>
299 </binding>
300 </bindings>