Todo list XBLification and key-binding improvements. More event-handling

goodness to come. r=desire-for-better-error-XBL-error-reporting.
This commit is contained in:
shaver%mozilla.org 2005-07-06 14:57:18 +00:00
parent bde71783c0
commit c5278fd003
6 changed files with 174 additions and 142 deletions

View File

@ -1,3 +1,7 @@
calendar-todo-list {
-moz-binding: url("calendar-todo-list.xml#calendar-todo-list");
}
calendar-todo-item {
-moz-binding: url("calendar-todo-list.xml#calendar-todo-item");
}

View File

@ -4,6 +4,145 @@
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>
<field name="mCalendar">null</field>
<field name="mOperationListener"><![CDATA[
({
todoList: this,
onAddItem: function onAddItem(aItem)
{
if (!(item instanceof Components.interfaces.calITodo))
return;
this.todoList.addTodo(aItem);
},
onDeleteItem: function onDeleteItem(aItem)
{
if (!(item instanceof Components.interfaces.calITodo))
return;
this.todoList.rebuildDisplay();
},
onModifyItem: function onModifyItem(aItem)
{
if (!(item instanceof Components.interfaces.calITodo))
return;
this.todoList.rebuildDisplay();
},
onCalendarAdded: function onCalendarAdded(aCalendar)
{
this.todoList.rebuildDisplay();
},
onCalendarRemoved: function onCalendarRemoved(aCalendar)
{
this.todoList.rebuildDisplay();
},
onGetResult: function onGetResult(aCalendar, aStatus, aItemType, aDetail, aCount, aItems)
{
if (!Components.isSuccessCode(aStatus))
return Components.util.reportError("Failed to fetch todo items: " + aStatus)
aItems.forEach(this.todoList.addTodo, this.todoList);
},
onOperationComplete: function onOperationComplete(aCalendar, aStatus, aOperationType, aId,
aDetail)
{
if (!Components.isSuccessCode(aStatus))
Components.util.reportError("Failed to fetch todo item (" +
aId + "): " + aStatus);
},
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();
]]></setter>
</property>
<method name="addTodo">
<parameter name="aTodo"/>
<body><![CDATA[
dump("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.setTodo(aTodo);
]]></body>
</method>
<method name="fetchTodos">
<body><![CDATA[
if (!this.mCalendar)
return;
const cIC = Components.interfaces.calICalendar;
var filter = cIC.ITEM_FILTER_TYPE_TODO | cIC.ITEM_FILTER_COMPLETED_ALL;
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[
dump("handling keypress " + event.keyCode + "\n");
const kKE = Components.interfaces.nsIDOMKeyEvent;
if (event.keyCode == kKE.DOM_VK_RETURN ||
event.keyCode == kKE.DOM_VK_ENTER) {
this.fireEvent("item-open");
} else if (event.keyCode == kKE.DOM_VK_BACK_SPACE ||
event.keyCode == kKE.DOM_VK_DELETE) {
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 flex="1">
@ -92,27 +231,5 @@
</method>
</implementation>
<handlers>
<handler event="dblclick"><![CDATA[
this.fireEvent("item-open");
]]>
</handler>
<handler event="keypress"><![CDATA[
dump("handling keypress " + event.keyCode + "\n");
const kKE = Components.interfaces.nsIDOMKeyEvent;
if (event.keyCode == 13) {
this.fireEvent("item-open");
} else if (event.keyCode == kKE.DOM_VK_BACK_SPACE ||
event.keyCode == kKE.DOM_VK_DELETE) {
this.fireEvent("item-delete");
} else if (event.keyCode == kKE.DOM_VK_SPACE) {
this.checkbox.checked = !this.checkbox.checked;
this.updateTodoFromDisplay();
}
]]>
</handler>
</handlers>
</binding>
</bindings>

View File

@ -7,7 +7,7 @@
<overlay xmlns="http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul">
<script type="application/x-javascript" src="chrome://lightning/content/todo-list.js"/>
<vbox id="todo-tab-panel">
<richlistbox flex="1" id="todo-outer-box"/>
<vbox id="todo-tab-panel" flex="1">
<calendar-todo-list id="calendar-todo-list" flex="1"/>
</vbox>
</overlay>

View File

@ -1,121 +1,7 @@
/* */
var todoListManager = {
mOuterBox: null
};
todoListManager.initialize =
function initialize()
{
this.mOuterBox = document.getElementById("todo-outer-box");
getCompositeCalendar().addObserver(this.calendarObserver);
this.populateTodoList();
};
todoListManager.rebuildList =
function rebuildList()
{
while (this.mOuterBox.firstChild)
this.mOuterBox.removeChild(this.mOuterBox.firstChild);
this.populateTodoList();
};
todoListManager.addTodo =
function addTodo(newTodo)
{
dump("adding new todo " + newTodo.title + "\n");
var newTodoElt = document.createElement("calendar-todo-item");
newTodoElt.setAttribute("item-calendar", newTodo.calendar.uri.spec);
this.mOuterBox.appendChild(newTodoElt);
newTodoElt.setTodo(newTodo);
};
todoListManager.calendarOpListener =
{
};
todoListManager.calendarOpListener.onOperationComplete =
function listener_onOperationComplete()
{
void("finished todo query!\n");
};
todoListManager.calendarOpListener.onGetResult =
function listener_onGetResult(calendar, status, itemtype, detail, count, items)
{
if (!Components.isSuccessCode(status))
return Components.reportError("get failed: " + status);
void("got " + count + " todos\n");
items.forEach(todoListManager.addTodo, todoListManager);
};
todoListManager.calendarObserver =
{
};
todoListManager.calendarObserver.QueryInterface =
function QueryInterface(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;
};
todoListManager.calendarObserver.onCalendarAdded =
todoListManager.calendarObserver.onCalendarRemoved =
function observer_onCalendarAddedOrRemoved(calendar)
{
todoListManager.rebuildList();
};
todoListManager.calendarObserver.onModifyItem =
function observer_onModifyItem(item)
{
if (!(item instanceof Components.interfaces.calITodo))
return;
todoListManager.rebuildList();
};
todoListManager.calendarObserver.onDeleteItem =
function observer_onDeleteItem(item)
{
if (!(item instanceof Components.interfaces.calITodo))
return;
todoListManager.rebuildList();
};
todoListManager.calendarObserver.onAddItem =
function observer_onAddItem(item)
{
if (!(item instanceof Components.interfaces.calITodo))
return;
todoListManager.addTodo(item);
};
todoListManager.populateTodoList =
function populateTodoList()
{
const cIC = Components.interfaces.calICalendar;
var filter = cIC.ITEM_FILTER_TYPE_TODO | cIC.ITEM_FILTER_COMPLETED_ALL;
getCompositeCalendar().getItems(filter, 0, null, null, this.calendarOpListener);
void("started todo query!\n");
};
function initializeTodoList()
{
todoListManager.initialize();
var todoList = document.getElementById("calendar-todo-list");
todoList.calendar = getCompositeCalendar();
}
window.addEventListener("load", initializeTodoList, false);

View File

@ -1,5 +1,14 @@
/* Skin-domain style rules for lightning UI (pinstripe version) */
calendar-todo-list {
background-color: -moz-Field;
color: -moz-FieldText;
}
calendar-todo-list[disabled="true"] {
color: GrayText;
}
calendar-todo-item {
-moz-box-align: center;
margin-top: 0;

View File

@ -1,7 +1,23 @@
/* Skin-domain style rules for lightning UI (winstripe version) */
#calendarTree {
background: #cccccc;
calendar-todo-list {
background-color: -moz-Field;
color: -moz-FieldText;
}
calendar-todo-list[disabled="true"] {
color: GrayText;
}
calendar-todo-item {
-moz-box-align: center;
margin-top: 0;
margin-bottom: 0;
}
calendar-todo-item[selected="true"] {
background-color: Highlight;
color: HighlightText;
}
treechildren::-moz-tree-cell(checked) {