From 96afa4b9506dfbf35e08902f273aca92457685db Mon Sep 17 00:00:00 2001 From: Francisco Ryan Tolmasky I Date: Thu, 10 Sep 2009 14:12:34 -0700 Subject: [PATCH] Added deferred loading for outline views (for remote data), and added CPTreeNode class. Reviewed by me. --- AppKit/CPOutlineView.j | 52 ++++++++++++++++++++++++++++++- AppKit/CPTreeNode.j | 69 ++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 120 insertions(+), 1 deletion(-) create mode 100644 AppKit/CPTreeNode.j diff --git a/AppKit/CPOutlineView.j b/AppKit/CPOutlineView.j index 3650055a1..ee4cddac4 100644 --- a/AppKit/CPOutlineView.j +++ b/AppKit/CPOutlineView.j @@ -26,6 +26,21 @@ #include "CoreGraphics/CGGeometry.h" +var CPOutlineViewDataSource_outlineView_setObjectValue_forTableColumn_byItem_ = 1 << 1, + CPOutlineViewDataSource_outlineView_shouldDeferDisplayingChildrenOfItem_ = 1 << 2, + + CPOutlineViewDataSource_outlineView_acceptDrop_item_childIndex_ = 1 << 3, + CPOutlineViewDataSource_outlineView_validateDrop_proposedItem_proposedChildIndex_ = 1 << 4, + CPOutlineViewDataSource_outlineView_validateDrop_proposedRow_proposedDropOperation_ = 1 << 5, + CPOutlineViewDataSource_outlineView_namesOfPromisedFilesDroppedAtDestination_forDraggedItems_ = 1 << 6, + + CPOutlineViewDataSource_outlineView_itemForPersistentObject_ = 1 << 7, + CPOutlineViewDataSource_outlineView_persistentObjectForItem_ = 1 << 8, + + CPOutlineViewDataSource_outlineView_writeItems_toPasteboard_ = 1 << 9, + + CPOutlineViewDataSource_outlineView_sortDescriptorsDidChange_ = 1 << 10; + @implementation CPOutlineView : CPTableView { id _outlineViewDataSource; @@ -33,6 +48,8 @@ float _indentationPerLevel; + CPInteger _implementedOutlineViewDataSourceMethods; + Object _rootItemInfo; CPMutableArray _itemsForRows; Object _itemInfosForItems; @@ -75,6 +92,37 @@ [CPException raise:CPInternalInconsistencyException reason:"Data source must implement 'outlineView:objectValueForTableColumn:byItem:'"]; _outlineViewDataSource = aDataSource; + _implementedOutlineViewDataSourceMethods = 0; + + if ([_outlineViewDataSource respondsToSelector:@selector(outlineView:setObjectValue:forTableColumn:byItem:)]) + _implementedOutlineViewDataSourceMethods |= CPOutlineViewDataSource_outlineView_setObjectValue_forTableColumn_byItem_; + + if ([_outlineViewDataSource respondsToSelector:@selector(outlineView:shouldDeferDisplayingChildrenOfItem:)]) + _implementedOutlineViewDataSourceMethods |= CPOutlineViewDataSource_outlineView_shouldDeferDisplayingChildrenOfItem_; + + if ([_outlineViewDataSource respondsToSelector:@selector(outlineView:acceptDrop:item:childIndex:)]) + _implementedOutlineViewDataSourceMethods |= CPOutlineViewDataSource_outlineView_acceptDrop_item_childIndex_; + + if ([_outlineViewDataSource respondsToSelector:@selector(outlineView:validateDrop:proposedItem:proposedChildIndex:)]) + _implementedOutlineViewDataSourceMethods |= CPOutlineViewDataSource_outlineView_validateDrop_proposedItem_proposedChildIndex_; + + if ([_outlineViewDataSource respondsToSelector:@selector(outlineView:validateDrop:proposedRow:proposedDropOperation:)]) + _implementedOutlineViewDataSourceMethods |= CPOutlineViewDataSource_outlineView_validateDrop_proposedRow_proposedDropOperation_; + + if ([_outlineViewDataSource respondsToSelector:@selector(outlineView:namesOfPromisedFilesDroppedAtDestination:forDraggedItems:)]) + _implementedOutlineViewDataSourceMethods |= CPOutlineViewDataSource_outlineView_namesOfPromisedFilesDroppedAtDestination_forDraggedItems_; + + if ([_outlineViewDataSource respondsToSelector:@selector(outlineView:itemForPersistentObject:)]) + _implementedOutlineViewDataSourceMethods |= CPOutlineViewDataSource_outlineView_itemForPersistentObject_; + + if ([_outlineViewDataSource respondsToSelector:@selector(outlineView:persistentObjectForItem:)]) + _implementedOutlineViewDataSourceMethods |= CPOutlineViewDataSource_outlineView_persistentObjectForItem_; + + if ([_outlineViewDataSource respondsToSelector:@selector(outlineView:writeItems:toPasteboard:)]) + _implementedOutlineViewDataSourceMethods |= CPOutlineViewDataSource_outlineView_writeItems_toPasteboard_; + + if ([_outlineViewDataSource respondsToSelector:@selector(outlineView:sortDescriptorsDidChange:)]) + _implementedOutlineViewDataSourceMethods |= CPOutlineViewDataSource_outlineView_sortDescriptorsDidChange_; [self reloadData]; } @@ -295,7 +343,9 @@ var _loadItemInfoForItem = function(/*CPOutlineView*/ anOutlineView, /*id*/ anIt var weight = itemInfo.weight, descendants = [anItem]; - if (itemInfo.isExpanded && shouldLoadChildren) + if (itemInfo.isExpanded && (shouldReloadData || shouldLoadChildren) && + (!(anOutlineView._implementedOutlineViewDataSourceMethods & CPOutlineViewDataSource_outlineView_shouldDeferDisplayingChildrenOfItem_) || + ![dataSource outlineView:anOutlineView shouldDeferDisplayingChildrenOfItem:anItem])) { var index = 0, count = [dataSource outlineView:anOutlineView numberOfChildrenOfItem:anItem], diff --git a/AppKit/CPTreeNode.j b/AppKit/CPTreeNode.j new file mode 100644 index 000000000..c6ba2ba20 --- /dev/null +++ b/AppKit/CPTreeNode.j @@ -0,0 +1,69 @@ + +@import + + +@implementation CPTreeNode : CPObject +{ + id _representedObject @accessors(readonly, property=representedObject); + + CPTreeNode _parentNode @accessors(readonly, property=parentNode); + CPMutableArray _childNodes @accessors(readonly, property=childNodes); +} + ++ (id)treeNodeWithRepresentedObject:(id)anObject +{ + return [[self alloc] initWithRepresentedObject:anObject]; +} + +- (id)initWithRepresentedObject:(id)anObject +{ + self = [super init]; + + if (self) + { + _representedObject = anObject; + _childNodes = []; + } + + return self; +} + +- (BOOL)isLeaf +{ + return [_childNodes count] <= 0; +} + +- (CPMutableArray)mutableChildNodes +{ + return [self mutableArrayValueForKey:@"childNodes"]; +} + +- (void)insertObject:(id)anObject inChildNodesAtIndex:(CPInteger)anIndex +{ + anObject._parentNode = self; + + [_childNodes addObject:anObject]; +} + +- (void)removeObjectFromChildNodesAtIndex:(CPInteger)anIndex +{ + anObject._parentNode = nil; + + [_childNodes removeObjectAtIndex:anIndex]; +} + +- (void)replaceObjectFromChildNodesAtIndex:(CPInteger)anIndex withObject:(id)anObject +{ + var oldObject = [_childNodes objectAtIndex:anIndex]; + + oldObject._parentNode = nil; + + [_childNodes replaceObjectAtIndex:anIndex withObject:anObject]; +} + +- (id)objectInChildNodesAtIndex:(CPInteger)anIndex +{ + return _childNodes[anIndex]; +} + +@end