81 #define SELECTION_SHOULD_CHANGE(anOutlineView) (!((anOutlineView)._implementedOutlineViewDelegateMethods & CPOutlineViewDelegate_selectionShouldChangeInOutlineView_) || [(anOutlineView)._outlineViewDelegate selectionShouldChangeInOutlineView:(anOutlineView)])
83 #define SHOULD_SELECT_ITEM(anOutlineView, anItem) (!((anOutlineView)._implementedOutlineViewDelegateMethods & CPOutlineViewDelegate_outlineView_shouldSelectItem_) || [(anOutlineView)._outlineViewDelegate outlineView:(anOutlineView) shouldSelectItem:(anItem)])
102 id _outlineViewDataSource;
103 id _outlineViewDelegate;
106 float _indentationPerLevel;
107 BOOL _indentationMarkerFollowsDataView;
109 CPInteger _implementedOutlineViewDataSourceMethods;
110 CPInteger _implementedOutlineViewDelegateMethods;
112 Object _rootItemInfo;
114 Object _itemInfosForItems;
117 CPArray _disclosureControlsForRows;
118 CPData _disclosureControlData;
119 CPArray _disclosureControlQueue;
121 BOOL _shouldRetargetItem;
124 BOOL _shouldRetargetChildIndex;
125 CPInteger _retargedChildIndex;
129 BOOL _coalesceSelectionNotificationState;
132 - (id)initWithFrame:(CGRect)aFrame
141 _rootItemInfo = { isExpanded:YES, isExpandable:NO, shouldShowOutlineDisclosureControl:NO, level:-1, row:-1, children:[], weight:0 };
144 _itemInfosForItems = { };
145 _disclosureControlsForRows = [];
147 _retargetedItem = nil;
148 _shouldRetargetItem = NO;
150 _retargedChildIndex = nil;
151 _shouldRetargetChildIndex = NO;
156 [
super setDataSource:[[_CPOutlineViewTableViewDataSource alloc] initWithOutlineView:self]];
157 [
super setDelegate:[[_CPOutlineViewTableViewDelegate alloc] initWithOutlineView:self]];
215 - (void)setDataSource:(
id)aDataSource
217 if (_outlineViewDataSource === aDataSource)
220 if (![aDataSource respondsToSelector:
@selector(outlineView:child:ofItem:)])
221 [
CPException raise:CPInternalInconsistencyException
reason:"Data source must implement 'outlineView:child:ofItem:'"];
223 if (![aDataSource respondsToSelector:
@selector(outlineView:isItemExpandable:)])
224 [
CPException raise:CPInternalInconsistencyException
reason:"Data source must implement 'outlineView:isItemExpandable:'"];
226 if (![aDataSource respondsToSelector:
@selector(outlineView:numberOfChildrenOfItem:)])
227 [
CPException raise:CPInternalInconsistencyException
reason:"Data source must implement 'outlineView:numberOfChildrenOfItem:'"];
229 if (![aDataSource respondsToSelector:
@selector(outlineView:objectValueForTableColumn:byItem:)])
230 [
CPException raise:CPInternalInconsistencyException
reason:"Data source must implement 'outlineView:objectValueForTableColumn:byItem:'"];
232 _outlineViewDataSource = aDataSource;
233 _implementedOutlineViewDataSourceMethods = 0;
235 if ([_outlineViewDataSource respondsToSelector:
@selector(outlineView:setObjectValue:forTableColumn:byItem:)])
238 if ([_outlineViewDataSource respondsToSelector:
@selector(outlineView:shouldDeferDisplayingChildrenOfItem:)])
241 if ([_outlineViewDataSource respondsToSelector:
@selector(outlineView:acceptDrop:item:childIndex:)])
244 if ([_outlineViewDataSource respondsToSelector:
@selector(outlineView:validateDrop:proposedItem:proposedChildIndex:)])
247 if ([_outlineViewDataSource respondsToSelector:
@selector(outlineView:validateDrop:proposedRow:proposedDropOperation:)])
250 if ([_outlineViewDataSource respondsToSelector:
@selector(outlineView:namesOfPromisedFilesDroppedAtDestination:forDraggedItems:)])
253 if ([_outlineViewDataSource respondsToSelector:
@selector(outlineView:itemForPersistentObject:)])
256 if ([_outlineViewDataSource respondsToSelector:
@selector(outlineView:persistentObjectForItem:)])
259 if ([_outlineViewDataSource respondsToSelector:
@selector(outlineView:writeItems:toPasteboard:)])
262 if ([_outlineViewDataSource respondsToSelector:
@selector(outlineView:sortDescriptorsDidChange:)])
275 return _outlineViewDataSource;
285 - (BOOL)isExpandable:(
id)anItem
290 var itemInfo = _itemInfosForItems[[anItem UID]];
295 return itemInfo.isExpandable;
298 - (BOOL)_shouldShowOutlineDisclosureControlForItem:(
id)anItem
303 var itemInfo = _itemInfosForItems[[anItem UID]];
308 return itemInfo.shouldShowOutlineDisclosureControl;
318 - (BOOL)isItemExpanded:(
id)anItem
323 var itemInfo = _itemInfosForItems[[anItem UID]];
328 return itemInfo.isExpanded;
336 - (void)expandItem:(
id)anItem
347 - (void)expandItem:(
id)anItem expandChildren:(BOOL)shouldExpandChildren
352 itemInfo = _rootItemInfo;
354 itemInfo = _itemInfosForItems[[anItem UID]];
363 if (!_coalesceSelectionNotificationState)
370 if (!itemInfo.isExpanded)
372 [
self _noteItemWillExpand:anItem];
376 itemInfo.isExpanded = YES;
378 [
self _noteItemDidExpand:anItem];
381 var rowCountDelta = [
self numberOfRows] - previousRowCount;
387 if ([selection intersectsIndexesInRange:
CPMakeRange(expandIndex, _itemsForRows.length)])
389 [
self _noteSelectionIsChanging];
390 [selection shiftIndexesStartingAtIndex:expandIndex by:rowCountDelta];
391 [
self _setSelectedRowIndexes:selection];
396 if (shouldExpandChildren)
398 var children = itemInfo.children,
399 childIndex = children.length;
407 var r = _coalesceSelectionNotificationState;
410 [
self _noteSelectionDidChange];
419 - (void)collapseItem:(
id)anItem
424 var itemInfo = _itemInfosForItems[[anItem UID]];
429 if (!itemInfo.isExpanded)
435 [
self _noteItemWillCollapse:anItem];
439 var collapseTopIndex = [
self rowForItem:anItem],
441 collapseEndIndex = collapseTopIndex;
443 while (collapseEndIndex + 1 < _itemsForRows.length && [
self levelForRow:collapseEndIndex + 1] > topLevel)
446 var collapseRange =
CPMakeRange(collapseTopIndex + 1, collapseEndIndex - collapseTopIndex);
448 if (collapseRange.length)
452 if ([selection intersectsIndexesInRange:collapseRange])
454 [
self _noteSelectionIsChanging];
455 [selection removeIndexesInRange:collapseRange];
456 [
self _setSelectedRowIndexes:selection];
460 if ([selection intersectsIndexesInRange:
CPMakeRange(collapseEndIndex + 1, _itemsForRows.length)])
462 [
self _noteSelectionIsChanging];
463 [selection shiftIndexesStartingAtIndex:collapseEndIndex + 1 by:-collapseRange.length];
464 [
self _setSelectedRowIndexes:selection];
467 itemInfo.isExpanded = NO;
470 [
self _noteItemDidCollapse:anItem];
474 var r = _coalesceSelectionNotificationState;
477 [
self _noteSelectionDidChange];
485 - (void)reloadItem:(
id)anItem
496 - (void)reloadItem:(
id)anItem reloadChildren:(BOOL)shouldReloadChildren
498 if (!!shouldReloadChildren || !anItem)
499 _loadItemInfoForItem(
self, anItem);
501 _reloadItem(
self, anItem);
512 - (id)itemAtRow:(CPInteger)aRow
514 return _itemsForRows[aRow] || nil;
523 - (CPInteger)rowForItem:(
id)anItem
526 return _rootItemInfo.row;
528 var itemInfo = _itemInfosForItems[[anItem UID]];
544 if (_outlineTableColumn === aTableColumn)
547 _outlineTableColumn = aTableColumn;
560 return _outlineTableColumn;
571 - (CPInteger)levelForItem:(
id)anItem
574 return _rootItemInfo.level;
576 var itemInfo = _itemInfosForItems[[anItem UID]];
581 return itemInfo.level;
591 - (CPInteger)levelForRow:(CPInteger)aRow
601 - (void)setIndentationPerLevel:(
float)anIndentationWidth
603 if (_indentationPerLevel === anIndentationWidth)
606 _indentationPerLevel = anIndentationWidth;
617 - (float)indentationPerLevel
619 return _indentationPerLevel;
629 - (void)setIndentationMarkerFollowsDataView:(BOOL)indentationMarkerShouldFollowDataView
631 if (_indentationMarkerFollowsDataView === indentationMarkerShouldFollowDataView)
634 _indentationMarkerFollowsDataView = indentationMarkerShouldFollowDataView;
647 - (BOOL)indentationMarkerFollowsDataView
649 return _indentationMarkerFollowsDataView;
659 - (id)parentForItem:(
id)anItem
664 var itemInfo = _itemInfosForItems[[anItem UID]];
669 var parent = itemInfo.parent;
672 if (itemInfo[[parent UID]] === _rootItemInfo)
683 - (CGRect)_frameOfOutlineDataViewAtRow:(CPInteger)aRow
685 var columnIndex = [[
self tableColumns] indexOfObject:_outlineTableColumn],
686 frame = [
super frameOfDataViewAtColumn:columnIndex row:aRow],
687 indentationWidth = ([
self levelForRow:aRow] + 1) * [self indentationPerLevel];
689 frame.origin.x += indentationWidth;
690 frame.size.width -= indentationWidth;
703 - (CGRect)frameOfOutlineDisclosureControlAtRow:(CPInteger)aRow
706 if (![
self isExpandable:theItem] || ![
self _shouldShowOutlineDisclosureControlForItem:theItem])
707 return _CGRectMakeZero();
709 var dataViewFrame = [
self _frameOfOutlineDataViewAtRow:aRow],
710 disclosureWidth = _CGRectGetWidth([_disclosureControlPrototype
frame]),
711 frame = _CGRectMake(_CGRectGetMinX(dataViewFrame) - disclosureWidth, _CGRectGetMinY(dataViewFrame), disclosureWidth, _CGRectGetHeight(dataViewFrame));
720 - (void)_performSelection:(BOOL)select forRow:(CPInteger)rowIndex context:(
id)context
722 [
super _performSelection:select forRow:rowIndex context:context];
724 var control = _disclosureControlsForRows[rowIndex],
725 selector = select ?
@"setThemeState:" :
@"unsetThemeState:";
727 [control performSelector:CPSelectorFromString(selector) withObject:CPThemeStateSelected];
806 - (void)setDelegate:(
id)aDelegate
808 if (_outlineViewDelegate === aDelegate)
813 if (_outlineViewDelegate)
815 if ([_outlineViewDelegate respondsToSelector:
@selector(outlineViewColumnDidMove:)])
817 removeObserver:_outlineViewDelegate
818 name:CPOutlineViewColumnDidMoveNotification
821 if ([_outlineViewDelegate respondsToSelector:
@selector(outlineViewColumnDidResize:)])
823 removeObserver:_outlineViewDelegate
824 name:CPOutlineViewColumnDidResizeNotification
827 if ([_outlineViewDelegate respondsToSelector:
@selector(outlineViewSelectionDidChange:)])
829 removeObserver:_outlineViewDelegate
830 name:CPOutlineViewSelectionDidChangeNotification
833 if ([_outlineViewDelegate respondsToSelector:
@selector(outlineViewSelectionIsChanging:)])
835 removeObserver:_outlineViewDelegate
836 name:CPOutlineViewSelectionIsChangingNotification
839 if ([_outlineViewDelegate respondsToSelector:
@selector(outlineViewItemWillExpand:)])
841 removeObserver:_outlineViewDelegate
842 name:CPOutlineViewItemWillExpandNotification
845 if ([_outlineViewDelegate respondsToSelector:
@selector(outlineViewItemDidExpand:)])
847 removeObserver:_outlineViewDelegate
848 name:CPOutlineViewItemDidExpandNotification
851 if ([_outlineViewDelegate respondsToSelector:
@selector(outlineViewItemWillCollapse:)])
853 removeObserver:_outlineViewDelegate
854 name:CPOutlineViewItemWillCollapseNotification
857 if ([_outlineViewDelegate respondsToSelector:
@selector(outlineViewItemDidCollapse:)])
859 removeObserver:_outlineViewDelegate
860 name:CPOutlineViewItemDidCollapseNotification
864 _outlineViewDelegate = aDelegate;
865 _implementedOutlineViewDelegateMethods = 0;
867 var delegateMethods = [
868 CPOutlineViewDelegate_outlineView_dataViewForTableColumn_item_ , @selector(outlineView:dataViewForTableColumn:item:),
869 CPOutlineViewDelegate_outlineView_didClickTableColumn_ , @selector(outlineView:didClickTableColumn:),
870 CPOutlineViewDelegate_outlineView_didDragTableColumn_ , @selector(outlineView:didDragTableColumn:),
871 CPOutlineViewDelegate_outlineView_heightOfRowByItem_ , @selector(outlineView:heightOfRowByItem:),
872 CPOutlineViewDelegate_outlineView_isGroupItem_ , @selector(outlineView:isGroupItem:),
873 CPOutlineViewDelegate_outlineView_mouseDownInHeaderOfTableColumn_ , @selector(outlineView:mouseDownInHeaderOfTableColumn:),
874 CPOutlineViewDelegate_outlineView_nextTypeSelectMatchFromItem_toItem_forString_ , @selector(outlineView:nextTypeSelectMatchFromItem:toItem:forString:),
875 CPOutlineViewDelegate_outlineView_selectionIndexesForProposedSelection_ , @selector(outlineView:selectionIndexesForProposedSelection:),
876 CPOutlineViewDelegate_outlineView_shouldCollapseItem_ , @selector(outlineView:shouldCollapseItem:),
877 CPOutlineViewDelegate_outlineView_shouldEditTableColumn_item_ , @selector(outlineView:shouldEditTableColumn:item:),
878 CPOutlineViewDelegate_outlineView_shouldExpandItem_ , @selector(outlineView:shouldExpandItem:),
879 CPOutlineViewDelegate_outlineView_shouldReorderColumn_toColumn_ , @selector(outlineView:shouldReorderColumn:toColumn:),
880 CPOutlineViewDelegate_outlineView_shouldSelectItem_ , @selector(outlineView:shouldSelectItem:),
881 CPOutlineViewDelegate_outlineView_shouldSelectTableColumn_ , @selector(outlineView:shouldSelectTableColumn:),
882 CPOutlineViewDelegate_outlineView_shouldShowOutlineDisclosureControlForItem_ , @selector(outlineView:shouldShowOutlineDisclosureControlForItem:),
883 CPOutlineViewDelegate_outlineView_shouldShowViewExpansionForTableColumn_item_ , @selector(outlineView:shouldShowViewExpansionForTableColumn:item:),
884 CPOutlineViewDelegate_outlineView_shouldTrackView_forTableColumn_item_ , @selector(outlineView:shouldTrackView:forTableColumn:item:),
885 CPOutlineViewDelegate_outlineView_shouldTypeSelectForEvent_withCurrentSearchString_ , @selector(outlineView:shouldTypeSelectForEvent:withCurrentSearchString:),
886 CPOutlineViewDelegate_outlineView_sizeToFitWidthOfColumn_ , @selector(outlineView:sizeToFitWidthOfColumn:),
887 CPOutlineViewDelegate_outlineView_toolTipForView_rect_tableColumn_item_mouseLocation_, @selector(outlineView:toolTipForView:rect:tableColumn:item:mouseLocation:),
888 CPOutlineViewDelegate_outlineView_typeSelectStringForTableColumn_item_ , @selector(outlineView:typeSelectStringForTableColumn:item:),
889 CPOutlineViewDelegate_outlineView_willDisplayOutlineView_forTableColumn_item_ , @selector(outlineView:willDisplayOutlineView:forTableColumn:item:),
890 CPOutlineViewDelegate_outlineView_willDisplayView_forTableColumn_item_ , @selector(outlineView:willDisplayView:forTableColumn:item:),
891 CPOutlineViewDelegate_selectionShouldChangeInOutlineView_ , @selector(selectionShouldChangeInOutlineView:),
892 CPOutlineViewDelegate_outlineView_menuForTableColumn_item_ , @selector(outlineView:menuForTableColumn:item:)
894 delegateCount = [delegateMethods count];
896 for (var i = 0; i < delegateCount; i += 2)
898 var bitMask = delegateMethods[i],
899 selector = delegateMethods[i + 1];
901 if ([_outlineViewDelegate respondsToSelector:selector])
902 _implementedOutlineViewDelegateMethods |= bitMask;
905 if ([_outlineViewDelegate respondsToSelector:
@selector(outlineViewColumnDidMove:)])
907 addObserver:_outlineViewDelegate
908 selector:@selector(outlineViewColumnDidMove:)
909 name:CPOutlineViewColumnDidMoveNotification
912 if ([_outlineViewDelegate respondsToSelector:
@selector(outlineViewColumnDidResize:)])
914 addObserver:_outlineViewDelegate
915 selector:@selector(outlineViewColumnDidMove:)
916 name:CPOutlineViewColumnDidResizeNotification
919 if ([_outlineViewDelegate respondsToSelector:
@selector(outlineViewSelectionDidChange:)])
921 addObserver:_outlineViewDelegate
922 selector:@selector(outlineViewSelectionDidChange:)
923 name:CPOutlineViewSelectionDidChangeNotification
926 if ([_outlineViewDelegate respondsToSelector:
@selector(outlineViewSelectionIsChanging:)])
928 addObserver:_outlineViewDelegate
929 selector:@selector(outlineViewSelectionIsChanging:)
930 name:CPOutlineViewSelectionIsChangingNotification
933 if ([_outlineViewDelegate respondsToSelector:
@selector(outlineViewItemWillExpand:)])
935 addObserver:_outlineViewDelegate
936 selector:@selector(outlineViewItemWillExpand:)
937 name:CPOutlineViewItemWillExpandNotification
940 if ([_outlineViewDelegate respondsToSelector:
@selector(outlineViewItemDidExpand:)])
942 addObserver:_outlineViewDelegate
943 selector:@selector(outlineViewItemDidExpand:)
944 name:CPOutlineViewItemDidExpandNotification
947 if ([_outlineViewDelegate respondsToSelector:
@selector(outlineViewItemWillCollapse:)])
949 addObserver:_outlineViewDelegate
950 selector:@selector(outlineViewItemWillCollapse:)
951 name:CPOutlineViewItemWillCollapseNotification
954 if ([_outlineViewDelegate respondsToSelector:
@selector(outlineViewItemDidCollapse:)])
956 addObserver:_outlineViewDelegate
957 selector:@selector(outlineViewItemDidCollapse:)
958 name:CPOutlineViewItemDidCollapseNotification
963 - (BOOL)_sendDelegateDeleteKeyPressed
965 if ([[
self delegate] respondsToSelector:
@selector(outlineViewDeleteKeyPressed:)])
967 [[
self delegate] outlineViewDeleteKeyPressed:self];
979 return _outlineViewDelegate;
989 - (void)setDisclosureControlPrototype:(
CPControl)aControl
991 _disclosureControlPrototype = aControl;
992 _disclosureControlData = nil;
993 _disclosureControlQueue = [];
1021 if ([
self numberOfColumns] === 1)
1022 _outlineTableColumn = aTableColumn;
1029 if (aTableColumn === [
self outlineTableColumn])
1030 CPLog(
"CPOutlineView cannot remove outlineTableColumn with removeTableColumn:. User setOutlineTableColumn: instead.");
1039 - (CGRect)frameOfDataViewAtColumn:(CPInteger)aColumn row:(CPInteger)aRow
1043 if (tableColumn === _outlineTableColumn)
1044 return [
self _frameOfOutlineDataViewAtRow:aRow];
1053 - (
CPView)_dragViewForColumn:(
int)theColumnIndex event:(
CPEvent)theDragEvent offset:(CPPointPointer)theDragViewOffset
1055 var dragView = [[_CPColumnDragView alloc] initWithLineColor:[
self gridColor]],
1056 tableColumn = [[
self tableColumns] objectAtIndex:theColumnIndex],
1057 bounds = _CGRectMake(0.0, 0.0, [tableColumn
width], _CGRectGetHeight([
self exposedRect]) + 23.0),
1058 columnRect = [
self rectOfColumn:theColumnIndex],
1059 headerView = [tableColumn headerView],
1060 row = [_exposedRows firstIndex];
1064 var dataView = [
self _newDataViewForRow:row tableColumn:tableColumn],
1065 dataViewFrame = [
self frameOfDataViewAtColumn:theColumnIndex row:row];
1068 dataViewFrame.origin.x = 0.0;
1071 dataViewFrame.origin.y = ( _CGRectGetMinY(dataViewFrame) - _CGRectGetMinY([self exposedRect]) ) + 23.0;
1072 [dataView setFrame:dataViewFrame];
1074 [dataView setObjectValue:[
self _objectValueForTableColumn:tableColumn row:row]];
1077 if (tableColumn === _outlineTableColumn)
1080 var indentationWidth = ([
self levelForRow:row] + 1) * [self indentationPerLevel];
1082 dataViewFrame.origin.x += indentationWidth;
1083 dataViewFrame.size.width -= indentationWidth;
1085 [dataView setFrame:dataViewFrame];
1088 [dragView addSubview:dataView];
1090 row = [_exposedRows indexGreaterThanIndex:row];
1094 var headerFrame = [headerView frame];
1095 headerFrame.origin = _CGPointMakeZero();
1097 var columnHeaderView = [[_CPTableColumnHeaderView alloc] initWithFrame:headerFrame];
1098 [columnHeaderView setStringValue:[headerView stringValue]];
1099 [columnHeaderView setThemeState:[headerView themeState]];
1100 [dragView addSubview:columnHeaderView];
1103 [dragView setAlphaValue:0.7];
1104 [dragView setFrame:bounds];
1124 - (void)setDropItem:(
id)theItem dropChildIndex:(
int)theIndex
1126 if (_dropItem !== theItem && theIndex < 0 && [
self isExpandable:theItem] && ![
self isItemExpanded:theItem])
1128 if (_dragHoverTimer)
1129 [_dragHoverTimer invalidate];
1131 var autoExpandCallBack =
function()
1135 [_dropOperationFeedbackView blink];
1145 [_dragHoverTimer invalidate];
1146 _dragHoverTimer = nil;
1149 _dropItem = theItem;
1150 _retargetedItem = theItem;
1151 _shouldRetargetItem = YES;
1153 _retargedChildIndex = theIndex;
1154 _shouldRetargetChildIndex = YES;
1157 var retargetedItemInfo = (_retargetedItem !== nil) ? _itemInfosForItems[[_retargetedItem UID]] : _rootItemInfo;
1159 if (_retargedChildIndex === [retargetedItemInfo.children count])
1161 var retargetedChildItem = [retargetedItemInfo.children lastObject];
1162 _retargetedDropRow = [
self rowForItem:retargetedChildItem] + 1;
1166 var retargetedChildItem = (_retargedChildIndex !==
CPOutlineViewDropOnItemIndex) ? retargetedItemInfo.children[_retargedChildIndex] : _retargetedItem;
1167 _retargetedDropRow = [
self rowForItem:retargetedChildItem];
1174 - (void)_draggingEnded
1176 [
super _draggingEnded];
1178 [_dragHoverTimer invalidate];
1179 _dragHoverTimer = nil;
1185 - (id)_parentItemForUpperRow:(
int)theUpperRowIndex andLowerRow:(
int)theLowerRowIndex atMouseOffset:(CPPoint)theOffset
1187 if (_shouldRetargetItem)
1188 return _retargetedItem;
1190 var lowerLevel = [
self levelForRow:theLowerRowIndex],
1191 upperItem = [
self itemAtRow:theUpperRowIndex],
1192 upperLevel = [
self levelForItem:upperItem];
1197 while (upperLevel > lowerLevel)
1199 upperLevel = [
self levelForItem:upperItem];
1202 if (theOffset.x > (upperLevel + 1) * [
self indentationPerLevel])
1203 return [
self parentForItem:upperItem];
1206 upperItem = [
self parentForItem:upperItem];
1209 return [
self parentForItem:[
self itemAtRow:theLowerRowIndex]];
1215 - (CPRect)_rectForDropHighlightViewBetweenUpperRow:(
int)theUpperRowIndex andLowerRow:(
int)theLowerRowIndex offset:(CPPoint)theOffset
1218 var rect = [
super _rectForDropHighlightViewBetweenUpperRow:theUpperRowIndex andLowerRow:theLowerRowIndex offset:theOffset],
1219 parentItem = [
self _parentItemForUpperRow:theUpperRowIndex andLowerRow:theLowerRowIndex atMouseOffset:theOffset],
1220 level = [
self levelForItem:parentItem];
1222 rect.origin.x = (level + 1) * [self indentationPerLevel];
1223 rect.size.width -= rect.origin.x;
1240 var columnIndex = 0,
1241 columnsCount = columnArray.length;
1243 for (; columnIndex < columnsCount; ++columnIndex)
1245 var column = columnArray[columnIndex],
1246 tableColumn = _tableColumns[column],
1247 tableColumnUID = [tableColumn UID],
1248 dataViewsForTableColumn = _dataViewsForTableColumns[tableColumnUID],
1250 rowsCount = rowArray.length;
1252 for (; rowIndex < rowsCount; ++rowIndex)
1254 var row = rowArray[rowIndex],
1255 dataView = dataViewsForTableColumn[row],
1256 dataViewFrame = [
self frameOfDataViewAtColumn:column row:row];
1258 [dataView setFrame:dataViewFrame];
1260 if (tableColumn === _outlineTableColumn)
1262 var control = _disclosureControlsForRows[row],
1263 frame = [
self frameOfOutlineDisclosureControlAtRow:row];
1265 [control setFrame:frame];
1276 [
super _loadDataViewsInRows:rows columns:columns];
1278 var outlineColumn = [[
self tableColumns] indexOfObjectIdenticalTo:[
self outlineTableColumn]];
1280 if (![columns containsIndex:outlineColumn] || [
self outlineTableColumn] === _draggedColumn)
1288 rowsCount = rowArray.length;
1290 for (; rowIndex < rowsCount; ++rowIndex)
1292 var row = rowArray[rowIndex],
1293 item = _itemsForRows[row],
1294 isExpandable = [
self isExpandable:item];
1299 var disclosureControlFrame = [
self frameOfOutlineDisclosureControlAtRow:row];
1301 if (_CGRectIsEmpty(disclosureControlFrame))
1304 var control = [
self _dequeueDisclosureControl];
1306 _disclosureControlsForRows[row] = control;
1308 [control setState:[
self isItemExpanded:item] ? CPOnState : CPOffState];
1309 var selector = [
self isRowSelected:row] ?
@"setThemeState:" :
@"unsetThemeState:";
1310 [control performSelector:CPSelectorFromString(selector) withObject:CPThemeStateSelected];
1311 [control setFrame:disclosureControlFrame];
1313 [
self addSubview:control];
1322 [
super _unloadDataViewsInRows:rows columns:columns];
1324 var outlineColumn = [[
self tableColumns] indexOfObjectIdenticalTo:[
self outlineTableColumn]];
1326 if (![columns containsIndex:outlineColumn])
1334 rowsCount = rowArray.length;
1336 for (; rowIndex < rowsCount; ++rowIndex)
1338 var row = rowArray[rowIndex],
1339 control = _disclosureControlsForRows[row];
1344 [control removeFromSuperview];
1346 [
self _enqueueDisclosureControl:control];
1348 _disclosureControlsForRows[row] = nil;
1355 - (void)_toggleFromDisclosureControl:(
CPControl)aControl
1357 var controlFrame = [aControl
frame],
1358 item = [
self itemAtRow:[
self rowAtPoint:_CGPointMake(_CGRectGetMinX(controlFrame), _CGRectGetMidY(controlFrame))]];
1360 if ([
self isItemExpanded:item])
1361 [
self collapseItem:item];
1364 [
self expandItem:item expandChildren:([[CPApp currentEvent] modifierFlags] & CPAlternateKeyMask)];
1370 - (void)_enqueueDisclosureControl:(
CPControl)aControl
1372 _disclosureControlQueue.push(aControl);
1380 if (_disclosureControlQueue.length)
1381 return _disclosureControlQueue.pop();
1383 if (!_disclosureControlData)
1384 if (!_disclosureControlPrototype)
1391 [disclosureControl setTarget:self];
1392 [disclosureControl setAction:@selector(_toggleFromDisclosureControl:)];
1394 return disclosureControl;
1400 - (void)_noteSelectionIsChanging
1417 - (void)_noteSelectionDidChange
1419 if (!_coalesceSelectionNotificationState)
1434 - (void)_noteItemWillExpand:(
id)item
1445 - (void)_noteItemDidExpand:(
id)item
1456 - (void)_noteItemWillCollapse:(
id)item
1467 - (void)_noteItemDidCollapse:(
id)item
1484 return [
super keyDown:anEvent];
1490 [rows getIndexes:indexes maxCount:-1 inIndexRange:nil];
1493 c = [indexes count];
1496 items.push([
self itemAtRow:indexes[i]]);
1500 for (var i = 0; i < c; i++)
1501 [
self expandItem:items[i]];
1509 var theItem = items[0];
1510 if (![
self isItemExpanded:theItem])
1524 for (var i = 0; i < c; i++)
1525 [
self collapseItem:items[i]];
1534 var _reloadItem =
function( anOutlineView, anItem)
1539 with (anOutlineView)
1542 var itemInfosForItems = _itemInfosForItems,
1543 dataSource = _outlineViewDataSource,
1544 itemUID = [anItem UID],
1545 itemInfo = itemInfosForItems[itemUID];
1552 var parent = itemInfo.parent,
1553 parentItemInfo = parent ? itemInfosForItems[[parent UID]] : _rootItemInfo,
1554 parentChildren = parentItemInfo.children,
1555 index = [parentChildren indexOfObjectIdenticalTo:anItem],
1556 newItem = [dataSource outlineView:anOutlineView child:index ofItem:parent];
1558 if (anItem !== newItem)
1560 itemInfosForItems[[anItem UID]] = nil;
1561 itemInfosForItems[[newItem UID]] = itemInfo;
1563 parentChildren[index] = newItem;
1564 _itemsForRows[itemInfo.row] = newItem;
1567 itemInfo.isExpandable = [dataSource outlineView:anOutlineView isItemExpandable:newItem];
1568 itemInfo.isExpanded = itemInfo.isExpandable && itemInfo.isExpanded;
1574 var _loadItemInfoForItem =
function( anOutlineView, anItem, isIntermediate)
1576 with (anOutlineView)
1578 var itemInfosForItems = _itemInfosForItems,
1579 dataSource = _outlineViewDataSource;
1582 var itemInfo = _rootItemInfo;
1587 var itemUID = [anItem UID],
1588 itemInfo = itemInfosForItems[itemUID];
1594 itemInfo.isExpandable = [dataSource outlineView:anOutlineView isItemExpandable:anItem];
1599 if (!itemInfo.isExpandable && itemInfo.isExpanded)
1601 itemInfo.isExpanded = NO;
1602 itemInfo.children = [];
1607 var weight = itemInfo.weight,
1608 descendants = anItem ? [anItem] : [];
1611 ![dataSource outlineView:anOutlineView shouldDeferDisplayingChildrenOfItem:anItem]))
1614 count = [dataSource outlineView:anOutlineView numberOfChildrenOfItem:anItem],
1615 level = itemInfo.level + 1;
1617 itemInfo.children = [];
1619 for (; index < count; ++index)
1621 var childItem = [dataSource outlineView:anOutlineView child:index ofItem:anItem],
1622 childItemInfo = itemInfosForItems[[childItem UID]];
1626 childItemInfo = { isExpanded:NO, isExpandable:NO, shouldShowOutlineDisclosureControl:YES, children:[], weight:1 };
1627 itemInfosForItems[[childItem UID]] = childItemInfo;
1630 itemInfo.children[index] = childItem;
1632 var childDescendants = _loadItemInfoForItem(anOutlineView, childItem, YES);
1634 childItemInfo.parent = anItem;
1635 childItemInfo.level = level;
1636 descendants = descendants.concat(childDescendants);
1640 itemInfo.weight = descendants.length;
1642 if (!isIntermediate)
1645 var index = MAX(itemInfo.row, 0),
1646 itemsForRows = _itemsForRows;
1648 descendants.unshift(index, weight);
1650 itemsForRows.splice.apply(itemsForRows, descendants);
1652 var count = itemsForRows.length;
1654 for (; index < count; ++index)
1655 itemInfosForItems[[itemsForRows[index] UID]].row = index;
1657 var deltaWeight = itemInfo.weight - weight;
1659 if (deltaWeight !== 0)
1661 var parent = itemInfo.parent;
1665 var parentItemInfo = itemInfosForItems[[parent UID]];
1667 parentItemInfo.weight += deltaWeight;
1668 parent = parentItemInfo.parent;
1672 _rootItemInfo.weight += deltaWeight;
1679 @implementation _CPOutlineViewTableViewDataSource :
CPObject
1686 self = [
super init];
1689 _outlineView = anOutlineView;
1694 - (CPInteger)numberOfRowsInTableView:(
CPTableView)anOutlineView
1696 return _outlineView._itemsForRows.length;
1701 return [_outlineView._outlineViewDataSource outlineView:_outlineView objectValueForTableColumn:aTableColumn byItem:_outlineView._itemsForRows[aRow]];
1708 [_outlineView._outlineViewDataSource outlineView:_outlineView setObjectValue:aValue forTableColumn:aColumn byItem:_outlineView._itemsForRows[aRow]];
1717 index = [theIndexes firstIndex];
1721 [items addObject:[_outlineView itemAtRow:index]]
1725 return [_outlineView._outlineViewDataSource outlineView:_outlineView writeItems:items toPasteboard:thePasteboard];
1728 - (int)_childIndexForDropOperation:(CPTableViewDropOperation)theDropOperation row:(
int)theRow offset:(CPPoint)theOffset
1730 if (_outlineView._shouldRetargetChildIndex)
1731 return _outlineView._retargedChildIndex;
1737 var parentItem = [_outlineView _parentItemForUpperRow:theRow - 1 andLowerRow:theRow atMouseOffset:theOffset],
1738 itemInfo = (parentItem !== nil) ? _outlineView._itemInfosForItems[[parentItem UID]] : _outlineView._rootItemInfo,
1739 children = itemInfo.children;
1741 childIndex = [children indexOfObject:[_outlineView itemAtRow:theRow]];
1744 childIndex = children.length;
1752 - (void)_parentItemForDropOperation:(CPTableViewDropOperation)theDropOperation row:(
int)theRow offset:(CPPoint)theOffset
1755 return [_outlineView _parentItemForUpperRow:theRow - 1 andLowerRow:theRow atMouseOffset:theOffset]
1757 return [_outlineView itemAtRow:theRow];
1761 proposedRow:(
int)theRow proposedDropOperation:(CPTableViewDropOperation)theOperation
1767 _outlineView._retargetedItem = nil;
1768 _outlineView._shouldRetargetItem = NO;
1770 _outlineView._retargedChildIndex = nil;
1771 _outlineView._shouldRetargetChildIndex = NO;
1773 var location = [_outlineView convertPoint:[theInfo
draggingLocation] fromView:nil],
1774 parentItem = [
self _parentItemForDropOperation:theOperation row:theRow offset:location],
1775 childIndex = [
self _childIndexForDropOperation:theOperation row:theRow offset:location];
1777 return [_outlineView._outlineViewDataSource outlineView:_outlineView validateDrop:theInfo proposedItem:parentItem proposedChildIndex:childIndex];
1785 var location = [_outlineView convertPoint:[theInfo
draggingLocation] fromView:nil],
1786 parentItem = [
self _parentItemForDropOperation:theOperation row:theRow offset:location],
1787 childIndex = [
self _childIndexForDropOperation:theOperation row:theRow offset:location];
1789 _outlineView._retargetedItem = nil;
1790 _outlineView._shouldRetargetItem = NO;
1792 _outlineView._retargedChildIndex = nil;
1793 _outlineView._shouldRetargetChildIndex = NO;
1795 return [_outlineView._outlineViewDataSource outlineView:_outlineView acceptDrop:theInfo item:parentItem childIndex:childIndex];
1800 if ((_outlineView._implementedOutlineViewDataSourceMethods &
1803 [[_outlineView dataSource] outlineView:_outlineView sortDescriptorsDidChange:oldSortDescriptors];
1809 @implementation _CPOutlineViewTableViewDelegate :
CPObject
1816 self = [
super init];
1819 _outlineView = anOutlineView;
1829 dataView = [_outlineView._outlineViewDelegate outlineView:_outlineView
1830 dataViewForTableColumn:theTableColumn
1831 item:[_outlineView itemAtRow:theRow]];
1844 - (BOOL)selectionShouldChangeInTableView:(
CPTableView)theTableView
1852 return [_outlineView._outlineViewDelegate outlineView:_outlineView shouldEditTableColumn:aColumn item:[_outlineView itemAtRow:aRow]];
1860 return [_outlineView._outlineViewDelegate outlineView:_outlineView heightOfRowByItem:[_outlineView itemAtRow:theRow]];
1869 var item = [_outlineView itemAtRow:aRowIndex];
1870 [_outlineView._outlineViewDelegate outlineView:_outlineView willDisplayView:aView forTableColumn:aTableColumn item:item];
1877 return [_outlineView._outlineViewDelegate outlineView:_outlineView isGroupItem:[_outlineView itemAtRow:aRow]];
1886 var item = [_outlineView itemAtRow:aRow];
1887 return [_outlineView._outlineViewDelegate outlineView:_outlineView menuForTableColumn:aTableColumn item:item]
1892 return [_outlineView menu] || [[_outlineView class] defaultMenu];
1902 - (id)initWithFrame:(CGRect)aFrame
1912 - (void)setState:(CPState)aState
1923 - (void)drawRect:(CGRect)aRect
1925 var bounds = [
self bounds],
1927 width = _CGRectGetWidth(bounds),
1928 height = _CGRectGetHeight(bounds);
1934 var centre = _CGPointMake(FLOOR(
width / 2.0), FLOOR(height / 2.0));
1982 _rootItemInfo = { isExpanded:YES, isExpandable:NO, level:-1, row:-1, children:[], weight:0 };
1985 _itemInfosForItems = { };
1986 _disclosureControlsForRows = [];
1991 _outlineTableColumn = [aCoder decodeObjectForKey:CPOutlineViewOutlineTableColumnKey];
1992 _indentationPerLevel = [aCoder decodeFloatForKey:CPOutlineViewIndentationPerLevelKey];
1994 _outlineViewDataSource = [aCoder decodeObjectForKey:CPOutlineViewDataSourceKey];
1995 _outlineViewDelegate = [aCoder decodeObjectForKey:CPOutlineViewDelegateKey];
1997 [
super setDataSource:[[_CPOutlineViewTableViewDataSource alloc] initWithOutlineView:self]];
1998 [
super setDelegate:[[_CPOutlineViewTableViewDelegate alloc] initWithOutlineView:self]];
2007 var internalDelegate = _delegate,
2008 internalDataSource = _dataSource;
2012 _delegate = internalDelegate;
2013 _dataSource = internalDataSource;
2015 [aCoder encodeObject:_outlineTableColumn forKey:CPOutlineViewOutlineTableColumnKey];
2016 [aCoder encodeFloat:_indentationPerLevel forKey:CPOutlineViewIndentationPerLevelKey];
2018 [aCoder encodeObject:_outlineViewDataSource forKey:CPOutlineViewDataSourceKey];
2019 [aCoder encodeObject:_outlineViewDelegate forKey:CPOutlineViewDelegateKey];
2032 ? [
CPColor colorWithCalibratedWhite:0.4 alpha: 1.0]
2033 : [
CPColor colorWithCalibratedWhite:0.5 alpha: 1.0]);