зеркало из https://github.com/mozilla/pjs.git
add month and day view to lightning
This commit is contained in:
Родитель
81fe555297
Коммит
c0227f925d
|
@ -0,0 +1,65 @@
|
|||
|
||||
@namespace url("http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul");
|
||||
|
||||
/*== calendar-month-view ==*/
|
||||
calendar-month-view {
|
||||
-moz-binding: url(chrome://calendar/content/calendar-month-view.xml#calendar-month-view);
|
||||
}
|
||||
|
||||
.calendar-month-view-grid-column {
|
||||
min-width: 1px;
|
||||
width: 1px;
|
||||
}
|
||||
|
||||
.calendar-month-view-grid-row {
|
||||
min-height: 1px;
|
||||
height: 1px;
|
||||
}
|
||||
|
||||
/*== calendar-month-day-box ==*/
|
||||
calendar-month-day-box {
|
||||
-moz-binding: url(chrome://calendar/content/calendar-month-view.xml#calendar-month-day-box);
|
||||
}
|
||||
|
||||
calendar-month-day-box {
|
||||
border: 1px solid #999999;
|
||||
}
|
||||
|
||||
.calendar-month-day-box-odd {
|
||||
background: #dddddd !important;
|
||||
}
|
||||
|
||||
.calendar-month-day-box-even {
|
||||
background: white;
|
||||
}
|
||||
|
||||
.calendar-month-day-box-weekend {
|
||||
background: #eeeeee;
|
||||
}
|
||||
|
||||
.calendar-month-day-box-date-label {
|
||||
color: #556;
|
||||
font-weight: bold;
|
||||
}
|
||||
|
||||
.calendar-month-day-box-date-event {
|
||||
}
|
||||
|
||||
/*== calendar-month-day-box-item ==*/
|
||||
calendar-month-day-box-item {
|
||||
-moz-binding: url(chrome://calendar/content/calendar-month-view.xml#calendar-month-day-box-item);
|
||||
}
|
||||
|
||||
.calendar-month-day-box-item-label {
|
||||
font-size: small;
|
||||
}
|
||||
|
||||
/*== calendar-month-view-column-header ==*/
|
||||
calendar-month-view-column-header {
|
||||
-moz-binding: url(chrome://calendar/content/calendar-month-view.xml#calendar-month-view-column-header);
|
||||
}
|
||||
|
||||
.calendar-month-view-column-header-label {
|
||||
font-weight: bold;
|
||||
padding: 3px 3px 3px 3px;
|
||||
}
|
|
@ -0,0 +1,729 @@
|
|||
<?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 calendar views.
|
||||
-
|
||||
- The Initial Developer of the Original Code is
|
||||
- Oracle Corporation
|
||||
- Portions created by the Initial Developer are Copyright (C) 2005
|
||||
- the Initial Developer. All Rights Reserved.
|
||||
-
|
||||
- Contributor(s):
|
||||
- Vladimir Vukicevic <vladimir@pobox.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-month-day-box-item">
|
||||
<content>
|
||||
<xul:label anonid="item-label" crop="end" class="calendar-month-day-box-item-label"/>
|
||||
</content>
|
||||
|
||||
<implementation>
|
||||
<field name="mItem">null</field>
|
||||
|
||||
<property name="item">
|
||||
<getter><![CDATA[
|
||||
return this.mItem;
|
||||
]]></getter>
|
||||
<setter><![CDATA[
|
||||
this.mItem = val;
|
||||
|
||||
function formatTime(aTime) {
|
||||
var m = aTime.minute;
|
||||
return (aTime.hour + ":" + (m < 10 ? "0" : "") + m);
|
||||
}
|
||||
|
||||
var str = null;
|
||||
if (val instanceof Components.interfaces.calIEvent) {
|
||||
str = formatTime(val.startDate) + " " + val.title;
|
||||
} else if (val instanceof Components.interfaces.calITodo) {
|
||||
// yeah, this should really be a little picture instead of a "*"
|
||||
str = "* " + val.title;
|
||||
} else {
|
||||
str = val.title;
|
||||
}
|
||||
|
||||
var label = document.getAnonymousElementByAttribute(this, "anonid", "item-label");
|
||||
if (label.firstChild)
|
||||
label.removeChild(label.firstChild);
|
||||
label.appendChild(document.createTextNode(str));
|
||||
|
||||
return val;
|
||||
]]></setter>
|
||||
</property>
|
||||
</implementation>
|
||||
</binding>
|
||||
|
||||
<binding id="calendar-month-day-box">
|
||||
<content>
|
||||
<xul:vbox>
|
||||
<xul:label anonid="day-label" crop="end" class="calendar-month-day-box-date-label"/>
|
||||
<xul:vbox anonid="day-items"/>
|
||||
</xul:vbox>
|
||||
</content>
|
||||
|
||||
<implementation>
|
||||
<field name="mDate">null</field>
|
||||
<!-- mItemData will always be kept sorted in display order -->
|
||||
<field name="mItemData">[]</field>
|
||||
|
||||
<property name="date">
|
||||
<getter>return this.mDate;</getter>
|
||||
<setter>this.setDate(val); return val;</setter>
|
||||
</property>
|
||||
|
||||
<property name="dayitems">
|
||||
<getter>return document.getAnonymousElementByAttribute(this, "anonid", "day-items");</getter>
|
||||
</property>
|
||||
|
||||
<method name="setDate">
|
||||
<parameter name="aDate"/>
|
||||
<body><![CDATA[
|
||||
if (!aDate)
|
||||
throw Components.results.NS_ERROR_NULL_POINTER;
|
||||
if (this.mDate && this.mDate.compare(aDate) == 0)
|
||||
return;
|
||||
|
||||
this.mDate = aDate;
|
||||
var daylabel = document.getAnonymousElementByAttribute(this, "anonid", "day-label");
|
||||
|
||||
if (aDate.compare(aDate.startOfMonth) == 0 ||
|
||||
aDate.compare(aDate.endOfMonth) == 0)
|
||||
{
|
||||
var monthNames = [ "Jan", "Feb", "Mar", "Apr", "May", "Jun", "Jul", "Aug", "Sep", "Oct", "Nov", "Dec" ];
|
||||
daylabel.setAttribute("value", aDate.day + " " + monthNames[aDate.month]);
|
||||
} else {
|
||||
daylabel.setAttribute("value", aDate.day);
|
||||
}
|
||||
]]></body>
|
||||
</method>
|
||||
|
||||
<method name="addItem">
|
||||
<parameter name="aItem"/>
|
||||
<body><![CDATA[
|
||||
for each (ed in this.mItemData) {
|
||||
if (ed.item == aItem ||
|
||||
(ed.item.id == aItem.id && ed.item.recurrence_id == aItem.recurrence_id))
|
||||
{
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
// insert the new item block, and then relayout
|
||||
this.mItemData.push({ item: aItem });
|
||||
|
||||
this.relayout();
|
||||
]]></body>
|
||||
</method>
|
||||
|
||||
<method name="deleteItem">
|
||||
<parameter name="aItem"/>
|
||||
<body><![CDATA[
|
||||
var deleted = [];
|
||||
|
||||
var origLen = this.mItemData.length;
|
||||
this.mItemData = this.mItemData.filter(
|
||||
function(itd) {
|
||||
if (itd.item == aItem ||
|
||||
(itd.item.id == aItem.id && itd.item.recurrence_id == aItem.recurrence_id))
|
||||
{
|
||||
deleted.push(itd);
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
});
|
||||
|
||||
if (deleted.length > 0) {
|
||||
for each (itd in deleted) {
|
||||
if (itd.box)
|
||||
this.dayitems.removeChild(itd.box);
|
||||
}
|
||||
// no need to relayout; all we did was delete
|
||||
//this.relayout();
|
||||
}
|
||||
]]></body>
|
||||
</method>
|
||||
|
||||
<method name="relayout">
|
||||
<body><![CDATA[
|
||||
function createXULElement(el) {
|
||||
return document.createElementNS("http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul", el);
|
||||
}
|
||||
|
||||
|
||||
this.mItemData.sort(
|
||||
function (a, b) {
|
||||
var aIsEvent = (a.item instanceof Components.interfaces.calIEvent);
|
||||
var aIsTodo = (a.item instanceof Components.interfaces.calITodo);
|
||||
|
||||
var bIsEvent = (b.item instanceof Components.interfaces.calIEvent);
|
||||
var bIsTodo = (b.item instanceof Components.interfaces.calITodo);
|
||||
|
||||
if ((!aIsEvent && !aIsTodo) || (!bIsEvent && !bIsTodo)) {
|
||||
// XXX ????
|
||||
dump ("Don't know how to sort these two events: " + a.item + " " + b.item + "\n");
|
||||
return 0;
|
||||
}
|
||||
|
||||
// sort todos before events
|
||||
if (aIsTodo && bIsEvent) return -1;
|
||||
if (aIsEvent && bIsTodo) return 1;
|
||||
|
||||
// XXX how do I sort todos?
|
||||
if (aIsTodo && bIsTodo) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (aIsEvent && bIsEvent) {
|
||||
var cmp;
|
||||
|
||||
cmp = a.item.startDate.compare(b.item.startDate);
|
||||
if (cmp != 0)
|
||||
return cmp;
|
||||
|
||||
cmp = a.item.endDate.compare(b.item.endDate);
|
||||
if (cmp != 0)
|
||||
return cmp;
|
||||
|
||||
if (a.item.title < b.item.title)
|
||||
return -1;
|
||||
if (a.item.title > b.item.title)
|
||||
return 1;
|
||||
}
|
||||
|
||||
return 0;
|
||||
});
|
||||
|
||||
for (var i = 0; i < this.mItemData.length; i++) {
|
||||
var itd = this.mItemData[i];
|
||||
|
||||
if (!itd.box) {
|
||||
// find what element to insert before
|
||||
var before = null;
|
||||
for (var j = i+1; !before && this.mItemData[j]; j++)
|
||||
before = this.mItemData[j].box;
|
||||
|
||||
var box = createXULElement("calendar-month-day-box-item");
|
||||
this.dayitems.insertBefore(box, before);
|
||||
|
||||
box.item = itd.item;
|
||||
itd.box = box;
|
||||
}
|
||||
}
|
||||
]]></body>
|
||||
</method>
|
||||
</implementation>
|
||||
</binding>
|
||||
|
||||
<binding id="calendar-month-view-column-header">
|
||||
<content>
|
||||
<xul:hbox flex="1">
|
||||
<xul:spacer flex="1"/>
|
||||
<xul:label anonid="label" crop="right" class="calendar-month-view-column-header-label" />
|
||||
<xul:spacer flex="1"/>
|
||||
</xul:hbox>
|
||||
</content>
|
||||
|
||||
<implementation>
|
||||
<field name="mIndex">-1</field>
|
||||
|
||||
<constructor><![CDATA[
|
||||
if (this.mIndex == -1) {
|
||||
var attrIndex = this.getAttribute("index");
|
||||
if (attrIndex)
|
||||
this.index = parseInt(attrIndex);
|
||||
}
|
||||
]]></constructor>
|
||||
|
||||
<property name="index">
|
||||
<getter>return this.mIndex;</getter>
|
||||
<setter><![CDATA[
|
||||
this.mIndex = val % 7;
|
||||
|
||||
// XXX aaaaaaaa
|
||||
var weekdayNames = [
|
||||
"Sunday",
|
||||
"Monday",
|
||||
"Tuesday",
|
||||
"Wednesday",
|
||||
"Thursday",
|
||||
"Friday",
|
||||
"Saturday",
|
||||
"Sunday"
|
||||
];
|
||||
|
||||
var label = document.getAnonymousElementByAttribute(this, "anonid", "label");
|
||||
label.setAttribute("value", weekdayNames[this.mIndex]);
|
||||
|
||||
return this.mIndex;
|
||||
]]></setter>
|
||||
</property>
|
||||
</implementation>
|
||||
</binding>
|
||||
|
||||
<binding id="calendar-month-view">
|
||||
<content>
|
||||
<xul:vbox flex="1">
|
||||
<xul:hbox anonid="headerbox" equalsize="always"/>
|
||||
|
||||
<xul:grid anonid="monthgrid" flex="1">
|
||||
<xul:columns anonid="monthgridcolumns" equalsize="always">
|
||||
<xul:column flex="1" class="calendar-month-view-grid-column"/>
|
||||
<xul:column flex="1" class="calendar-month-view-grid-column"/>
|
||||
<xul:column flex="1" class="calendar-month-view-grid-column"/>
|
||||
<xul:column flex="1" class="calendar-month-view-grid-column"/>
|
||||
<xul:column flex="1" class="calendar-month-view-grid-column"/>
|
||||
<xul:column flex="1" class="calendar-month-view-grid-column"/>
|
||||
<xul:column flex="1" class="calendar-month-view-grid-column"/>
|
||||
</xul:columns>
|
||||
|
||||
<xul:rows anonid="monthgridrows" equalsize="always"/>
|
||||
</xul:grid>
|
||||
</xul:vbox>
|
||||
</content>
|
||||
|
||||
<implementation implements="calICalendarView">
|
||||
|
||||
<!-- constructor -->
|
||||
<constructor><![CDATA[
|
||||
function createXULElement(el) {
|
||||
return document.createElementNS("http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul", el);
|
||||
}
|
||||
|
||||
var headerbox = document.getAnonymousElementByAttribute(this, "anonid", "headerbox")
|
||||
for (var i = 0; i < 7; i++) {
|
||||
var hdr = createXULElement("calendar-month-view-column-header");
|
||||
hdr.setAttribute("flex", "1");
|
||||
headerbox.appendChild(hdr);
|
||||
hdr.index = i;
|
||||
}
|
||||
]]></constructor>
|
||||
|
||||
<!-- fields -->
|
||||
|
||||
<field name="mCalendar">null</field>
|
||||
<field name="mController">null</field>
|
||||
<field name="mStartDate">null</field>
|
||||
<field name="mEndDate">null</field>
|
||||
<field name="mDateBoxes">null</field>
|
||||
|
||||
<field name="mShowDaysOutsideMonth">true</field>
|
||||
|
||||
<!-- calICalendarView -->
|
||||
|
||||
<property name="supportsDisjointDates" readonly="true"
|
||||
onget="return false;"/>
|
||||
<property name="hasDisjointDates" readonly="true"
|
||||
onget="return false;"/>
|
||||
|
||||
<property name="displayCalendar">
|
||||
<getter><![CDATA[
|
||||
return this.mCalendar;
|
||||
]]></getter>
|
||||
<setter><![CDATA[
|
||||
if (this.mCalendar != val) {
|
||||
this.mCalendar = val;
|
||||
this.refresh();
|
||||
}
|
||||
return val;
|
||||
]]></setter>
|
||||
</property>
|
||||
|
||||
<property name="controller"
|
||||
onget="return this.mController;"
|
||||
onset="return this.mController = val;"/>
|
||||
|
||||
<property name="startDate" readonly="true"
|
||||
onget="return this.mStartDate"/>
|
||||
|
||||
<property name="endDate" readonly="true">
|
||||
<getter><![CDATA[
|
||||
if (!this.mEndDate)
|
||||
return null;
|
||||
var realEnd = this.mEndDate.clone();
|
||||
realEnd.day -= 1;
|
||||
realEnd.normalize();
|
||||
return realEnd;
|
||||
]]></getter>
|
||||
</property>
|
||||
|
||||
<property name="selectedItem">
|
||||
<getter><![CDATA[
|
||||
return this.mSelectedItem;
|
||||
]]></getter>
|
||||
<setter><![CDATA[
|
||||
]]></setter>
|
||||
</property>
|
||||
|
||||
<method name="showDate">
|
||||
<parameter name="aDate"/>
|
||||
<body><![CDATA[
|
||||
dump ("showDate: " + aDate + "\n");
|
||||
var realEnd = aDate.endOfMonth;
|
||||
realEnd.day += 1;
|
||||
realEnd.normalize();
|
||||
this.setDateRange(aDate.startOfMonth, realEnd);
|
||||
]]></body>
|
||||
</method>
|
||||
|
||||
<method name="setDateRange">
|
||||
<parameter name="aStartDate"/>
|
||||
<parameter name="aEndDate"/>
|
||||
<body><![CDATA[
|
||||
var realStart = aStartDate.startOfWeek;
|
||||
var realEnd = aEndDate.endOfWeek;
|
||||
|
||||
dump ("setDateRange: " + aStartDate + " -> " + aEndDate + "\n");
|
||||
realEnd.day += 1;
|
||||
realEnd.normalize();
|
||||
|
||||
this.mStartDate = realStart;
|
||||
this.mEndDate = realEnd;
|
||||
|
||||
dump ("setDateRange: " + realStart + " -> " + realEnd + "\n");
|
||||
|
||||
this.refresh();
|
||||
]]></body>
|
||||
</method>
|
||||
|
||||
<method name="setDateList">
|
||||
<parameter name="aCount"/>
|
||||
<parameter name="aDates"/>
|
||||
<body><![CDATA[
|
||||
throw Components.results.NS_ERROR_NOT_IMPLEMENTED;
|
||||
]]></body>
|
||||
</method>
|
||||
|
||||
<method name="getDateList">
|
||||
<parameter name="aCount"/>
|
||||
<body><![CDATA[
|
||||
if (!this.mStartDate || !this.mEndDate) {
|
||||
aCount.value = 0;
|
||||
return [];
|
||||
}
|
||||
|
||||
var results = [];
|
||||
var curDate = this.mStartDate.clone();
|
||||
curDate.isDate = true;
|
||||
curDate.normalize();
|
||||
|
||||
while (curDate.compare(this.mEndDate) < 0) {
|
||||
results.push(curDate.clone());
|
||||
curDate.day += 1;
|
||||
curDate.normalize();
|
||||
}
|
||||
aCount.value = results.length;
|
||||
return results;
|
||||
]]></body>
|
||||
</method>
|
||||
|
||||
<!-- public properties and methods -->
|
||||
|
||||
<!-- whether to show days outside of the current month -->
|
||||
<property name="showDaysOutsideMonth">
|
||||
<getter><![CDATA[
|
||||
return this.mShowDaysOutsideMonth;
|
||||
]]></getter>
|
||||
<setter><![CDATA[
|
||||
if (this.mShowDaysOutsideMonth != val) {
|
||||
this.mShowDaysOutsideMonth = val;
|
||||
this.refresh();
|
||||
}
|
||||
return val;
|
||||
]]></setter>
|
||||
</property>
|
||||
|
||||
<!-- private properties and methods -->
|
||||
|
||||
<property name="monthgrid" readonly="true"
|
||||
onget="return document.getAnonymousElementByAttribute(this, 'anonid', 'monthgrid');"/>
|
||||
|
||||
<property name="monthgridrows" readonly="true"
|
||||
onget="return document.getAnonymousElementByAttribute(this, 'anonid', 'monthgridrows');"/>
|
||||
|
||||
<method name="refresh">
|
||||
<body><![CDATA[
|
||||
this.relayout();
|
||||
|
||||
if (!this.mCalendar)
|
||||
return;
|
||||
|
||||
this.mCalendar.getItems(this.mCalendar.ITEM_FILTER_COMPLETED_ALL |
|
||||
this.mCalendar.ITEM_FILTER_TYPE_ALL |
|
||||
this.mCalendar.ITEM_FILTER_CLASS_OCCURRENCES,
|
||||
0,
|
||||
this.startDate,
|
||||
this.endDate,
|
||||
this.mOperationListener);
|
||||
]]></body>
|
||||
</method>
|
||||
|
||||
<method name="relayout">
|
||||
<body><![CDATA[
|
||||
function createXULElement(el) {
|
||||
return document.createElementNS("http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul", el);
|
||||
}
|
||||
|
||||
var gridrows = this.monthgridrows;
|
||||
|
||||
// XXX - reuse the grid boxes!
|
||||
// clear out the grid
|
||||
while (gridrows.lastChild)
|
||||
gridrows.removeChild(gridrows.lastChild);
|
||||
|
||||
if (!this.mStartDate || !this.mEndDate)
|
||||
return;
|
||||
|
||||
// we're going to cheat and make sure that the first full
|
||||
// month is "even". The only time when this wouldn't be
|
||||
// valid is if the first of the month actually falls to
|
||||
// whatever the first weekday is that we're displaying.
|
||||
|
||||
var isEven = 0;
|
||||
if (this.mStartDate.day == 1)
|
||||
isEven = 1;
|
||||
|
||||
var dateBoxes = [];
|
||||
|
||||
var first = true;
|
||||
var lastMonth = this.mStartDate.month;
|
||||
var lastWeekNo = null;
|
||||
var curRow = null;
|
||||
|
||||
for each (var date in this.getDateList({})) {
|
||||
var box = createXULElement("calendar-month-day-box");
|
||||
if (lastMonth != date.month && !first) {
|
||||
isEven = !isEven;
|
||||
lastMonth = date.month;
|
||||
}
|
||||
|
||||
// XXX take into account real start week
|
||||
var weekno = Math.floor ((date.yearday - date.weekday) / 7);
|
||||
|
||||
if (weekno != lastWeekNo) {
|
||||
// start a new row
|
||||
curRow = createXULElement("row");
|
||||
curRow.setAttribute("flex", "1");
|
||||
curRow.setAttribute("class", "calendar-month-view-grid-row");
|
||||
|
||||
gridrows.appendChild(curRow);
|
||||
lastWeekNo = weekno;
|
||||
}
|
||||
|
||||
var class = "calendar-month-day-box-" + (isEven ? "even" : "odd");
|
||||
// XXX isWeekend?
|
||||
if (date.weekday == 0 || date.weekday == 6)
|
||||
class = "calendar-month-day-box-weekend " + class;
|
||||
box.setAttribute("class", class);
|
||||
curRow.appendChild(box);
|
||||
|
||||
box.setDate(date);
|
||||
|
||||
var boxdata = {
|
||||
date: date,
|
||||
row: curRow,
|
||||
box: box
|
||||
};
|
||||
|
||||
first = false;
|
||||
|
||||
dateBoxes.push(boxdata);
|
||||
}
|
||||
|
||||
this.mDateBoxes = dateBoxes;
|
||||
]]></body>
|
||||
</method>
|
||||
|
||||
<method name="findBoxForItem">
|
||||
<parameter name="aItem"/>
|
||||
<body><![CDATA[
|
||||
var targetDate = null;
|
||||
if (aItem instanceof Components.interfaces.calIEvent) {
|
||||
targetDate = aItem.startDate;
|
||||
} else if (aItem instanceof Components.interfaces.calITodo) {
|
||||
targetDate = aItem.startDate || aItem.entryDate;
|
||||
}
|
||||
|
||||
if (!targetDate)
|
||||
return null;
|
||||
|
||||
for each (box in this.mDateBoxes) {
|
||||
if (box.date.compare(targetDate) == 0)
|
||||
return box;
|
||||
}
|
||||
|
||||
return null;
|
||||
]]></body>
|
||||
</method>
|
||||
|
||||
<method name="doAddItem">
|
||||
<parameter name="aItem"/>
|
||||
<body><![CDATA[
|
||||
var box = this.findBoxForItem(aItem);
|
||||
if (!box)
|
||||
return;
|
||||
|
||||
box.box.addItem(aItem);
|
||||
]]></body>
|
||||
</method>
|
||||
|
||||
<method name="doDeleteItem">
|
||||
<parameter name="aItem"/>
|
||||
<body><![CDATA[
|
||||
var box = this.findBoxForItem(aItem);
|
||||
if (!box)
|
||||
return;
|
||||
|
||||
box.deleteItem(aItem);
|
||||
]]></body>
|
||||
</method>
|
||||
|
||||
<!-- our private observers and listeners -->
|
||||
|
||||
<field name="mOperationListener"><![CDATA[
|
||||
({
|
||||
calView: this,
|
||||
|
||||
QueryInterface: function (aIID) {
|
||||
if (!aIID.equals(Components.interfaces.calIOperationListener) &&
|
||||
!aIID.equals(Components.interfaces.nsISupports)) {
|
||||
throw Components.results.NS_ERROR_NO_INTERFACE;
|
||||
}
|
||||
|
||||
return this;
|
||||
},
|
||||
|
||||
onOperationComplete: function(aCalendar, aStatus, aOperationType, aId, aDetail) {
|
||||
// nothing to do
|
||||
//dump ("+++ OnOperationComplete (detail: " + aDetail + ")\n");
|
||||
},
|
||||
onGetResult: function(aCalendar, aStatus, aItemType, aDetail, aCount, aItems) {
|
||||
if (!Components.isSuccessCode(aStatus))
|
||||
return;
|
||||
|
||||
for each (var item in aItems) {
|
||||
this.calView.doAddItem(item);
|
||||
}
|
||||
}
|
||||
})
|
||||
]]></field>
|
||||
|
||||
<field name="mObserver"><![CDATA[
|
||||
// the calIObserver, and calICompositeObserver
|
||||
({
|
||||
calView: this,
|
||||
|
||||
QueryInterface: function (aIID) {
|
||||
if (!aIID.equals(Components.interfaces.calIObserver) &&
|
||||
!aIID.equals(Components.interfaces.calICompositeObserver) &&
|
||||
!aIID.equals(Components.interfaces.nsISupports)) {
|
||||
throw Components.results.NS_ERROR_NO_INTERFACE;
|
||||
}
|
||||
|
||||
return this;
|
||||
},
|
||||
|
||||
onStartBatch: function() {
|
||||
this.calView.mBatchCount++;
|
||||
},
|
||||
onEndBatch: function() {
|
||||
this.mBatchCount--;
|
||||
if (this.mBatchCount == 0) {
|
||||
this.calView.refresh();
|
||||
}
|
||||
},
|
||||
onLoad: function() {
|
||||
this.calView.refresh();
|
||||
},
|
||||
onAddItem: function (aItem) {
|
||||
var occs = aItem.getOccurrencesBetween(this.calView.startDate,
|
||||
this.calView.endDate,
|
||||
{});
|
||||
for each (var occ in occs)
|
||||
this.calView.doAddItem(occ);
|
||||
},
|
||||
onModifyItem: function (aNewItem, aOldItem) {
|
||||
var occs;
|
||||
occs = aOldItem.getOccurrencesBetween(this.calView.startDate,
|
||||
this.calView.endDate,
|
||||
{});
|
||||
for each (var occ in occs)
|
||||
this.calView.doDeleteItem(occ);
|
||||
|
||||
occs = aNewItem.getOccurrencesBetween(this.calView.startDate,
|
||||
this.calView.endDate,
|
||||
{});
|
||||
for each (var occ in occs)
|
||||
this.calView.doAddItem(occ);
|
||||
},
|
||||
onDeleteItem: function (aItem) {
|
||||
if (!(aItem instanceof Components.interfaces.calIEvent))
|
||||
return;
|
||||
|
||||
var occs = aItem.getOccurrencesBetween(this.calView.startDate,
|
||||
this.calView.endDate,
|
||||
{});
|
||||
for each (var occ in occs) {
|
||||
this.calView.doDeleteEvent(occ);
|
||||
}
|
||||
},
|
||||
//XXXvv Alarm could, in theory, flash the event or something
|
||||
onAlarm: function (aAlarmItem) { },
|
||||
onError: function (aErrNo, aMessage) { },
|
||||
|
||||
//
|
||||
// calICompositeObserver stuff
|
||||
// XXXvv we can be smarter about how we handle this stuff
|
||||
//
|
||||
onCalendarAdded: function (aCalendar) {
|
||||
this.calView.refresh();
|
||||
},
|
||||
|
||||
onCalendarRemoved: function (aCalendar) {
|
||||
this.calView.refresh();
|
||||
},
|
||||
|
||||
onDefaultCalendarChanged: function (aNewDefaultCalendar) {
|
||||
// don't care, for now
|
||||
}
|
||||
})
|
||||
]]></field>
|
||||
|
||||
</implementation>
|
||||
</binding>
|
||||
|
||||
</bindings>
|
||||
|
||||
<!-- -*- Mode: xml; indent-tabs-mode: nil; -*- -->
|
|
@ -238,10 +238,10 @@
|
|||
-->
|
||||
<binding id="calendar-event-column">
|
||||
<content>
|
||||
<xul:stack anonid="boxstack" flex="1">
|
||||
<xul:box anonid="bgbox" flex="1"/>
|
||||
<xul:box anonid="topbox" flex="1" equalsize="always"/>
|
||||
<xul:box anonid="fgbox" flex="1" class="fgdragcontainer">
|
||||
<xul:stack anonid="boxstack" flex="1" style="min-width: 1px; min-height: 1px">
|
||||
<xul:box anonid="bgbox" flex="1" style="min-width: 1px; min-height: 1px"/>
|
||||
<xul:box anonid="topbox" flex="1" equalsize="always" style="min-width: 1px; min-height: 1px"/>
|
||||
<xul:box anonid="fgbox" flex="1" class="fgdragcontainer" style="min-width: 1px; min-height: 1px">
|
||||
<xul:box anonid="fgdragspacer" style="display: inherit; overflow: hidden;">
|
||||
<xul:spacer flex="1"/>
|
||||
<xul:label anonid="fgdragbox-startlabel" class="fgdragbox-label"/>
|
||||
|
@ -564,6 +564,8 @@
|
|||
else
|
||||
box.setAttribute("width", dur * this.mPixPerMin);
|
||||
|
||||
box.setAttribute("style", "min-width: 1px; min-height: 1px;");
|
||||
|
||||
this.bgbox.appendChild(box);
|
||||
theMin += 60;
|
||||
}
|
||||
|
@ -583,6 +585,7 @@
|
|||
var xulColumn = createXULElement("box");
|
||||
xulColumn.setAttribute("orient", orient);
|
||||
xulColumn.setAttribute("flex", "1");
|
||||
xulColumn.setAttribute("style", "min-width: 1px; min-height: 1px;");
|
||||
this.topbox.appendChild(xulColumn);
|
||||
|
||||
var numBlocksInserted = 0
|
||||
|
@ -611,6 +614,7 @@
|
|||
|
||||
if (chunk.event) {
|
||||
var chunkBox = createXULElement("calendar-event-box");
|
||||
chunkBox.setAttribute("style", "min-width: 1px; min-height: 1px;");
|
||||
chunkBox.setAttribute("orient", orient);
|
||||
// chunkBox.setAttribute("style", "background: #eeeeff; padding: 0px 1px 0px 1px");
|
||||
|
||||
|
@ -629,6 +633,7 @@
|
|||
chunk.event.eventbox = chunkBox;
|
||||
} else {
|
||||
var chunkBox = createXULElement("spacer");
|
||||
chunkBox.setAttribute("style", "min-width: 1px; min-height: 1px;");
|
||||
chunkBox.setAttribute("orient", orient);
|
||||
chunkBox.setAttribute("class", "calendar-empty-space-box");
|
||||
xulColumn.appendChild(chunkBox);
|
||||
|
@ -1318,10 +1323,34 @@
|
|||
|
||||
<implementation implements="calICalendarView">
|
||||
|
||||
<field name="mResizeHandler">null</field>
|
||||
<constructor><![CDATA[
|
||||
var self = this;
|
||||
this.mResizeHandler = function() { self.onResize(); };
|
||||
window.addEventListener("resize", this.mResizeHandler, true);
|
||||
this.reorient();
|
||||
]]></constructor>
|
||||
|
||||
<method name="onResize">
|
||||
<body><![CDATA[
|
||||
var timebar = document.getAnonymousElementByAttribute(this, "anonid", "timebar");
|
||||
var daybox = document.getAnonymousElementByAttribute(this, "anonid", "daybox");
|
||||
|
||||
var orient = this.orient;
|
||||
var size;
|
||||
if (this.orient == "horizontal")
|
||||
size = daybox.boxObject.width;
|
||||
else
|
||||
size = daybox.boxObject.height;
|
||||
|
||||
// ask the
|
||||
var minutes = timebar.endMinute - timebar.startMinute;
|
||||
var ppm = size / minutes;
|
||||
dump ("new ppm: " + ppm + "\n");
|
||||
this.pixelsPerMinute = ppm;
|
||||
]]></body>
|
||||
</method>
|
||||
|
||||
<field name="mController">null</field>
|
||||
<field name="mCalendar">null</field>
|
||||
<field name="mStartDate">null</field>
|
||||
|
@ -1514,10 +1543,21 @@
|
|||
}
|
||||
}
|
||||
|
||||
var wkStart = aDate.startOfWeek;
|
||||
var wkEnd = aDate.endOfWeek;
|
||||
// if we're only showing one date, then continue
|
||||
// to only show one date; otherwise, show the week.
|
||||
if (this.numVisibleDates == 1) {
|
||||
var st = aDate;
|
||||
var end = aDate.clone();
|
||||
end.day += 1;
|
||||
end.normalize();
|
||||
|
||||
this.setDateRange(wkStart, wkEnd);
|
||||
this.setDateRange(st, end);
|
||||
} else {
|
||||
var wkStart = aDate.startOfWeek;
|
||||
var wkEnd = aDate.endOfWeek;
|
||||
|
||||
this.setDateRange(wkStart, wkEnd);
|
||||
}
|
||||
]]></body>
|
||||
</method>
|
||||
|
||||
|
@ -1530,6 +1570,8 @@
|
|||
this.mStartDate = aStartDate.clone();
|
||||
this.mStartDate.makeImmutable();
|
||||
this.mEndDate = aEndDate.clone();
|
||||
this.mEndDate.day -= 1;
|
||||
this.mEndDate.normalize();
|
||||
this.mEndDate.makeImmutable();
|
||||
|
||||
// this function needs to be smarter, and needs to compare
|
||||
|
@ -1624,9 +1666,27 @@
|
|||
|
||||
<!-- private -->
|
||||
|
||||
<property name="numVisibleDates" readonly="true">
|
||||
<getter><![CDATA[
|
||||
if (this.mDateList)
|
||||
return this.mDateList.length;
|
||||
|
||||
var count = 0;
|
||||
|
||||
var d = this.mStartDate.clone();
|
||||
while (d.compare(this.mEndDate) <= 0) {
|
||||
count++;
|
||||
d.day += 1;
|
||||
d.normalize();
|
||||
}
|
||||
|
||||
return count;
|
||||
]]></getter>
|
||||
</property>
|
||||
|
||||
<property name="orient">
|
||||
<getter>return this.getAttribute("orient");</getter>
|
||||
<setter>return this.setAttribute("orient", val);</setter>
|
||||
<getter>return (this.getAttribute("orient") || "vertical");</getter>
|
||||
<setter>this.setAttribute("orient", val); return val;</setter>
|
||||
</property>
|
||||
|
||||
<method name="setAttribute">
|
||||
|
@ -1835,8 +1895,8 @@
|
|||
this.mDateColumns.push ( { date: d, column: dayEventsBox, header: dayHeaderBox } );
|
||||
}
|
||||
|
||||
daybox.removeAttribute("flex");
|
||||
daybox.setAttribute("flex", "1");
|
||||
// fix pixels-per-minute
|
||||
this.onResize();
|
||||
]]></body>
|
||||
</method>
|
||||
|
||||
|
|
|
@ -65,8 +65,8 @@ interface calICalendarView : nsISupports
|
|||
void showDate(in calIDateTime aDate);
|
||||
|
||||
/**
|
||||
* Set a date range for the view to display, from aStartDate to
|
||||
* aEndDate, inclusive.
|
||||
* Set a date range for the view to display, from aStartDate
|
||||
* inclusive to aEndDate, not inclusive.
|
||||
*
|
||||
* Some views may decide to utilize the time portion of these
|
||||
* calIDateTimes; pass in calIDateTimes that are dates if you
|
||||
|
@ -82,7 +82,10 @@ interface calICalendarView : nsISupports
|
|||
|
||||
/**
|
||||
* The start date of the view's display. If the view is displaying
|
||||
* disjoint dates, this will be the latestdate that's displayed.
|
||||
* disjoint dates, this will be the latest date that's displayed.
|
||||
*
|
||||
* Note that this won't be equivalent to the aEndDate passed to
|
||||
* setDateRange, because that date isn't actually displayed!
|
||||
*/
|
||||
readonly attribute calIDateTime endDate;
|
||||
|
||||
|
|
|
@ -128,7 +128,7 @@ var ltnCalendarViewController = {
|
|||
},
|
||||
|
||||
deleteOccurrence: function (aOccurrence) {
|
||||
if (aOccurrence.parentItem) {
|
||||
if (aOccurrence.parentItem != aOccurrence) {
|
||||
var event = aOccurrence.parentItem.clone();
|
||||
event.recurrenceInfo.removeOccurrenceAt(aOccurrence.recurrenceId);
|
||||
event.calendar.modifyItem(event, aOccurrence, null);
|
||||
|
|
|
@ -49,8 +49,9 @@ function ltnMinimonthPick(which, minimonth)
|
|||
|
||||
var cdt = new CalDateTime();
|
||||
cdt.jsDate = minimonth.value;
|
||||
|
||||
cdt = cdt.getInTimezone(calendarDefaultTimezone());
|
||||
cdt.isDate = true;
|
||||
cdt.timezone = calendarDefaultTimezone();
|
||||
currentView().showDate(cdt);
|
||||
|
||||
showCalendar(false);
|
||||
|
@ -71,7 +72,8 @@ function ltnOnLoad(event)
|
|||
|
||||
function currentView()
|
||||
{
|
||||
return document.getElementById("calendar-multiday-view");
|
||||
var calendarViewBox = document.getElementById("calendar-view-box");
|
||||
return calendarViewBox.selectedPanel;
|
||||
}
|
||||
|
||||
function showCalendar(jumpToToday)
|
||||
|
@ -94,19 +96,52 @@ function showCalendar(jumpToToday)
|
|||
}
|
||||
|
||||
function switchView(type) {
|
||||
var messengerDisplayDeck = document.getElementById("displayDeck");
|
||||
var calendarViewBox = document.getElementById("calendar-view-box");
|
||||
|
||||
switch (type) {
|
||||
case "month":
|
||||
calendarViewBox.selectedPanel = document.getElementById("calendar-month-view");
|
||||
break;
|
||||
case "week":
|
||||
default:
|
||||
calendarViewBox.selectedPanel = document.getElementById("calendar-multiday-view");
|
||||
break;
|
||||
var monthView = document.getElementById("calendar-month-view");
|
||||
var multidayView = document.getElementById("calendar-multiday-view");
|
||||
|
||||
// XXX we need a selectedDate in calICalendarView.idl!
|
||||
var selectedDate = calendarViewBox.selectedPanel.startDate;
|
||||
|
||||
if (!selectedDate) {
|
||||
var d = Components.classes['@mozilla.org/calendar/datetime;1'].createInstance(Components.interfaces.calIDateTime);
|
||||
d.jsDate = new Date();
|
||||
selectedDate = d.getInTimezone(calendarDefaultTimezone());
|
||||
}
|
||||
|
||||
document.getElementById("displayDeck").selectedPanel = calendarViewBox;
|
||||
switch (type) {
|
||||
case "month": {
|
||||
monthView.showDate(selectedDate);
|
||||
calendarViewBox.selectedPanel = monthView;
|
||||
}
|
||||
break;
|
||||
case "week": {
|
||||
var start = selectedDate.startOfWeek;
|
||||
var end = selectedDate.endOfWeek.clone();
|
||||
end.day += 1;
|
||||
end.normalize();
|
||||
multidayView.setDateRange(start, end);
|
||||
calendarViewBox.selectedPanel = multidayView;
|
||||
}
|
||||
break;
|
||||
case "day":
|
||||
default: {
|
||||
var start = selectedDate;
|
||||
var end = selectedDate.clone();
|
||||
end.day += 1;
|
||||
end.normalize();
|
||||
multidayView.setDateRange(start, end);
|
||||
calendarViewBox.selectedPanel = multidayView;
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
if (messengerDisplayDeck.selectedPanel = calendarViewBox)
|
||||
showCalendar(false);
|
||||
else
|
||||
showCalendar(true);
|
||||
}
|
||||
|
||||
function selectedCalendarPane(event)
|
||||
|
|
|
@ -5,6 +5,7 @@
|
|||
<?xml-stylesheet href="chrome://lightning/skin/lightning.css" type="text/css"?>
|
||||
|
||||
<?xml-stylesheet href="chrome://calendar/content/calendar-multiday-view.css" type="text/css"?>
|
||||
<?xml-stylesheet href="chrome://calendar/content/calendar-month-view.css" type="text/css"?>
|
||||
<?xml-stylesheet href="chrome://calendar/content/datetimepickers/minimonth.css" type="text/css"?>
|
||||
|
||||
<overlay xmlns="http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul">
|
||||
|
@ -15,6 +16,7 @@
|
|||
<script type="application/x-javascript" src="chrome://lightning/content/lightning-utils.js"/>
|
||||
<script type="application/x-javascript" src="chrome://lightning/content/calendar-management.js"/>
|
||||
<script type="application/x-javascript" src="chrome://lightning/content/messenger-overlay-sidebar.js"/>
|
||||
<script type="application/x-javascript" src="chrome://lightning/content/agenda-tree.js"/>
|
||||
|
||||
<vbox id="folderPaneBox">
|
||||
<commandset id="calendar_commands">
|
||||
|
@ -64,9 +66,8 @@
|
|||
|
||||
<deck id="displayDeck">
|
||||
<deck id="calendar-view-box" flex="1">
|
||||
<calendar-multiday-view orient="vertical" id="calendar-multiday-view" style="overflow:-moz-scrollbars-vertical" flex="1" />
|
||||
<vbox id="calendar-month-view"><label value="blah"/></vbox>
|
||||
<!-- <vbox id="week-view-box" flex="1"/> -->
|
||||
<calendar-month-view id="calendar-month-view" flex="1" />
|
||||
<calendar-multiday-view orient="vertical" id="calendar-multiday-view" flex="1" />
|
||||
</deck>
|
||||
</deck>
|
||||
</overlay>
|
||||
|
|
|
@ -16,6 +16,7 @@
|
|||
<toolbarbutton id="calendar-new-event-button" class="cal-toolbarbutton-1" label="New Event" tooltiptext="New Event" oncommand="createEventWithDialog()"/>
|
||||
<toolbarbutton id="calendar-week-view-button" class="cal-toolbarbutton-1" label="Week View" tooltiptext="Month View" oncommand="switchView('week')"/>
|
||||
<toolbarbutton id="calendar-month-view-button" class="cal-toolbarbutton-1" label="Month View" tooltiptext="Month View" oncommand="switchView('month')"/>
|
||||
<toolbarbutton id="calendar-day-view-button" class="cal-toolbarbutton-1" label="Day View" tooltiptext="Day View" oncommand="switchView('day')"/>
|
||||
|
||||
</toolbarpalette>
|
||||
|
||||
|
|
|
@ -28,6 +28,8 @@ calendar.jar:
|
|||
content/calendar/calendar-dialog-utils.js (/calendar/base/content/calendar-dialog-utils.js)
|
||||
content/calendar/calendar-multiday-view.css (/calendar/base/content/calendar-multiday-view.css)
|
||||
content/calendar/calendar-multiday-view.xml (/calendar/base/content/calendar-multiday-view.xml)
|
||||
content/calendar/calendar-month-view.css (/calendar/base/content/calendar-month-view.css)
|
||||
content/calendar/calendar-month-view.xml (/calendar/base/content/calendar-month-view.xml)
|
||||
content/calendar/calendar-item-editing.js (/calendar/base/content/calendar-item-editing.js)
|
||||
content/calendar/calendar-alarm-dialog.xul (/calendar/base/content/calendar-alarm-dialog.xul)
|
||||
content/calendar/calendar-alarm-dialog.js (/calendar/base/content/calendar-alarm-dialog.js)
|
||||
|
|
Загрузка…
Ссылка в новой задаче