Item.inCollection(collectionID) -- test if an item belongs to a given collection (currently uses a DB call--I'll optimize that later)

Scholar.Notifier framework to handle update notifications between data layer and interface

 - Notifier.registerColumnTree(ref) and Notifier.registerItemTree(ref) pass back a unique hash that can be used to unregister the tree later with unregister*(hash) (and must be, lest we leak treeViews and probably entire browser windows if the browser window is closed without unregistering the treeView)

 - Data layer calls Scholar.Notify.trigger(event, type, id) after various events (only two calls in the data layer at the moment--more coming later)

 - Notify.trigger() calls notify(event, type, id) on all registered trees of the appropriate type -- the data layer usually knows what collection the action pertains to, but we decided that it's cleaner to just let the tree decide what it wants to do rather than add all that logic into the data layer)

 (Note: Item collection adds appear to be buggy on the interface side, but removes seem to be working)
This commit is contained in:
Dan Stillman 2006-06-01 20:03:53 +00:00
parent 0d27815694
commit 38d87463af
4 changed files with 98 additions and 5 deletions

View file

@ -6,7 +6,7 @@ Scholar.ItemTreeView = function(itemGroup)
this._itemGroup = itemGroup; this._itemGroup = itemGroup;
this.refresh(); this.refresh();
// this._unregisterID = Scholar.registerItemTree(this); this._unregisterID = Scholar.Notifier.registerItemTree(this);
} }
Scholar.ItemTreeView.prototype.refresh = function() Scholar.ItemTreeView.prototype.refresh = function()
@ -23,7 +23,7 @@ Scholar.ItemTreeView.prototype.refresh = function()
Scholar.ItemTreeView.prototype.unregister = function() Scholar.ItemTreeView.prototype.unregister = function()
{ {
Scholar.unregisterItemTree(this._unregisterID); Scholar.Notifier.unregisterItemTree(this._unregisterID);
} }
Scholar.ItemTreeView.prototype.setTree = function(treebox) Scholar.ItemTreeView.prototype.setTree = function(treebox)
@ -172,7 +172,7 @@ Scholar.ItemTreeView.prototype.notify = function(action, type, id)
{ {
var item = Scholar.Items.get(id); var item = Scholar.Items.get(id);
if(this._itemGroup.isLibrary() || item.hasParent(this.getCollectionID())) if(this._itemGroup.isLibrary() || item.inCollection(this.getCollectionID()))
{ {
this._showItem(item,this.rowCount); this._showItem(item,this.rowCount);
this._treebox.rowCountChanged(this.rowCount,1); this._treebox.rowCountChanged(this.rowCount,1);

View file

@ -150,6 +150,16 @@ Scholar.Item.prototype.getCollections = function(){
} }
/**
* Determine whether the item belongs to a given collectionID
**/
Scholar.Item.prototype.inCollection = function(collectionID){
return !!parseInt(Scholar.DB.valueQuery("SELECT COUNT(*) collectionID "
+ "FROM collectionItems WHERE collectionID=" + collectionID + " AND "
+ "itemID=" + this.getID()));
}
/* /*
* Returns the number of creators for this item * Returns the number of creators for this item
*/ */
@ -839,8 +849,6 @@ Scholar.Items = new function(){
var obj = this.get(id); var obj = this.get(id);
obj.erase(); // calls unload() obj.erase(); // calls unload()
obj = undefined; obj = undefined;
// TODO: trigger reload of treeview
} }
@ -976,8 +984,11 @@ Scholar.Collection.prototype.addItem = function(itemID){
this._childItems.set(itemID); this._childItems.set(itemID);
this._hasChildItems = true; this._hasChildItems = true;
Scholar.Notifier.trigger('add', 'item', itemID);
} }
Scholar.Collection.prototype.removeItem = function(itemID){ Scholar.Collection.prototype.removeItem = function(itemID){
Scholar.DB.beginTransaction(); Scholar.DB.beginTransaction();
@ -1009,6 +1020,8 @@ Scholar.Collection.prototype.removeItem = function(itemID){
if (!this._childItems.length){ if (!this._childItems.length){
this._hasChildItems = false; this._hasChildItems = false;
} }
Scholar.Notifier.trigger('remove', 'item', itemID);
} }

View file

@ -0,0 +1,76 @@
Scholar.Notifier = new function(){
var _observers = new Array();
_observers['columnTree'] = new Array();
_observers['itemTree'] = new Array();
this.registerColumnTree = registerColumnTree;
this.registerItemTree = registerItemTree;
this.unregisterColumnTree = unregisterColumnTree;
this.unregisterItemTree = unregisterItemTree;
this.trigger = trigger;
function registerColumnTree(ref){
_register('columnTree', ref);
}
function registerItemTree(ref){
_register('itemTree', ref);
}
function unregisterColumnTree(hash){
_unregister('columnTree', hash);
}
function unregisterItemTree(hash){
_unregister('columnTree', hash);
}
/**
* event is one of 'add', 'remove', 'modify'
* type is one of 'collection', 'smartcollection', 'item'
**/
function trigger(event, type, id){
switch (type){
case 'item':
var treeType = 'itemTree';
break;
case 'collection':
case 'smartcollection':
var treeType = 'columnTree';
break;
default:
throw('Invalid type in Notifier.trigger()');
}
for (i in _observers[treeType]){
Scholar.debug("Calling _observers['" + treeType + "']['" + i + "'].notify('" + event
+ "', " + type + "', " + id + ")", 4);
_observers[treeType][i].notify(event, type, id);
}
}
function _register(type, ref){
var len = 6;
var tries = 10;
do {
// Increase the hash length if we can't find a unique key
if (!tries){
len++;
tries = 10;
}
var hash = Scholar.randomString(len);
tries--;
}
while (_observers[type][hash]);
Scholar.debug('Registering ' + type + " with hash '" + hash + "'", 4);
_observers[type][hash] = ref;
return hash;
}
function _unregister(type, hash){
delete _observers[type][hash];
}
}

View file

@ -27,6 +27,10 @@ Cc["@mozilla.org/moz/jssubscript-loader;1"]
.getService(Ci.mozIJSSubScriptLoader) .getService(Ci.mozIJSSubScriptLoader)
.loadSubScript("chrome://scholar/content/xpcom/data_access.js"); .loadSubScript("chrome://scholar/content/xpcom/data_access.js");
Cc["@mozilla.org/moz/jssubscript-loader;1"]
.getService(Ci.mozIJSSubScriptLoader)
.loadSubScript("chrome://scholar/content/xpcom/notifier.js");
/********************************************************************/ /********************************************************************/