diff --git a/mozilla/calendar/base/content/calendar-month-view.xml b/mozilla/calendar/base/content/calendar-month-view.xml index 626c252d4e5..deeb51db063 100644 --- a/mozilla/calendar/base/content/calendar-month-view.xml +++ b/mozilla/calendar/base/content/calendar-month-view.xml @@ -1134,13 +1134,20 @@ aEndDate = aEndDate.getInTimezone(this.mTimezone); } - this.mStartDate = aStartDate.startOfWeek; - this.mEndDate = aEndDate.endOfWeek; + var startDate = aStartDate.startOfWeek; + var endDate = aEndDate.endOfWeek; + startDate.day += this.mWeekStartOffset; + endDate.day += this.mWeekStartOffset; - this.mStartDate.day += this.mWeekStartOffset; - this.mEndDate.day += this.mWeekStartOffset; + if (!this.mStartDate || !this.mEndDate || + this.mStartDate.compare(startDate) != 0 || + this.mEndDate.compare(endDate) != 0) { + // Only refresh if the date range actually changed. + this.mStartDate = startDate; + this.mEndDate = endDate; - this.refresh(); + this.refresh(); + } ]]> diff --git a/mozilla/calendar/base/content/calendar-multiday-view.xml b/mozilla/calendar/base/content/calendar-multiday-view.xml index 982f4fdd31d..bd9ba3e1402 100644 --- a/mozilla/calendar/base/content/calendar-multiday-view.xml +++ b/mozilla/calendar/base/content/calendar-multiday-view.xml @@ -2788,6 +2788,13 @@ // make sure unnormalized version not used below aStartDate = aEndDate = null; + if (this.mStartDate && this.mEndDate && + this.mStartDate.compare(startDate) == 0 && + this.mEndDate.compare(endDate) == 0) { + // Do not change anything if the date range already matches. + return; + } + if (this.mDisplayDaysOff) { startDate.makeImmutable(); endDate.makeImmutable(); diff --git a/mozilla/calendar/base/content/calendar-task-tree.xml b/mozilla/calendar/base/content/calendar-task-tree.xml index 79c698adab9..24cc15e9fa7 100644 --- a/mozilla/calendar/base/content/calendar-task-tree.xml +++ b/mozilla/calendar/base/content/calendar-task-tree.xml @@ -148,6 +148,10 @@ var tasks = []; var start = {}; var end = {}; + if (!this.mTreeView.selection) { + return tasks; + } + var rangeCount = this.mTreeView.selection.getRangeCount(); for (var range = 0; range < rangeCount; range++) { this.mTreeView.selection.getRangeAt(range, start, end); diff --git a/mozilla/calendar/base/content/calendar-unifinder.js b/mozilla/calendar/base/content/calendar-unifinder.js index 907e3460f70..50dd841f553 100644 --- a/mozilla/calendar/base/content/calendar-unifinder.js +++ b/mozilla/calendar/base/content/calendar-unifinder.js @@ -58,73 +58,26 @@ var kEventStatusOrder = ["TENTATIVE", "CONFIRMED", "CANCELLED"]; // multiple selection var gCalendarEventTreeClicked = false; -var gEventArray = new Array(); - // Store the start and enddate, because the providers can't be trusted when // dealing with all-day events. So we need to filter later. See bug 306157 var gStartDate; var gEndDate; var kDefaultTimezone; -var doingSelection = false; var gUnifinderNeedsRefresh = true; -function resetAllowSelection() { - /** - * Do not change anything in the following lines, they are needed as - * described in the selection observer above - */ - doingSelection = false; - - var searchTree = document.getElementById("unifinder-search-results-tree"); - searchTree.view.selection.selectEventsSuppressed = false; - searchTree.addEventListener("select", unifinderOnSelect, true); -} - function isUnifinderHidden() { return document.getElementById("bottom-events-box").hidden; } -function selectSelectedEventsInTree(aEventsToSelect) { - if (doingSelection === true || isUnifinderHidden()) { - return; - } - - doingSelection = true; - - if (aEventsToSelect === false) { - aEventsToSelect = currentView().getSelectedItems({}); - } - var searchTree = document.getElementById("unifinder-search-results-tree"); - - /** - * The following is a brutal hack, caused by - * http://lxr.mozilla.org/mozilla1.0/source/layout/xul/base/src/tree/src/nsTreeSelection.cpp#555 - * and described in bug 168211 - * http://bugzilla.mozilla.org/show_bug.cgi?id=168211 - * Do NOT remove anything in the next 3 lines, or the selection in the tree will not work. - */ - searchTree.onselect = null; - searchTree.removeEventListener("select", unifinderOnSelect, true); - searchTree.view.selection.selectEventsSuppressed = true; - searchTree.view.selection.clearSelection(); - - if (aEventsToSelect && aEventsToSelect.length == 1) { - var rowToScrollTo = searchTree.eventView.getRowOfCalendarEvent(aEventsToSelect[0]); - - if (rowToScrollTo != "null") { - searchTree.treeBoxObject.ensureRowIsVisible(rowToScrollTo); - searchTree.view.selection.timedSelect(rowToScrollTo, 1); - } - } else if (aEventsToSelect && aEventsToSelect.length > 1) { - for (var i in aEventsToSelect) { - var row = searchTree.eventView.getRowOfCalendarEvent(aEventsToSelect[i]); - searchTree.view.selection.rangedSelect(row, row, true); - } - } - - // This needs to be in a setTimeout - setTimeout("resetAllowSelection()", 1); +// Extra check to see if the events are in the daterange. Some providers +// are broken when looking at all-day events. +function fixAlldayDates(aItem) { + // Using .compare on the views start and end, not on the events dates, + // because .compare uses the timezone of the datetime it is called on. + // The view's timezone is what is important here. + return ((!gEndDate || gEndDate.compare(aItem.startDate) >= 0) && + (!gStartDate || gStartDate.compare(aItem.endDate) < 0)); } /** @@ -161,12 +114,8 @@ var unifinderObserver = { // produce invalid entries in the unifinder. From now on, ignore // those operations and refresh as soon as the unifinder is shown // again. - var unifinderTree = document.getElementById("unifinder-search-results-tree"); - gUnifinderNeedsRefresh = true; - gEventArray = []; - unifinderTree.view = unifinderTreeView; - unifinderTree.eventView = new calendarEventView(gEventArray); + unifinderTreeView.clearEvents(); } if (!this.mInBatch) { refreshEventTree(); @@ -174,38 +123,20 @@ var unifinderObserver = { }, onAddItem: function uO_onAddItem(aItem) { - if (!(aItem instanceof Components.interfaces.calIEvent) || - this.mInBatch || - gUnifinderNeedsRefresh) { - return; + if (isEvent(aItem) && !this.mInBatch && !gUnifinderNeedsRefresh) { + this.addItemToTree(aItem); } - this.addItemToTree(aItem); }, onModifyItem: function uO_onModifyItem(aNewItem, aOldItem) { - if (this.mInBatch || gUnifinderNeedsRefresh) { - return; - } - if (aOldItem instanceof Components.interfaces.calIEvent) { - this.removeItemFromTree(aOldItem); - } - if (aNewItem instanceof Components.interfaces.calIEvent) { - this.addItemToTree(aNewItem); - } + this.onDeleteItem(aOldItem); + this.onAddItem(aNewItem); }, onDeleteItem: function uO_onDeleteItem(aDeletedItem) { - if (!(aDeletedItem instanceof Components.interfaces.calIEvent) || - this.mInBatch || - gUnifinderNeedsRefresh) { - return; + if (isEvent(aDeletedItem) && !this.mInBatch && !gUnifinderNeedsRefresh) { + this.removeItemFromTree(aDeletedItem); } - this.removeItemFromTree(aDeletedItem); - }, - - dateFilter: function uO_dateFilter(event) { - return ((!gEndDate || gEndDate.compare(event.startDate) >= 0) && - (!gStartDate || gStartDate.compare(event.endDate) < 0)); }, // It is safe to call these for any event. The functions will determine @@ -217,14 +148,7 @@ var unifinderObserver = { } else { items = [aItem]; } - items = items.filter(this.dateFilter); - gEventArray = gEventArray.concat(items); - unifinderTreeView.sortCalendarEvents(); - var tree = document.getElementById("unifinder-search-results-tree"); - for each (var item in items) { - var row = tree.eventView.getRowOfCalendarEvent(item); - tree.treeBoxObject.rowCountChanged(row, 1); - } + unifinderTreeView.addItems(items.filter(fixAlldayDates)); }, removeItemFromTree: function uO_removeItemFromTree(aItem) { var items; @@ -233,13 +157,7 @@ var unifinderObserver = { } else { items = [aItem]; } - items = items.filter(this.dateFilter); - var tree = document.getElementById("unifinder-search-results-tree"); - for each (var item in items) { - var row = tree.eventView.getRowOfCalendarEvent(item); - gEventArray.splice(row, 1); - tree.treeBoxObject.rowCountChanged(row, -1); - } + unifinderTreeView.removeItems(items.filter(fixAlldayDates)); }, onError: function uO_onError(aErrNo, aMessage) {}, @@ -267,9 +185,11 @@ var unifinderObserver = { * Called when the calendar is loaded */ function prepareCalendarUnifinder() { - function onGridSelect(aEvent) { - selectSelectedEventsInTree(aEvent.detail); - } + // Only load once + window.removeEventListener("load", prepareCalendarUnifinder, false); + + LOG("PREPARE UNIFINDER " + STACK()); + var unifinderTree = document.getElementById("unifinder-search-results-tree"); // set up our calendar event observer var ccalendar = getCompositeCalendar(); @@ -277,13 +197,17 @@ function prepareCalendarUnifinder() { kDefaultTimezone = calendarDefaultTimezone(); + // Set up the unifinder views. + unifinderTreeView.treeElement = unifinderTree; + unifinderTree.view = unifinderTreeView; + // Listen for changes in the selected day, so we can update if need be var viewDeck = getViewDeck(); if (viewDeck) { - viewDeck.addEventListener("dayselect", unifinderOnDaySelect, false); - viewDeck.addEventListener("itemselect", onGridSelect, true); + viewDeck.addEventListener("dayselect", unifinderDaySelect, false); + viewDeck.addEventListener("itemselect", unifinderItemSelect, true); } - + // Display something upon first load. onLoad doesn't work properly for // observers if (!isUnifinderHidden()) { @@ -296,17 +220,30 @@ function prepareCalendarUnifinder() { * Called when the calendar is unloaded */ function finishCalendarUnifinder() { - var ccalendar = getCompositeCalendar(); - ccalendar.removeObserver(unifinderObserver); + var ccalendar = getCompositeCalendar(); + ccalendar.removeObserver(unifinderObserver); + + var viewDeck = getViewDeck(); + if (viewDeck) { + viewDeck.removeEventListener("dayselect", unifinderDaySelect, false); + viewDeck.removeEventListener("itemselect", unifinderItemSelect, true); + } } -function unifinderOnDaySelect() { +/** + * Event listeners for dayselect and itemselect events + */ +function unifinderDaySelect() { var filterList = document.getElementById("event-filter-menulist"); if (filterList.selectedItem.value == "current") { refreshEventTree(); } } +function unifinderItemSelect(aEvent) { + unifinderTreeView.setSelectedItems(aEvent.detail); +} + /** * Helper function to display event datetimes in the unifinder */ @@ -316,83 +253,6 @@ function formatUnifinderEventDateTime(aDatetime) { return dateFormatter.formatDateTime(aDatetime.getInTimezone(kDefaultTimezone)); } -/** - * This is attached to the ondblclik attribute of the events shown in the - * unifinder - */ -function unifinderDoubleClickEvent(event) { - // we only care about button 0 (left click) events - if (event.button != 0) return; - - // find event by id - var calendarEvent = getCalendarEventFromEvent(event); - - if (calendarEvent != null) { - modifyEventWithDialog(getOccurrenceOrParent(calendarEvent)); - } else { - createEventWithDialog(); - } -} - -/** - * Get the calendar from the given event - */ -function getCalendarEventFromEvent(event) { - var tree = document.getElementById("unifinder-search-results-tree"); - var row = tree.treeBoxObject.getRowAt(event.clientX, event.clientY); - - if (row != -1 && row < tree.view.rowCount) { - return tree.eventView.getCalendarEventAtRow(row); - } else { - return null; - } -} - -/** -* This is attached to the onclik attribute of the events shown in the unifinder -*/ -function unifinderOnSelect(event) { - if (event.target.view.selection.getRangeCount() == 0) { - return; - } - - var arrayOfEvents = new Array(); - - gCalendarEventTreeClicked = true; - - var calendarEvent; - - // Get the selected events from the tree - var tree = document.getElementById("unifinder-search-results-tree"); - var start = new Object(); - var end = new Object(); - var numRanges = tree.view.selection.getRangeCount(); - - for (var t = 0; t < numRanges; t++){ - tree.view.selection.getRangeAt(t, start, end); - - for (var v = start.value; v <= end.value; v++){ - try { - calendarEvent = tree.eventView.getCalendarEventAtRow(v); - } catch (e) { - dump("Error getting Event from row: " + e + "\n"); - return; - } - if (calendarEvent) { - arrayOfEvents.push(calendarEvent); - } - } - } - - if (arrayOfEvents.length == 1) { - currentView().goToDay(arrayOfEvents[0].startDate); - } - - // Pass in true, so we don't end up in a circular loop - currentView().setSelectedItems(arrayOfEvents.length, arrayOfEvents, true); - onSelectionChanged({detail: arrayOfEvents}); -} - /** * This is called from the unifinder when a key is pressed in the search field */ @@ -421,30 +281,262 @@ function clearSearchTimer() { } /** - * This function returns the event table. + * Unifinder event handlers (click,select,etc) */ -function changeEventFilter(event) { - refreshEventTree(); +function unifinderDoubleClick(event) { + // We only care about button 0 (left click) events + if (event.button != 0) { + return; + } - // The following isn't exactly right. It should actually reload after the - // next event happens. + // find event by id + var calendarEvent = unifinderTreeView.getItemFromEvent(event); - // get the current time - var now = new Date(); + if (calendarEvent != null) { + modifyEventWithDialog(getOccurrenceOrParent(calendarEvent)); + } else { + createEventWithDialog(); + } +} - var tomorrow = new Date(now.getFullYear(), now.getMonth(), (now.getDate() + 1)); +function unifinderSelect(event) { + var tree = unifinderTreeView.treeElement; + if (!tree.view.selection || tree.view.selection.getRangeCount() == 0) { + return; + } - var milliSecsTillTomorrow = tomorrow.getTime() - now.getTime(); + var selectedItems = []; + gCalendarEventTreeClicked = true; - setTimeout("refreshEventTree()", milliSecsTillTomorrow); + // Get the selected events from the tree + var start = {}; + var end = {}; + var numRanges = tree.view.selection.getRangeCount(); + + for (var t = 0; t < numRanges; t++) { + tree.view.selection.getRangeAt(t, start, end); + + for (var v = start.value; v <= end.value; v++) { + try { + selectedItems.push(unifinderTreeView.getItemAt(v)); + } catch (e) { + WARN("Error getting Event from row: " + e + "\n"); + } + } + } + + if (selectedItems.length == 1) { + // Go to the day of the selected item in the current view. + currentView().goToDay(selectedItems[0].startDate); + } + + // Set up the selected items in the view. Pass in true, so we don't end + // up in a circular loop + currentView().setSelectedItems(selectedItems.length, selectedItems, true); + onSelectionChanged({detail: selectedItems}); +} + +function unifinderKeyPress(aEvent) { + const kKE = Components.interfaces.nsIDOMKeyEvent; + switch (aEvent.keyCode) { + case 13: + // Enter, edit the event + editSelectedEvents(); + break; + case kKE.DOM_VK_BACK_SPACE: + case kKE.DOM_VK_DELETE: + deleteSelectedEvents(); + break; + } } /** -* Redraw the categories unifinder tree -*/ + * Tree controller for unifinder search results + */ var unifinderTreeView = { - get rowCount() { - return gEventArray.length; + + tree: null, + treeElement: null, + doingSelection: false, + + /** + * Event functions + */ + + eventArray: [], + eventIndexMap: {}, + + addItems: function uTV_addItems(aItemArray, aDontSort) { + this.eventArray = this.eventArray.concat(aItemArray); + this.tree.rowCountChanged(this.eventArray.length - aItemArray.length, + aItemArray.length); + if (!aDontSort) { + this.sortItems(); + } + }, + + removeItems: function uTV_removeItems(aItemArray) { + for each (var item in aItemArray) { + var row = this.getItemRow(item); + this.eventArray = this.eventArray.splice(row, 1); + this.tree.rowCountChanged(row, -1); + } + }, + + clearItems: function uTV_clearItems() { + this.eventArray = []; + this.tree.invalidate(); + }, + + setItems: function uTV_setItems(aItemArray, aDontSort) { + this.eventArray = aItemArray.splice(0); + if (aDontSort) { + this.tree.invalidate(); + } else { + this.sortItems(); + } + }, + + sortItems: function uTV_sortItems() { + // Get a current locale string collator for compareEvents + var localeService = + Components + .classes["@mozilla.org/intl/nslocaleservice;1"] + .getService(Components.interfaces.nsILocaleService); + this.localeCollator = + Components + .classes["@mozilla.org/intl/collation-factory;1"] + .getService(Components.interfaces.nsICollationFactory) + .CreateCollation(localeService.getApplicationLocale()); + + // cache sort keys, used by compareEvents + this.sortKeyByEvent_cache = new Object(); + for (var i in this.eventArray) { + var sortEvent = this.eventArray[i]; + this.sortKeyByEvent_cache_put(sortEvent, getEventSortKey(sortEvent)); + } + + this.sortStartedTime = new Date().getTime(); // for null/0 dates in sort + this.eventArray.sort(compareEvents); + + // Set up eventIndexMap + this.eventIndexMap = {}; + for (var i = 0 ; i < this.eventArray.length; i++) { + this.eventIndexMap[this.eventArray[i].hashId] = i; + } + + this.sortKeyByEvent_cache = null; + + // Setting the view again refreshes the tree + this.treeElement.view = unifinderTreeView; + }, + + getItemRow: function uTV_getItemRow(item) { + return this.eventIndexMap[item.hashId]; + }, + + getItemAt: function uTV_getItemAt(aRow) { + return this.eventArray[aRow]; + }, + + /** + * Get the calendar item from the given event + */ + getItemFromEvent: function uTV_getItemFromEvent(event) { + var row = this.tree.getRowAt(event.clientX, event.clientY); + + if (row > -1) { + return this.getItemAt(row); + } + return null; + }, + + setSelectedItems: function uTV_setSelectedItems(aItemArray) { + if (this.doingSelection) { + return; + } + + this.doingSelection = true; + + // If no items were passed, get the selected items from the view. + aItemArray = aItemArray || currentView().getSelectedItems({}); + + /** + * The following is a brutal hack, caused by + * http://lxr.mozilla.org/mozilla1.0/source/layout/xul/base/src/tree/src/nsTreeSelection.cpp#555 + * and described in bug 168211 + * http://bugzilla.mozilla.org/show_bug.cgi?id=168211 + * Do NOT remove anything in the next 3 lines, or the selection in the tree will not work. + */ + this.treeElement.onselect = null; + this.treeElement.removeEventListener("select", unifinderSelect, true); + this.tree.view.selection.selectEventsSuppressed = true; + this.tree.view.selection.clearSelection(); + + if (aItemArray && aItemArray.length == 1) { + // If only one item is selected, scroll to it + var rowToScrollTo = this.getItemRow(aItemArray[0]); + if (rowToScrollTo > -1) { + this.tree.ensureRowIsVisible(rowToScrollTo); + this.tree.view.selection.timedSelect(rowToScrollTo, 1); + } + } else if (aItemArray && aItemArray.length > 1) { + // If there is more than one item, just select them all. + for (var i in aItemArray) { + var row = this.getItemRow(aItemArray[i]); + this.tree.view.selection.rangedSelect(row, row, true); + } + } + + // This needs to be in a setTimeout + setTimeout("unifinderTreeView.resetAllowSelection()", 1); + }, + + resetAllowSelection: function uTV_resetAllowSelection() { + /** + * Do not change anything in the following lines, they are needed as + * described in the selection observer above + */ + this.doingSelection = false; + + this.tree.view.selection.selectEventsSuppressed = false; + this.treeElement.addEventListener("select", unifinderSelect, true); + }, + + /** + * Tree View Implementation + */ + get rowCount uTV_getRowCount() { + return this.eventArray.length; + }, + + /* event is a calendar event. value is sortKey, a string or number */ + sortKeyByEvent_cache_put : function uTV_cache_put( calEvent, value ) { + var earlierValues = this.sortKeyByEvent_cache[calEvent.id]; + if (earlierValues == null && value != null) { + // common entry is just the value + this.sortKeyByEvent_cache[calEvent.id] = value; + } else { + // null key or rare dup id: link event & value to earlier value(s) + // id may be duplicated if event is in more than one calendar file. + var entry = new Object(); + entry.isSortKeyByEventCacheEntry = true; + entry.event = calEvent; + entry.value = value; + entry.rest = earlierValues; + this.sortKeyByEvent_cache[calEvent.id] = entry; + } + }, + + sortKeyByEvent_cache_get : function uTV_cache_get( calEvent ) { + var entry = this.sortKeyByEvent_cache[calEvent.id]; + while (typeof(entry) == "object" && + "isSortKeyByEventCacheEntry" in entry) { + if (entry.event === calEvent) //pointer identity + return entry.value; + entry = entry.rest; + } + return entry; // only or last entry is first value put }, selectedColumn: null, @@ -484,72 +576,15 @@ var unifinderTreeView = { col.element.setAttribute("sortActive", "true"); col.element.setAttribute("sortDirection", this.sortDirection); - this.sortCalendarEvents(); + this.sortItems(); document.getElementById("unifinder-search-results-tree").view = this; }, - sortCalendarEvents : function uTV_sortCalendarEvents() - { - // get a current locale string collator for compareEvents - var localeService = - Components - .classes["@mozilla.org/intl/nslocaleservice;1"] - .getService(Components.interfaces.nsILocaleService); - this.localeCollator = - Components - .classes["@mozilla.org/intl/collation-factory;1"] - .getService(Components.interfaces.nsICollationFactory) - .CreateCollation(localeService.getApplicationLocale()); - - // cache sort keys, used by compareEvents - this.sortKeyByEvent_cache = new Object(); - for (var i in gEventArray) { - var sortEvent = gEventArray[i]; - this.sortKeyByEvent_cache_put(sortEvent, getEventSortKey(sortEvent)); - } - - this.sortStartedTime = new Date().getTime(); // for null/0 dates in sort - gEventArray.sort(compareEvents); - - this.sortKeyByEvent_cache = null; - }, - - /* event is a calendar event. value is sortKey, a string or number */ - sortKeyByEvent_cache_put : function uTV_cache_put( calEvent, value ) - { - var earlierValues = this.sortKeyByEvent_cache[calEvent.id]; - if (earlierValues == null && value != null) { - // common entry is just the value - this.sortKeyByEvent_cache[calEvent.id] = value; - } else { - // null key or rare dup id: link event & value to earlier value(s) - // id may be duplicated if event is in more than one calendar file. - var entry = new Object(); - entry.isSortKeyByEventCacheEntry = true; - entry.event = calEvent; - entry.value = value; - entry.rest = earlierValues; - this.sortKeyByEvent_cache[calEvent.id] = entry; - } - }, - - sortKeyByEvent_cache_get : function uTV_cache_get( calEvent ) - { - var entry = this.sortKeyByEvent_cache[calEvent.id]; - while (typeof(entry) == "object" && - "isSortKeyByEventCacheEntry" in entry) { - if (entry.event === calEvent) //pointer identity - return entry.value; - entry = entry.rest; - } - return entry; // only or last entry is first value put - }, - setTree: function uTV_setTree(tree) { this.tree = tree; }, getCellText: function uTV_getCellText(row, column) { - calendarEvent = gEventArray[row]; + calendarEvent = this.eventArray[row]; switch (column.id) { case "unifinder-search-results-tree-col-title": @@ -614,11 +649,10 @@ function getEventSortKey(calEvent) { } } -function compareEvents( calEventA, calEventB ) -{ - var modifier = (unifinderTreeView.sortDirection == "descending"? -1 : 1); - - switch(unifinderTreeView.selectedColumn) { +function compareEvents(calEventA, calEventB) { + var modifier = (unifinderTreeView.sortDirection == "descending" ? -1 : 1); + + switch (unifinderTreeView.selectedColumn) { case "unifinder-search-results-tree-col-startdate": case "unifinder-search-results-tree-col-enddate": var msA = unifinderTreeView.sortKeyByEvent_cache_get(calEventA); @@ -639,12 +673,12 @@ function compareEvents( calEventA, calEventB ) return -(strA.length - strB.length) * modifier; } var comparison = - unifinderTreeView.localeCollator.compareString(0, strA, strB); + unifinderTreeView.localeCollator.compareString(0, strA, strB); return comparison * modifier; - + default: return 0; - } + } } function compareMSTime(a, b) { @@ -689,30 +723,6 @@ function dateToMilliseconds(date) { return ms; } -function calendarEventView(eventArray) { - this.eventArray = eventArray; -} - -calendarEventView.prototype = { - eventArray: null, - - getCalendarEventAtRow: function(i) { - return gEventArray[i]; - }, - - getRowOfCalendarEvent: function(event) { - if (!event) { - return null; - } - for (var i in gEventArray) { - if (gEventArray[i].hashId == event.hashId) { - return i; - } - } - return null; - } -}; - function refreshEventTree() { if (isUnifinderHidden()) { // If the unifinder is hidden, don't refresh the events to reduce needed @@ -816,79 +826,44 @@ function refreshEventTree() { if (StartDate && EndDate) { filter |= ccalendar.ITEM_FILTER_CLASS_OCCURRENCES; } + + LOG("GETITEMS FOR UNIFINDER " + STACK()); ccalendar.getItems(filter, 0, gStartDate, gEndDate, refreshListener); } function refreshEventTreeInternal(eventArray) { var searchText = document.getElementById("unifinder-search-field").value; + var unifinderTree = document.getElementById("unifinder-search-results-tree"); searchText = searchText.toLowerCase(); - // XXX match for strings with only whitespace. Skip those too - if (searchText.length) { - gEventArray = new Array(); - var fieldsToSearch = ["DESCRIPTION", "LOCATION", "CATEGORIES", "URL"]; + if (searchText.length && !searchText.match(/^\s*$/)) { + unifinderTreeView.clearItems(); + const fieldsToSearch = ["SUMMARY", "DESCRIPTION", "LOCATION", "CATEGORIES", "URL"]; for (var j in eventArray) { - var event = eventArray[j]; - if (event.title && - event.title.toLowerCase().indexOf(searchText) != -1) { - gEventArray.push(event); - } else { - for (var k in fieldsToSearch) { - var val = event.getProperty(fieldsToSearch[k]); - if (val && val.toLowerCase().indexOf(searchText) != -1) { - gEventArray.push(event); - break; - } + var item = eventArray[j]; + if (!fixAlldayDates(item)) { + continue; + } + + for each (var field in fieldsToSearch) { + var val = event.getProperty(fieldsToSearch[field]); + if (val && val.toLowerCase().indexOf(searchText) != -1) { + unifinderTreeView.addItems([event], true); + break; } } } + + // Finally, sort the items since it was suppressed above + unifinderTreeView.sortItems(); } else { - gEventArray = eventArray; + unifinderTreeView.setItems(eventArray.filter(fixAlldayDates)); } - // Extra check to see if the events are in the daterange. Some providers - // are broken when looking at all-day events. - function dateFilter(event) { - // Using .compare on the views start and end, not on the events dates, - // because .compare uses the timezone of the datetime it is called on. - // The view's timezone is what is important here. - return ((!gEndDate || gEndDate.compare(event.startDate) >= 0) && - (!gStartDate || gStartDate.compare(event.endDate) < 0)); - } - gEventArray = gEventArray.filter(dateFilter); - - var unifinderTree = document.getElementById("unifinder-search-results-tree"); - var arrayOfTreeCols = unifinderTree.getElementsByTagName("treecol"); - - for (var i = 0; i < arrayOfTreeCols.length; i++) { - if (arrayOfTreeCols[i].getAttribute("sortActive") == "true") { - unifinderTreeView.selectedColumn = arrayOfTreeCols[i].getAttribute("id"); - unifinderTreeView.sortDirection = arrayOfTreeCols[i].getAttribute("sortDirection"); - unifinderTreeView.sortCalendarEvents(); - break; - } - } - - unifinderTree.view = unifinderTreeView; - unifinderTree.eventView = new calendarEventView(gEventArray); - - // Select selected events in the tree. - selectSelectedEventsInTree(false); -} - -function unifinderKeyPress(aEvent) { - const kKE = Components.interfaces.nsIDOMKeyEvent; - switch (aEvent.keyCode) { - case 13: - // Enter, edit the event - editSelectedEvents(); - break; - case kKE.DOM_VK_BACK_SPACE: - case kKE.DOM_VK_DELETE: - deleteSelectedEvents(); - break; - } + // Select selected events in the tree. Not passing the argument gets the + // items from the view. + unifinderTreeView.setSelectedItems(); } function focusSearch() { diff --git a/mozilla/calendar/base/content/calendar-unifinder.xul b/mozilla/calendar/base/content/calendar-unifinder.xul index 71e1af6c51b..99ddf66b37e 100644 --- a/mozilla/calendar/base/content/calendar-unifinder.xul +++ b/mozilla/calendar/base/content/calendar-unifinder.xul @@ -61,7 +61,7 @@ - + @@ -96,7 +96,7 @@ @@ -142,7 +142,7 @@ diff --git a/mozilla/calendar/lightning/content/messenger-overlay-sidebar.js b/mozilla/calendar/lightning/content/messenger-overlay-sidebar.js index 8547d02b74a..b1d1b2f57c3 100644 --- a/mozilla/calendar/lightning/content/messenger-overlay-sidebar.js +++ b/mozilla/calendar/lightning/content/messenger-overlay-sidebar.js @@ -306,6 +306,10 @@ function refreshUIBits() { if (TodayPane.showsYesterday()) { TodayPane.setDay(now()); } + + // update the unifinder + refreshEventTree(); + // schedule our next update... scheduleMidnightUpdate(refreshUIBits); } diff --git a/mozilla/calendar/resources/content/calendar.js b/mozilla/calendar/resources/content/calendar.js index 13d0df13d8c..8426b12114a 100644 --- a/mozilla/calendar/resources/content/calendar.js +++ b/mozilla/calendar/resources/content/calendar.js @@ -82,7 +82,6 @@ function calendarInit() { currentView().goToDay(currentView().selectedDay); // set up the unifinder - prepareCalendarUnifinder(); prepareCalendarToDoUnifinder(); scheduleMidnightUpdate(refreshUIBits); @@ -214,12 +213,10 @@ function calendarFinish() var tabbox = document.getElementById("tablist"); tabbox.setAttribute("selectedIndex", tabbox.selectedIndex); - finishCalendarUnifinder(); - unloadCalendarManager(); - // Finish the offline manager - calendarOfflineManager.uninit(); + // Finish the offline manager + calendarOfflineManager.uninit(); } function closeCalendar() diff --git a/mozilla/calendar/resources/content/mouseoverPreviews.js b/mozilla/calendar/resources/content/mouseoverPreviews.js index 0f3d5e4aecd..b59cde37f2d 100644 --- a/mozilla/calendar/resources/content/mouseoverPreviews.js +++ b/mozilla/calendar/resources/content/mouseoverPreviews.js @@ -26,6 +26,7 @@ * Mike Norton * ArentJan Banck * Eric Belhaire + * Philipp Kewisch * * 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 @@ -82,7 +83,7 @@ function onMouseOverItem( occurrenceBoxMouseEvent ) /** For all instances of an event, as displayed by unifinder. **/ function onMouseOverEventTree( toolTip, mouseEvent ) { - var item = getCalendarEventFromEvent( mouseEvent ); + var item = unifinderTreeView.getItemFromEvent(mouseEvent); if (isEvent(item)) { var holderBox = getPreviewForEvent(item); if (holderBox) {