Mozilla/mozilla/calendar/lightning/content/calendar-todo-list.xml
daniel.boelzle%sun.com 90cd0574e0 Bug 384726: avoid duplicate items, r=mickey
git-svn-id: svn://10.0.0.236/trunk@228308 18797224-902f-48f8-a5cc-f745e15eee43
2007-06-19 08:47:48 +00:00

342 lines
13 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 Lightning code.
-
- 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):
- Mike Shaver <shaver@mozilla.org>
- Dan Mosedale <dmose@mozilla.org>
- Olli.Pettay@helsinki.fi
- Daniel Boelzle <daniel.boelzle@sun.com>
- Joey Minta <jminta@gmail.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-todo-bindings"
xmlns="http://www.mozilla.org/xbl"
xmlns:xul="http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul"
xmlns:xbl="http://www.mozilla.org/xbl">
<binding id="calendar-todo-list" extends="chrome://global/content/bindings/richlistbox.xml#richlistbox"
implements="calIObserver, calICompositeObserver, calIOperationListener">
<implementation>
<destructor><![CDATA[
if (this.mCalendar)
this.mCalendar.removeObserver(this.mOperationListener);
]]></destructor>
<field name="mCalendar">null</field>
<field name="mShowCompleted">true</field>
<field name="mOperationListener"><![CDATA[
({
todoList: this,
mBatchCount: 0,
onStartBatch: function onStartBatch()
{
this.mBatchCount++;
return;
},
onEndBatch: function onEndBatch()
{
this.mBatchCount--;
if (this.mBatchCount == 0) {
this.todoList.rebuildDisplay();
}
return;
},
onLoad: function onLoad()
{
return;
},
onAddItem: function onAddItem(aItem)
{
if (!(aItem instanceof Components.interfaces.calITodo) ||
this.mBatchCount)
return;
this.todoList.addTodo(aItem);
},
onDeleteItem: function onDeleteItem(aItem)
{
if (!(aItem instanceof Components.interfaces.calITodo) ||
this.mBatchCount)
return;
this.todoList.removeTodo(aItem);
},
onModifyItem: function onModifyItem(aNewItem, aOldItem)
{
if (!(aNewItem instanceof Components.interfaces.calITodo) ||
this.mBatchCount)
return;
this.todoList.removeTodo(aOldItem);
this.todoList.addTodo(aNewItem);
},
onError: function onError(aErrNo, aMessage)
{
},
onCalendarAdded: function onCalendarAdded(aCalendar)
{
this.todoList.rebuildDisplay();
},
onCalendarRemoved: function onCalendarRemoved(aCalendar)
{
this.todoList.rebuildDisplay();
},
onDefaultCalendarChanged: function onDefaultCalendarChanged(aCalendar)
{
return;
},
onGetResult: function onGetResult(aCalendar, aStatus, aItemType, aDetail, aCount, aItems)
{
if (!Components.isSuccessCode(aStatus)) {
Components.utils.reportError(
"Failed to fetch todo items: 0x" +
aStatus.toString(16));
return;
}
aItems.forEach(this.todoList.addTodo, this.todoList);
},
onOperationComplete: function onOperationComplete(aCalendar, aStatus, aOperationType, aId,
aDetail)
{
if (!Components.isSuccessCode(aStatus))
Components.utils.reportError("Failed to fetch todo item"
+ "(" + aId + "): 0x" +
aStatus.toString(16));
},
QueryInterface: function QueryInterface(aIID) {
if (!aIID.equals(Components.interfaces.calIObserver) &&
!aIID.equals(Components.interfaces.calICompositeObserver) &&
!aIID.equals(Components.interfaces.calIOperationListener) &&
!aIID.equals(Components.interfaces.nsISupports)) {
throw Components.results.NS_ERROR_NO_INTERFACE;
}
return this;
}
})
]]></field>
<property name="calendar">
<getter><![CDATA[ return this.mCalendar; ]]></getter>
<setter><![CDATA[
if (this.mCalendar)
this.mCalendar.removeObserver(this.mOperationListener);
this.mCalendar = val;
if (this.mCalendar)
this.mCalendar.addObserver(this.mOperationListener);
this.rebuildDisplay();
return val;
]]></setter>
</property>
<property name="showCompleted">
<getter><![CDATA[ return this.mShowCompleted; ]]></getter>
<setter><![CDATA[
this.mShowCompleted = val;
this.rebuildDisplay();
]]></setter>
</property>
<method name="fireEvent">
<parameter name="aEventType"/>
<body><![CDATA[
var e = document.createEvent("Events");
e.initEvent("todo-" + aEventType, true, true);
this.dispatchEvent(e);
]]></body>
</method>
<method name="addTodo">
<parameter name="aTodo"/>
<body><![CDATA[
for (var i=0; i < this.childNodes.length; i++) {
var elem = this.childNodes[i];
if (elem.todo.hasSameIds(aTodo)) {
return;
}
}
void("adding new todo " + aTodo.title + "\n");
var newTodoElt = document.createElement("calendar-todo-item");
newTodoElt.setAttribute("item-calendar", aTodo.calendar.uri.spec);
this.appendChild(newTodoElt);
newTodoElt.todo = aTodo;
]]></body>
</method>
<method name="removeTodo">
<parameter name="aTodo"/>
<body><![CDATA[
// don't use for each, because the 'in' operator will return
// other properties of childNodes as well, which don't have .todo
for (var i=0; i < this.childNodes.length; i++) {
var elem = this.childNodes[i];
if (elem.todo.hasSameIds(aTodo)) {
this.removeChild(elem);
}
}
]]></body>
</method>
<method name="fetchTodos">
<body><![CDATA[
if (!this.mCalendar)
return;
const cIC = Components.interfaces.calICalendar;
var filter = cIC.ITEM_FILTER_TYPE_TODO;
if (this.mShowCompleted) {
filter |= cIC.ITEM_FILTER_COMPLETED_ALL;
} else {
filter |= cIC.ITEM_FILTER_COMPLETED_NO;
}
this.mCalendar.getItems(filter, 0, null, null, this.mOperationListener);
]]></body>
</method>
<method name="rebuildDisplay">
<body><![CDATA[
while (this.firstChild)
this.removeChild(this.firstChild);
this.fetchTodos();
]]></body>
</method>
</implementation>
<handlers>
<handler event="dblclick"><![CDATA[
if (this.selectedItem)
this.fireEvent("item-open");
else
this.fireEvent("empty-dblclick");
]]></handler>
<handler event="keypress"><![CDATA[
const kKE = Components.interfaces.nsIDOMKeyEvent;
if (event.keyCode == kKE.DOM_VK_RETURN ||
event.keyCode == kKE.DOM_VK_ENTER) {
event.stopPropagation();
this.fireEvent("item-open");
} else if (event.keyCode == kKE.DOM_VK_BACK_SPACE ||
event.keyCode == kKE.DOM_VK_DELETE) {
event.stopPropagation();
this.fireEvent("item-delete");
} else if (event.keyCode == kKE.DOM_VK_SPACE) {
var selected = this.selectedItem;
selected.checkbox.checked = !this.checkbox.checked;
selected.updateTodoFromDisplay();
}
]]></handler>
</handlers>
</binding>
<binding id="calendar-todo-item" extends="chrome://global/content/bindings/richlistbox.xml#richlistitem">
<content>
<xul:hbox align="center" flex="1">
<xul:checkbox class="calendar-todo-item-checkbox" anonid="todo-check" xbl:inherits="checked=completed" oncommand="document.getBindingParent(this).updateTodoFromDisplay();"/>
<xul:label class="calendar-todo-item-label" anonid="todo-label" crop="end" xbl:inherits="item-calendar,value=label"/>
</xul:hbox>
</content>
<implementation>
<field name="mTodo">null</field>
<property name="checkbox">
<getter><![CDATA[ return document.getAnonymousElementByAttribute(this, "anonid", "todo-check");]]></getter>
</property>
<property name="manager">
<getter><![CDATA[ return this.mManager; ]]></getter>
<setter><![CDATA[ this.mManager = val; return val; ]]></setter>
</property>
<property name="label">
<getter><![CDATA[ return document.getAnonymousElementByAttribute(this, "anonid", "todo-label");]]></getter>
</property>
<property name="todo" onget="return this.mTodo;"
onset="this.mTodo = val; this.updateDisplayFromTodo();"/>
<method name="setAttribute">
<parameter name="aAttr"/>
<parameter name="aVal"/>
<body><![CDATA[
if (aAttr == "completed")
this.checkbox.setAttribute("checked", aVal);
else if (aAttr == "label")
this.label.setAttribute("value", aVal);
return XULElement.prototype.setAttribute.call(this, aAttr, aVal);
]]></body>
</method>
<method name="updateTodoFromDisplay">
<body><![CDATA[
var dirty = false;
var clone = this.mTodo.clone();
if (this.mTodo.isCompleted != this.checkbox.checked) {
clone.isCompleted = this.checkbox.checked;
dirty = true;
}
if (this.mTodo.title != this.label.value) {
clone.title = this.label.value;
dirty = true;
}
if (dirty) {
this.mTodo.calendar.modifyItem(clone, this.mTodo, null);
// dump(clone.icalComponent.serializeToICS() + "\n");
this.mTodo = clone;
}
]]></body>
</method>
<method name="updateDisplayFromTodo">
<body><![CDATA[
this.setAttribute("completed", this.mTodo.isCompleted);
this.setAttribute("label", this.mTodo.title);
]]></body>
</method>
</implementation>
</binding>
</bindings>