[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 
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()



More information about the chandler-dev mailing list