[Chandler-dev] annotating selection
Alec Flett
alecf at osafoundation.org
Thu Mar 30 17:40:33 PST 2006
I've been thinking a lot lately about collections. I'd like to take
some time to discuss IndexedSelectionCollection and its role in chandler...
To bring everyone up to speed, I'll summarize how
IndexedSelectionCollection works, what it buys us, and the problems I
see with it. I've specifically sent this message to John, Andi, and pje
because I'd like to brainstorm some ideas and they are the folks that
will have the best handle on the issues.... but anyone else is welcome
to offer up ideas as well.
(John, I do realize that the actual ISCollection is more general than
what I'm about to describe, but I'm trying to discuss the specific use
case that it was designed for..)
IndexedSelectionCollection works by 'wrapping' or referencing a 'source'
collection. This source collection is usually a SmartCollection stored
in the sidebar. When a collection is clicked in the sidebar, it is
'wrapped' with an IndexedSelectionCollection that is specific for that
particular combination of (collection, kind filter).. so that if I have
a collection 'School' and I click on the 'Mail' button in the toolbar, I
get a new IndexedSelectionCollection (and a FilteredCollection, but
that's beyond the scope of what I'm trying to get at) just for that, and
that ISCollection is what is passed to the Table. The table and calendar
use this ISCollection exclusively to persistently store its collection
and current sort (by storing the index name as an attribute on the
ISCollection instance) However, they need to go back to the original
collection in order to get other metainformation such as color.
So what is IndexedSelectionCollection doing for us?
1) provides a "view"-side way of representing and persisting selection
of items in the source collection - i.e. each instance of a table widget
can have its own selection by having its own instance of an ISCollection
which points back to the original source collection. Selection is
automatically updated as the collection changes due to the RangeSet work
that Andi and John did.
2) provides a container to store indexes for the items in the source
collection. Rather than storing indexes on the original collection, it
is storing indexes in the ISCollection. The RangeSet stuff is
intricately tied to the indexes stored on the collection.
3) provides persistent storage of the 'current sort'
I would argue that 2) and 3) aren't really valuable and here's why:
2) Indexes on a collection should be on the original collection, not on
some derivative collection. This allows any consumer of that collection
to leverage the indexes without going and tracking down an
IndexedSelectionCollection that references it. For instance, if a
collection has a 'date' index, then that date index should be available
to as many views as want it, rather than requiring each
IndexedSelectionCollection to keep its own 'date' index.
3) I think the 'current sort' is really owned by the CPIA Block or
Widget referencing the collection, not some intermediate collection. The
Block/Widget should be persisting the name of the index being used for
sorting, and be accessing the collection using that index.. so to access
element x, we currently write
item = self.contents[x]
...and expect that self.contents knows which index to use (as determined
by self.contents.indexName)
What if instead we wrote:
item = self.contents.getByIndex(self.currentIndex, x)
Now we don't need an intermediary collection just to hold the current
index name.
The tricky case is 1). How do we keep selection off the main collection
and yet have it update automatically when items are added/removed from
the collection? I thought first about Annotations. We still haven't
solved the problem of how to maintain selection when changing the
current index, so perhaps instead we could think about the selection as
a sort of Annotated dictionary-style attribute, keyed off of some part
of the block. Basically you'd be hanging a bunch of selections off of
the collection,
So if we had an annotation called SelectionCollection, the block could say:
selection = SelectionCollection(self.contents).getSelection(self.blockName)
[I'm using blockName as an example, we'd probably want something more
unique]
The only trick is getting all the selections to stay current. I realized
this could be accomplished if every selection was just a well-known
index on a collection.
Then SelectionCollection wouldn't need to even be an Annotation, even
though that is the effect:
class SelectionCollection(object):
def __init__(self, collection):
self.collection = collection
def getSelectionRanges(self, selectionKey):
indexName = 'selection_' + selectionKey
if not self.collection.hasIndex(indexName):
self.collection.addIndex(indexName, 'numeric')
return self.collection.getIndex(indexName).getRanges()
Thoughts?
Alec
More information about the chandler-dev
mailing list