From c44715bef4579916c1bf55bfe2605b8da940acba Mon Sep 17 00:00:00 2001 From: Klaas Pieter Annema Date: Thu, 21 Jan 2010 11:59:28 +0100 Subject: [PATCH 01/58] added CPSpaceKeyCode to CPResponder --- AppKit/CPResponder.j | 1 + 1 file changed, 1 insertion(+) diff --git a/AppKit/CPResponder.j b/AppKit/CPResponder.j index 32de1dfaa..99c9b0ab5 100644 --- a/AppKit/CPResponder.j +++ b/AppKit/CPResponder.j @@ -27,6 +27,7 @@ CPDeleteKeyCode = 8; CPTabKeyCode = 9; CPReturnKeyCode = 13; CPEscapeKeyCode = 27; +CPSpaceKeyCode = 32; CPLeftArrowKeyCode = 37; CPUpArrowKeyCode = 38; CPRightArrowKeyCode = 39; From 050b75a2df6880ed1a635c374ff3ebf8e186606a Mon Sep 17 00:00:00 2001 From: Klaas Pieter Annema Date: Fri, 22 Jan 2010 20:17:34 +0100 Subject: [PATCH 02/58] Implemented visual feedback when dragging in CPTableView --- AppKit/CPTableView.j | 91 ++++++++++++++++++++++++++++++++++++-------- 1 file changed, 75 insertions(+), 16 deletions(-) diff --git a/AppKit/CPTableView.j b/AppKit/CPTableView.j index 43da901b4..864945f13 100644 --- a/AppKit/CPTableView.j +++ b/AppKit/CPTableView.j @@ -1451,14 +1451,56 @@ window.setTimeout(function(){ return YES; } -- (CPImage)dragImageForRowsWithIndexes:(CPIndexSet)dragRows tableColumns:(CPArray)theTableColumns event:(CPEvent)dragEvent offset:(CPPointPointer)dragImageOffset +- (CPImage)dragImageForRowsWithIndexes:(CPIndexSet)dragRows + tableColumns:(CPArray)theTableColumns + event:(CPEvent)dragEvent + offset:(CPPointPointer)dragImageOffset { - // FIXME: by default we should construct an image/view of the selcted rows which are visible - //var theDragView = [[CPImageView alloc] initWithFrame:_CGRectMake(0,0,32,32)]; - //[theDragView setImage:[[CPImage alloc] initWithContentsOfFile:@"Frameworks/AppKit/Resources/GenericFile.png" size:CGSizeMake(32,32)]]; - var image = [[CPImage alloc] initWithContentsOfFile:@"Frameworks/AppKit/Resources/GenericFile.png" size:CGSizeMake(32,32)]; - //return theDragView; - return image; + return [[CPImage alloc] initWithContentsOfFile:@"Frameworks/AppKit/Resources/GenericFile.png" size:CGSizeMake(32,32)]; +} + +- (CPView)dragViewForRowsWithIndexes:(CPIndexSet)theDraggedRows + tableColumns:(CPArray)theTableColumns + event:(CPEvent)theDragEvent + offset:(CPPoint)dragViewOffset +{ + var size = [self bounds].size, + view = [[CPView alloc] initWithFrame:CPMakeRect(dragViewOffset.x, dragViewOffset.y, size.width, size.height)]; + + [view setBackgroundColor:[CPColor clearColor]]; + [view setAlphaValue:0.7]; + + // We have to fetch all the data views for the selected rows and columns + // After that we can copy these add them to a transparent drag view and use that drag view + // to make it appear we are dragging images of those rows (as you would do in regular Cocoa) + var firstExposedColumn = [_exposedColumns firstIndex], + exposedLength = [_exposedColumns lastIndex] - firstExposedColumn + 1, + columns = []; + + [_exposedColumns getIndexes:columns maxCount:-1 inIndexRange:CPMakeRange(firstExposedColumn, exposedLength)]; + + var columnIndex = [columns count], + draggedDataViews = [], + dragViewHeight = 0.0; + + while (columnIndex--) { + var column = [_tableColumns objectAtIndex:columnIndex], + yOffset = 0, + rowIndex = CPNotFound; + + while ((rowIndex = [_selectedRowIndexes indexGreaterThanIndex:rowIndex]) !== CPNotFound) + { + var dataView = [self _newDataViewForRow:rowIndex tableColumn:column]; + + [dataView setBackgroundColor:[CPColor clearColor]]; + [dataView setFrame:[self frameOfDataViewAtColumn:columnIndex row:rowIndex]]; + [dataView setObjectValue:[self _objectValueForTableColumn:column row:rowIndex]]; + + [view addSubview:dataView]; + } + } + + return view; } - (void)setDraggingSourceOperationMask:(CPDragOperation)mask forLocal:(BOOL)isLocal @@ -1531,6 +1573,7 @@ window.setTimeout(function(){ - (id)_objectValueForTableColumn:(CPTableColumn)aTableColumn row:(CPInteger)aRowIndex { + CPLog.debug(@"_objectValueForTableColumn:%@ row: %@", aTableColumn, aRowIndex); var tableColumnUID = [aTableColumn UID], tableColumnObjectValues = _objectValues[tableColumnUID]; @@ -1548,6 +1591,7 @@ window.setTimeout(function(){ tableColumnObjectValues[aRowIndex] = objectValue; } + CPLog.debug(@"return %@", objectValue); return objectValue; } @@ -2157,15 +2201,30 @@ window.setTimeout(function(){ if([self canDragRowsWithIndexes:_draggedRowIndexes atPoint:aPoint] && [_dataSource tableView:self writeRowsWithIndexes:_draggedRowIndexes toPasteboard:pboard]) { - //create drag view/image - var theDragImage = [self dragImageForRowsWithIndexes:_draggedRowIndexes tableColumns:_exposedColumns event:[CPApp currentEvent] offset:CGSizeMakeZero()]; - //we should begin the drag opperation here - [self dragImage:theDragImage at:aPoint offset:CGSizeMakeZero() event:[CPApp currentEvent] pasteboard:pboard source:self slideBack:YES]; - //console.log([[CPDragServer sharedDragServer] draggingSource]) - // FIX ME: figure out what to do with the damn operation mask, does capp not support this yet? - // FIX ME: set the operation mask to _dragOperationDefaultMask - - //stop tracking + var currentEvent = [CPApp currentEvent], + offset = CPPointMakeZero(); + + // We deviate from the default Cocoa implementation here by asking for a view in stead of an image + // We support both, but the view prefered over the image because we can mimic the rows we are dragging + // by re-creating the data views for the dragged rows + var view = [self dragViewForRowsWithIndexes:_draggedRowIndexes + tableColumns:_exposedColumns + event:currentEvent + offset:CPPointMakeZero()]; + + if (!view) { + var image = [self dragImageForRowsWithIndexes:_draggedRowIndexes + tableColumns:_exposedColumns + event:currentEvent + offset:CPPointMakeZero()]; + + view = [[CPImageView alloc] initWithFrame:CPMakeRect(aPoint.x, aPoint.y, [image size].width, [image size].height)]; + [view setImage:image]; + + offset = aPoint; + } + + [self dragView:view at:offset offset:CPPointMakeZero() event:[CPApp currentEvent] pasteboard:pboard source:self slideBack:YES]; return NO; } } From 6749fa57ada0c39748d294b2b732c32817a775ac Mon Sep 17 00:00:00 2001 From: Klaas Pieter Annema Date: Fri, 22 Jan 2010 20:25:14 +0100 Subject: [PATCH 03/58] started implementing CPOutlineView drag & drop support --- AppKit/CPOutlineView.j | 81 ++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 81 insertions(+) diff --git a/AppKit/CPOutlineView.j b/AppKit/CPOutlineView.j index 972d48d64..848312d31 100644 --- a/AppKit/CPOutlineView.j +++ b/AppKit/CPOutlineView.j @@ -145,6 +145,8 @@ var CPOutlineViewDataSource_outlineView_setObjectValue_forTableColumn_byItem_ if ([_outlineViewDataSource respondsToSelector:@selector(outlineView:sortDescriptorsDidChange:)]) _implementedOutlineViewDataSourceMethods |= CPOutlineViewDataSource_outlineView_sortDescriptorsDidChange_; + [[super dataSource] setImplementedDataSourceMethods:_implementedOutlineViewDataSourceMethods]; + [self reloadData]; } @@ -488,6 +490,48 @@ var CPOutlineViewDataSource_outlineView_setObjectValue_forTableColumn_byItem_ return [super frameOfDataViewAtColumn:aColumn row:aRow]; } +// - (BOOL)continueTracking:(CGPoint)lastPoint at:(CGPoint)aPoint +// { +// if (!_isSelectingSession && _implementedOutlineViewDataSourceMethods & CPOutlineViewDataSource_outlineView_writeItems_toPasteboard_) +// { // Start dragging of the current rows is selected or the mouse was moved enough to initiate a drag +// // This isn't the best way to do this because this requires the user to move the mouse at a certain speed +// // TODO: mouseDown currently always selects a row +// var offset = CPMakePoint(lastPoint.x - aPoint.x, ABS(lastPoint.y - aPoint.y)); +// if (offset.x > 3.0 || ([self verticalMotionCanBeginDrag] && ABS(offset.y) > 3) || ([_selectedRowIndexes containsIndex:row])) +// { +// var row = [self rowAtPoint:aPoint]; +// +// CPLog.debug(@"start drag") +// +// var draggedItems = []; +// // Check if we are dragging a selection or a single row +// if ([_selectedRowIndexes containsIndex:row]) +// { +// // Get all the items from the current selection +// var draggedIndexes = []; +// [_selectedRowIndexes getIndexes:draggedIndexes maxCount:[_selectedRowIndexes count] inIndexRange:nil] +// +// var index = [draggedIndexes count]; +// while (index--) +// [draggedItems addObject:[self itemAtRow:draggedIndexes[index]]]; +// +// var pasteboard = [CPPasteboard pasteboardWithName:CPDragPboard]; +// } +// else +// [draggedItems addObject:[self itemAtRow:row]]; +// +// // Tell the datasource to write the items to the paste board +// // We stop the drag if it's not allowed +// if (![_outlineViewDataSource writeItems:draggedIndexes toPasteboard:pasteboard]) +// return [super continueTracking:lastPoint at:aPoint]; +// +// CPLog.debug(@"dragged items: %@", draggedItems); +// } +// } +// +// return [super continueTracking:lastPoint at:aPoint]; +// } + - (void)_loadDataViewsInRows:(CPIndexSet)rows columns:(CPIndexSet)columns { [super _loadDataViewsInRows:rows columns:columns]; @@ -757,6 +801,7 @@ var _loadItemInfoForItem = function(/*CPOutlineView*/ anOutlineView, /*id*/ anIt @implementation _CPOutlineViewTableViewDataSource : CPObject { + int _implementedDataSourceMethods @accessors(property=implementedDataSourceMethods); CPObject _outlineView; } @@ -780,6 +825,42 @@ var _loadItemInfoForItem = function(/*CPOutlineView*/ anOutlineView, /*id*/ anIt return [_outlineView._outlineViewDataSource outlineView:_outlineView objectValueForTableColumn:aTableColumn byItem:_outlineView._itemsForRows[aRow]]; } +- (BOOL)tableView:(CPTableView)aTableColumn writeRowsWithIndexes:(CPIndexSet)theIndexes toPasteboard:(CPPasteboard)thePasteboard +{ + if (!_outlineView._implementedOutlineViewDataSourceMethods & CPOutlineViewDataSource_outlineView_writeItems_toPasteboard_) + return NO; + + var rowIndexes = []; + [theIndexes getIndexes:rowIndexes maxCount:[theIndexes count] inIndexRange:nil]; + + var rowIndex = [rowIndexes count], + items = []; + + while (rowIndex--) + [items addObject:[_outlineView itemAtRow:[rowIndexes objectAtIndex:rowIndex]]]; + + return [_outlineView._outlineViewDataSource outlineView:_outlineView writeItems:items toPasteboard:thePasteboard]; +} + +- (CPDragOperation)tableView:(CPTableView)aTableView validateDrop:(id < CPDraggingInfo >)theInfo + proposedRow:(int)theRow proposedDropOperation:(CPTableViewDropOperation)theOperation +{ + if (!_outlineView._implementedOutlineViewDataSourceMethods & CPOutlineViewDataSource_outlineView_validateDrop_proposedItem_proposedChildIndex_) + return CPDragOperationNone; + + return [_outlineView._outlineViewDataSource outlineView:_outlineView validateDrop:theInfo proposedItem:[_outlineView itemAtRow:theRow] proposedChildIndex:theRow]; +} + +- (BOOL)tableView:(CPTableView)aTableView acceptDrop:(id )theInfo row:(int)theRow dropOperation:(CPTableViewDropOperation)theOperation +{ + + CPLog.debug(@"tableview accept dorp"); + if (!_outlineView._implementedOutlineViewDataSourceMethods & CPOutlineViewDataSource_outlineView_acceptDrop_item_childIndex_) + return NO; + + return [_outlineView._outlineViewDataSource outlineView:_outlineView acceptDrop:theInfo item:[_outlineView itemAtRow:theRow] childIndex:0]; +} + @end @implementation _CPOutlineViewTableViewDelegate : CPObject From 76717c7177349c858bac857a9178925babb1bbd1 Mon Sep 17 00:00:00 2001 From: Klaas Pieter Annema Date: Fri, 22 Jan 2010 20:37:17 +0100 Subject: [PATCH 04/58] converted spaces to tabs --- AppKit/CPTableView.j | 222 +++++++++++++++++++++---------------------- 1 file changed, 111 insertions(+), 111 deletions(-) diff --git a/AppKit/CPTableView.j b/AppKit/CPTableView.j index 864945f13..ff6f6e56d 100644 --- a/AppKit/CPTableView.j +++ b/AppKit/CPTableView.j @@ -481,10 +481,10 @@ window.setTimeout(function(){ [self setSelectionHightlightColor:[CPColor selectionColorSourceView]]; _destinationDragStyle = CPTableViewDraggingDestinationFeedbackStyleSourceList; } - else - { - [self setSelectionHightlightColor:[CPColor selectionColor]]; - _destinationDragStyle = CPTableViewDraggingDestinationFeedbackStyleRegular; + else + { + [self setSelectionHightlightColor:[CPColor selectionColor]]; + _destinationDragStyle = CPTableViewDraggingDestinationFeedbackStyleRegular; } } @@ -1452,55 +1452,55 @@ window.setTimeout(function(){ } - (CPImage)dragImageForRowsWithIndexes:(CPIndexSet)dragRows - tableColumns:(CPArray)theTableColumns - event:(CPEvent)dragEvent - offset:(CPPointPointer)dragImageOffset + tableColumns:(CPArray)theTableColumns + event:(CPEvent)dragEvent + offset:(CPPointPointer)dragImageOffset { return [[CPImage alloc] initWithContentsOfFile:@"Frameworks/AppKit/Resources/GenericFile.png" size:CGSizeMake(32,32)]; } - (CPView)dragViewForRowsWithIndexes:(CPIndexSet)theDraggedRows - tableColumns:(CPArray)theTableColumns - event:(CPEvent)theDragEvent - offset:(CPPoint)dragViewOffset + tableColumns:(CPArray)theTableColumns + event:(CPEvent)theDragEvent + offset:(CPPoint)dragViewOffset { - var size = [self bounds].size, - view = [[CPView alloc] initWithFrame:CPMakeRect(dragViewOffset.x, dragViewOffset.y, size.width, size.height)]; - - [view setBackgroundColor:[CPColor clearColor]]; - [view setAlphaValue:0.7]; - - // We have to fetch all the data views for the selected rows and columns - // After that we can copy these add them to a transparent drag view and use that drag view - // to make it appear we are dragging images of those rows (as you would do in regular Cocoa) - var firstExposedColumn = [_exposedColumns firstIndex], - exposedLength = [_exposedColumns lastIndex] - firstExposedColumn + 1, - columns = []; - - [_exposedColumns getIndexes:columns maxCount:-1 inIndexRange:CPMakeRange(firstExposedColumn, exposedLength)]; - - var columnIndex = [columns count], - draggedDataViews = [], - dragViewHeight = 0.0; - - while (columnIndex--) { - var column = [_tableColumns objectAtIndex:columnIndex], - yOffset = 0, - rowIndex = CPNotFound; - - while ((rowIndex = [_selectedRowIndexes indexGreaterThanIndex:rowIndex]) !== CPNotFound) - { - var dataView = [self _newDataViewForRow:rowIndex tableColumn:column]; - - [dataView setBackgroundColor:[CPColor clearColor]]; - [dataView setFrame:[self frameOfDataViewAtColumn:columnIndex row:rowIndex]]; - [dataView setObjectValue:[self _objectValueForTableColumn:column row:rowIndex]]; - - [view addSubview:dataView]; - } - } - - return view; + var size = [self bounds].size, + view = [[CPView alloc] initWithFrame:CPMakeRect(dragViewOffset.x, dragViewOffset.y, size.width, size.height)]; + + [view setBackgroundColor:[CPColor clearColor]]; + [view setAlphaValue:0.7]; + + // We have to fetch all the data views for the selected rows and columns + // After that we can copy these add them to a transparent drag view and use that drag view + // to make it appear we are dragging images of those rows (as you would do in regular Cocoa) + var firstExposedColumn = [_exposedColumns firstIndex], + exposedLength = [_exposedColumns lastIndex] - firstExposedColumn + 1, + columns = []; + + [_exposedColumns getIndexes:columns maxCount:-1 inIndexRange:CPMakeRange(firstExposedColumn, exposedLength)]; + + var columnIndex = [columns count], + draggedDataViews = [], + dragViewHeight = 0.0; + + while (columnIndex--) { + var column = [_tableColumns objectAtIndex:columnIndex], + yOffset = 0, + rowIndex = CPNotFound; + + while ((rowIndex = [_selectedRowIndexes indexGreaterThanIndex:rowIndex]) !== CPNotFound) + { + var dataView = [self _newDataViewForRow:rowIndex tableColumn:column]; + + [dataView setBackgroundColor:[CPColor clearColor]]; + [dataView setFrame:[self frameOfDataViewAtColumn:columnIndex row:rowIndex]]; + [dataView setObjectValue:[self _objectValueForTableColumn:column row:rowIndex]]; + + [view addSubview:dataView]; + } + } + + return view; } - (void)setDraggingSourceOperationMask:(CPDragOperation)mask forLocal:(BOOL)isLocal @@ -1573,7 +1573,7 @@ window.setTimeout(function(){ - (id)_objectValueForTableColumn:(CPTableColumn)aTableColumn row:(CPInteger)aRowIndex { - CPLog.debug(@"_objectValueForTableColumn:%@ row: %@", aTableColumn, aRowIndex); + CPLog.debug(@"_objectValueForTableColumn:%@ row: %@", aTableColumn, aRowIndex); var tableColumnUID = [aTableColumn UID], tableColumnObjectValues = _objectValues[tableColumnUID]; @@ -1591,7 +1591,7 @@ window.setTimeout(function(){ tableColumnObjectValues[aRowIndex] = objectValue; } - CPLog.debug(@"return %@", objectValue); + CPLog.debug(@"return %@", objectValue); return objectValue; } @@ -1991,7 +1991,7 @@ window.setTimeout(function(){ indexes = [], rectSelector = @selector(rectOfRow:); - [_selectionHightlightColor setFill]; + [_selectionHightlightColor setFill]; if ([_selectedRowIndexes count] >= 1) @@ -2201,30 +2201,30 @@ window.setTimeout(function(){ if([self canDragRowsWithIndexes:_draggedRowIndexes atPoint:aPoint] && [_dataSource tableView:self writeRowsWithIndexes:_draggedRowIndexes toPasteboard:pboard]) { - var currentEvent = [CPApp currentEvent], - offset = CPPointMakeZero(); - - // We deviate from the default Cocoa implementation here by asking for a view in stead of an image - // We support both, but the view prefered over the image because we can mimic the rows we are dragging - // by re-creating the data views for the dragged rows - var view = [self dragViewForRowsWithIndexes:_draggedRowIndexes - tableColumns:_exposedColumns - event:currentEvent - offset:CPPointMakeZero()]; - - if (!view) { - var image = [self dragImageForRowsWithIndexes:_draggedRowIndexes - tableColumns:_exposedColumns - event:currentEvent - offset:CPPointMakeZero()]; - - view = [[CPImageView alloc] initWithFrame:CPMakeRect(aPoint.x, aPoint.y, [image size].width, [image size].height)]; - [view setImage:image]; - - offset = aPoint; - } - - [self dragView:view at:offset offset:CPPointMakeZero() event:[CPApp currentEvent] pasteboard:pboard source:self slideBack:YES]; + var currentEvent = [CPApp currentEvent], + offset = CPPointMakeZero(); + + // We deviate from the default Cocoa implementation here by asking for a view in stead of an image + // We support both, but the view prefered over the image because we can mimic the rows we are dragging + // by re-creating the data views for the dragged rows + var view = [self dragViewForRowsWithIndexes:_draggedRowIndexes + tableColumns:_exposedColumns + event:currentEvent + offset:CPPointMakeZero()]; + + if (!view) { + var image = [self dragImageForRowsWithIndexes:_draggedRowIndexes + tableColumns:_exposedColumns + event:currentEvent + offset:CPPointMakeZero()]; + + view = [[CPImageView alloc] initWithFrame:CPMakeRect(aPoint.x, aPoint.y, [image size].width, [image size].height)]; + [view setImage:image]; + + offset = aPoint; + } + + [self dragView:view at:offset offset:CPPointMakeZero() event:[CPApp currentEvent] pasteboard:pboard source:self slideBack:YES]; return NO; } } @@ -2595,32 +2595,32 @@ window.setTimeout(function(){ var anEvent = [events objectAtIndex:i], key = [anEvent keyCode]; - if(key === CPDeleteKeyCode && [_delegate respondsToSelector: @selector(tableViewDeleteKeyPressed:)]) + if(key === CPDeleteKeyCode && [_delegate respondsToSelector: @selector(tableViewDeleteKeyPressed:)]) [_delegate tableViewDeleteKeyPressed:self]; - if(key === CPUpArrowKeyCode) - { - if([[self selectedRowIndexes] count] > 0) - { - var extend = NO; + if(key === CPUpArrowKeyCode) + { + if([[self selectedRowIndexes] count] > 0) + { + var extend = NO; - if(([anEvent modifierFlags] & CPShiftKeyMask) && _allowsMultipleSelection) + if(([anEvent modifierFlags] & CPShiftKeyMask) && _allowsMultipleSelection) extend = YES; - var i = [[self selectedRowIndexes] firstIndex]; - if(i > 0) - i--; //set index to the prev row before the first row selected - } + var i = [[self selectedRowIndexes] firstIndex]; + if(i > 0) + i--; //set index to the prev row before the first row selected + } else - { - var extend = NO; - //no rows are currently selected - if([self numberOfRows] > 0) - var i = [self numberOfRows] - 1; //select the first row - } + { + var extend = NO; + //no rows are currently selected + if([self numberOfRows] > 0) + var i = [self numberOfRows] - 1; //select the first row + } - if(_implementedDelegateMethods & CPTableViewDelegate_tableView_shouldSelectRow_) + if(_implementedDelegateMethods & CPTableViewDelegate_tableView_shouldSelectRow_) { while((![_delegate tableView:self shouldSelectRow:i]) && i > 0) @@ -2641,31 +2641,31 @@ window.setTimeout(function(){ [self scrollRowToVisible:i]; [self _noteSelectionDidChange]; } - } + } - if(key == CPDownArrowKeyCode) - { - if([[self selectedRowIndexes] count] > 0) - { - var extend = NO; + if(key == CPDownArrowKeyCode) + { + if([[self selectedRowIndexes] count] > 0) + { + var extend = NO; - if(([anEvent modifierFlags] & CPShiftKeyMask) && _allowsMultipleSelection) + if(([anEvent modifierFlags] & CPShiftKeyMask) && _allowsMultipleSelection) extend = YES; - var i = [[self selectedRowIndexes] lastIndex]; - if(i<[self numberOfRows] - 1) - i++; //set index to the next row after the last row selected - } + var i = [[self selectedRowIndexes] lastIndex]; + if(i<[self numberOfRows] - 1) + i++; //set index to the next row after the last row selected + } else - { - var extend = NO; - //no rows are currently selected - if([self numberOfRows] > 0) - var i = 0; //select the first row - } + { + var extend = NO; + //no rows are currently selected + if([self numberOfRows] > 0) + var i = 0; //select the first row + } - if(_implementedDelegateMethods & CPTableViewDelegate_tableView_shouldSelectRow_) + if(_implementedDelegateMethods & CPTableViewDelegate_tableView_shouldSelectRow_) { while((![_delegate tableView:self shouldSelectRow:i]) && i<[self numberOfRows]) @@ -2686,7 +2686,7 @@ window.setTimeout(function(){ [self scrollRowToVisible:i]; [self _noteSelectionDidChange]; } - } + } } } From e09b63183c4475d310a1a17041d6555e4d897586 Mon Sep 17 00:00:00 2001 From: Klaas Pieter Annema Date: Fri, 22 Jan 2010 20:44:58 +0100 Subject: [PATCH 05/58] added cpviewanimation --- AppKit/CPViewAnimation.j | 184 +++++++++++++++++++++++++++++++++++++++ 1 file changed, 184 insertions(+) create mode 100644 AppKit/CPViewAnimation.j diff --git a/AppKit/CPViewAnimation.j b/AppKit/CPViewAnimation.j new file mode 100644 index 000000000..5950d9609 --- /dev/null +++ b/AppKit/CPViewAnimation.j @@ -0,0 +1,184 @@ +/* + * CPViewAnimation.j + * + * Created by Klaas Pieter Annema on September 3, 2009. + * Copyright 2009, Sofa BV + */ + + +@import + +CPViewAnimationTargetKey = @"CPViewAnimationTarget"; +CPViewAnimationStartFrameKey = @"CPViewAnimationStartFrame"; +CPViewAnimationEndFrameKey = @"CPViewAnimationEndFrame"; +CPViewAnimationEffectKey = @"CPViewAnimationEffect"; + +CPViewAnimationFadeInEffect = @"CPViewAnimationFadeIn"; +CPViewAnimationFadeOutEffect = @"CPViewAnimationFadeOut"; + +@implementation CPViewAnimation : CPAnimation +{ + CPArray _viewAnimations; +} + +- (id)initWithViewAnimations:(CPArray)viewAnimations +{ + if(self = [super initWithDuration:0.5 animationCurve:CPAnimationLinear]) + { + [self setViewAnimations:viewAnimations]; + } + return self; +} + +// ============= +// = ANIMATION = +// ============= +- (void)startAnimation +{ + var animationIndex = [_viewAnimations count]; + + while (animationIndex--) + { + var dictionary = [_viewAnimations objectAtIndex:animationIndex]; + + var view = [self _targetView:dictionary], + startFrame = [self _startFrame:dictionary]; + + [view setFrame:startFrame]; + + var effect = [self _effect:dictionary]; + + if (effect === CPViewAnimationFadeInEffect) + { + [view setAlphaValue:0.0]; + [view setHidden:NO]; + } + else if (effect === CPViewAnimationFadeOutEffect) + [view setAlphaValue:1.0]; + } + + [super startAnimation]; +} + +- (void)setCurrentProgress:(NSAnimationProgress)progress +{ + [super setCurrentProgress:progress]; + + var animationIndex = [_viewAnimations count]; + while (animationIndex--) + { + var dictionary = [_viewAnimations objectAtIndex:animationIndex]; + + // Update the view's frame + var view = [self _targetView:dictionary] + startFrame = [self _startFrame:dictionary] + endFrame = [self _endFrame:dictionary] + differenceFrame = CPRectMakeZero(); + + differenceFrame.origin.x = endFrame.origin.x - startFrame.origin.x; + differenceFrame.origin.y = endFrame.origin.y - startFrame.origin.y; + differenceFrame.size.width = endFrame.size.width - startFrame.size.width; + differenceFrame.size.height = endFrame.size.height - startFrame.size.height; + + var intermediateFrame = CPRectMakeZero(); + intermediateFrame.origin.x = startFrame.origin.x + differenceFrame.origin.x * progress; + intermediateFrame.origin.y = startFrame.origin.y + differenceFrame.origin.y * progress; + intermediateFrame.size.width = startFrame.size.width + differenceFrame.size.width * progress; + intermediateFrame.size.height = startFrame.size.height + differenceFrame.size.height * progress; + + [view setFrame:intermediateFrame]; + + // Update the view's alpha value + var effect = [self _effect:dictionary]; + + if (effect === CPViewAnimationFadeInEffect) + [view setAlphaValue:1.0 * progress]; + else if (effect === CPViewAnimationFadeOutEffect) + [view setAlphaValue:1.0 + ( 0.0 - 1.0 ) * progress]; + + if (progress === 1.0) + [view setHidden:CPRectIsNull(endFrame) || [view alphaValue] === 0.0]; + } +} + +- (void)stopAnimation +{ + var animationIndex = [_viewAnimations count]; + while (animationIndex--) + { + var dictionary = [_viewAnimations objectAtIndex:animationIndex]; + + var view = [self _targetView:dictionary], + endFrame = [self _endFrame:dictionary]; + + [view setFrame:endFrame]; + + var effect = [self _effect:dictionary]; + + if (effect === CPViewAnimationFadeInEffect) + [view setAlphaValue:1.0]; + else if (effect === CPViewAnimationFadeOutEffect) + [view setAlphaValue:0.0]; + + [view setHidden:CPRectIsNull(endFrame) || [view alphaValue] === 0.0]; + } + + [super stopAnimation]; +} + +// =============== +// = CONVENIENCE = +// =============== +- (id)_targetView:(CPDictionary)dictionary +{ + var targetView = [dictionary valueForKey:CPViewAnimationTargetKey]; + + if (!targetView) + [CPException raise:CPInternalInconsistencyException reason:[CPString stringWithFormat:@"view animation: %@ does not have a target view", [dictionary description]]]; + + return targetView; +} + +- (CPRect)_startFrame:(CPDictionary)dictionary +{ + var startFrame = [dictionary valueForKey:CPViewAnimationStartFrameKey]; + + if (!startFrame) + return [[self _targetView:dictionary] frame]; + + return startFrame; +} + +- (CPRect)_endFrame:(CPDictionary)dictionary +{ + var endFrame = [dictionary valueForKey:CPViewAnimationEndFrameKey]; + + if (!endFrame) + return [[self _targetView:dictionary] frame]; + + return endFrame; +} + +- (CPString)_effect:(CPDictionary)dictionary +{ + return [dictionary valueForKey:CPViewAnimationEffectKey]; +} + +// ============= +// = ACCESSORS = +// ============= +- (CPArray)viewAnimations +{ + return _viewAnimations; +} + +- (void)setViewAnimations:(CPArray)viewAnimations +{ + if (viewAnimations != _viewAnimations) + { + [self stopAnimation]; + _viewAnimations = [viewAnimations copy]; + } +} + +@end From 913a18eaaf30e5fc902e25b3694183b87bed2c0f Mon Sep 17 00:00:00 2001 From: Klaas Pieter Annema Date: Wed, 27 Jan 2010 10:40:51 +0100 Subject: [PATCH 06/58] completed tableview merge --- AppKit/CPTableView.j | 60 +------------------------------------------- 1 file changed, 1 insertion(+), 59 deletions(-) diff --git a/AppKit/CPTableView.j b/AppKit/CPTableView.j index c1e985b69..28872aaf5 100644 --- a/AppKit/CPTableView.j +++ b/AppKit/CPTableView.j @@ -1484,64 +1484,6 @@ window.setTimeout(function(){ return view; } -- (CPImage)dragViewForRowsWithIndexes:(CPIndexSet)dragRows tableColumns:(CPArray)theTableColumns event:(CPEvent)dragEvent offset:(CPPointPointer)dragImageOffset -{ - var draggedRowsArray = [], - colCount = [theTableColumns count], - rowsCount = [dragRows count], - firstRowIndex = [dragRows firstIndex], - rowIndexesLength = [dragRows lastIndex] - firstRowIndex + 1, - - firstRowRect = [self rectOfRow:firstRowIndex], - exposedMinX = CGRectGetMinX([self exposedClipRect]), - dragViewWidth = CGRectGetWidth([self exposedClipRect]), - dragViewHeight = rowIndexesLength * _rowHeight, - - location = [self convertPoint:[dragEvent locationInWindow] fromView:nil]; - - dragImageOffset.x = exposedMinX + CGRectGetMinX(firstRowRect) - location.x + dragViewWidth/2; - dragImageOffset.y = CGRectGetMinY(firstRowRect) - location.y + dragViewHeight/2; - - var draggedView = [[CPView alloc] initWithFrame:CGRectMake(0, 0, dragViewWidth, dragViewHeight)]; - - [dragRows getIndexes:draggedRowsArray maxCount:-1 inIndexRange:CPMakeRange(firstRowIndex, rowIndexesLength)]; - - // calculate the dragImageOffset : we want the ghost row to be where the real row is. - - for (var i = 0; i < rowsCount ; i++) - { - var rowIndex = draggedRowsArray[i]; - var dataViewOriginY = (rowIndex - firstRowIndex) * [self rowHeight]; - for (var c = 0; c < colCount; c++) - { - var column = [theTableColumns objectAtIndex:c], - tableColumnUID = [column UID], - dataView = _dataViewsForTableColumns[tableColumnUID][rowIndex]; - - var frame = [dataView frame]; - frame.origin.y = dataViewOriginY; - frame.origin.x -= exposedMinX; - - // Mega hack: The default CPView impl. doesn't implement -copy so we copy the innerHTML - // It ok because it's a temporary view and we won't have to interact with it later ... - // ... except we want the text to be normal when it's a selected row (unset the highlighted theme state) - // and that does'nt work. - // Possible fix: only for default dataviews (CPTextField), we can implement -copy and unset the state - var html = dataView._DOMElement.innerHTML; - var dataViewCopy = [[CPView alloc] initWithFrame:frame]; - dataViewCopy._DOMElement.innerHTML = html; - - // This works (don't know how ?!). Until we fix the previous bug, we can stay with a white transparent bg - // so at least we have a visible feedback of the dragged row. Maybe less opaque ... - [dataViewCopy setBackgroundColor:[CPColor colorWithWhite:1 alpha:0.7]]; - - [draggedView addSubview:dataViewCopy]; - } - } - - return draggedView; -} - - (void)setDraggingSourceOperationMask:(CPDragOperation)mask forLocal:(BOOL)isLocal { //ignoral local for the time being since only one capp app can run at a time... @@ -2243,7 +2185,7 @@ window.setTimeout(function(){ var pboard = [CPPasteboard pasteboardWithName:CPDragPboard]; if([self canDragRowsWithIndexes:_draggedRowIndexes atPoint:aPoint] && [_dataSource tableView:self writeRowsWithIndexes:_draggedRowIndexes toPasteboard:pboard]) - {ยง + { var currentEvent = [CPApp currentEvent], offset = CPPointMakeZero(); From def314b5ad91df4e9fb3374430b9bbbbba61fcf9 Mon Sep 17 00:00:00 2001 From: Klaas Pieter Annema Date: Wed, 27 Jan 2010 11:05:31 +0100 Subject: [PATCH 07/58] removed log statements from cptableview --- AppKit/CPTableView.j | 2 -- 1 file changed, 2 deletions(-) diff --git a/AppKit/CPTableView.j b/AppKit/CPTableView.j index 28872aaf5..72726402b 100644 --- a/AppKit/CPTableView.j +++ b/AppKit/CPTableView.j @@ -1554,7 +1554,6 @@ window.setTimeout(function(){ - (id)_objectValueForTableColumn:(CPTableColumn)aTableColumn row:(CPInteger)aRowIndex { - CPLog.debug(@"_objectValueForTableColumn:%@ row: %@", aTableColumn, aRowIndex); var tableColumnUID = [aTableColumn UID], tableColumnObjectValues = _objectValues[tableColumnUID]; @@ -1572,7 +1571,6 @@ window.setTimeout(function(){ tableColumnObjectValues[aRowIndex] = objectValue; } - CPLog.debug(@"return %@", objectValue); return objectValue; } From 99df7f6acb78c5bd8afd301ef2efa508dd338287 Mon Sep 17 00:00:00 2001 From: Klaas Pieter Annema Date: Thu, 28 Jan 2010 16:54:50 +0100 Subject: [PATCH 08/58] - further implemented CPOutlineView drag & drop support - implemented a work around in CPPlatformWindow+DOM.j for the javascript drop event never being fired --- AppKit/CPOutlineView.j | 74 ++++------ AppKit/CPTableView.j | 155 ++++++++++++++------- AppKit/Platform/DOM/CPPlatformWindow+DOM.j | 5 +- 3 files changed, 138 insertions(+), 96 deletions(-) diff --git a/AppKit/CPOutlineView.j b/AppKit/CPOutlineView.j index 848312d31..c654d333e 100644 --- a/AppKit/CPOutlineView.j +++ b/AppKit/CPOutlineView.j @@ -490,47 +490,15 @@ var CPOutlineViewDataSource_outlineView_setObjectValue_forTableColumn_byItem_ return [super frameOfDataViewAtColumn:aColumn row:aRow]; } -// - (BOOL)continueTracking:(CGPoint)lastPoint at:(CGPoint)aPoint -// { -// if (!_isSelectingSession && _implementedOutlineViewDataSourceMethods & CPOutlineViewDataSource_outlineView_writeItems_toPasteboard_) -// { // Start dragging of the current rows is selected or the mouse was moved enough to initiate a drag -// // This isn't the best way to do this because this requires the user to move the mouse at a certain speed -// // TODO: mouseDown currently always selects a row -// var offset = CPMakePoint(lastPoint.x - aPoint.x, ABS(lastPoint.y - aPoint.y)); -// if (offset.x > 3.0 || ([self verticalMotionCanBeginDrag] && ABS(offset.y) > 3) || ([_selectedRowIndexes containsIndex:row])) -// { -// var row = [self rowAtPoint:aPoint]; -// -// CPLog.debug(@"start drag") -// -// var draggedItems = []; -// // Check if we are dragging a selection or a single row -// if ([_selectedRowIndexes containsIndex:row]) -// { -// // Get all the items from the current selection -// var draggedIndexes = []; -// [_selectedRowIndexes getIndexes:draggedIndexes maxCount:[_selectedRowIndexes count] inIndexRange:nil] -// -// var index = [draggedIndexes count]; -// while (index--) -// [draggedItems addObject:[self itemAtRow:draggedIndexes[index]]]; -// -// var pasteboard = [CPPasteboard pasteboardWithName:CPDragPboard]; -// } -// else -// [draggedItems addObject:[self itemAtRow:row]]; -// -// // Tell the datasource to write the items to the paste board -// // We stop the drag if it's not allowed -// if (![_outlineViewDataSource writeItems:draggedIndexes toPasteboard:pasteboard]) -// return [super continueTracking:lastPoint at:aPoint]; -// -// CPLog.debug(@"dragged items: %@", draggedItems); -// } -// } -// -// return [super continueTracking:lastPoint at:aPoint]; -// } +- (CPRect)rectForDropHighlightViewBetweenUpperRow:(int)theUpperRowIndex andLowerRow:(int)theLowerRowIndex +{ + // Just call super and update the x to reflect the current indentation level + var level = [self levelForRow:theLowerRowIndex], + rect = [super rectForDropHighlightViewBetweenUpperRow:theUpperRowIndex andLowerRow:theLowerRowIndex]; + + rect.origin.x = level * [self indentationPerLevel]; + return rect; +} - (void)_loadDataViewsInRows:(CPIndexSet)rows columns:(CPIndexSet)columns { @@ -847,18 +815,30 @@ var _loadItemInfoForItem = function(/*CPOutlineView*/ anOutlineView, /*id*/ anIt { if (!_outlineView._implementedOutlineViewDataSourceMethods & CPOutlineViewDataSource_outlineView_validateDrop_proposedItem_proposedChildIndex_) return CPDragOperationNone; - - return [_outlineView._outlineViewDataSource outlineView:_outlineView validateDrop:theInfo proposedItem:[_outlineView itemAtRow:theRow] proposedChildIndex:theRow]; + + var droppedItem = [_outlineView itemAtRow:theRow], + parentItem = [_outlineView parentForItem:droppedItem], + + var itemInfo = (parentItem != nil) ? _outlineView._itemInfosForItems[[parentItem UID]] : _outlineView._rootItemInfo, + children = itemInfo.children, + childIndex = [children indexOfObject:droppedItem]; + + return [_outlineView._outlineViewDataSource outlineView:_outlineView validateDrop:theInfo proposedItem:parentItem proposedChildIndex:childIndex]; } - (BOOL)tableView:(CPTableView)aTableView acceptDrop:(id )theInfo row:(int)theRow dropOperation:(CPTableViewDropOperation)theOperation { - - CPLog.debug(@"tableview accept dorp"); if (!_outlineView._implementedOutlineViewDataSourceMethods & CPOutlineViewDataSource_outlineView_acceptDrop_item_childIndex_) return NO; - - return [_outlineView._outlineViewDataSource outlineView:_outlineView acceptDrop:theInfo item:[_outlineView itemAtRow:theRow] childIndex:0]; + + var droppedItem = [_outlineView itemAtRow:theRow], + parentItem = [_outlineView parentForItem:droppedItem], + + var itemInfo = (parentItem != nil) ? _outlineView._itemInfosForItems[[parentItem UID]] : _outlineView._rootItemInfo, + children = itemInfo.children, + childIndex = [children indexOfObject:droppedItem]; + + return [_outlineView._outlineViewDataSource outlineView:_outlineView acceptDrop:theInfo item:parentItem childIndex:childIndex]; } @end diff --git a/AppKit/CPTableView.j b/AppKit/CPTableView.j index 72726402b..eee98fbe2 100644 --- a/AppKit/CPTableView.j +++ b/AppKit/CPTableView.j @@ -182,6 +182,8 @@ CPTableViewFirstColumnOnlyAutoresizingStyle = 5; SEL _doubleAction; unsigned _columnAutoResizingStyle; + CPView _dropOperationFeedbackView; + // BOOL _verticalMotionCanDrag; // unsigned _destinationDragStyle; // BOOL _isSelectingSession; @@ -249,10 +251,10 @@ window.setTimeout(function(){ self._retargetedDropOperation = nil; self._dragOperationDefaultMask = nil; self._destinationDragStyle = CPTableViewDraggingDestinationFeedbackStyleRegular; - self._dropOperationFeedbackView = [[_dropOperationDrawingView alloc] initWithFrame:_CGRectMakeZero()]; - [self addSubview:_dropOperationFeedbackView]; - [_dropOperationFeedbackView setHidden:YES]; - [_dropOperationFeedbackView setTableView:self]; + // self._dropOperationFeedbackView = [[_dropOperationDrawingView alloc] initWithFrame:_CGRectMakeZero()]; + // [self addSubview:_dropOperationFeedbackView]; + // [_dropOperationFeedbackView setHidden:YES]; + // [_dropOperationFeedbackView setTableView:self]; },0); _tableDrawView = [[_CPTableDrawView alloc] initWithTableView:self]; @@ -1535,8 +1537,6 @@ window.setTimeout(function(){ return _verticalMotionCanDrag; } - - //Sorting /* * - setSortDescriptors: @@ -2297,18 +2297,29 @@ window.setTimeout(function(){ [self sendAction:_doubleAction to:_target]; } +- (CPView)_dropOperationFeedbackView +{ + return _dropOperationFeedbackView; +} + +- (void)_setDropOperationFeedbackView:(CPView)theFeedbackView +{ + if (_dropOperationFeedbackView === theFeedbackView) + return; + + [_dropOperationFeedbackView removeFromSuperview]; + _dropOperationFeedbackView = theFeedbackView; + [self addSubview:_dropOperationFeedbackView positioned:CPWindowBelow relativeTo:nil]; +} + /* @ignore */ - (CPDragOperation)draggingEntered:(id)sender { - var dropOperation = [self _proposedDropOperation], - draggingLocation = [sender draggingLocation], - row; - - var location = [self convertPoint:draggingLocation fromView:nil]; - - row = [self _proposedRowAtPoint:location]; + var location = [self convertPoint:[sender draggingLocation] fromView:nil], + dropOperation = [self _proposedDropOperationAtPoint:location], + row = [self _proposedRowAtPoint:location]; if(_retargetedDropRow !== nil) row = _retargetedDropRow; @@ -2331,7 +2342,7 @@ window.setTimeout(function(){ */ - (void)draggingExited:(id)sender { - [_dropOperationFeedbackView setHidden:YES]; + [[self _dropOperationFeedbackView] setHidden:NO]; } /* @@ -2347,7 +2358,7 @@ window.setTimeout(function(){ _retargetedDropOperation = nil; _retargetedDropRow = nil; _draggedRowIndexes = [CPIndexSet indexSet]; - [_dropOperationFeedbackView setHidden:YES]; + [[self _dropOperationFeedbackView] setHidden:YES]; } /* @ignore @@ -2360,14 +2371,19 @@ window.setTimeout(function(){ /* @ignore */ -- (CPTableViewDropOperation)_proposedDropOperation +- (CPTableViewDropOperation)_proposedDropOperationAtPoint:(CGPoint)theDragPoint { - //check is something is forced... - // otherwise we use the above action by default - if(_retargetedDropOperation !== nil) - return _retargetedDropOperation; - else - return CPTableViewDropAbove; + if(_retargetedDropOperation !== nil) + return _retargetedDropOperation; + + + var row = [self rowAtPoint:theDragPoint], + rowRect = [self rectOfRow:row]; + + if (CGRectContainsPoint(rowRect, theDragPoint)) + return CPTableViewDropOn; + + return CPTableViewDropAbove; } /* @@ -2382,7 +2398,7 @@ window.setTimeout(function(){ if (dragPoint.y > numberOfRows * (_rowHeight + _intercellSpacing.height)) { - if ([self _proposedDropOperation] === CPTableViewDropAbove) + if ([self _proposedDropOperationAtPoint:dragPoint] === CPTableViewDropAbove) row = numberOfRows; else row = numberOfRows - 1; @@ -2401,39 +2417,86 @@ window.setTimeout(function(){ return CPDragOperationNone; } +/*! + Returns the subview that will draw the drop highlight on the row. + Sublcasses can override this to return a custom view to draw their drop highlight + @param theRowIndex the row index that should be highlighted +*/ +- (CPView)viewForDropHighlightOnRow:(int)theRowIndex +{ + var view = [[CPView alloc] initWithFrame:[self rectOfRow:theRowIndex]]; + [view setBackgroundColor:[CPColor colorWithRed:175.0 / 255.0 green:193.0 / 255.0 blue:220.0 / 255.0 alpha:1.0]]; + return view; +} + +- (CPRect)rectForDropHighlightViewBetweenUpperRow:(int)theUpperRowIndex andLowerRow:(int)theLowerRowIndex +{ + // The default table view implemenation does not use the offset so we just place the view at x 0.0 + var upperRowRect = [self rectOfRow:theUpperRowIndex], + lowerRowRect = [self rectOfRow:theLowerRowIndex]; + + // Place the highlight view in the middle of the rows or in the middle of the intercell spacing + // TODO: this currently looks off because the row highlights and labels are not drawn in the middle of the row + var yLocation = CPRectGetMaxY(upperRowRect) + [self intercellSpacing].height / 2.0 - 1.0, + rect = CPRectMake(0.0, + yLocation, + CPRectGetWidth([self frame]), + 2.0); + + return rect; +} + +/*! + Returns the subview that will draw the drop highlight between the rows. + Sublcasses can override this to return a custom view to draw their drop highlight + @param theUpperRowIndex the index of the upper row + @param theLowerRowIndex the index of the lower row +*/ +- (CPView)viewForDropHighlightBetweenUpperRow:(int)theUpperRowIndex andLowerRow:(int)theLowerRowIndex +{ + var view = [[CPView alloc] initWithFrame:[self rectForDropHighlightViewBetweenUpperRow:theUpperRowIndex andLowerRow:theLowerRowIndex]]; + [view setBackgroundColor:[CPColor greenColor]]; + return view; +} + - (CPDragOperation)draggingUpdated:(id)sender { - var dropOperation = [self _proposedDropOperation], - numberOfRows = [self numberOfRows], - draggingLocation = [sender draggingLocation], - dragOperation, - row; + var location = [self convertPoint:[sender draggingLocation] fromView:nil], + dropOperation = [self _proposedDropOperationAtPoint:location], + numberOfRows = [self numberOfRows]; - var location = [self convertPoint:draggingLocation fromView:nil]; - - row = [self _proposedRowAtPoint:location]; - dragOperation = [self _validateDrop:sender proposedRow:row proposedDropOperation:dropOperation]; + var row = [self _proposedRowAtPoint:location], + dragOperation = [self _validateDrop:sender proposedRow:row proposedDropOperation:dropOperation]; if(_retargetedDropRow !== nil) row = _retargetedDropRow; - //if the user forces -1 then we should highlight the whole tabelview - var rowRect; + //if the user forces -1 then we should highlight the whole tableview + var rowRect = CPRectMakeZero(); if(_retargetedDropRow === -1) rowRect = [self exposedClipRect]; else rowRect = [self rectOfRow:row]; - var exposedClipRect = [self exposedClipRect]; - var visibleWidth = _CGRectGetWidth(exposedClipRect); + var exposedClipRect = [self exposedClipRect], + visibleWidth = _CGRectGetWidth(exposedClipRect); rowRect = _CGRectMake(_CGRectGetMinX(exposedClipRect), rowRect.origin.y, visibleWidth, rowRect.size.height); - - [_dropOperationFeedbackView setDropOperation:dropOperation]; - [_dropOperationFeedbackView setHidden:(dragOperation == CPDragOperationNone)]; - [_dropOperationFeedbackView setFrame:rowRect]; - [_dropOperationFeedbackView setCurrentRow:row]; - [self addSubview:_dropOperationFeedbackView]; + + // Ask for the feedback view and cache it so we can remove it from the view hierarchy later + var dropOperationFeedbackView = nil; + + if (dropOperation === CPTableViewDropAbove) + dropOperationFeedbackView = [self viewForDropHighlightBetweenUpperRow:row - 1 andLowerRow:row]; + else if (dropOperation === CPTableViewDropOn) + dropOperationFeedbackView = [self viewForDropHighlightOnRow:row]; + + [self _setDropOperationFeedbackView:dropOperationFeedbackView]; + + if (CGRectIsNull([[self _dropOperationFeedbackView] frame])) + [[self _dropOperationFeedbackView] setFrame:rowRect]; + + [[self _dropOperationFeedbackView] setHidden:NO]; // FIXME : Maybe we should do this in a timer outside this method. Problem: we don't know when the scroll ends and neighter when the next -draggingUpdated is called. Which one will come first ? if (row > 0 && location.y - CGRectGetMinY(exposedClipRect) < _rowHeight) @@ -2451,8 +2514,6 @@ window.setTimeout(function(){ { // FIX ME: is there anything else that needs to happen here? // actual validation is called in dragginUpdated: - [_dropOperationFeedbackView setHidden:YES]; - return (_implementedDataSourceMethods & CPTableViewDataSource_tableView_validateDrop_proposedRow_proposedDropOperation_); } @@ -2461,10 +2522,8 @@ window.setTimeout(function(){ */ - (BOOL)performDragOperation:(id)sender { - var operation = [self _proposedDropOperation], - draggingLocation = [sender draggingLocation]; - - var location = [self convertPoint:draggingLocation fromView:nil]; + var location = [self convertPoint:[sender draggingLocation] fromView:nil]; + operation = [self _proposedDropOperationAtPoint:location], if(_retargetedDropRow !== nil) var row = _retargetedDropRow; diff --git a/AppKit/Platform/DOM/CPPlatformWindow+DOM.j b/AppKit/Platform/DOM/CPPlatformWindow+DOM.j index 152373698..b5128896b 100644 --- a/AppKit/Platform/DOM/CPPlatformWindow+DOM.j +++ b/AppKit/Platform/DOM/CPPlatformWindow+DOM.j @@ -549,7 +549,10 @@ var supportsNativeDragAndDrop = [CPPlatform supportsDragAndDrop]; dragOperation = CPDragOperationLink; else dragOperation = CPDragOperationNone; - + + // Temporary hack to work around the 'drop' event type never being fired + [dragServer performDragOperationInPlatformWindow:self]; + [dragServer draggingEndedInPlatformWindow:self globalLocation:[CPPlatform isBrowser] ? location : _CGPointMake(aDOMEvent.screenX, aDOMEvent.screenY) operation:dragOperation]; } From 0cb66ddc6e14bff31350e7e66fd4869761bfef74 Mon Sep 17 00:00:00 2001 From: Klaas Pieter Annema Date: Thu, 28 Jan 2010 18:52:01 +0100 Subject: [PATCH 09/58] set the default CPTableColumn dataview's center vertical-alignment (because it looks better) --- AppKit/CPTableColumn.j | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/AppKit/CPTableColumn.j b/AppKit/CPTableColumn.j index 993acd22d..29c69b3dd 100644 --- a/AppKit/CPTableColumn.j +++ b/AppKit/CPTableColumn.j @@ -75,9 +75,10 @@ CPTableColumnUserResizingMask = 2; [header setBackgroundColor:[CPColor colorWithPatternImage:CPAppKitImage("tableview-headerview.png", CGSizeMake(1.0, 23.0))]]; [self setHeaderView:header]; - var textDataView = [CPTextField new]; + var textDataView = [[CPTextField alloc] init]; [textDataView setValue:[CPColor whiteColor] forThemeAttribute:@"text-color" inState:CPThemeStateHighlighted]; [textDataView setValue:[CPFont boldSystemFontOfSize:12] forThemeAttribute:@"font" inState:CPThemeStateHighlighted]; + [textDataView setValue:CPCenterVerticalTextAlignment forThemeAttribute:@"vertical-alignment"]; [self setDataView:textDataView]; } From 477d2f9d82b4a9f518a9b8323feb436718a96778 Mon Sep 17 00:00:00 2001 From: Klaas Pieter Annema Date: Thu, 28 Jan 2010 20:10:14 +0100 Subject: [PATCH 10/58] fixed the disclosure triangle highlighting behavior --- AppKit/CPOutlineView.j | 41 ++++++++++++++++++++++++++++++++++++++++- 1 file changed, 40 insertions(+), 1 deletion(-) diff --git a/AppKit/CPOutlineView.j b/AppKit/CPOutlineView.j index c654d333e..85d8c3580 100644 --- a/AppKit/CPOutlineView.j +++ b/AppKit/CPOutlineView.j @@ -340,6 +340,45 @@ var CPOutlineViewDataSource_outlineView_setObjectValue_forTableColumn_byItem_ return frame; } +- (void)selectRowIndexes:(CPIndexSet)rows byExtendingSelection:(BOOL)shouldExtendSelection +{ + // First un highlight the old disclosure controls + var previousSelectedRows = []; + [[self selectedRowIndexes] getIndexes:previousSelectedRows maxCount:-1 inIndexRange:nil]; + + var index = [previousSelectedRows count]; + while (index--) + { + var rowIndex = previousSelectedRows[index], + item = [self itemAtRow:rowIndex]; + + if (![self isExpandable:item]) + return; + + var control = _disclosureControlsForRows[rowIndex]; + [control setHighlighted:NO]; + } + + [super selectRowIndexes:rows byExtendingSelection:shouldExtendSelection]; + + // Now highlight the new disclosure controls + var selectedRows = []; + [rows getIndexes:selectedRows maxCount:-1 inIndexRange:nil]; + + var index = [selectedRows count]; + while (index--) + { + var rowIndex = selectedRows[index], + item = [self itemAtRow:rowIndex]; + + if (![self isExpandable:item]) + return; + + var control = _disclosureControlsForRows[rowIndex]; + [control setHighlighted:YES]; + } +} + - (void)setDelegate:(id)aDelegate { if (_outlineViewDelegate === aDelegate) @@ -907,7 +946,7 @@ var _loadItemInfoForItem = function(/*CPOutlineView*/ anOutlineView, /*id*/ anIt CGContextClosePath(context); - CGContextSetFillColor(context, ([self themeState] & CPThemeState("highlighted")) ? [CPColor blackColor] : [CPColor grayColor]); + CGContextSetFillColor(context, [self isHighlighted] ? [CPColor whiteColor] : [CPColor grayColor]); CGContextFillPath(context); } From dba047187f748c94d2a58372cd1807874c6458ec Mon Sep 17 00:00:00 2001 From: Klaas Pieter Annema Date: Fri, 29 Jan 2010 10:47:49 +0100 Subject: [PATCH 11/58] improved the way a CPTableView renders the drag & drop highlight between rows --- AppKit/CPTableView.j | 126 ++++++++++++++----------------------------- 1 file changed, 41 insertions(+), 85 deletions(-) diff --git a/AppKit/CPTableView.j b/AppKit/CPTableView.j index eee98fbe2..d361d84fc 100644 --- a/AppKit/CPTableView.j +++ b/AppKit/CPTableView.j @@ -2375,11 +2375,15 @@ window.setTimeout(function(){ { if(_retargetedDropOperation !== nil) return _retargetedDropOperation; - var row = [self rowAtPoint:theDragPoint], rowRect = [self rectOfRow:row]; + // If there is no (the default) or to little inter cell spacing we create some room for the CPTableViewDropAbove indicator + // This probably doesn't work if the row height is smaller than or around 5.0 + if ([self intercellSpacing].height < 5.0) + rowRect = CPRectInset(rowRect, 0.0, 5.0 - [self intercellSpacing].height); + if (CGRectContainsPoint(rowRect, theDragPoint)) return CPTableViewDropOn; @@ -2435,14 +2439,15 @@ window.setTimeout(function(){ var upperRowRect = [self rectOfRow:theUpperRowIndex], lowerRowRect = [self rectOfRow:theLowerRowIndex]; - // Place the highlight view in the middle of the rows or in the middle of the intercell spacing - // TODO: this currently looks off because the row highlights and labels are not drawn in the middle of the row - var yLocation = CPRectGetMaxY(upperRowRect) + [self intercellSpacing].height / 2.0 - 1.0, - rect = CPRectMake(0.0, - yLocation, - CPRectGetWidth([self frame]), - 2.0); - + // Place the highlight view in the middle of the rows or in the middle of the intercell spacing + // TODO: this currently looks off because the row highlights and labels are not drawn in the middle of the row + var rect = CPRectMake(0.0, 0.0, CPRectGetWidth([self frame]), 2.0); + + rect.origin.y = CPRectGetMaxY(upperRowRect) - ( rect.size.height / 2.0 ); + + if (!CPSizeEqualToSize(CPSizeMakeZero(), [self intercellSpacing])) + rect.origin.y += [self intercellSpacing].height / 2.0; + return rect; } @@ -2454,7 +2459,9 @@ window.setTimeout(function(){ */ - (CPView)viewForDropHighlightBetweenUpperRow:(int)theUpperRowIndex andLowerRow:(int)theLowerRowIndex { - var view = [[CPView alloc] initWithFrame:[self rectForDropHighlightViewBetweenUpperRow:theUpperRowIndex andLowerRow:theLowerRowIndex]]; + var view = [[CPImageView alloc] initWithFrame: + [self rectForDropHighlightViewBetweenUpperRow:theUpperRowIndex andLowerRow:theLowerRowIndex]]; + [view setBackgroundColor:[CPColor greenColor]]; return view; } @@ -2908,78 +2915,27 @@ var CPTableViewDataSourceKey = @"CPTableViewDataSourceKey", @end -@implementation _dropOperationDrawingView : CPView -{ - unsigned dropOperation @accessors; - CPTableView tableView @accessors; - int currentRow @accessors; -} - -- (void)drawRect:(CGRect)aRect -{ - if(tableView._destinationDragStyle === CPTableViewDraggingDestinationFeedbackStyleNone) - return; - - var context = [[CPGraphicsContext currentContext] graphicsPort]; - - CGContextSetStrokeColor(context, [CPColor colorWithHexString:@"4886ca"]); - CGContextSetLineWidth(context, 3); - - if(dropOperation === CPTableViewDropOn) - { - //if row is selected don't fill and stroke white - var selectedRows = [tableView selectedRowIndexes]; - var newRect = _CGRectMake(aRect.origin.x + 2, aRect.origin.y + 2, aRect.size.width - 4, aRect.size.height - 5); - if([selectedRows containsIndex:currentRow]) - { - CGContextSetLineWidth(context, 2); - CGContextSetStrokeColor(context, [CPColor whiteColor]); - } - else - { - CGContextSetFillColor(context, [CPColor colorWithRed:72/255 green:134/255 blue:202/255 alpha:0.25]); - CGContextFillRoundedRectangleInRect(context, newRect, 8, YES, YES, YES, YES); - } - CGContextStrokeRoundedRectangleInRect(context, newRect, 8, YES, YES, YES, YES); - - } - - - if(dropOperation === CPTableViewDropAbove) - { - - - //reposition the view up a tad - [self setFrameOrigin:CGPointMake(_frame.origin.x, _frame.origin.y - 8)]; - - var selectedRows = [tableView selectedRowIndexes]; - - if([selectedRows containsIndex:currentRow - 1] || [selectedRows containsIndex:currentRow]) - { - CGContextSetStrokeColor(context, [CPColor whiteColor]); - CGContextSetLineWidth(context, 4); - //draw the circle thing - CGContextStrokeEllipseInRect(context, _CGRectMake(aRect.origin.x + 4, aRect.origin.y + 4, 8, 8)); - //then draw the line - CGContextBeginPath(context); - CGContextMoveToPoint(context, 10, aRect.origin.y + 8); - CGContextAddLineToPoint(context, aRect.size.width - aRect.origin.y - 8, aRect.origin.y + 8); - CGContextClosePath(context); - CGContextStrokePath(context); - - CGContextSetStrokeColor(context, [CPColor colorWithHexString:@"4886ca"]); - CGContextSetLineWidth(context, 3); - } - - //draw the circle thing - CGContextStrokeEllipseInRect(context, _CGRectMake(aRect.origin.x + 4, aRect.origin.y + 4, 8, 8)); - //then draw the line - CGContextBeginPath(context); - CGContextMoveToPoint(context, 10, aRect.origin.y + 8); - CGContextAddLineToPoint(context, aRect.size.width - aRect.origin.y - 8, aRect.origin.y + 8); - CGContextClosePath(context); - CGContextStrokePath(context); - //CGContextStrokeLineSegments(context, [aRect.origin.x + 8, aRect.origin.y + 8, 300 , aRect.origin.y + 8]); - } -} -@end +// @implementation _CPDropOperationDrawView : CPView +// { +// } +// +// - (void)drawRect:(CGRect)aRect +// { +// var context = [[CPGraphicsContext currentContext] graphicsPort]; +// +// CGContextSetStrokeColor(context, [CPColor colorWithHexString:@"4886ca"]); +// CGContextSetLineWidth(context, 3); +// +// //draw the circle thing +// CGContextStrokeEllipseInRect(context, _CGRectMake(aRect.origin.x + 4, aRect.origin.y + 4, 8, 8)); +// +// //then draw the line +// CGContextBeginPath(context); +// CGContextMoveToPoint(context, 10, aRect.origin.y + 8); +// CGContextAddLineToPoint(context, aRect.size.width - aRect.origin.y - 8, aRect.origin.y + 8); +// CGContextClosePath(context); +// CGContextStrokePath(context); +// +// } +// } +// @end From 6798a5777aa74e9d81da5557562069b0d282c163 Mon Sep 17 00:00:00 2001 From: Klaas Pieter Annema Date: Fri, 29 Jan 2010 10:57:34 +0100 Subject: [PATCH 12/58] added the cpoutlineview test app --- .../Manual/CPOutlineViewTest/AppController.j | 220 ++++++++++++++++++ Tests/Manual/CPOutlineViewTest/Info.plist | 12 + Tests/Manual/CPOutlineViewTest/Jakefile | 38 +++ .../CPOutlineViewTest/Resources/spinner.gif | Bin 0 -> 1849 bytes .../Manual/CPOutlineViewTest/index-debug.html | 84 +++++++ Tests/Manual/CPOutlineViewTest/index.html | 69 ++++++ Tests/Manual/CPOutlineViewTest/main.j | 18 ++ 7 files changed, 441 insertions(+) create mode 100644 Tests/Manual/CPOutlineViewTest/AppController.j create mode 100644 Tests/Manual/CPOutlineViewTest/Info.plist create mode 100644 Tests/Manual/CPOutlineViewTest/Jakefile create mode 100644 Tests/Manual/CPOutlineViewTest/Resources/spinner.gif create mode 100644 Tests/Manual/CPOutlineViewTest/index-debug.html create mode 100644 Tests/Manual/CPOutlineViewTest/index.html create mode 100644 Tests/Manual/CPOutlineViewTest/main.j diff --git a/Tests/Manual/CPOutlineViewTest/AppController.j b/Tests/Manual/CPOutlineViewTest/AppController.j new file mode 100644 index 000000000..33a7e8ced --- /dev/null +++ b/Tests/Manual/CPOutlineViewTest/AppController.j @@ -0,0 +1,220 @@ +/* + * AppController.j + * outlineview + * + * Created by You on January 22, 2010. + * Copyright 2010, Your Company All rights reserved. + */ + +@import +@import "AppKit/CPOutlineView.j" + +CPLogRegister(CPLogConsole); + +@implementation Menu : CPObject +{ + CPString _title @accessors(property=title); + CPArray _children @accessors(property=children); +} + ++ (id)menuWithTitle:(CPString)theTitle +{ + return [[self alloc] initWithTitle:theTitle]; +} + ++ (id)menuWithTitle:(CPString)theTitle children:(CPArray)theChildren +{ + return [[self alloc] initWithTitle:theTitle children:theChildren]; +} + +- (id)initWithTitle:(CPString)theTitle +{ + return [self initWithTitle:theTitle children:nil]; +} + +- (id)initWithTitle:(CPString)theTitle children:(CPArray)theChildren +{ + if ((self = [super init])) + { + _title = theTitle; + _children = theChildren; + } + + return self; +} + +- (CPString)description +{ + var description = [super description] + @" " + [self title]; + + // if ([[self children] count] > 0) + // description = @"\n" + [description stringByAppendingFormat:@": %@", [self children]]; + + return description; +} + +- (id)initWithCoder:(CPCoder)theCoder +{ + if (self = [super init]) + { + _title = [theCoder decodeObjectForKey:@"MenuTitleKey"]; + _children = [theCoder decodeObjectForKey:@"MenuChildrenKey"]; + } +} + +- (void)encodeWithCoder:(CPCoder)aCoder +{ + [aCoder encodeObject:_title forKey:@"MenuTitleKey"]; + [aCoder encodeObject:_children forKey:@"MenuChildrenKey"]; +} + +@end + +@implementation AppController : CPObject +{ + Menu _menu @accessors(property=menu); + CPOutlineView _outlineView; +} + +- (void)applicationDidFinishLaunching:(CPNotification)aNotification +{ + var theWindow = [[CPWindow alloc] initWithContentRect:CGRectMakeZero() styleMask:CPBorderlessBridgeWindowMask], + contentView = [theWindow contentView]; + + _menu = [Menu menuWithTitle:@"Top" children:[ + [Menu menuWithTitle:@"1" children:[ + [Menu menuWithTitle:@"1.1" children:[ + [Menu menuWithTitle:@"1.1.1"], + [Menu menuWithTitle:@"1.1.2"], + ]], + [Menu menuWithTitle:@"1.2" children:[ + [Menu menuWithTitle:@"1.2.1"], + [Menu menuWithTitle:@"1.2.2"], + [Menu menuWithTitle:@"1.2.3"] + ]] + ]], + [Menu menuWithTitle:@"2" children:[ + [Menu menuWithTitle:@"2.1" children:[ + [Menu menuWithTitle:@"2.1.1"], + [Menu menuWithTitle:@"2.1.2"], + [Menu menuWithTitle:@"2.1.3"], + ]], + [Menu menuWithTitle:@"2.2" children:[ + [Menu menuWithTitle:@"2.2.1"], + [Menu menuWithTitle:@"2.2.2"], + ]] + ]], + [Menu menuWithTitle:@"3" children:[ + [Menu menuWithTitle:@"3.1" children:[ + [Menu menuWithTitle:@"3.1.1"], + [Menu menuWithTitle:@"3.1.2"], + [Menu menuWithTitle:@"3.1.3"], + ]], + [Menu menuWithTitle:@"3.2" children:[ + [Menu menuWithTitle:@"3.2.1"], + [Menu menuWithTitle:@"3.2.2"], + [Menu menuWithTitle:@"3.2.3"], + [Menu menuWithTitle:@"3.2.4"], + ]], + [Menu menuWithTitle:@"3.3" children:[ + [Menu menuWithTitle:@"3.3.1"], + [Menu menuWithTitle:@"3.3.2"], + [Menu menuWithTitle:@"3.3.3"], + [Menu menuWithTitle:@"3.3.4"], + [Menu menuWithTitle:@"3.3.5"], + ]] + ]] + ]]; + + var scrollView = [[CPScrollView alloc] initWithFrame:[contentView bounds]]; + [theWindow setContentView:scrollView]; + + _outlineView = [[CPOutlineView alloc] initWithFrame:[contentView bounds]]; + + var column = [[CPTableColumn alloc] initWithIdentifier:@""]; + [_outlineView addTableColumn:column]; + [_outlineView setOutlineTableColumn:column]; + [_outlineView registerForDraggedTypes:[@"CustomType"]]; + + [_outlineView setDataSource:self]; + [_outlineView setAllowsMultipleSelection:YES]; + // [_outlineView setIntercellSpacing:CPSizeMake(0.0, 0.0)] + + [scrollView setDocumentView:_outlineView]; + + [self expandItem:[self menu]]; + + [theWindow orderFront:self]; +} + +- (void)expandItem:(Menu)item +{ + var children = [item children], + childIndex = [children count]; + + while (childIndex--) + [self expandItem:[children objectAtIndex:childIndex]]; + + [_outlineView expandItem:item]; +} + +- (id)outlineView:(CPOutlineView)theOutlineView child:(int)theIndex ofItem:(id)theItem +{ + if (theItem === nil) + theItem = [self menu]; + + // CPLog.debug(@"child: %i ofItem:%@ : %@", theIndex, theItem, [[theItem children] objectAtIndex:theIndex]); + + return [[theItem children] objectAtIndex:theIndex]; +} + +- (BOOL)outlineView:(CPOutlineView)theOutlineView isItemExpandable:(id)theItem +{ + if (theItem === nil) + theItem = [self menu]; + + // CPLog.debug(@"isItemExpandable:%@ : %@", theItem, [[theItem children] count] > 0); + + return [[theItem children] count] > 0; +} + +- (int)outlineView:(CPOutlineView)theOutlineView numberOfChildrenOfItem:(id)theItem +{ + if (theItem === nil) + theItem = [self menu]; + + // CPLog.debug(@"numberOfChildrenOfItem:%@ : %i", theItem, [[theItem children] count]); + + return [[theItem children] count]; +} + +- (id)outlineView:(CPOutlineView)anOutlineView objectValueForTableColumn:(CPTableColumn)theColumn byItem:(id)theItem +{ + if (theItem === nil) + theItem = [self menu]; + + // CPLog.debug(@"objectValueForTableColumn:%@ byItem:%@ : %@", theColumn, theItem, [theItem title]); + + return [theItem title]; +} + +- (BOOL)outlineView:(CPOutlineView)anOutlineView writeItems:(CPArray)theItems toPasteboard:(CPPasteBoard)thePasteBoard +{ + [thePasteBoard declareTypes:[@"CustomType"] owner:self]; + [thePasteBoard setData:[CPKeyedArchiver archivedDataWithRootObject:theItems] forType:@"CustomType"]; + return YES; +} + +- (CPDragOperation)outlineView:(CPOutlineView)anOutlineView validateDrop:(id < CPDraggingInfo >)theInfo proposedItem:(id)theItem proposedChildIndex:(int)theIndex +{ + // CPLog.debug(@"parent: %@ index: %i", theItem, theIndex); + return CPDragOperationEvery; +} + +- (BOOL)outlineView:(CPOutlineView)outlineView acceptDrop:(id < CPDraggingInfo >)theInfo item:(id)theItem childIndex:(int)theIndex +{ + CPLog.debug(@"accept drop at index: %i item: %@", theIndex, theItem); + return YES; +} + +@end diff --git a/Tests/Manual/CPOutlineViewTest/Info.plist b/Tests/Manual/CPOutlineViewTest/Info.plist new file mode 100644 index 000000000..64faa0026 --- /dev/null +++ b/Tests/Manual/CPOutlineViewTest/Info.plist @@ -0,0 +1,12 @@ + + + + + CPApplicationDelegateClass + AppController + CPBundleName + outlineview + CPPrincipalClass + CPApplication + + diff --git a/Tests/Manual/CPOutlineViewTest/Jakefile b/Tests/Manual/CPOutlineViewTest/Jakefile new file mode 100644 index 000000000..3a5432575 --- /dev/null +++ b/Tests/Manual/CPOutlineViewTest/Jakefile @@ -0,0 +1,38 @@ +/* + * Jakefile + * outlineview + * + * Created by You on January 22, 2010. + * Copyright 2010, Your Company All rights reserved. + */ + +var ENV = require("system").env, + FILE = require("file"), + task = require("jake").task, + FileList = require("jake").FileList, + app = require("cappuccino/jake").app, + configuration = ENV["CONFIG"] || ENV["CONFIGURATION"] || ENV["c"] || "Debug"; + +app ("outlineview", function(task) +{ + task.setBuildIntermediatesPath(FILE.join("Build", "outlineview.build", configuration)); + task.setBuildPath(FILE.join("Build", configuration)); + + task.setProductName("outlineview"); + task.setIdentifier("com.yourcompany.outlineview"); + task.setVersion("1.0"); + task.setAuthor("Your Company"); + task.setEmail("feedback @nospam@ yourcompany.com"); + task.setSummary("outlineview"); + task.setSources(new FileList("**/*.j")); + task.setResources(new FileList("Resources/*")); + task.setIndexFilePath("index.html"); + task.setInfoPlistPath("Info.plist"); + + if (configuration === "Debug") + task.setCompilerFlags("-DDEBUG -g"); + else + task.setCompilerFlags("-O"); +}); + +task ("default", ["outlineview"]); diff --git a/Tests/Manual/CPOutlineViewTest/Resources/spinner.gif b/Tests/Manual/CPOutlineViewTest/Resources/spinner.gif new file mode 100644 index 0000000000000000000000000000000000000000..06dbc2bc21dddcf0e09b566d5b211aee89570f52 GIT binary patch literal 1849 zcma*odr(tX9tZHtz31lM+(&Y`A`Ou`NeG&R#DrIfV%?hng21vs6v>ooRQQFbk7E_K!V( z{?5!fpZWgIZ%*d6t%i*j24bL}AZUJm9)h6R*;%L4IWse3G#VWaN1#$zSSXcBhlYlH zJ|D}n{r&w2f+Qp)SS*&n?*G4}{}!h?td_mjU6Kad-rW*QwWYCUk7d^e+sjpZAn6kT z5rM;`{~_}-wm+L@%+E;JphLm}C3WzQAQD0wBoY|rOTQX{(@pp-WAA8Iw0HKl|15j) zhGh(SFWu#5zUCw^T!}C~eC}~?{xG-r7ugQC>taC+|L^xr&a%{#cgUOZXIM&v?)k^2 z1i5%0!U00wq)r4vlAwXBA_m5J5WNeuBm-XJQ5pG4GD%vc|K){+TJ{AkHqN@SJKczX zU}QRd9n*_bf^h94)6Ctv{CUfz_;qs#RDuQ$DR%y1&5G-a6rhf*4Y zl+UOD1*GE{GQ7vv;c-tTIMkz0ovO>9j%b5hpa@a*CBJ#W!0@ndSwF|%hMkdFtXiU) z`BEp+yhkt8ZY>tg&uyH@%^%K4jDrbA;et&vnnzZ3z22@e6<27z2Vk13kb7OtISyxv z(XoO-LNQCZe3lfzc%*pNqU<9T+p~teThOEB+~e&U0mC|zS{Q)dJZ)!^1f7L(zg*L> z*vSW%?dR~@@0(}x6-V^A`~ImD;)NaBUnP8;RH=bS2@pk`wp>>8r&jGjmGPy%1BW}v zoPo}ca$~bze@efc3kapuEVW1!%teOZT3j2Tw5=hjiAf02d}7dL0oFC%@=RXp5Ow#% z@a>+AM|YWt$n&e`>sB-32gBcuTi>R>*|8@lp`y6thc7ydyqDsuUn~YzZf|{-R@-3y zL#wx{Ii}xxL_csiW*LBn0-A$>zp4WOmkf6=ilrjlW?-l9+bCd7|i?*b5NTmy<<6NZ0T8$SN@mwdC2f z6jqK=N@bS@!=YSj%>h0}*4p+%0HbTIrE$w7UMT6+AZZ&DAo*qZAAi(OtNbIfl#Dw^ zJWeiCp~zi#&t6x}m9)O^eR4HiLV3QA<<0>HZ8%$^lrSE94Wb}=+MM^!b>n#5&-JQR zkr-CEu9C;_F*7DqDisulV6Pmg$nFL0TPn%~*m^-`Z3^BgU(sNpnx%nW(!eV9A&FvI zHL3X3lw8Wji^6=8KbQDE-e%b?svdFxxdh$8r97@7$ojeI`6AL8Ob6QC$qh&>ZWVDX1F{0vJnT%%mE;GveKWR%C} zM&4d;Jf3s9|HAA)yVUPo`Aq;0do#)uHSXi5*QF*)x@MVVHr+cN)uMZ__F|&Ta#p8d z53TOKtce!PJUuie8UWol-S(`c2nH?UGqJP{!4RR4u$LCfn)q-hj0^f=h(VYy)T6eN zhRO!ja-aDBTcgeyP(8Ua4IdiOog^*CQa?R(cP#9AgL9`j>EX-6Yf1lzX(!~``M1XC zNmM<4<6d~wWZ$Xrk0K}UteTrq@LBBk#MsjkK;pbuVhe)NI7(7Pf(l?lxC7=1Z7Pzl zMbS;nV4NI5_N{1$P)&XC)huOGQ+h^zpYUZfb*1n6>!`#*b3y52LGmi+<4sY5jyD#- zw&$d}DTguLAfnRtjrM*JfqtHqUu6rQoU=g%1E9xk%;)TDm^2<8n-0IhTsQFaek)MY}>PK4;nBk=ow4pF>vzkO& gna%Org-kgQCf=+BeMi^RbuY;YE~rTjend;_cdi8t>i_@% literal 0 HcmV?d00001 diff --git a/Tests/Manual/CPOutlineViewTest/index-debug.html b/Tests/Manual/CPOutlineViewTest/index-debug.html new file mode 100644 index 000000000..30fd821ac --- /dev/null +++ b/Tests/Manual/CPOutlineViewTest/index-debug.html @@ -0,0 +1,84 @@ + + + + + + + + outlineview + + + + + + + + + + + + + + +
+ + + +
+ + + diff --git a/Tests/Manual/CPOutlineViewTest/index.html b/Tests/Manual/CPOutlineViewTest/index.html new file mode 100644 index 000000000..e0a035c11 --- /dev/null +++ b/Tests/Manual/CPOutlineViewTest/index.html @@ -0,0 +1,69 @@ + + + + + + + + outlineview + + + + + + + + + + + + +
+ + + +
+ + + + diff --git a/Tests/Manual/CPOutlineViewTest/main.j b/Tests/Manual/CPOutlineViewTest/main.j new file mode 100644 index 000000000..c35f7b26c --- /dev/null +++ b/Tests/Manual/CPOutlineViewTest/main.j @@ -0,0 +1,18 @@ +/* + * AppController.j + * outlineview + * + * Created by You on January 22, 2010. + * Copyright 2010, Your Company All rights reserved. + */ + +@import +@import + +@import "AppController.j" + + +function main(args, namedArgs) +{ + CPApplicationMain(args, namedArgs); +} From 78083eea4889d1540361b0f87c200217b8e6c694 Mon Sep 17 00:00:00 2001 From: Klaas Pieter Annema Date: Fri, 29 Jan 2010 12:14:08 +0100 Subject: [PATCH 13/58] made sure CPControl's trackMouse: doesn't eat mouse events when the tableview is in a drag session #431 --- AppKit/CPTableView.j | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/AppKit/CPTableView.j b/AppKit/CPTableView.j index ff105e47a..de4397fc3 100644 --- a/AppKit/CPTableView.j +++ b/AppKit/CPTableView.j @@ -2160,6 +2160,15 @@ window.setTimeout(function(){ return YES; } +- (void)trackMouse:(CPEvent)anEvent +{ + // Prevent CPControl from eating the mouse events when we are in a drag session + if (![_draggedRowIndexes count]) + [super trackMouse:anEvent]; + else + [CPApp sendEvent:anEvent]; +} + /* ignore */ - (BOOL)continueTracking:(CGPoint)lastPoint at:(CGPoint)aPoint { From 436f1d1541bfc9d37521e9947cc7920ad74068ef Mon Sep 17 00:00:00 2001 From: Klaas Pieter Annema Date: Fri, 29 Jan 2010 14:24:44 +0100 Subject: [PATCH 14/58] improved the way drop highlights are shown --- AppKit/CPTableView.j | 62 +++++++++++++++++++++++--------------------- 1 file changed, 32 insertions(+), 30 deletions(-) diff --git a/AppKit/CPTableView.j b/AppKit/CPTableView.j index d67d45d0c..e2562cc21 100644 --- a/AppKit/CPTableView.j +++ b/AppKit/CPTableView.j @@ -2318,7 +2318,6 @@ window.setTimeout(function(){ [_dropOperationFeedbackView removeFromSuperview]; _dropOperationFeedbackView = theFeedbackView; - [self addSubview:_dropOperationFeedbackView positioned:CPWindowBelow relativeTo:nil]; } /* @@ -2450,7 +2449,7 @@ window.setTimeout(function(){ // Place the highlight view in the middle of the rows or in the middle of the intercell spacing // TODO: this currently looks off because the row highlights and labels are not drawn in the middle of the row - var rect = CPRectMake(0.0, 0.0, CPRectGetWidth([self frame]), 2.0); + var rect = CPRectMake(0.0, 0.0, CPRectGetWidth([self frame]), 10.0); rect.origin.y = CPRectGetMaxY(upperRowRect) - ( rect.size.height / 2.0 ); @@ -2468,11 +2467,8 @@ window.setTimeout(function(){ */ - (CPView)viewForDropHighlightBetweenUpperRow:(int)theUpperRowIndex andLowerRow:(int)theLowerRowIndex { - var view = [[CPImageView alloc] initWithFrame: + return [[_CPDropOperationDrawView alloc] initWithFrame: [self rectForDropHighlightViewBetweenUpperRow:theUpperRowIndex andLowerRow:theLowerRowIndex]]; - - [view setBackgroundColor:[CPColor greenColor]]; - return view; } - (CPDragOperation)draggingUpdated:(id)sender @@ -2502,10 +2498,17 @@ window.setTimeout(function(){ // Ask for the feedback view and cache it so we can remove it from the view hierarchy later var dropOperationFeedbackView = nil; + // Get the correct drop feedback view and add it to the view hierarchy if (dropOperation === CPTableViewDropAbove) + { dropOperationFeedbackView = [self viewForDropHighlightBetweenUpperRow:row - 1 andLowerRow:row]; + [self addSubview:dropOperationFeedbackView positioned:CPWindowAbove relativeTo:nil]; + } else if (dropOperation === CPTableViewDropOn) + { dropOperationFeedbackView = [self viewForDropHighlightOnRow:row]; + [self addSubview:dropOperationFeedbackView positioned:CPWindowBelow relativeTo:nil]; + } [self _setDropOperationFeedbackView:dropOperationFeedbackView]; @@ -2920,27 +2923,26 @@ var CPTableViewDataSourceKey = @"CPTableViewDataSourceKey", @end -// @implementation _CPDropOperationDrawView : CPView -// { -// } -// -// - (void)drawRect:(CGRect)aRect -// { -// var context = [[CPGraphicsContext currentContext] graphicsPort]; -// -// CGContextSetStrokeColor(context, [CPColor colorWithHexString:@"4886ca"]); -// CGContextSetLineWidth(context, 3); -// -// //draw the circle thing -// CGContextStrokeEllipseInRect(context, _CGRectMake(aRect.origin.x + 4, aRect.origin.y + 4, 8, 8)); -// -// //then draw the line -// CGContextBeginPath(context); -// CGContextMoveToPoint(context, 10, aRect.origin.y + 8); -// CGContextAddLineToPoint(context, aRect.size.width - aRect.origin.y - 8, aRect.origin.y + 8); -// CGContextClosePath(context); -// CGContextStrokePath(context); -// -// } -// } -// @end +@implementation _CPDropOperationDrawView : CPView +{ +} + +- (void)drawRect:(CGRect)aRect +{ + var context = [[CPGraphicsContext currentContext] graphicsPort], + rect = [self bounds]; + + CGContextSetStrokeColor(context, [CPColor selectionColor]); + CGContextSetLineWidth(context, 3.0); + + // We want the ellipse to fit in a square so we make sure the width and the height of the ellipse are equal + var ellipesRect = CPRectMake(rect.origin.x + 2.5, rect.origin.y + 2.5, rect.size.height - 4.0, rect.size.height - 4.0); + CGContextStrokeEllipseInRect(context, ellipesRect); + + CGContextBeginPath(context); + CGContextMoveToPoint(context, CPRectGetMaxX(ellipesRect), CPRectGetMidY(ellipesRect)); + CGContextAddLineToPoint(context, CPRectGetMaxX(rect) - CPRectGetMaxX(ellipesRect), CPRectGetMidY(ellipesRect)); + CGContextClosePath(context); + CGContextStrokePath(context); +} +@end From ec5dcb47c95a0c2cad159bff8d59deaaa65baea2 Mon Sep 17 00:00:00 2001 From: Klaas Pieter Annema Date: Fri, 29 Jan 2010 14:58:45 +0100 Subject: [PATCH 15/58] - fixed a bug where the tableview would send the wrong concluded dropped row to it's datasource - implemented CPCollectioView drop on behavior --- AppKit/CPOutlineView.j | 38 ++++++++++++++----- AppKit/CPTableView.j | 8 ++-- .../Manual/CPOutlineViewTest/AppController.j | 2 +- 3 files changed, 35 insertions(+), 13 deletions(-) diff --git a/AppKit/CPOutlineView.j b/AppKit/CPOutlineView.j index 85d8c3580..19f194c8d 100644 --- a/AppKit/CPOutlineView.j +++ b/AppKit/CPOutlineView.j @@ -854,28 +854,48 @@ var _loadItemInfoForItem = function(/*CPOutlineView*/ anOutlineView, /*id*/ anIt { if (!_outlineView._implementedOutlineViewDataSourceMethods & CPOutlineViewDataSource_outlineView_validateDrop_proposedItem_proposedChildIndex_) return CPDragOperationNone; - + var droppedItem = [_outlineView itemAtRow:theRow], - parentItem = [_outlineView parentForItem:droppedItem], - - var itemInfo = (parentItem != nil) ? _outlineView._itemInfosForItems[[parentItem UID]] : _outlineView._rootItemInfo, - children = itemInfo.children, + parentItem = [_outlineView parentForItem:droppedItem]; + childIndex = CPNotFound; + + if (theOperation === CPTableViewDropAbove) + { + var itemInfo = (parentItem != nil) ? _outlineView._itemInfosForItems[[parentItem UID]] : _outlineView._rootItemInfo, + children = itemInfo.children, + childIndex = [children indexOfObject:droppedItem]; + } + else if (theOperation === CPTableViewDropOn) + { + parentItem = droppedItem; + childIndex = -1; + } return [_outlineView._outlineViewDataSource outlineView:_outlineView validateDrop:theInfo proposedItem:parentItem proposedChildIndex:childIndex]; } - (BOOL)tableView:(CPTableView)aTableView acceptDrop:(id )theInfo row:(int)theRow dropOperation:(CPTableViewDropOperation)theOperation -{ +{ if (!_outlineView._implementedOutlineViewDataSourceMethods & CPOutlineViewDataSource_outlineView_acceptDrop_item_childIndex_) return NO; var droppedItem = [_outlineView itemAtRow:theRow], - parentItem = [_outlineView parentForItem:droppedItem], + parentItem = [_outlineView parentForItem:droppedItem]; + childIndex = CPNotFound; + + if (theOperation === CPTableViewDropAbove) + { + var itemInfo = (parentItem != nil) ? _outlineView._itemInfosForItems[[parentItem UID]] : _outlineView._rootItemInfo, + children = itemInfo.children, - var itemInfo = (parentItem != nil) ? _outlineView._itemInfosForItems[[parentItem UID]] : _outlineView._rootItemInfo, - children = itemInfo.children, childIndex = [children indexOfObject:droppedItem]; + } + else if (theOperation === CPTableViewDropOn) + { + parentItem = droppedItem; + childIndex = -1; + } return [_outlineView._outlineViewDataSource outlineView:_outlineView acceptDrop:theInfo item:parentItem childIndex:childIndex]; } diff --git a/AppKit/CPTableView.j b/AppKit/CPTableView.j index e2562cc21..423b820f0 100644 --- a/AppKit/CPTableView.j +++ b/AppKit/CPTableView.j @@ -2507,9 +2507,11 @@ window.setTimeout(function(){ else if (dropOperation === CPTableViewDropOn) { dropOperationFeedbackView = [self viewForDropHighlightOnRow:row]; + + // FIXME: this doesn't work for tableviews that have alternating row background colors [self addSubview:dropOperationFeedbackView positioned:CPWindowBelow relativeTo:nil]; } - + [self _setDropOperationFeedbackView:dropOperationFeedbackView]; if (CGRectIsNull([[self _dropOperationFeedbackView] frame])) @@ -2542,12 +2544,12 @@ window.setTimeout(function(){ - (BOOL)performDragOperation:(id)sender { var location = [self convertPoint:[sender draggingLocation] fromView:nil]; - operation = [self _proposedDropOperationAtPoint:location], + operation = [self _proposedDropOperationAtPoint:location]; if(_retargetedDropRow !== nil) var row = _retargetedDropRow; else - var row = [self rowAtPoint:location] - 1; + var row = [self rowAtPoint:location]; return [_dataSource tableView:self acceptDrop:sender row:row dropOperation:operation]; } diff --git a/Tests/Manual/CPOutlineViewTest/AppController.j b/Tests/Manual/CPOutlineViewTest/AppController.j index 33a7e8ced..d3d7ce805 100644 --- a/Tests/Manual/CPOutlineViewTest/AppController.j +++ b/Tests/Manual/CPOutlineViewTest/AppController.j @@ -207,7 +207,7 @@ CPLogRegister(CPLogConsole); - (CPDragOperation)outlineView:(CPOutlineView)anOutlineView validateDrop:(id < CPDraggingInfo >)theInfo proposedItem:(id)theItem proposedChildIndex:(int)theIndex { - // CPLog.debug(@"parent: %@ index: %i", theItem, theIndex); + CPLog.debug(@"validate drop at index: %i item: %@", theIndex, theItem); return CPDragOperationEvery; } From bfdbe2a34a06e3a3083bc04bf02c4dfc94e8713f Mon Sep 17 00:00:00 2001 From: Klaas Pieter Annema Date: Fri, 29 Jan 2010 16:46:56 +0100 Subject: [PATCH 16/58] updated the collection view sample to actually move the dragged items --- .../Manual/CPOutlineViewTest/AppController.j | 152 +++++++++++++----- 1 file changed, 112 insertions(+), 40 deletions(-) diff --git a/Tests/Manual/CPOutlineViewTest/AppController.j b/Tests/Manual/CPOutlineViewTest/AppController.j index d3d7ce805..37d9cf451 100644 --- a/Tests/Manual/CPOutlineViewTest/AppController.j +++ b/Tests/Manual/CPOutlineViewTest/AppController.j @@ -11,8 +11,12 @@ CPLogRegister(CPLogConsole); +CustomOutlineViewDragType = @"CustomOutlineViewDragType"; + @implementation Menu : CPObject { + Menu _menu @accessors(property=menu); + CPString _title @accessors(property=title); CPArray _children @accessors(property=children); } @@ -37,33 +41,82 @@ CPLogRegister(CPLogConsole); if ((self = [super init])) { _title = theTitle; - _children = theChildren; + [self setChildren:theChildren]; } return self; } - (CPString)description +{ + return [self descriptionWithChildren:YES]; +} + +- (CPString)descriptionWithChildren:(BOOL)showChildren { var description = [super description] + @" " + [self title]; - // if ([[self children] count] > 0) - // description = @"\n" + [description stringByAppendingFormat:@": %@", [self children]]; + if (showChildren && [[self children] count] > 0) + description = @"\n" + [description stringByAppendingFormat:@" children: %@", [self children]]; return description; } +- (void)insertSubmenu:(Menu)theItem atIndex:(int)theIndex +{ + CPLog.debug(@"insert menu: %@ in menu: %@ at index: %i", [theItem descriptionWithChildren:NO], [self descriptionWithChildren:NO], theIndex); + + if ([[self children] containsObject:theItem]) + return; + + if ([theItem menu]) + [theItem removeFromMenu]; + + [theItem setMenu:self]; + [[self children] insertObject:theItem atIndex:theIndex]; +} + +- (void)removeFromMenu +{ + CPLog.debug(@"remove menu: %@ from menu: %@", [self descriptionWithChildren:NO], [[self menu] descriptionWithChildren:NO]); + + [[[self menu] children] removeObject:self]; + + CPLog.debug([[self menu] children]); + + [self setMenu:nil]; +} + +- (void)setChildren:(CPArray)theChildren +{ + if (_children === theChildren) + return; + + var childIndex = [theChildren count]; + while (childIndex--) + { + var child = theChildren[childIndex]; + [child setMenu:self]; + } + + _children = theChildren; +} + - (id)initWithCoder:(CPCoder)theCoder { if (self = [super init]) { + _menu = [theCoder decodeObjectForKey:@"MenuSuperMenuKey"]; _title = [theCoder decodeObjectForKey:@"MenuTitleKey"]; - _children = [theCoder decodeObjectForKey:@"MenuChildrenKey"]; + [self setChildren:[theCoder decodeObjectForKey:@"MenuChildrenKey"]]; } + + return self; } - (void)encodeWithCoder:(CPCoder)aCoder { + [aCoder encodeObject:_menu forKey:@"MenuSuperMenuKey"]; [aCoder encodeObject:_title forKey:@"MenuTitleKey"]; [aCoder encodeObject:_children forKey:@"MenuChildrenKey"]; } @@ -74,6 +127,8 @@ CPLogRegister(CPLogConsole); { Menu _menu @accessors(property=menu); CPOutlineView _outlineView; + + CPArray _draggedItems; } - (void)applicationDidFinishLaunching:(CPNotification)aNotification @@ -93,37 +148,37 @@ CPLogRegister(CPLogConsole); [Menu menuWithTitle:@"1.2.3"] ]] ]], - [Menu menuWithTitle:@"2" children:[ - [Menu menuWithTitle:@"2.1" children:[ - [Menu menuWithTitle:@"2.1.1"], - [Menu menuWithTitle:@"2.1.2"], - [Menu menuWithTitle:@"2.1.3"], - ]], - [Menu menuWithTitle:@"2.2" children:[ - [Menu menuWithTitle:@"2.2.1"], - [Menu menuWithTitle:@"2.2.2"], - ]] - ]], - [Menu menuWithTitle:@"3" children:[ - [Menu menuWithTitle:@"3.1" children:[ - [Menu menuWithTitle:@"3.1.1"], - [Menu menuWithTitle:@"3.1.2"], - [Menu menuWithTitle:@"3.1.3"], - ]], - [Menu menuWithTitle:@"3.2" children:[ - [Menu menuWithTitle:@"3.2.1"], - [Menu menuWithTitle:@"3.2.2"], - [Menu menuWithTitle:@"3.2.3"], - [Menu menuWithTitle:@"3.2.4"], - ]], - [Menu menuWithTitle:@"3.3" children:[ - [Menu menuWithTitle:@"3.3.1"], - [Menu menuWithTitle:@"3.3.2"], - [Menu menuWithTitle:@"3.3.3"], - [Menu menuWithTitle:@"3.3.4"], - [Menu menuWithTitle:@"3.3.5"], - ]] - ]] + // [Menu menuWithTitle:@"2" children:[ + // [Menu menuWithTitle:@"2.1" children:[ + // [Menu menuWithTitle:@"2.1.1"], + // [Menu menuWithTitle:@"2.1.2"], + // [Menu menuWithTitle:@"2.1.3"], + // ]], + // [Menu menuWithTitle:@"2.2" children:[ + // [Menu menuWithTitle:@"2.2.1"], + // [Menu menuWithTitle:@"2.2.2"], + // ]] + // ]], + // [Menu menuWithTitle:@"3" children:[ + // [Menu menuWithTitle:@"3.1" children:[ + // [Menu menuWithTitle:@"3.1.1"], + // [Menu menuWithTitle:@"3.1.2"], + // [Menu menuWithTitle:@"3.1.3"], + // ]], + // [Menu menuWithTitle:@"3.2" children:[ + // [Menu menuWithTitle:@"3.2.1"], + // [Menu menuWithTitle:@"3.2.2"], + // [Menu menuWithTitle:@"3.2.3"], + // [Menu menuWithTitle:@"3.2.4"], + // ]], + // [Menu menuWithTitle:@"3.3" children:[ + // [Menu menuWithTitle:@"3.3.1"], + // [Menu menuWithTitle:@"3.3.2"], + // [Menu menuWithTitle:@"3.3.3"], + // [Menu menuWithTitle:@"3.3.4"], + // [Menu menuWithTitle:@"3.3.5"], + // ]] + // ]] ]]; var scrollView = [[CPScrollView alloc] initWithFrame:[contentView bounds]]; @@ -134,7 +189,7 @@ CPLogRegister(CPLogConsole); var column = [[CPTableColumn alloc] initWithIdentifier:@""]; [_outlineView addTableColumn:column]; [_outlineView setOutlineTableColumn:column]; - [_outlineView registerForDraggedTypes:[@"CustomType"]]; + [_outlineView registerForDraggedTypes:[CustomOutlineViewDragType]]; [_outlineView setDataSource:self]; [_outlineView setAllowsMultipleSelection:YES]; @@ -200,20 +255,37 @@ CPLogRegister(CPLogConsole); - (BOOL)outlineView:(CPOutlineView)anOutlineView writeItems:(CPArray)theItems toPasteboard:(CPPasteBoard)thePasteBoard { - [thePasteBoard declareTypes:[@"CustomType"] owner:self]; - [thePasteBoard setData:[CPKeyedArchiver archivedDataWithRootObject:theItems] forType:@"CustomType"]; + _draggedItems = theItems; + [thePasteBoard declareTypes:[CustomOutlineViewDragType] owner:self]; + [thePasteBoard setData:[CPKeyedArchiver archivedDataWithRootObject:theItems] forType:CustomOutlineViewDragType]; + return YES; } - (CPDragOperation)outlineView:(CPOutlineView)anOutlineView validateDrop:(id < CPDraggingInfo >)theInfo proposedItem:(id)theItem proposedChildIndex:(int)theIndex { - CPLog.debug(@"validate drop at index: %i item: %@", theIndex, theItem); return CPDragOperationEvery; } - (BOOL)outlineView:(CPOutlineView)outlineView acceptDrop:(id < CPDraggingInfo >)theInfo item:(id)theItem childIndex:(int)theIndex { - CPLog.debug(@"accept drop at index: %i item: %@", theIndex, theItem); + if (theItem === nil) + theItem = [self menu]; + + var menuIndex = [_draggedItems count]; + while (menuIndex--) + { + var menu = [_draggedItems objectAtIndex:menuIndex]; + + // CPLog.debug(@"move item: %@ to: %@ index: %@", menu, theItem, theIndex); + + [menu removeFromMenu]; + [theItem insertSubmenu:menu atIndex:theIndex]; + theIndex += 1; + } + + CPLog.debug([[self menu] descriptionWithChildren:YES]); + return YES; } From a18ea750a61c2123d24fbba0a4bb2bf668aad433 Mon Sep 17 00:00:00 2001 From: Klaas Pieter Annema Date: Fri, 29 Jan 2010 18:01:46 +0100 Subject: [PATCH 17/58] Fixed a bug where CPOutlineView would not call super's implementation of selectRowIndexes:byExtendingSelection: --- AppKit/CPOutlineView.j | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/AppKit/CPOutlineView.j b/AppKit/CPOutlineView.j index 19f194c8d..75eaf6371 100644 --- a/AppKit/CPOutlineView.j +++ b/AppKit/CPOutlineView.j @@ -353,7 +353,7 @@ var CPOutlineViewDataSource_outlineView_setObjectValue_forTableColumn_byItem_ item = [self itemAtRow:rowIndex]; if (![self isExpandable:item]) - return; + continue; var control = _disclosureControlsForRows[rowIndex]; [control setHighlighted:NO]; @@ -363,16 +363,16 @@ var CPOutlineViewDataSource_outlineView_setObjectValue_forTableColumn_byItem_ // Now highlight the new disclosure controls var selectedRows = []; - [rows getIndexes:selectedRows maxCount:-1 inIndexRange:nil]; + [rows getIndexes:selectedRows maxCount:-1 inIndexRange:nil]; - var index = [selectedRows count]; + var index = [selectedRows count]; while (index--) { var rowIndex = selectedRows[index], item = [self itemAtRow:rowIndex]; if (![self isExpandable:item]) - return; + continue; var control = _disclosureControlsForRows[rowIndex]; [control setHighlighted:YES]; From e3a075a6a60bd6fee0c686e5596fffcf990528ae Mon Sep 17 00:00:00 2001 From: Klaas Pieter Annema Date: Mon, 1 Feb 2010 11:22:57 +0100 Subject: [PATCH 18/58] - implemented CPOutlineView drag & drop - improved CPTableView drag & drop feedback --- AppKit/CPOutlineView.j | 196 +++++----- AppKit/CPTableView.j | 342 ++++++++-------- .../Manual/CPOutlineViewTest/AppController.j | 364 +++++++++--------- 3 files changed, 451 insertions(+), 451 deletions(-) diff --git a/AppKit/CPOutlineView.j b/AppKit/CPOutlineView.j index 75eaf6371..1a18b1866 100644 --- a/AppKit/CPOutlineView.j +++ b/AppKit/CPOutlineView.j @@ -145,7 +145,7 @@ var CPOutlineViewDataSource_outlineView_setObjectValue_forTableColumn_byItem_ if ([_outlineViewDataSource respondsToSelector:@selector(outlineView:sortDescriptorsDidChange:)]) _implementedOutlineViewDataSourceMethods |= CPOutlineViewDataSource_outlineView_sortDescriptorsDidChange_; - [[super dataSource] setImplementedDataSourceMethods:_implementedOutlineViewDataSourceMethods]; + [[super dataSource] setImplementedDataSourceMethods:_implementedOutlineViewDataSourceMethods]; [self reloadData]; } @@ -342,41 +342,41 @@ var CPOutlineViewDataSource_outlineView_setObjectValue_forTableColumn_byItem_ - (void)selectRowIndexes:(CPIndexSet)rows byExtendingSelection:(BOOL)shouldExtendSelection { - // First un highlight the old disclosure controls - var previousSelectedRows = []; - [[self selectedRowIndexes] getIndexes:previousSelectedRows maxCount:-1 inIndexRange:nil]; - - var index = [previousSelectedRows count]; - while (index--) - { - var rowIndex = previousSelectedRows[index], - item = [self itemAtRow:rowIndex]; - - if (![self isExpandable:item]) - continue; - - var control = _disclosureControlsForRows[rowIndex]; - [control setHighlighted:NO]; - } - - [super selectRowIndexes:rows byExtendingSelection:shouldExtendSelection]; - - // Now highlight the new disclosure controls - var selectedRows = []; - [rows getIndexes:selectedRows maxCount:-1 inIndexRange:nil]; - - var index = [selectedRows count]; - while (index--) - { - var rowIndex = selectedRows[index], - item = [self itemAtRow:rowIndex]; - - if (![self isExpandable:item]) - continue; - - var control = _disclosureControlsForRows[rowIndex]; - [control setHighlighted:YES]; - } + // First un highlight the old disclosure controls + var previousSelectedRows = []; + [[self selectedRowIndexes] getIndexes:previousSelectedRows maxCount:-1 inIndexRange:nil]; + + var index = [previousSelectedRows count]; + while (index--) + { + var rowIndex = previousSelectedRows[index], + item = [self itemAtRow:rowIndex]; + + if (![self isExpandable:item]) + continue; + + var control = _disclosureControlsForRows[rowIndex]; + [control setHighlighted:NO]; + } + + [super selectRowIndexes:rows byExtendingSelection:shouldExtendSelection]; + + // Now highlight the new disclosure controls + var selectedRows = []; + [rows getIndexes:selectedRows maxCount:-1 inIndexRange:nil]; + + var index = [selectedRows count]; + while (index--) + { + var rowIndex = selectedRows[index], + item = [self itemAtRow:rowIndex]; + + if (![self isExpandable:item]) + continue; + + var control = _disclosureControlsForRows[rowIndex]; + [control setHighlighted:YES]; + } } - (void)setDelegate:(id)aDelegate @@ -531,12 +531,12 @@ var CPOutlineViewDataSource_outlineView_setObjectValue_forTableColumn_byItem_ - (CPRect)rectForDropHighlightViewBetweenUpperRow:(int)theUpperRowIndex andLowerRow:(int)theLowerRowIndex { - // Just call super and update the x to reflect the current indentation level - var level = [self levelForRow:theLowerRowIndex], - rect = [super rectForDropHighlightViewBetweenUpperRow:theUpperRowIndex andLowerRow:theLowerRowIndex]; - - rect.origin.x = level * [self indentationPerLevel]; - return rect; + // Just call super and update the x to reflect the current indentation level + var level = [self levelForRow:theLowerRowIndex], + rect = [super rectForDropHighlightViewBetweenUpperRow:theUpperRowIndex andLowerRow:theLowerRowIndex]; + + rect.origin.x = level * [self indentationPerLevel]; + return rect; } - (void)_loadDataViewsInRows:(CPIndexSet)rows columns:(CPIndexSet)columns @@ -808,7 +808,7 @@ var _loadItemInfoForItem = function(/*CPOutlineView*/ anOutlineView, /*id*/ anIt @implementation _CPOutlineViewTableViewDataSource : CPObject { - int _implementedDataSourceMethods @accessors(property=implementedDataSourceMethods); + int _implementedDataSourceMethods @accessors(property=implementedDataSourceMethods); CPObject _outlineView; } @@ -834,70 +834,70 @@ var _loadItemInfoForItem = function(/*CPOutlineView*/ anOutlineView, /*id*/ anIt - (BOOL)tableView:(CPTableView)aTableColumn writeRowsWithIndexes:(CPIndexSet)theIndexes toPasteboard:(CPPasteboard)thePasteboard { - if (!_outlineView._implementedOutlineViewDataSourceMethods & CPOutlineViewDataSource_outlineView_writeItems_toPasteboard_) - return NO; - - var rowIndexes = []; - [theIndexes getIndexes:rowIndexes maxCount:[theIndexes count] inIndexRange:nil]; - - var rowIndex = [rowIndexes count], - items = []; - - while (rowIndex--) - [items addObject:[_outlineView itemAtRow:[rowIndexes objectAtIndex:rowIndex]]]; - - return [_outlineView._outlineViewDataSource outlineView:_outlineView writeItems:items toPasteboard:thePasteboard]; + if (!_outlineView._implementedOutlineViewDataSourceMethods & CPOutlineViewDataSource_outlineView_writeItems_toPasteboard_) + return NO; + + var rowIndexes = []; + [theIndexes getIndexes:rowIndexes maxCount:[theIndexes count] inIndexRange:nil]; + + var rowIndex = [rowIndexes count], + items = []; + + while (rowIndex--) + [items addObject:[_outlineView itemAtRow:[rowIndexes objectAtIndex:rowIndex]]]; + + return [_outlineView._outlineViewDataSource outlineView:_outlineView writeItems:items toPasteboard:thePasteboard]; } - (CPDragOperation)tableView:(CPTableView)aTableView validateDrop:(id < CPDraggingInfo >)theInfo - proposedRow:(int)theRow proposedDropOperation:(CPTableViewDropOperation)theOperation + proposedRow:(int)theRow proposedDropOperation:(CPTableViewDropOperation)theOperation { - if (!_outlineView._implementedOutlineViewDataSourceMethods & CPOutlineViewDataSource_outlineView_validateDrop_proposedItem_proposedChildIndex_) - return CPDragOperationNone; - - var droppedItem = [_outlineView itemAtRow:theRow], - parentItem = [_outlineView parentForItem:droppedItem]; - childIndex = CPNotFound; - - if (theOperation === CPTableViewDropAbove) - { - var itemInfo = (parentItem != nil) ? _outlineView._itemInfosForItems[[parentItem UID]] : _outlineView._rootItemInfo, - children = itemInfo.children, - - childIndex = [children indexOfObject:droppedItem]; - } - else if (theOperation === CPTableViewDropOn) - { - parentItem = droppedItem; - childIndex = -1; - } - - return [_outlineView._outlineViewDataSource outlineView:_outlineView validateDrop:theInfo proposedItem:parentItem proposedChildIndex:childIndex]; + if (!_outlineView._implementedOutlineViewDataSourceMethods & CPOutlineViewDataSource_outlineView_validateDrop_proposedItem_proposedChildIndex_) + return CPDragOperationNone; + + var droppedItem = [_outlineView itemAtRow:theRow], + parentItem = [_outlineView parentForItem:droppedItem]; + childIndex = CPNotFound; + + if (theOperation === CPTableViewDropAbove) + { + var itemInfo = (parentItem != nil) ? _outlineView._itemInfosForItems[[parentItem UID]] : _outlineView._rootItemInfo, + children = itemInfo.children, + + childIndex = [children indexOfObject:droppedItem]; + } + else if (theOperation === CPTableViewDropOn) + { + parentItem = droppedItem; + childIndex = -1; + } + + return [_outlineView._outlineViewDataSource outlineView:_outlineView validateDrop:theInfo proposedItem:parentItem proposedChildIndex:childIndex]; } - (BOOL)tableView:(CPTableView)aTableView acceptDrop:(id )theInfo row:(int)theRow dropOperation:(CPTableViewDropOperation)theOperation -{ - if (!_outlineView._implementedOutlineViewDataSourceMethods & CPOutlineViewDataSource_outlineView_acceptDrop_item_childIndex_) - return NO; - - var droppedItem = [_outlineView itemAtRow:theRow], - parentItem = [_outlineView parentForItem:droppedItem]; - childIndex = CPNotFound; +{ + if (!_outlineView._implementedOutlineViewDataSourceMethods & CPOutlineViewDataSource_outlineView_acceptDrop_item_childIndex_) + return NO; + + var droppedItem = [_outlineView itemAtRow:theRow], + parentItem = [_outlineView parentForItem:droppedItem]; + childIndex = CPNotFound; - if (theOperation === CPTableViewDropAbove) - { - var itemInfo = (parentItem != nil) ? _outlineView._itemInfosForItems[[parentItem UID]] : _outlineView._rootItemInfo, - children = itemInfo.children, + if (theOperation === CPTableViewDropAbove) + { + var itemInfo = (parentItem != nil) ? _outlineView._itemInfosForItems[[parentItem UID]] : _outlineView._rootItemInfo, + children = itemInfo.children, - childIndex = [children indexOfObject:droppedItem]; - } - else if (theOperation === CPTableViewDropOn) - { - parentItem = droppedItem; - childIndex = -1; - } - - return [_outlineView._outlineViewDataSource outlineView:_outlineView acceptDrop:theInfo item:parentItem childIndex:childIndex]; + childIndex = [children indexOfObject:droppedItem]; + } + else if (theOperation === CPTableViewDropOn) + { + parentItem = droppedItem; + childIndex = -1; + } + + return [_outlineView._outlineViewDataSource outlineView:_outlineView acceptDrop:theInfo item:parentItem childIndex:childIndex]; } @end diff --git a/AppKit/CPTableView.j b/AppKit/CPTableView.j index eeaf4fcb9..b2902664b 100644 --- a/AppKit/CPTableView.j +++ b/AppKit/CPTableView.j @@ -190,7 +190,7 @@ CPTableViewFirstColumnOnlyAutoresizingStyle = 5; SEL _doubleAction; unsigned _columnAutoResizingStyle; - CPView _dropOperationFeedbackView; + CPView _dropOperationFeedbackView; // BOOL _verticalMotionCanDrag; // unsigned _destinationDragStyle; @@ -527,10 +527,10 @@ window.setTimeout(function(){ [self setSelectionHightlightColor:[CPColor selectionColorSourceView]]; _destinationDragStyle = CPTableViewDraggingDestinationFeedbackStyleSourceList; } - else - { - [self setSelectionHightlightColor:[CPColor selectionColor]]; - _destinationDragStyle = CPTableViewDraggingDestinationFeedbackStyleRegular; + else + { + [self setSelectionHightlightColor:[CPColor selectionColor]]; + _destinationDragStyle = CPTableViewDraggingDestinationFeedbackStyleRegular; } } @@ -1556,63 +1556,63 @@ window.setTimeout(function(){ } - (CPImage)dragImageForRowsWithIndexes:(CPIndexSet)dragRows - tableColumns:(CPArray)theTableColumns - event:(CPEvent)dragEvent - offset:(CPPointPointer)dragImageOffset + tableColumns:(CPArray)theTableColumns + event:(CPEvent)dragEvent + offset:(CPPointPointer)dragImageOffset { return [[CPImage alloc] initWithContentsOfFile:@"Frameworks/AppKit/Resources/GenericFile.png" size:CGSizeMake(32,32)]; } - (CPView)dragViewForRowsWithIndexes:(CPIndexSet)theDraggedRows - tableColumns:(CPArray)theTableColumns - event:(CPEvent)theDragEvent - offset:(CPPoint)dragViewOffset + tableColumns:(CPArray)theTableColumns + event:(CPEvent)theDragEvent + offset:(CPPoint)dragViewOffset { - var bounds = [self bounds], - view = [[CPView alloc] initWithFrame:bounds]; - - [view setBackgroundColor:[CPColor clearColor]]; - [view setAlphaValue:0.7]; - - // We have to fetch all the data views for the selected rows and columns - // After that we can copy these add them to a transparent drag view and use that drag view - // to make it appear we are dragging images of those rows (as you would do in regular Cocoa) - var firstExposedColumn = [_exposedColumns firstIndex], - firstExposedRow = [_exposedRows firstIndex], - exposedColumnsLength = [_exposedColumns lastIndex] - firstExposedColumn + 1, - exposedRowsLength = [_exposedRows lastIndex] - firstExposedRow + 1, - columns = [], - rows = []; - - [_exposedColumns getIndexes:columns maxCount:-1 inIndexRange:CPMakeRange(firstExposedColumn, exposedColumnsLength)]; + var bounds = [self bounds], + view = [[CPView alloc] initWithFrame:bounds]; + + [view setBackgroundColor:[CPColor clearColor]]; + [view setAlphaValue:0.7]; + + // We have to fetch all the data views for the selected rows and columns + // After that we can copy these add them to a transparent drag view and use that drag view + // to make it appear we are dragging images of those rows (as you would do in regular Cocoa) + var firstExposedColumn = [_exposedColumns firstIndex], + firstExposedRow = [_exposedRows firstIndex], + exposedColumnsLength = [_exposedColumns lastIndex] - firstExposedColumn + 1, + exposedRowsLength = [_exposedRows lastIndex] - firstExposedRow + 1, + columns = [], + rows = []; + + [_exposedColumns getIndexes:columns maxCount:-1 inIndexRange:CPMakeRange(firstExposedColumn, exposedColumnsLength)]; [theDraggedRows getIndexes:rows maxCount:-1 inIndexRange:CPMakeRange(firstExposedRow, exposedRowsLength)]; - var columnIndex = [columns count]; - - while (columnIndex--) - { - var column = columns[columnIndex], - tableColumn = [_tableColumns objectAtIndex:column], - rowIndex = [rows count]; - - while (rowIndex--) - { - var row = rows[rowIndex]; - var dataView = [self _newDataViewForRow:row tableColumn:tableColumn]; - - [dataView setBackgroundColor:[CPColor clearColor]]; - [dataView setFrame:[self frameOfDataViewAtColumn:column row:row]]; - [dataView setObjectValue:[self _objectValueForTableColumn:tableColumn row:row]]; - - [view addSubview:dataView]; - } - } - - var dragPoint = [self convertPoint:[theDragEvent locationInWindow] fromView:nil]; - dragViewOffset.x = CGRectGetWidth(bounds)/2 - dragPoint.x; - dragViewOffset.y = CGRectGetHeight(bounds)/2 - dragPoint.y; - - return view; + var columnIndex = [columns count]; + + while (columnIndex--) + { + var column = columns[columnIndex], + tableColumn = [_tableColumns objectAtIndex:column], + rowIndex = [rows count]; + + while (rowIndex--) + { + var row = rows[rowIndex]; + var dataView = [self _newDataViewForRow:row tableColumn:tableColumn]; + + [dataView setBackgroundColor:[CPColor clearColor]]; + [dataView setFrame:[self frameOfDataViewAtColumn:column row:row]]; + [dataView setObjectValue:[self _objectValueForTableColumn:tableColumn row:row]]; + + [view addSubview:dataView]; + } + } + + var dragPoint = [self convertPoint:[theDragEvent locationInWindow] fromView:nil]; + dragViewOffset.x = CGRectGetWidth(bounds)/2 - dragPoint.x; + dragViewOffset.y = CGRectGetHeight(bounds)/2 - dragPoint.y; + + return view; } - (void)setDraggingSourceOperationMask:(CPDragOperation)mask forLocal:(BOOL)isLocal @@ -2110,7 +2110,7 @@ window.setTimeout(function(){ indexes = [], rectSelector = @selector(rectOfRow:); - [_selectionHightlightColor setFill]; + [_selectionHightlightColor setFill]; if ([_selectedRowIndexes count] >= 1) @@ -2299,11 +2299,11 @@ window.setTimeout(function(){ */ - (void)trackMouse:(CPEvent)anEvent { - // Prevent CPControl from eating the mouse events when we are in a drag session - if (![_draggedRowIndexes count]) - [super trackMouse:anEvent]; - else - [CPApp sendEvent:anEvent]; + // Prevent CPControl from eating the mouse events when we are in a drag session + if (![_draggedRowIndexes count]) + [super trackMouse:anEvent]; + else + [CPApp sendEvent:anEvent]; } /* @@ -2335,32 +2335,32 @@ window.setTimeout(function(){ if ([self canDragRowsWithIndexes:_draggedRowIndexes atPoint:aPoint] && [_dataSource tableView:self writeRowsWithIndexes:_draggedRowIndexes toPasteboard:pboard]) { - var currentEvent = [CPApp currentEvent], - offset = CPPointMakeZero(), - tableColumns = [_tableColumns objectsAtIndexes:_exposedColumns]; - - // We deviate from the default Cocoa implementation here by asking for a view in stead of an image - // We support both, but the view prefered over the image because we can mimic the rows we are dragging - // by re-creating the data views for the dragged rows - var view = [self dragViewForRowsWithIndexes:_draggedRowIndexes - tableColumns:tableColumns - event:currentEvent - offset:offset]; - - if (!view) - { - var image = [self dragImageForRowsWithIndexes:_draggedRowIndexes - tableColumns:tableColumns - event:currentEvent - offset:offset]; - view = [[CPImageView alloc] initWithFrame:CPMakeRect(0, 0, [image size].width, [image size].height)]; - [view setImage:image]; - } - - var bounds = [view bounds]; - var viewLocation = CPPointMake(aPoint.x - CGRectGetWidth(bounds)/2 + offset.x, aPoint.y - CGRectGetHeight(bounds)/2 + offset.y); - [self dragView:view at:viewLocation offset:CPPointMakeZero() event:[CPApp currentEvent] pasteboard:pboard source:self slideBack:YES]; - + var currentEvent = [CPApp currentEvent], + offset = CPPointMakeZero(), + tableColumns = [_tableColumns objectsAtIndexes:_exposedColumns]; + + // We deviate from the default Cocoa implementation here by asking for a view in stead of an image + // We support both, but the view prefered over the image because we can mimic the rows we are dragging + // by re-creating the data views for the dragged rows + var view = [self dragViewForRowsWithIndexes:_draggedRowIndexes + tableColumns:tableColumns + event:currentEvent + offset:offset]; + + if (!view) + { + var image = [self dragImageForRowsWithIndexes:_draggedRowIndexes + tableColumns:tableColumns + event:currentEvent + offset:offset]; + view = [[CPImageView alloc] initWithFrame:CPMakeRect(0, 0, [image size].width, [image size].height)]; + [view setImage:image]; + } + + var bounds = [view bounds]; + var viewLocation = CPPointMake(aPoint.x - CGRectGetWidth(bounds)/2 + offset.x, aPoint.y - CGRectGetHeight(bounds)/2 + offset.y); + [self dragView:view at:viewLocation offset:CPPointMakeZero() event:[CPApp currentEvent] pasteboard:pboard source:self slideBack:YES]; + return NO; } } @@ -2450,16 +2450,16 @@ window.setTimeout(function(){ - (CPView)_dropOperationFeedbackView { - return _dropOperationFeedbackView; + return _dropOperationFeedbackView; } - (void)_setDropOperationFeedbackView:(CPView)theFeedbackView { - if (_dropOperationFeedbackView === theFeedbackView) - return; - - [_dropOperationFeedbackView removeFromSuperview]; - _dropOperationFeedbackView = theFeedbackView; + if (_dropOperationFeedbackView === theFeedbackView) + return; + + [_dropOperationFeedbackView removeFromSuperview]; + _dropOperationFeedbackView = theFeedbackView; } /* @@ -2468,8 +2468,8 @@ window.setTimeout(function(){ - (CPDragOperation)draggingEntered:(id)sender { var location = [self convertPoint:[sender draggingLocation] fromView:nil], - dropOperation = [self _proposedDropOperationAtPoint:location], - row = [self _proposedRowAtPoint:location]; + dropOperation = [self _proposedDropOperationAtPoint:location], + row = [self _proposedRowAtPoint:location]; if(_retargetedDropRow !== nil) row = _retargetedDropRow; @@ -2492,7 +2492,7 @@ window.setTimeout(function(){ */ - (void)draggingExited:(id)sender { - [[self _dropOperationFeedbackView] setHidden:NO]; + [[self _dropOperationFeedbackView] setHidden:NO]; } /* @@ -2508,7 +2508,7 @@ window.setTimeout(function(){ _retargetedDropOperation = nil; _retargetedDropRow = nil; _draggedRowIndexes = [CPIndexSet indexSet]; - [[self _dropOperationFeedbackView] setHidden:YES]; + [[self _dropOperationFeedbackView] setHidden:YES]; } /* @ignore @@ -2523,21 +2523,21 @@ window.setTimeout(function(){ */ - (CPTableViewDropOperation)_proposedDropOperationAtPoint:(CGPoint)theDragPoint { - if(_retargetedDropOperation !== nil) - return _retargetedDropOperation; + if(_retargetedDropOperation !== nil) + return _retargetedDropOperation; - var row = [self rowAtPoint:theDragPoint], - rowRect = [self rectOfRow:row]; - - // If there is no (the default) or to little inter cell spacing we create some room for the CPTableViewDropAbove indicator - // This probably doesn't work if the row height is smaller than or around 5.0 - if ([self intercellSpacing].height < 5.0) - rowRect = CPRectInset(rowRect, 0.0, 5.0 - [self intercellSpacing].height); - - if (CGRectContainsPoint(rowRect, theDragPoint)) - return CPTableViewDropOn; - - return CPTableViewDropAbove; + var row = [self rowAtPoint:theDragPoint], + rowRect = [self rectOfRow:row]; + + // If there is no (the default) or to little inter cell spacing we create some room for the CPTableViewDropAbove indicator + // This probably doesn't work if the row height is smaller than or around 5.0 + if ([self intercellSpacing].height < 5.0) + rowRect = CPRectInset(rowRect, 0.0, 5.0 - [self intercellSpacing].height); + + if (CGRectContainsPoint(rowRect, theDragPoint)) + return CPTableViewDropOn; + + return CPTableViewDropAbove; } /* @@ -2573,54 +2573,54 @@ window.setTimeout(function(){ /*! Returns the subview that will draw the drop highlight on the row. - Sublcasses can override this to return a custom view to draw their drop highlight + Sublcasses can override this to return a custom view to draw their drop highlight @param theRowIndex the row index that should be highlighted */ - (CPView)viewForDropHighlightOnRow:(int)theRowIndex { - var view = [[CPView alloc] initWithFrame:[self rectOfRow:theRowIndex]]; - [view setBackgroundColor:[CPColor colorWithRed:175.0 / 255.0 green:193.0 / 255.0 blue:220.0 / 255.0 alpha:1.0]]; - return view; + var view = [[CPView alloc] initWithFrame:[self rectOfRow:theRowIndex]]; + [view setBackgroundColor:[CPColor colorWithRed:175.0 / 255.0 green:193.0 / 255.0 blue:220.0 / 255.0 alpha:1.0]]; + return view; } - (CPRect)rectForDropHighlightViewBetweenUpperRow:(int)theUpperRowIndex andLowerRow:(int)theLowerRowIndex { - // The default table view implemenation does not use the offset so we just place the view at x 0.0 - var upperRowRect = [self rectOfRow:theUpperRowIndex], - lowerRowRect = [self rectOfRow:theLowerRowIndex]; - - // Place the highlight view in the middle of the rows or in the middle of the intercell spacing - // TODO: this currently looks off because the row highlights and labels are not drawn in the middle of the row - var rect = CPRectMake(0.0, 0.0, CPRectGetWidth([self frame]), 10.0); - - rect.origin.y = CPRectGetMaxY(upperRowRect) - ( rect.size.height / 2.0 ); - - if (!CPSizeEqualToSize(CPSizeMakeZero(), [self intercellSpacing])) - rect.origin.y += [self intercellSpacing].height / 2.0; - - return rect; + // The default table view implemenation does not use the offset so we just place the view at x 0.0 + var upperRowRect = [self rectOfRow:theUpperRowIndex], + lowerRowRect = [self rectOfRow:theLowerRowIndex]; + + // Place the highlight view in the middle of the rows or in the middle of the intercell spacing + // TODO: this currently looks off because the row highlights and labels are not drawn in the middle of the row + var rect = CPRectMake(0.0, 0.0, CPRectGetWidth([self frame]), 10.0); + + rect.origin.y = CPRectGetMaxY(upperRowRect) - ( rect.size.height / 2.0 ); + + if (!CPSizeEqualToSize(CPSizeMakeZero(), [self intercellSpacing])) + rect.origin.y += [self intercellSpacing].height / 2.0; + + return rect; } /*! Returns the subview that will draw the drop highlight between the rows. - Sublcasses can override this to return a custom view to draw their drop highlight + Sublcasses can override this to return a custom view to draw their drop highlight @param theUpperRowIndex the index of the upper row - @param theLowerRowIndex the index of the lower row + @param theLowerRowIndex the index of the lower row */ - (CPView)viewForDropHighlightBetweenUpperRow:(int)theUpperRowIndex andLowerRow:(int)theLowerRowIndex { - return [[_CPDropOperationDrawView alloc] initWithFrame: - [self rectForDropHighlightViewBetweenUpperRow:theUpperRowIndex andLowerRow:theLowerRowIndex]]; + return [[_CPDropOperationDrawView alloc] initWithFrame: + [self rectForDropHighlightViewBetweenUpperRow:theUpperRowIndex andLowerRow:theLowerRowIndex]]; } - (CPDragOperation)draggingUpdated:(id)sender { var location = [self convertPoint:[sender draggingLocation] fromView:nil], - dropOperation = [self _proposedDropOperationAtPoint:location], + dropOperation = [self _proposedDropOperationAtPoint:location], numberOfRows = [self numberOfRows]; var row = [self _proposedRowAtPoint:location], - dragOperation = [self _validateDrop:sender proposedRow:row proposedDropOperation:dropOperation]; + dragOperation = [self _validateDrop:sender proposedRow:row proposedDropOperation:dropOperation]; if(_retargetedDropRow !== nil) row = _retargetedDropRow; @@ -2633,33 +2633,33 @@ window.setTimeout(function(){ rowRect = [self rectOfRow:row]; var exposedClipRect = [self exposedClipRect], - visibleWidth = _CGRectGetWidth(exposedClipRect); + visibleWidth = _CGRectGetWidth(exposedClipRect); rowRect = _CGRectMake(_CGRectGetMinX(exposedClipRect), rowRect.origin.y, visibleWidth, rowRect.size.height); - - // Ask for the feedback view and cache it so we can remove it from the view hierarchy later - var dropOperationFeedbackView = nil; - - // Get the correct drop feedback view and add it to the view hierarchy - if (dropOperation === CPTableViewDropAbove) - { - dropOperationFeedbackView = [self viewForDropHighlightBetweenUpperRow:row - 1 andLowerRow:row]; - [self addSubview:dropOperationFeedbackView positioned:CPWindowAbove relativeTo:nil]; - } - else if (dropOperation === CPTableViewDropOn) - { - dropOperationFeedbackView = [self viewForDropHighlightOnRow:row]; - - // FIXME: this doesn't work for tableviews that have alternating row background colors - [self addSubview:dropOperationFeedbackView positioned:CPWindowBelow relativeTo:nil]; - } - - [self _setDropOperationFeedbackView:dropOperationFeedbackView]; - - if (CGRectIsNull([[self _dropOperationFeedbackView] frame])) - [[self _dropOperationFeedbackView] setFrame:rowRect]; - - [[self _dropOperationFeedbackView] setHidden:NO]; + + // Ask for the feedback view and cache it so we can remove it from the view hierarchy later + var dropOperationFeedbackView = nil; + + // Get the correct drop feedback view and add it to the view hierarchy + if (dropOperation === CPTableViewDropAbove) + { + dropOperationFeedbackView = [self viewForDropHighlightBetweenUpperRow:row - 1 andLowerRow:row]; + [self addSubview:dropOperationFeedbackView positioned:CPWindowAbove relativeTo:nil]; + } + else if (dropOperation === CPTableViewDropOn) + { + dropOperationFeedbackView = [self viewForDropHighlightOnRow:row]; + + // FIXME: this doesn't work for tableviews that have alternating row background colors + [self addSubview:dropOperationFeedbackView positioned:CPWindowBelow relativeTo:nil]; + } + + [self _setDropOperationFeedbackView:dropOperationFeedbackView]; + + if (CGRectIsNull([[self _dropOperationFeedbackView] frame])) + [[self _dropOperationFeedbackView] setFrame:rowRect]; + + [[self _dropOperationFeedbackView] setHidden:NO]; // FIXME : Maybe we should do this in a timer outside this method. Problem: we don't know when the scroll ends and neighter when the next -draggingUpdated is called. Which one will come first ? if (row > 0 && location.y - CGRectGetMinY(exposedClipRect) < _rowHeight) @@ -2686,7 +2686,7 @@ window.setTimeout(function(){ - (BOOL)performDragOperation:(id)sender { var location = [self convertPoint:[sender draggingLocation] fromView:nil]; - operation = [self _proposedDropOperationAtPoint:location]; + operation = [self _proposedDropOperationAtPoint:location]; if(_retargetedDropRow !== nil) var row = _retargetedDropRow; @@ -2887,7 +2887,7 @@ window.setTimeout(function(){ var anEvent = [CPApp currentEvent]; if([[self selectedRowIndexes] count] > 0) - { + { var extend = NO; if(([anEvent modifierFlags] & CPShiftKeyMask) && _allowsMultipleSelection) @@ -3074,19 +3074,19 @@ var CPTableViewDataSourceKey = @"CPTableViewDataSourceKey", - (void)drawRect:(CGRect)aRect { var context = [[CPGraphicsContext currentContext] graphicsPort], - rect = [self bounds]; + rect = [self bounds]; CGContextSetStrokeColor(context, [CPColor selectionColor]); CGContextSetLineWidth(context, 3.0); - // We want the ellipse to fit in a square so we make sure the width and the height of the ellipse are equal - var ellipesRect = CPRectMake(rect.origin.x + 2.5, rect.origin.y + 2.5, rect.size.height - 4.0, rect.size.height - 4.0); - CGContextStrokeEllipseInRect(context, ellipesRect); - - CGContextBeginPath(context); - CGContextMoveToPoint(context, CPRectGetMaxX(ellipesRect), CPRectGetMidY(ellipesRect)); - CGContextAddLineToPoint(context, CPRectGetMaxX(rect) - CPRectGetMaxX(ellipesRect), CPRectGetMidY(ellipesRect)); - CGContextClosePath(context); - CGContextStrokePath(context); + // We want the ellipse to fit in a square so we make sure the width and the height of the ellipse are equal + var ellipesRect = CPRectMake(rect.origin.x + 2.5, rect.origin.y + 2.5, rect.size.height - 4.0, rect.size.height - 4.0); + CGContextStrokeEllipseInRect(context, ellipesRect); + + CGContextBeginPath(context); + CGContextMoveToPoint(context, CPRectGetMaxX(ellipesRect), CPRectGetMidY(ellipesRect)); + CGContextAddLineToPoint(context, CPRectGetMaxX(rect) - CPRectGetMaxX(ellipesRect), CPRectGetMidY(ellipesRect)); + CGContextClosePath(context); + CGContextStrokePath(context); } @end diff --git a/Tests/Manual/CPOutlineViewTest/AppController.j b/Tests/Manual/CPOutlineViewTest/AppController.j index 37d9cf451..0ecf904e9 100644 --- a/Tests/Manual/CPOutlineViewTest/AppController.j +++ b/Tests/Manual/CPOutlineViewTest/AppController.j @@ -15,278 +15,278 @@ CustomOutlineViewDragType = @"CustomOutlineViewDragType"; @implementation Menu : CPObject { - Menu _menu @accessors(property=menu); - - CPString _title @accessors(property=title); - CPArray _children @accessors(property=children); + Menu _menu @accessors(property=menu); + + CPString _title @accessors(property=title); + CPArray _children @accessors(property=children); } + (id)menuWithTitle:(CPString)theTitle { - return [[self alloc] initWithTitle:theTitle]; + return [[self alloc] initWithTitle:theTitle]; } + (id)menuWithTitle:(CPString)theTitle children:(CPArray)theChildren { - return [[self alloc] initWithTitle:theTitle children:theChildren]; + return [[self alloc] initWithTitle:theTitle children:theChildren]; } - (id)initWithTitle:(CPString)theTitle { - return [self initWithTitle:theTitle children:nil]; + return [self initWithTitle:theTitle children:nil]; } - (id)initWithTitle:(CPString)theTitle children:(CPArray)theChildren { - if ((self = [super init])) - { - _title = theTitle; - [self setChildren:theChildren]; - } - - return self; + if ((self = [super init])) + { + _title = theTitle; + [self setChildren:theChildren]; + } + + return self; } - (CPString)description { - return [self descriptionWithChildren:YES]; + return [self descriptionWithChildren:YES]; } - (CPString)descriptionWithChildren:(BOOL)showChildren { - var description = [super description] + @" " + [self title]; - - if (showChildren && [[self children] count] > 0) - description = @"\n" + [description stringByAppendingFormat:@" children: %@", [self children]]; + var description = [super description] + @" " + [self title]; + + if (showChildren && [[self children] count] > 0) + description = @"\n" + [description stringByAppendingFormat:@" children: %@", [self children]]; - return description; + return description; } - (void)insertSubmenu:(Menu)theItem atIndex:(int)theIndex { - CPLog.debug(@"insert menu: %@ in menu: %@ at index: %i", [theItem descriptionWithChildren:NO], [self descriptionWithChildren:NO], theIndex); - - if ([[self children] containsObject:theItem]) - return; - - if ([theItem menu]) - [theItem removeFromMenu]; - - [theItem setMenu:self]; - [[self children] insertObject:theItem atIndex:theIndex]; + CPLog.debug(@"insert menu: %@ in menu: %@ at index: %i", [theItem descriptionWithChildren:NO], [self descriptionWithChildren:NO], theIndex); + + if ([[self children] containsObject:theItem]) + return; + + if ([theItem menu]) + [theItem removeFromMenu]; + + [theItem setMenu:self]; + [[self children] insertObject:theItem atIndex:theIndex]; } - (void)removeFromMenu { - CPLog.debug(@"remove menu: %@ from menu: %@", [self descriptionWithChildren:NO], [[self menu] descriptionWithChildren:NO]); - - [[[self menu] children] removeObject:self]; - - CPLog.debug([[self menu] children]); - - [self setMenu:nil]; + CPLog.debug(@"remove menu: %@ from menu: %@", [self descriptionWithChildren:NO], [[self menu] descriptionWithChildren:NO]); + + [[[self menu] children] removeObject:self]; + + CPLog.debug([[self menu] children]); + + [self setMenu:nil]; } - (void)setChildren:(CPArray)theChildren { - if (_children === theChildren) - return; - - var childIndex = [theChildren count]; - while (childIndex--) - { - var child = theChildren[childIndex]; - [child setMenu:self]; - } - - _children = theChildren; + if (_children === theChildren) + return; + + var childIndex = [theChildren count]; + while (childIndex--) + { + var child = theChildren[childIndex]; + [child setMenu:self]; + } + + _children = theChildren; } - (id)initWithCoder:(CPCoder)theCoder { - if (self = [super init]) - { - _menu = [theCoder decodeObjectForKey:@"MenuSuperMenuKey"]; - _title = [theCoder decodeObjectForKey:@"MenuTitleKey"]; - [self setChildren:[theCoder decodeObjectForKey:@"MenuChildrenKey"]]; - } - - return self; + if (self = [super init]) + { + _menu = [theCoder decodeObjectForKey:@"MenuSuperMenuKey"]; + _title = [theCoder decodeObjectForKey:@"MenuTitleKey"]; + [self setChildren:[theCoder decodeObjectForKey:@"MenuChildrenKey"]]; + } + + return self; } - (void)encodeWithCoder:(CPCoder)aCoder { - [aCoder encodeObject:_menu forKey:@"MenuSuperMenuKey"]; - [aCoder encodeObject:_title forKey:@"MenuTitleKey"]; - [aCoder encodeObject:_children forKey:@"MenuChildrenKey"]; + [aCoder encodeObject:_menu forKey:@"MenuSuperMenuKey"]; + [aCoder encodeObject:_title forKey:@"MenuTitleKey"]; + [aCoder encodeObject:_children forKey:@"MenuChildrenKey"]; } @end @implementation AppController : CPObject { - Menu _menu @accessors(property=menu); - CPOutlineView _outlineView; - - CPArray _draggedItems; + Menu _menu @accessors(property=menu); + CPOutlineView _outlineView; + + CPArray _draggedItems; } - (void)applicationDidFinishLaunching:(CPNotification)aNotification { - var theWindow = [[CPWindow alloc] initWithContentRect:CGRectMakeZero() styleMask:CPBorderlessBridgeWindowMask], - contentView = [theWindow contentView]; + var theWindow = [[CPWindow alloc] initWithContentRect:CGRectMakeZero() styleMask:CPBorderlessBridgeWindowMask], + contentView = [theWindow contentView]; - _menu = [Menu menuWithTitle:@"Top" children:[ - [Menu menuWithTitle:@"1" children:[ - [Menu menuWithTitle:@"1.1" children:[ - [Menu menuWithTitle:@"1.1.1"], - [Menu menuWithTitle:@"1.1.2"], - ]], - [Menu menuWithTitle:@"1.2" children:[ - [Menu menuWithTitle:@"1.2.1"], - [Menu menuWithTitle:@"1.2.2"], - [Menu menuWithTitle:@"1.2.3"] - ]] - ]], - // [Menu menuWithTitle:@"2" children:[ - // [Menu menuWithTitle:@"2.1" children:[ - // [Menu menuWithTitle:@"2.1.1"], - // [Menu menuWithTitle:@"2.1.2"], - // [Menu menuWithTitle:@"2.1.3"], - // ]], - // [Menu menuWithTitle:@"2.2" children:[ - // [Menu menuWithTitle:@"2.2.1"], - // [Menu menuWithTitle:@"2.2.2"], - // ]] - // ]], - // [Menu menuWithTitle:@"3" children:[ - // [Menu menuWithTitle:@"3.1" children:[ - // [Menu menuWithTitle:@"3.1.1"], - // [Menu menuWithTitle:@"3.1.2"], - // [Menu menuWithTitle:@"3.1.3"], - // ]], - // [Menu menuWithTitle:@"3.2" children:[ - // [Menu menuWithTitle:@"3.2.1"], - // [Menu menuWithTitle:@"3.2.2"], - // [Menu menuWithTitle:@"3.2.3"], - // [Menu menuWithTitle:@"3.2.4"], - // ]], - // [Menu menuWithTitle:@"3.3" children:[ - // [Menu menuWithTitle:@"3.3.1"], - // [Menu menuWithTitle:@"3.3.2"], - // [Menu menuWithTitle:@"3.3.3"], - // [Menu menuWithTitle:@"3.3.4"], - // [Menu menuWithTitle:@"3.3.5"], - // ]] - // ]] - ]]; - - var scrollView = [[CPScrollView alloc] initWithFrame:[contentView bounds]]; - [theWindow setContentView:scrollView]; - - _outlineView = [[CPOutlineView alloc] initWithFrame:[contentView bounds]]; - - var column = [[CPTableColumn alloc] initWithIdentifier:@""]; - [_outlineView addTableColumn:column]; - [_outlineView setOutlineTableColumn:column]; - [_outlineView registerForDraggedTypes:[CustomOutlineViewDragType]]; - - [_outlineView setDataSource:self]; - [_outlineView setAllowsMultipleSelection:YES]; - // [_outlineView setIntercellSpacing:CPSizeMake(0.0, 0.0)] - - [scrollView setDocumentView:_outlineView]; + _menu = [Menu menuWithTitle:@"Top" children:[ + [Menu menuWithTitle:@"1" children:[ + [Menu menuWithTitle:@"1.1" children:[ + [Menu menuWithTitle:@"1.1.1"], + [Menu menuWithTitle:@"1.1.2"], + ]], + [Menu menuWithTitle:@"1.2" children:[ + [Menu menuWithTitle:@"1.2.1"], + [Menu menuWithTitle:@"1.2.2"], + [Menu menuWithTitle:@"1.2.3"] + ]] + ]], + // [Menu menuWithTitle:@"2" children:[ + // [Menu menuWithTitle:@"2.1" children:[ + // [Menu menuWithTitle:@"2.1.1"], + // [Menu menuWithTitle:@"2.1.2"], + // [Menu menuWithTitle:@"2.1.3"], + // ]], + // [Menu menuWithTitle:@"2.2" children:[ + // [Menu menuWithTitle:@"2.2.1"], + // [Menu menuWithTitle:@"2.2.2"], + // ]] + // ]], + // [Menu menuWithTitle:@"3" children:[ + // [Menu menuWithTitle:@"3.1" children:[ + // [Menu menuWithTitle:@"3.1.1"], + // [Menu menuWithTitle:@"3.1.2"], + // [Menu menuWithTitle:@"3.1.3"], + // ]], + // [Menu menuWithTitle:@"3.2" children:[ + // [Menu menuWithTitle:@"3.2.1"], + // [Menu menuWithTitle:@"3.2.2"], + // [Menu menuWithTitle:@"3.2.3"], + // [Menu menuWithTitle:@"3.2.4"], + // ]], + // [Menu menuWithTitle:@"3.3" children:[ + // [Menu menuWithTitle:@"3.3.1"], + // [Menu menuWithTitle:@"3.3.2"], + // [Menu menuWithTitle:@"3.3.3"], + // [Menu menuWithTitle:@"3.3.4"], + // [Menu menuWithTitle:@"3.3.5"], + // ]] + // ]] + ]]; + + var scrollView = [[CPScrollView alloc] initWithFrame:[contentView bounds]]; + [theWindow setContentView:scrollView]; + + _outlineView = [[CPOutlineView alloc] initWithFrame:[contentView bounds]]; + + var column = [[CPTableColumn alloc] initWithIdentifier:@""]; + [_outlineView addTableColumn:column]; + [_outlineView setOutlineTableColumn:column]; + [_outlineView registerForDraggedTypes:[CustomOutlineViewDragType]]; + + [_outlineView setDataSource:self]; + [_outlineView setAllowsMultipleSelection:YES]; + // [_outlineView setIntercellSpacing:CPSizeMake(0.0, 0.0)] + + [scrollView setDocumentView:_outlineView]; - [self expandItem:[self menu]]; + [self expandItem:[self menu]]; [theWindow orderFront:self]; } - (void)expandItem:(Menu)item { - var children = [item children], - childIndex = [children count]; - - while (childIndex--) - [self expandItem:[children objectAtIndex:childIndex]]; - - [_outlineView expandItem:item]; + var children = [item children], + childIndex = [children count]; + + while (childIndex--) + [self expandItem:[children objectAtIndex:childIndex]]; + + [_outlineView expandItem:item]; } - (id)outlineView:(CPOutlineView)theOutlineView child:(int)theIndex ofItem:(id)theItem { - if (theItem === nil) - theItem = [self menu]; - - // CPLog.debug(@"child: %i ofItem:%@ : %@", theIndex, theItem, [[theItem children] objectAtIndex:theIndex]); - - return [[theItem children] objectAtIndex:theIndex]; + if (theItem === nil) + theItem = [self menu]; + + // CPLog.debug(@"child: %i ofItem:%@ : %@", theIndex, theItem, [[theItem children] objectAtIndex:theIndex]); + + return [[theItem children] objectAtIndex:theIndex]; } - (BOOL)outlineView:(CPOutlineView)theOutlineView isItemExpandable:(id)theItem { - if (theItem === nil) - theItem = [self menu]; - - // CPLog.debug(@"isItemExpandable:%@ : %@", theItem, [[theItem children] count] > 0); - - return [[theItem children] count] > 0; + if (theItem === nil) + theItem = [self menu]; + + // CPLog.debug(@"isItemExpandable:%@ : %@", theItem, [[theItem children] count] > 0); + + return [[theItem children] count] > 0; } - (int)outlineView:(CPOutlineView)theOutlineView numberOfChildrenOfItem:(id)theItem { - if (theItem === nil) - theItem = [self menu]; - - // CPLog.debug(@"numberOfChildrenOfItem:%@ : %i", theItem, [[theItem children] count]); - - return [[theItem children] count]; + if (theItem === nil) + theItem = [self menu]; + + // CPLog.debug(@"numberOfChildrenOfItem:%@ : %i", theItem, [[theItem children] count]); + + return [[theItem children] count]; } - (id)outlineView:(CPOutlineView)anOutlineView objectValueForTableColumn:(CPTableColumn)theColumn byItem:(id)theItem -{ - if (theItem === nil) - theItem = [self menu]; - - // CPLog.debug(@"objectValueForTableColumn:%@ byItem:%@ : %@", theColumn, theItem, [theItem title]); - - return [theItem title]; +{ + if (theItem === nil) + theItem = [self menu]; + + // CPLog.debug(@"objectValueForTableColumn:%@ byItem:%@ : %@", theColumn, theItem, [theItem title]); + + return [theItem title]; } - (BOOL)outlineView:(CPOutlineView)anOutlineView writeItems:(CPArray)theItems toPasteboard:(CPPasteBoard)thePasteBoard { - _draggedItems = theItems; - [thePasteBoard declareTypes:[CustomOutlineViewDragType] owner:self]; - [thePasteBoard setData:[CPKeyedArchiver archivedDataWithRootObject:theItems] forType:CustomOutlineViewDragType]; - - return YES; + _draggedItems = theItems; + [thePasteBoard declareTypes:[CustomOutlineViewDragType] owner:self]; + [thePasteBoard setData:[CPKeyedArchiver archivedDataWithRootObject:theItems] forType:CustomOutlineViewDragType]; + + return YES; } - (CPDragOperation)outlineView:(CPOutlineView)anOutlineView validateDrop:(id < CPDraggingInfo >)theInfo proposedItem:(id)theItem proposedChildIndex:(int)theIndex { - return CPDragOperationEvery; + return CPDragOperationEvery; } - (BOOL)outlineView:(CPOutlineView)outlineView acceptDrop:(id < CPDraggingInfo >)theInfo item:(id)theItem childIndex:(int)theIndex { - if (theItem === nil) - theItem = [self menu]; - - var menuIndex = [_draggedItems count]; - while (menuIndex--) - { - var menu = [_draggedItems objectAtIndex:menuIndex]; - - // CPLog.debug(@"move item: %@ to: %@ index: %@", menu, theItem, theIndex); - - [menu removeFromMenu]; - [theItem insertSubmenu:menu atIndex:theIndex]; - theIndex += 1; - } - - CPLog.debug([[self menu] descriptionWithChildren:YES]); - - return YES; + if (theItem === nil) + theItem = [self menu]; + + var menuIndex = [_draggedItems count]; + while (menuIndex--) + { + var menu = [_draggedItems objectAtIndex:menuIndex]; + + // CPLog.debug(@"move item: %@ to: %@ index: %@", menu, theItem, theIndex); + + [menu removeFromMenu]; + [theItem insertSubmenu:menu atIndex:theIndex]; + theIndex += 1; + } + + CPLog.debug([[self menu] descriptionWithChildren:YES]); + + return YES; } @end From 4006b35a5e385e8b3bdc9805f1ece6a9bc822a9b Mon Sep 17 00:00:00 2001 From: Klaas Pieter Annema Date: Mon, 1 Feb 2010 12:39:22 +0100 Subject: [PATCH 19/58] fixed a bug where the outline view would send drag & drop datasource messages to it's datasource when they are not implemented --- AppKit/CPOutlineView.j | 6 +++--- Tests/Manual/CPOutlineViewTest/AppController.j | 7 ++++--- 2 files changed, 7 insertions(+), 6 deletions(-) diff --git a/AppKit/CPOutlineView.j b/AppKit/CPOutlineView.j index 1a18b1866..b61545148 100644 --- a/AppKit/CPOutlineView.j +++ b/AppKit/CPOutlineView.j @@ -834,7 +834,7 @@ var _loadItemInfoForItem = function(/*CPOutlineView*/ anOutlineView, /*id*/ anIt - (BOOL)tableView:(CPTableView)aTableColumn writeRowsWithIndexes:(CPIndexSet)theIndexes toPasteboard:(CPPasteboard)thePasteboard { - if (!_outlineView._implementedOutlineViewDataSourceMethods & CPOutlineViewDataSource_outlineView_writeItems_toPasteboard_) + if (!(_outlineView._implementedOutlineViewDataSourceMethods & CPOutlineViewDataSource_outlineView_writeItems_toPasteboard_)) return NO; var rowIndexes = []; @@ -852,7 +852,7 @@ var _loadItemInfoForItem = function(/*CPOutlineView*/ anOutlineView, /*id*/ anIt - (CPDragOperation)tableView:(CPTableView)aTableView validateDrop:(id < CPDraggingInfo >)theInfo proposedRow:(int)theRow proposedDropOperation:(CPTableViewDropOperation)theOperation { - if (!_outlineView._implementedOutlineViewDataSourceMethods & CPOutlineViewDataSource_outlineView_validateDrop_proposedItem_proposedChildIndex_) + if (!(_outlineView._implementedOutlineViewDataSourceMethods & CPOutlineViewDataSource_outlineView_validateDrop_proposedItem_proposedChildIndex_)) return CPDragOperationNone; var droppedItem = [_outlineView itemAtRow:theRow], @@ -877,7 +877,7 @@ var _loadItemInfoForItem = function(/*CPOutlineView*/ anOutlineView, /*id*/ anIt - (BOOL)tableView:(CPTableView)aTableView acceptDrop:(id )theInfo row:(int)theRow dropOperation:(CPTableViewDropOperation)theOperation { - if (!_outlineView._implementedOutlineViewDataSourceMethods & CPOutlineViewDataSource_outlineView_acceptDrop_item_childIndex_) + if (!(_outlineView._implementedOutlineViewDataSourceMethods & CPOutlineViewDataSource_outlineView_acceptDrop_item_childIndex_)) return NO; var droppedItem = [_outlineView itemAtRow:theRow], diff --git a/Tests/Manual/CPOutlineViewTest/AppController.j b/Tests/Manual/CPOutlineViewTest/AppController.j index 0ecf904e9..e4adeb0b5 100644 --- a/Tests/Manual/CPOutlineViewTest/AppController.j +++ b/Tests/Manual/CPOutlineViewTest/AppController.j @@ -181,8 +181,8 @@ CustomOutlineViewDragType = @"CustomOutlineViewDragType"; // ]] ]]; - var scrollView = [[CPScrollView alloc] initWithFrame:[contentView bounds]]; - [theWindow setContentView:scrollView]; + // var scrollView = [[CPScrollView alloc] initWithFrame:[contentView bounds]]; + _outlineView = [[CPOutlineView alloc] initWithFrame:[contentView bounds]]; @@ -195,7 +195,8 @@ CustomOutlineViewDragType = @"CustomOutlineViewDragType"; [_outlineView setAllowsMultipleSelection:YES]; // [_outlineView setIntercellSpacing:CPSizeMake(0.0, 0.0)] - [scrollView setDocumentView:_outlineView]; + // [scrollView setDocumentView:_outlineView]; + [theWindow setContentView:_outlineView]; [self expandItem:[self menu]]; From 77303c1aeb695dd6bb375a0b103e8161c76983af Mon Sep 17 00:00:00 2001 From: Klaas Pieter Annema Date: Mon, 1 Feb 2010 19:00:48 +0100 Subject: [PATCH 20/58] - implemented CPTableView's dataViewForTableColumn:row: delegate method - implemented CPOutlineView's dataViewForTableColumn:item: delegate method --- AppKit/CPOutlineView.j | 79 +++++-------------- AppKit/CPTableView.j | 13 ++- .../Manual/CPOutlineViewTest/AppController.j | 2 +- 3 files changed, 31 insertions(+), 63 deletions(-) diff --git a/AppKit/CPOutlineView.j b/AppKit/CPOutlineView.j index b61545148..db858fb68 100644 --- a/AppKit/CPOutlineView.j +++ b/AppKit/CPOutlineView.j @@ -50,6 +50,11 @@ var CPOutlineViewDataSource_outlineView_setObjectValue_forTableColumn_byItem_ CPOutlineViewDataSource_outlineView_sortDescriptorsDidChange_ = 1 << 10; + +var CPOutlineViewDelegate_outlineView_dataViewForTableColumn_item_ = 1 << 1; + + + @implementation CPOutlineView : CPTableView { id _outlineViewDataSource; @@ -60,6 +65,7 @@ var CPOutlineViewDataSource_outlineView_setObjectValue_forTableColumn_byItem_ BOOL _indentationMarkerFollowsDataView; CPInteger _implementedOutlineViewDataSourceMethods; + CPInteger _implementedOutlineViewDelegateMethods; Object _rootItemInfo; CPMutableArray _itemsForRows; @@ -88,6 +94,7 @@ var CPOutlineViewDataSource_outlineView_setObjectValue_forTableColumn_byItem_ [self setIndentationMarkerFollowsDataView:YES]; [super setDataSource:[[_CPOutlineViewTableViewDataSource alloc] initWithOutlineView:self]]; + [super setDelegate:[[_CPOutlineViewTableViewDelegate alloc] initWithOutlineView:self]]; [self setDisclosureControlPrototype:[[CPDisclosureButton alloc] initWithFrame:CGRectMake(0.0, 0.0, 10.0, 10.0)]]; } @@ -145,8 +152,6 @@ var CPOutlineViewDataSource_outlineView_setObjectValue_forTableColumn_byItem_ if ([_outlineViewDataSource respondsToSelector:@selector(outlineView:sortDescriptorsDidChange:)]) _implementedOutlineViewDataSourceMethods |= CPOutlineViewDataSource_outlineView_sortDescriptorsDidChange_; - [[super dataSource] setImplementedDataSourceMethods:_implementedOutlineViewDataSourceMethods]; - [self reloadData]; } @@ -413,63 +418,12 @@ var CPOutlineViewDataSource_outlineView_setObjectValue_forTableColumn_byItem_ object:self]; } - _outlineViewDelegate = aDelegate;/* - _implementedDelegateMethods = 0; + _outlineViewDelegate = aDelegate; + _implementedOutlineViewDelegateMethods = 0; - if ([_outlineViewDelegate respondsToSelector:@selector(selectionShouldChangeInTableView:)]) - _implementedDelegateMethods |= CPTableViewDelegate_selectionShouldChangeInTableView_; + if ([_outlineViewDelegate respondsToSelector:@selector(outlineView:dataViewForTableColumn:item:)]) + _implementedOutlineViewDelegateMethods |= CPOutlineViewDelegate_outlineView_dataViewForTableColumn_item_; - if ([_outlineViewDelegate respondsToSelector:@selector(tableView:dataViewForTableColumn:row:)]) - _implementedDelegateMethods |= CPTableViewDelegate_tableView_dataViewForTableColumn_row_; - - if ([_outlineViewDelegate respondsToSelector:@selector(tableView:didClickTableColumn:)]) - _implementedDelegateMethods |= CPTableViewDelegate_tableView_didClickTableColumn_; - - if ([_outlineViewDelegate respondsToSelector:@selector(tableView:didDragTableColumn:)]) - _implementedDelegateMethods |= CPTableViewDelegate_tableView_didDragTableColumn_; - - if ([_outlineViewDelegate respondsToSelector:@selector(tableView:heightOfRow:)]) - _implementedDelegateMethods |= CPTableViewDelegate_tableView_heightOfRow_; - - if ([_outlineViewDelegate respondsToSelector:@selector(tableView:isGroupRow:)]) - _implementedDelegateMethods |= CPTableViewDelegate_tableView_isGroupRow_; - - if ([_outlineViewDelegate respondsToSelector:@selector(tableView:mouseDownInHeaderOfTableColumn:)]) - _implementedDelegateMethods |= CPTableViewDelegate_tableView_mouseDownInHeaderOfTableColumn_; - - if ([_outlineViewDelegate respondsToSelector:@selector(tableView:nextTypeSelectMatchFromRow:toRow:forString:)]) - _implementedDelegateMethods |= CPTableViewDelegate_tableView_nextTypeSelectMatchFromRow_toRow_forString_; - - if ([_outlineViewDelegate respondsToSelector:@selector(tableView:selectionIndexesForProposedSelection:)]) - _implementedDelegateMethods |= CPTableViewDelegate_tableView_selectionIndexesForProposedSelection_; - - if ([_outlineViewDelegate respondsToSelector:@selector(tableView:shouldEditTableColumn:row:)]) - _implementedDelegateMethods |= CPTableViewDelegate_tableView_shouldEditTableColumn_row_; - - if ([_outlineViewDelegate respondsToSelector:@selector(tableView:shouldSelectRow:)]) - _implementedDelegateMethods |= CPTableViewDelegate_tableView_shouldSelectRow_; - - if ([_outlineViewDelegate respondsToSelector:@selector(tableView:shouldSelectTableColumn:)]) - _implementedDelegateMethods |= CPTableViewDelegate_tableView_shouldSelectTableColumn_; - - if ([_outlineViewDelegate respondsToSelector:@selector(tableView:shouldShowViewExpansionForTableColumn:row:)]) - _implementedDelegateMethods |= CPTableViewDelegate_tableView_shouldShowViewExpansionForTableColumn_row_; - - if ([_outlineViewDelegate respondsToSelector:@selector(tableView:shouldTrackView:forTableColumn:row:)]) - _implementedDelegateMethods |= CPTableViewDelegate_tableView_shouldTrackView_forTableColumn_row_; - - if ([_outlineViewDelegate respondsToSelector:@selector(tableView:shouldTypeSelectForEvent:withCurrentSearchString:)]) - _implementedDelegateMethods |= CPTableViewDelegate_tableView_shouldTypeSelectForEvent_withCurrentSearchString_; - - if ([_outlineViewDelegate respondsToSelector:@selector(tableView:toolTipForView:rect:tableColumn:row:mouseLocation:)]) - _implementedDelegateMethods |= CPTableViewDelegate_tableView_toolTipForView_rect_tableColumn_row_mouseLocation_; - - if ([_outlineViewDelegate respondsToSelector:@selector(tableView:typeSelectStringForTableColumn:row:)]) - _implementedDelegateMethods |= CPTableViewDelegate_tableView_typeSelectStringForTableColumn_row_; - - if ([_outlineViewDelegate respondsToSelector:@selector(tableView:willDisplayView:forTableColumn:row:)]) - _implementedDelegateMethods |= CPTableViewDelegate_tableView_willDisplayView_forTableColumn_row_; -*/ if ([_outlineViewDelegate respondsToSelector:@selector(outlineViewColumnDidMove:)]) [defaultCenter addObserver:_outlineViewDelegate @@ -707,7 +661,7 @@ var _reloadItem = function(/*CPOutlineView*/ anOutlineView, /*id*/ anItem) var _loadItemInfoForItem = function(/*CPOutlineView*/ anOutlineView, /*id*/ anItem, /*BOOL*/ isIntermediate) { var itemInfosForItems = anOutlineView._itemInfosForItems, - dataSource = anOutlineView._outlineViewDataSource; + dataSource = [anOutlineView dataSource]; // Somehow accessing the property directly doesn't work when a delegate was set if (!anItem) var itemInfo = anOutlineView._rootItemInfo; @@ -808,7 +762,6 @@ var _loadItemInfoForItem = function(/*CPOutlineView*/ anOutlineView, /*id*/ anIt @implementation _CPOutlineViewTableViewDataSource : CPObject { - int _implementedDataSourceMethods @accessors(property=implementedDataSourceMethods); CPObject _outlineView; } @@ -917,6 +870,14 @@ var _loadItemInfoForItem = function(/*CPOutlineView*/ anOutlineView, /*id*/ anIt return self; } +- (CPView)tableView:(CPTableView)theTableView dataViewForTableColumn:(CPTableColumn)theTableColumn row:(int)theRow +{ + if (!(_outlineView._implementedOutlineViewDelegateMethods & CPOutlineViewDelegate_outlineView_dataViewForTableColumn_item_)) + return [theTableColumn dataViewForRow:theRow]; + + return [_outlineView._outlineViewDelegate outlineView:_outlineView dataViewForTableColumn:theTableColumn item:[_outlineView itemAtRow:theRow]]; +} + @end @implementation CPDisclosureButton : CPButton diff --git a/AppKit/CPTableView.j b/AppKit/CPTableView.j index b2902664b..0491d67a9 100644 --- a/AppKit/CPTableView.j +++ b/AppKit/CPTableView.j @@ -1872,7 +1872,7 @@ window.setTimeout(function(){ [dataView unsetThemeState:CPThemeStateHighlighted]; if (_implementedDelegateMethods & CPTableViewDelegate_tableView_willDisplayView_forTableColumn_row_) - [[self delegate] tableView:self willDisplayView:dataView forTableColumn:tableColumn row:row]; + [_delegate tableView:self willDisplayView:dataView forTableColumn:tableColumn row:row]; if ([dataView superview] !== self) [self addSubview:dataView]; @@ -1910,6 +1910,13 @@ window.setTimeout(function(){ - (CPView)_newDataViewForRow:(CPInteger)aRow tableColumn:(CPTableColumn)aTableColumn { + if ((_implementedDelegateMethods & CPTableViewDelegate_tableView_dataViewForTableColumn_row_)) + { + var dataView = [_delegate tableView:self dataViewForTableColumn:aTableColumn row:aRow]; + [aTableColumn setDataView:dataView]; + } + + return [aTableColumn _newDataViewForRow:aRow]; } @@ -2999,8 +3006,8 @@ var CPTableViewDataSourceKey = @"CPTableViewDataSourceKey", _selectedColumnIndexes = [CPIndexSet indexSet]; _selectedRowIndexes = [CPIndexSet indexSet]; - [self setDataSource:[aCoder decodeObjectForKey:CPTableViewDataSourceKey]]; - [self setDelegate:[aCoder decodeObjectForKey:CPTableViewDelegateKey]]; + _dataSource = [aCoder decodeObjectForKey:CPTableViewDataSourceKey]; + _delegate = [aCoder decodeObjectForKey:CPTableViewDelegateKey]; _tableDrawView = [[_CPTableDrawView alloc] initWithTableView:self]; [_tableDrawView setBackgroundColor:[CPColor clearColor]]; diff --git a/Tests/Manual/CPOutlineViewTest/AppController.j b/Tests/Manual/CPOutlineViewTest/AppController.j index e4adeb0b5..78287f661 100644 --- a/Tests/Manual/CPOutlineViewTest/AppController.j +++ b/Tests/Manual/CPOutlineViewTest/AppController.j @@ -181,7 +181,7 @@ CustomOutlineViewDragType = @"CustomOutlineViewDragType"; // ]] ]]; - // var scrollView = [[CPScrollView alloc] initWithFrame:[contentView bounds]]; + var scrollView = [[CPScrollView alloc] initWithFrame:[contentView bounds]]; _outlineView = [[CPOutlineView alloc] initWithFrame:[contentView bounds]]; From 7f78c323e98369c6fffae6ac1bca8aebfc9f5692 Mon Sep 17 00:00:00 2001 From: Klaas Pieter Annema Date: Mon, 1 Feb 2010 19:08:22 +0100 Subject: [PATCH 21/58] implemented outlineView:shouldSelectItem delegate method --- AppKit/CPOutlineView.j | 22 ++++++++++++++++++---- 1 file changed, 18 insertions(+), 4 deletions(-) diff --git a/AppKit/CPOutlineView.j b/AppKit/CPOutlineView.j index db858fb68..f4d871b18 100644 --- a/AppKit/CPOutlineView.j +++ b/AppKit/CPOutlineView.j @@ -51,7 +51,8 @@ var CPOutlineViewDataSource_outlineView_setObjectValue_forTableColumn_byItem_ CPOutlineViewDataSource_outlineView_sortDescriptorsDidChange_ = 1 << 10; -var CPOutlineViewDelegate_outlineView_dataViewForTableColumn_item_ = 1 << 1; +var CPOutlineViewDelegate_outlineView_dataViewForTableColumn_item_ = 1 << 1, + CPOutlineViewDelegate_outlineView_shouldSelectItem_ = 1 << 2; @@ -423,6 +424,9 @@ var CPOutlineViewDelegate_outlineView_dataViewForTableColumn_item_ = 1 < if ([_outlineViewDelegate respondsToSelector:@selector(outlineView:dataViewForTableColumn:item:)]) _implementedOutlineViewDelegateMethods |= CPOutlineViewDelegate_outlineView_dataViewForTableColumn_item_; + + if ([_outlineViewDelegate respondsToSelector:@selector(outlineView:shouldSelectItem:)]) + _implementedOutlineViewDelegateMethods |= CPOutlineViewDelegate_outlineView_shouldSelectItem_; if ([_outlineViewDelegate respondsToSelector:@selector(outlineViewColumnDidMove:)]) [defaultCenter @@ -872,10 +876,20 @@ var _loadItemInfoForItem = function(/*CPOutlineView*/ anOutlineView, /*id*/ anIt - (CPView)tableView:(CPTableView)theTableView dataViewForTableColumn:(CPTableColumn)theTableColumn row:(int)theRow { - if (!(_outlineView._implementedOutlineViewDelegateMethods & CPOutlineViewDelegate_outlineView_dataViewForTableColumn_item_)) - return [theTableColumn dataViewForRow:theRow]; + if ((_outlineView._implementedOutlineViewDelegateMethods & CPOutlineViewDelegate_outlineView_dataViewForTableColumn_item_)) + return [_outlineView._outlineViewDelegate outlineView:_outlineView + dataViewForTableColumn:theTableColumn + item:[_outlineView itemAtRow:theRow]]; + + return [theTableColumn dataViewForRow:theRow]; +} + +- (BOOL)tableView:(CPTableView)theTableView shouldSelectRow:(int)theRow +{ + if ((_outlineView._implementedOutlineViewDelegateMethods & CPOutlineViewDelegate_outlineView_shouldSelectItem_)) + return [_outlineView._outlineViewDelegate outlineView:_outlineView shouldSelectItem:[_outlineView itemAtRow:theRow]]; - return [_outlineView._outlineViewDelegate outlineView:_outlineView dataViewForTableColumn:theTableColumn item:[_outlineView itemAtRow:theRow]]; + return YES; } @end From 0e6cef02685578517fcc86fb8265349fe3b920d1 Mon Sep 17 00:00:00 2001 From: Klaas Pieter Annema Date: Tue, 2 Feb 2010 11:23:24 +0100 Subject: [PATCH 22/58] implement outlineview expandItem:expandChildren: --- AppKit/CPOutlineView.j | 33 +++++++++++++++++++++------------ 1 file changed, 21 insertions(+), 12 deletions(-) diff --git a/AppKit/CPOutlineView.j b/AppKit/CPOutlineView.j index 77f1b6b38..120098f1e 100644 --- a/AppKit/CPOutlineView.j +++ b/AppKit/CPOutlineView.j @@ -189,20 +189,29 @@ var CPOutlineViewDelegate_outlineView_dataViewForTableColumn_item_ = 1 < - (void)expandItem:(id)anItem { - if (!anItem) - return; - - var itemInfo = _itemInfosForItems[[anItem UID]]; - - if (!itemInfo) - return; - - if (itemInfo.isExpanded) - return; - - itemInfo.isExpanded = YES; + [self expandItem:anItem expandChildren:NO]; +} +- (void)expandItem:(id)anItem expandChildren:(BOOL)shouldExpandChildren +{ + var itemInfo = null; + + if (!anItem) + itemInfo = _rootItemInfo; + else + itemInfo = _itemInfosForItems[[anItem UID]]; + + itemInfo.isExpanded = YES; [self reloadItem:anItem reloadChildren:YES]; + + if (shouldExpandChildren) + { + var children = itemInfo.children, + childIndex = children.length; + + while (childIndex--) + [self expandItem:children[childIndex] expandChildren:YES]; + } } - (void)collapseItem:(id)anItem From 8edf05c0009c483439684e864d1e143eb05b6fa8 Mon Sep 17 00:00:00 2001 From: Klaas Pieter Annema Date: Tue, 2 Feb 2010 11:37:57 +0100 Subject: [PATCH 23/58] made sure the outline view returns a dataview if it's delegate doesn't implement dataViewForTableColumn:item: or if that method returned nil --- AppKit/CPOutlineView.j | 11 ++++++++--- 1 file changed, 8 insertions(+), 3 deletions(-) diff --git a/AppKit/CPOutlineView.j b/AppKit/CPOutlineView.j index 120098f1e..ad5535402 100644 --- a/AppKit/CPOutlineView.j +++ b/AppKit/CPOutlineView.j @@ -892,12 +892,17 @@ var _loadItemInfoForItem = function(/*CPOutlineView*/ anOutlineView, /*id*/ anIt - (CPView)tableView:(CPTableView)theTableView dataViewForTableColumn:(CPTableColumn)theTableColumn row:(int)theRow { + var dataView = nil; + if ((_outlineView._implementedOutlineViewDelegateMethods & CPOutlineViewDelegate_outlineView_dataViewForTableColumn_item_)) - return [_outlineView._outlineViewDelegate outlineView:_outlineView + dataView = [_outlineView._outlineViewDelegate outlineView:_outlineView dataViewForTableColumn:theTableColumn item:[_outlineView itemAtRow:theRow]]; - - return [theTableColumn dataViewForRow:theRow]; + + if (!dataView) + dataView = [theTableColumn dataViewForRow:theRow]; + + return dataView; } - (BOOL)tableView:(CPTableView)theTableView shouldSelectRow:(int)theRow From 2d69509d5e341fb336e40ad06824534d69986500 Mon Sep 17 00:00:00 2001 From: Klaas Pieter Annema Date: Tue, 2 Feb 2010 14:15:22 +0100 Subject: [PATCH 24/58] - implemented CPTableView heightOfRow: delegate method - implemented CPOutlineView heightForItem: delegate method - made CPTableView work correctly with variable sized rows --- AppKit/CPOutlineView.j | 96 ++++++++++++++++++++++++------------------ AppKit/CPTableView.j | 64 ++++++++++++++++++++++------ 2 files changed, 104 insertions(+), 56 deletions(-) diff --git a/AppKit/CPOutlineView.j b/AppKit/CPOutlineView.j index ad5535402..59870af6f 100644 --- a/AppKit/CPOutlineView.j +++ b/AppKit/CPOutlineView.j @@ -51,8 +51,9 @@ var CPOutlineViewDataSource_outlineView_setObjectValue_forTableColumn_byItem_ CPOutlineViewDataSource_outlineView_sortDescriptorsDidChange_ = 1 << 10; -var CPOutlineViewDelegate_outlineView_dataViewForTableColumn_item_ = 1 << 1, - CPOutlineViewDelegate_outlineView_shouldSelectItem_ = 1 << 2; +var CPOutlineViewDelegate_outlineView_dataViewForTableColumn_item_ = 1 << 1, + CPOutlineViewDelegate_outlineView_shouldSelectItem_ = 1 << 2; + CPOutlineViewDelegate_outlineView_heightOfRowByItem_ = 1 << 3; @@ -66,7 +67,7 @@ var CPOutlineViewDelegate_outlineView_dataViewForTableColumn_item_ = 1 < BOOL _indentationMarkerFollowsDataView; CPInteger _implementedOutlineViewDataSourceMethods; - CPInteger _implementedOutlineViewDelegateMethods; + CPInteger _implementedOutlineViewDelegateMethods; Object _rootItemInfo; CPMutableArray _itemsForRows; @@ -95,7 +96,7 @@ var CPOutlineViewDelegate_outlineView_dataViewForTableColumn_item_ = 1 < [self setIndentationMarkerFollowsDataView:YES]; [super setDataSource:[[_CPOutlineViewTableViewDataSource alloc] initWithOutlineView:self]]; - [super setDelegate:[[_CPOutlineViewTableViewDelegate alloc] initWithOutlineView:self]]; + [super setDelegate:[[_CPOutlineViewTableViewDelegate alloc] initWithOutlineView:self]]; [self setDisclosureControlPrototype:[[CPDisclosureButton alloc] initWithFrame:CGRectMake(0.0, 0.0, 10.0, 10.0)]]; } @@ -189,29 +190,29 @@ var CPOutlineViewDelegate_outlineView_dataViewForTableColumn_item_ = 1 < - (void)expandItem:(id)anItem { - [self expandItem:anItem expandChildren:NO]; + [self expandItem:anItem expandChildren:NO]; } - (void)expandItem:(id)anItem expandChildren:(BOOL)shouldExpandChildren { - var itemInfo = null; - - if (!anItem) - itemInfo = _rootItemInfo; - else - itemInfo = _itemInfosForItems[[anItem UID]]; - - itemInfo.isExpanded = YES; + var itemInfo = null; + + if (!anItem) + itemInfo = _rootItemInfo; + else + itemInfo = _itemInfosForItems[[anItem UID]]; + + itemInfo.isExpanded = YES; [self reloadItem:anItem reloadChildren:YES]; - - if (shouldExpandChildren) - { - var children = itemInfo.children, - childIndex = children.length; - - while (childIndex--) - [self expandItem:children[childIndex] expandChildren:YES]; - } + + if (shouldExpandChildren) + { + var children = itemInfo.children, + childIndex = children.length; + + while (childIndex--) + [self expandItem:children[childIndex] expandChildren:YES]; + } } - (void)collapseItem:(id)anItem @@ -429,13 +430,16 @@ var CPOutlineViewDelegate_outlineView_dataViewForTableColumn_item_ = 1 < } _outlineViewDelegate = aDelegate; - _implementedOutlineViewDelegateMethods = 0; + _implementedOutlineViewDelegateMethods = 0; - if ([_outlineViewDelegate respondsToSelector:@selector(outlineView:dataViewForTableColumn:item:)]) - _implementedOutlineViewDelegateMethods |= CPOutlineViewDelegate_outlineView_dataViewForTableColumn_item_; - - if ([_outlineViewDelegate respondsToSelector:@selector(outlineView:shouldSelectItem:)]) - _implementedOutlineViewDelegateMethods |= CPOutlineViewDelegate_outlineView_shouldSelectItem_; + if ([_outlineViewDelegate respondsToSelector:@selector(outlineView:dataViewForTableColumn:item:)]) + _implementedOutlineViewDelegateMethods |= CPOutlineViewDelegate_outlineView_dataViewForTableColumn_item_; + + if ([_outlineViewDelegate respondsToSelector:@selector(outlineView:shouldSelectItem:)]) + _implementedOutlineViewDelegateMethods |= CPOutlineViewDelegate_outlineView_shouldSelectItem_; + + if ([_outlineViewDelegate respondsToSelector:@selector(outlineView:heightOfRowByItem:)]) + _implementedOutlineViewDelegateMethods |= CPOutlineViewDelegate_outlineView_heightOfRowByItem_; if ([_outlineViewDelegate respondsToSelector:@selector(outlineViewColumnDidMove:)]) [defaultCenter @@ -892,25 +896,33 @@ var _loadItemInfoForItem = function(/*CPOutlineView*/ anOutlineView, /*id*/ anIt - (CPView)tableView:(CPTableView)theTableView dataViewForTableColumn:(CPTableColumn)theTableColumn row:(int)theRow { - var dataView = nil; - - if ((_outlineView._implementedOutlineViewDelegateMethods & CPOutlineViewDelegate_outlineView_dataViewForTableColumn_item_)) - dataView = [_outlineView._outlineViewDelegate outlineView:_outlineView - dataViewForTableColumn:theTableColumn - item:[_outlineView itemAtRow:theRow]]; + var dataView = nil; + + if ((_outlineView._implementedOutlineViewDelegateMethods & CPOutlineViewDelegate_outlineView_dataViewForTableColumn_item_)) + dataView = [_outlineView._outlineViewDelegate outlineView:_outlineView + dataViewForTableColumn:theTableColumn + item:[_outlineView itemAtRow:theRow]]; - if (!dataView) - dataView = [theTableColumn dataViewForRow:theRow]; - - return dataView; + if (!dataView) + dataView = [theTableColumn dataViewForRow:theRow]; + + return dataView; } - (BOOL)tableView:(CPTableView)theTableView shouldSelectRow:(int)theRow { - if ((_outlineView._implementedOutlineViewDelegateMethods & CPOutlineViewDelegate_outlineView_shouldSelectItem_)) - return [_outlineView._outlineViewDelegate outlineView:_outlineView shouldSelectItem:[_outlineView itemAtRow:theRow]]; - - return YES; + if ((_outlineView._implementedOutlineViewDelegateMethods & CPOutlineViewDelegate_outlineView_shouldSelectItem_)) + return [_outlineView._outlineViewDelegate outlineView:_outlineView shouldSelectItem:[_outlineView itemAtRow:theRow]]; + + return YES; +} + +- (float)tableView:(CPTableView)theTableView heightOfRow:(int)theRow +{ + if ((_outlineView._implementedOutlineViewDelegateMethods & CPOutlineViewDelegate_outlineView_heightOfRowByItem_)) + return [_outlineView._outlineViewDelegate outlineView:_outlineView heightOfRowByItem:[_outlineView itemAtRow:theRow]]; + + return [theTableView rowHeight]; } @end diff --git a/AppKit/CPTableView.j b/AppKit/CPTableView.j index d1f9805da..d2f30aadb 100644 --- a/AppKit/CPTableView.j +++ b/AppKit/CPTableView.j @@ -161,6 +161,8 @@ CPTableViewFirstColumnOnlyAutoresizingStyle = 5; CGSize _intercellSpacing; float _rowHeight; + BOOL _hasVariableRowHeight; + BOOL _usesAlternatingRowBackgroundColors; CPArray _alternatingRowBackgroundColors; @@ -1035,11 +1037,23 @@ CPTableViewFirstColumnOnlyAutoresizingStyle = 5; - (CGRect)rectOfRow:(CPInteger)aRowIndex { - if (NO) - return NULL; - + if (aRowIndex === -1) + return CPRectMakeZero(); + + var rowHeight = _rowHeight; + + if ((_implementedDelegateMethods & CPTableViewDelegate_tableView_heightOfRow_)) + { + rowHeight = [_delegate tableView:self heightOfRow:aRowIndex]; + if (rowHeight !== _rowHeight) + _hasVariableRowHeight = YES; + } + else + _hasVariableRowHeight = NO; + // FIXME: WRONG: ASK TABLE COLUMN RANGE - return _CGRectMake(0.0, (aRowIndex * (_rowHeight + _intercellSpacing.height)), _CGRectGetWidth([self bounds]), _rowHeight); + var previousRowRect = [self rectOfRow:aRowIndex - 1]; + return CPRectMake(0.0, CPRectGetMaxY(previousRowRect) + _intercellSpacing.height, CPRectGetWidth([self bounds]), rowHeight); } // Complexity: @@ -1156,9 +1170,31 @@ CPTableViewFirstColumnOnlyAutoresizingStyle = 5; - (CPInteger)rowAtPoint:(CGPoint)aPoint { - var y = aPoint.y; - - var row = FLOOR(y / (_rowHeight + _intercellSpacing.height)); + var row = -1; + + // Check if we are using variable sized rows + // to determine if we can use the quicker way to determine the row at point + if (!_hasVariableRowHeight) + row = FLOOR(aPoint.y / (_rowHeight + _intercellSpacing.height)); + else + { + // We are using variable sized rows so we'll have to loop over all the rows and determine if it's at the current point + var rowArray = []; + [_exposedRows getIndexes:rowArray maxCount:-1 inIndexRange:nil]; + + var rowIndex = [rowArray count]; + + while (rowIndex--) + { + row = [rowArray objectAtIndex:rowIndex]; + + if (CPRectContainsPoint([self rectOfRow:[rowArray objectAtIndex:rowIndex]], aPoint)) + break; + + // Make sure that the row is not found if we exit the loop without breaking + row = -1; + } + } if (row >= _numberOfRows) return -1; @@ -1908,13 +1944,13 @@ CPTableViewFirstColumnOnlyAutoresizingStyle = 5; - (CPView)_newDataViewForRow:(CPInteger)aRow tableColumn:(CPTableColumn)aTableColumn { - if ((_implementedDelegateMethods & CPTableViewDelegate_tableView_dataViewForTableColumn_row_)) - { - var dataView = [_delegate tableView:self dataViewForTableColumn:aTableColumn row:aRow]; - [aTableColumn setDataView:dataView]; - } - - + if ((_implementedDelegateMethods & CPTableViewDelegate_tableView_dataViewForTableColumn_row_)) + { + var dataView = [_delegate tableView:self dataViewForTableColumn:aTableColumn row:aRow]; + [aTableColumn setDataView:dataView]; + } + + return [aTableColumn _newDataViewForRow:aRow]; } From 1571b6daa2da11f2ede511b9a3c85dfb46293eb2 Mon Sep 17 00:00:00 2001 From: Klaas Pieter Annema Date: Tue, 2 Feb 2010 15:44:23 +0100 Subject: [PATCH 25/58] fixed CPTableView's header view reliance on row height --- AppKit/CPTableView.j | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/AppKit/CPTableView.j b/AppKit/CPTableView.j index d2f30aadb..e503efd5a 100644 --- a/AppKit/CPTableView.j +++ b/AppKit/CPTableView.j @@ -244,7 +244,7 @@ CPTableViewFirstColumnOnlyAutoresizingStyle = 5; [self setGridColor:[CPColor grayColor]]; [self setGridStyleMask:CPTableViewGridNone]; - _headerView = [[CPTableHeaderView alloc] initWithFrame:CGRectMake(0, 0, [self bounds].size.width, _rowHeight)]; + _headerView = [[CPTableHeaderView alloc] initWithFrame:CGRectMake(0, 0, [self bounds].size.width, 23.0)]; [_headerView setTableView:self]; @@ -3027,7 +3027,7 @@ var CPTableViewDataSourceKey = @"CPTableViewDataSourceKey", [self setGridColor:[CPColor grayColor]]; [self setGridStyleMask:CPTableViewGridNone]; - _headerView = [[CPTableHeaderView alloc] initWithFrame:CGRectMake(0, 0, [self bounds].size.width, _rowHeight)]; + _headerView = [[CPTableHeaderView alloc] initWithFrame:CGRectMake(0, 0, [self bounds].size.width, 23.0)]; [_headerView setTableView:self]; From 8b32f561ec35e39e795eceb037773bbccc6db9f6 Mon Sep 17 00:00:00 2001 From: Klaas Pieter Annema Date: Tue, 2 Feb 2010 15:57:15 +0100 Subject: [PATCH 26/58] added selectedRow to CPTableView --- AppKit/CPTableView.j | 9 +++++++-- 1 file changed, 7 insertions(+), 2 deletions(-) diff --git a/AppKit/CPTableView.j b/AppKit/CPTableView.j index e503efd5a..6631c721d 100644 --- a/AppKit/CPTableView.j +++ b/AppKit/CPTableView.j @@ -244,7 +244,7 @@ CPTableViewFirstColumnOnlyAutoresizingStyle = 5; [self setGridColor:[CPColor grayColor]]; [self setGridStyleMask:CPTableViewGridNone]; - _headerView = [[CPTableHeaderView alloc] initWithFrame:CGRectMake(0, 0, [self bounds].size.width, 23.0)]; + _headerView = [[CPTableHeaderView alloc] initWithFrame:CGRectMake(0, 0, [self bounds].size.width, _rowHeight)]; [_headerView setTableView:self]; @@ -844,6 +844,11 @@ CPTableViewFirstColumnOnlyAutoresizingStyle = 5; return _selectedColumnIndexes; } +- (int)selectedRow +{ + return [_selectedRowIndexes lastIndex]; +} + - (CPIndexSet)selectedRowIndexes { return _selectedRowIndexes; @@ -3027,7 +3032,7 @@ var CPTableViewDataSourceKey = @"CPTableViewDataSourceKey", [self setGridColor:[CPColor grayColor]]; [self setGridStyleMask:CPTableViewGridNone]; - _headerView = [[CPTableHeaderView alloc] initWithFrame:CGRectMake(0, 0, [self bounds].size.width, 23.0)]; + _headerView = [[CPTableHeaderView alloc] initWithFrame:CGRectMake(0, 0, [self bounds].size.width, _rowHeight)]; [_headerView setTableView:self]; From c85e33c034836b1a98c15c6aa5e81293c13aa8a8 Mon Sep 17 00:00:00 2001 From: Klaas Pieter Annema Date: Wed, 3 Feb 2010 10:11:32 +0100 Subject: [PATCH 27/58] Fixed a bug where the CPTextField value was not updated properly when the update happened in the same 'runloop' iteration as becomeFirstResponder --- AppKit/CPTextField.j | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/AppKit/CPTextField.j b/AppKit/CPTextField.j index c906e80ca..c92985bf7 100644 --- a/AppKit/CPTextField.j +++ b/AppKit/CPTextField.j @@ -691,9 +691,10 @@ CPTextFieldStatePlaceholder = CPThemeState("placeholder"); - (void)setObjectValue:(id)aValue { [super setObjectValue:aValue]; - + #if PLATFORM(DOM) - if (CPTextFieldInputOwner === self) + + if (CPTextFieldInputOwner === self || [[self window] firstResponder] === self) [self _inputElement].value = aValue; #endif From ee6160e7962ddcb844517bdb6c822aae232c2416 Mon Sep 17 00:00:00 2001 From: Klaas Pieter Annema Date: Wed, 3 Feb 2010 15:06:42 +0100 Subject: [PATCH 28/58] - fixed some issues with variable sized - made CPOutlineView return the last index when dragging the row outside of it's bounds --- AppKit/CPOutlineView.j | 5 +++++ AppKit/CPTableView.j | 31 ++++++++++++++----------------- 2 files changed, 19 insertions(+), 17 deletions(-) diff --git a/AppKit/CPOutlineView.j b/AppKit/CPOutlineView.j index 59870af6f..aee074e09 100644 --- a/AppKit/CPOutlineView.j +++ b/AppKit/CPOutlineView.j @@ -842,6 +842,11 @@ var _loadItemInfoForItem = function(/*CPOutlineView*/ anOutlineView, /*id*/ anIt children = itemInfo.children, childIndex = [children indexOfObject:droppedItem]; + + // When no child is found the index we want to add the item below all it's children + // Think about dragging an item below the collectionview + if (childIndex === -1) + childIndex = [children count]; } else if (theOperation === CPTableViewDropOn) { diff --git a/AppKit/CPTableView.j b/AppKit/CPTableView.j index 6631c721d..63450685c 100644 --- a/AppKit/CPTableView.j +++ b/AppKit/CPTableView.j @@ -846,7 +846,7 @@ CPTableViewFirstColumnOnlyAutoresizingStyle = 5; - (int)selectedRow { - return [_selectedRowIndexes lastIndex]; + return [_selectedRowIndexes lastIndex]; } - (CPIndexSet)selectedRowIndexes @@ -1050,8 +1050,7 @@ CPTableViewFirstColumnOnlyAutoresizingStyle = 5; if ((_implementedDelegateMethods & CPTableViewDelegate_tableView_heightOfRow_)) { rowHeight = [_delegate tableView:self heightOfRow:aRowIndex]; - if (rowHeight !== _rowHeight) - _hasVariableRowHeight = YES; + _hasVariableRowHeight = YES; } else _hasVariableRowHeight = NO; @@ -1193,7 +1192,7 @@ CPTableViewFirstColumnOnlyAutoresizingStyle = 5; { row = [rowArray objectAtIndex:rowIndex]; - if (CPRectContainsPoint([self rectOfRow:[rowArray objectAtIndex:rowIndex]], aPoint)) + if (CPRectContainsPoint([self rectOfRow:row], aPoint)) break; // Make sure that the row is not found if we exit the loop without breaking @@ -1202,7 +1201,7 @@ CPTableViewFirstColumnOnlyAutoresizingStyle = 5; } if (row >= _numberOfRows) - return -1; + row = -1; return row; } @@ -2587,20 +2586,18 @@ CPTableViewFirstColumnOnlyAutoresizingStyle = 5; */ - (CPInteger)_proposedRowAtPoint:(CGPoint)dragPoint { - var numberOfRows = [self numberOfRows], - row; - // cocoa seems to jump to the next row when we approach the below row - dragPoint.y += FLOOR(_rowHeight/4); + dragPoint.y += 5.0; - if (dragPoint.y > numberOfRows * (_rowHeight + _intercellSpacing.height)) - { - if ([self _proposedDropOperationAtPoint:dragPoint] === CPTableViewDropAbove) - row = numberOfRows; - else - row = numberOfRows - 1; - } - else + var numberOfRows = [self numberOfRows], row = [self rowAtPoint:dragPoint]; + + // cocoa seems to jump to the next row when we approach the below row + // dragPoint.y += FLOOR(CPRectGetHeight([self rectOfRow:row]) / 4); + + // Check if we are dragging outside the tableview + // if we are we want the drag highlight to be below the last row + if (row === -1) + row = numberOfRows + 1; return row; } From b07f2ed186f0583899aa69bb239b28046771369f Mon Sep 17 00:00:00 2001 From: Klaas Pieter Annema Date: Wed, 3 Feb 2010 15:24:34 +0100 Subject: [PATCH 29/58] improved the location of the drag feedback view --- AppKit/CPTableView.j | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/AppKit/CPTableView.j b/AppKit/CPTableView.j index 63450685c..7a74b2217 100644 --- a/AppKit/CPTableView.j +++ b/AppKit/CPTableView.j @@ -1042,7 +1042,7 @@ CPTableViewFirstColumnOnlyAutoresizingStyle = 5; - (CGRect)rectOfRow:(CPInteger)aRowIndex { - if (aRowIndex === -1) + if (aRowIndex < 0) return CPRectMakeZero(); var rowHeight = _rowHeight; @@ -1057,6 +1057,7 @@ CPTableViewFirstColumnOnlyAutoresizingStyle = 5; // FIXME: WRONG: ASK TABLE COLUMN RANGE var previousRowRect = [self rectOfRow:aRowIndex - 1]; + return CPRectMake(0.0, CPRectGetMaxY(previousRowRect) + _intercellSpacing.height, CPRectGetWidth([self bounds]), rowHeight); } @@ -2586,16 +2587,15 @@ CPTableViewFirstColumnOnlyAutoresizingStyle = 5; */ - (CPInteger)_proposedRowAtPoint:(CGPoint)dragPoint { - dragPoint.y += 5.0; - var numberOfRows = [self numberOfRows], row = [self rowAtPoint:dragPoint]; - // cocoa seems to jump to the next row when we approach the below row - // dragPoint.y += FLOOR(CPRectGetHeight([self rectOfRow:row]) / 4); - + // cocoa seems to jump to the next row when we approach the below row + dragPoint.y += FLOOR(CPRectGetHeight([self rectOfRow:row]) / 4.0); + row = [self rowAtPoint:dragPoint]; + // Check if we are dragging outside the tableview - // if we are we want the drag highlight to be below the last row + // because we want the drag highlight to be below the last row if (row === -1) row = numberOfRows + 1; From 766073f77a4cf706ef17f815c5c29330b91ef9ff Mon Sep 17 00:00:00 2001 From: Klaas Pieter Annema Date: Thu, 4 Feb 2010 13:09:10 +0100 Subject: [PATCH 30/58] reverted some of my drop highlight changes --- AppKit/CPTableView.j | 209 ++++++++++++++++++------------------------- 1 file changed, 89 insertions(+), 120 deletions(-) diff --git a/AppKit/CPTableView.j b/AppKit/CPTableView.j index d8e350522..36e6d402f 100644 --- a/AppKit/CPTableView.j +++ b/AppKit/CPTableView.j @@ -192,8 +192,6 @@ CPTableViewFirstColumnOnlyAutoresizingStyle = 5; SEL _doubleAction; unsigned _columnAutoResizingStyle; - CPView _dropOperationFeedbackView; - BOOL _verticalMotionCanDrag; unsigned _destinationDragStyle; BOOL _isSelectingSession; @@ -260,10 +258,10 @@ CPTableViewFirstColumnOnlyAutoresizingStyle = 5; _retargetedDropOperation = nil; _dragOperationDefaultMask = nil; _destinationDragStyle = CPTableViewDraggingDestinationFeedbackStyleRegular; - // _dropOperationFeedbackView = [[_dropOperationDrawingView alloc] initWithFrame:_CGRectMakeZero()]; - // [self addSubview:_dropOperationFeedbackView]; - // [_dropOperationFeedbackView setHidden:YES]; - // [_dropOperationFeedbackView setTableView:self]; + _dropOperationFeedbackView = [[_dropOperationDrawingView alloc] initWithFrame:_CGRectMakeZero()]; + [self addSubview:_dropOperationFeedbackView]; + [_dropOperationFeedbackView setHidden:YES]; + [_dropOperationFeedbackView setTableView:self]; _tableDrawView = [[_CPTableDrawView alloc] initWithTableView:self]; [_tableDrawView setBackgroundColor:[CPColor clearColor]]; @@ -1058,7 +1056,7 @@ CPTableViewFirstColumnOnlyAutoresizingStyle = 5; // FIXME: WRONG: ASK TABLE COLUMN RANGE var previousRowRect = [self rectOfRow:aRowIndex - 1]; - return CPRectMake(0.0, CPRectGetMaxY(previousRowRect) + _intercellSpacing.height, CPRectGetWidth([self bounds]), rowHeight); + return CPRectMake(0.0, CPRectGetMaxY(previousRowRect) + _intercellSpacing.height, CPRectGetWidth([self bounds]), _rowHeight); } // Complexity: @@ -2494,27 +2492,13 @@ CPTableViewFirstColumnOnlyAutoresizingStyle = 5; [self sendAction:_doubleAction to:_target]; } -- (CPView)_dropOperationFeedbackView -{ - return _dropOperationFeedbackView; -} - -- (void)_setDropOperationFeedbackView:(CPView)theFeedbackView -{ - if (_dropOperationFeedbackView === theFeedbackView) - return; - - [_dropOperationFeedbackView removeFromSuperview]; - _dropOperationFeedbackView = theFeedbackView; -} - /* @ignore */ - (CPDragOperation)draggingEntered:(id)sender { var location = [self convertPoint:[sender draggingLocation] fromView:nil], - dropOperation = [self _proposedDropOperationAtPoint:location], + dropOperation = [self _proposedDropOperation], row = [self _proposedRowAtPoint:location]; if(_retargetedDropRow !== nil) @@ -2538,7 +2522,7 @@ CPTableViewFirstColumnOnlyAutoresizingStyle = 5; */ - (void)draggingExited:(id)sender { - [[self _dropOperationFeedbackView] setHidden:NO]; + [_dropOperationFeedbackView setHidden:YES]; } /* @@ -2554,7 +2538,7 @@ CPTableViewFirstColumnOnlyAutoresizingStyle = 5; _retargetedDropOperation = nil; _retargetedDropRow = nil; _draggedRowIndexes = [CPIndexSet indexSet]; - [[self _dropOperationFeedbackView] setHidden:YES]; + [_dropOperationFeedbackView setHidden:YES]; } /* @ignore @@ -2567,23 +2551,14 @@ CPTableViewFirstColumnOnlyAutoresizingStyle = 5; /* @ignore */ -- (CPTableViewDropOperation)_proposedDropOperationAtPoint:(CGPoint)theDragPoint +- (CPTableViewDropOperation)_proposedDropOperation { - if(_retargetedDropOperation !== nil) + //check is something is forced... + // otherwise we use the above action by default + if(_retargetedDropOperation !== nil) return _retargetedDropOperation; - - var row = [self rowAtPoint:theDragPoint], - rowRect = [self rectOfRow:row]; - - // If there is no (the default) or to little inter cell spacing we create some room for the CPTableViewDropAbove indicator - // This probably doesn't work if the row height is smaller than or around 5.0 - if ([self intercellSpacing].height < 5.0) - rowRect = CPRectInset(rowRect, 0.0, 5.0 - [self intercellSpacing].height); - - if (CGRectContainsPoint(rowRect, theDragPoint)) - return CPTableViewDropOn; - - return CPTableViewDropAbove; + else + return CPTableViewDropAbove; } /* @@ -2614,52 +2589,10 @@ CPTableViewFirstColumnOnlyAutoresizingStyle = 5; return CPDragOperationNone; } -/*! - Returns the subview that will draw the drop highlight on the row. - Sublcasses can override this to return a custom view to draw their drop highlight - @param theRowIndex the row index that should be highlighted -*/ -- (CPView)viewForDropHighlightOnRow:(int)theRowIndex -{ - var view = [[CPView alloc] initWithFrame:[self rectOfRow:theRowIndex]]; - [view setBackgroundColor:[CPColor colorWithRed:175.0 / 255.0 green:193.0 / 255.0 blue:220.0 / 255.0 alpha:1.0]]; - return view; -} - -- (CPRect)rectForDropHighlightViewBetweenUpperRow:(int)theUpperRowIndex andLowerRow:(int)theLowerRowIndex -{ - // The default table view implemenation does not use the offset so we just place the view at x 0.0 - var upperRowRect = [self rectOfRow:theUpperRowIndex], - lowerRowRect = [self rectOfRow:theLowerRowIndex]; - - // Place the highlight view in the middle of the rows or in the middle of the intercell spacing - // TODO: this currently looks off because the row highlights and labels are not drawn in the middle of the row - var rect = CPRectMake(0.0, 0.0, CPRectGetWidth([self frame]), 10.0); - - rect.origin.y = CPRectGetMaxY(upperRowRect) - ( rect.size.height / 2.0 ); - - if (!CPSizeEqualToSize(CPSizeMakeZero(), [self intercellSpacing])) - rect.origin.y += [self intercellSpacing].height / 2.0; - - return rect; -} - -/*! - Returns the subview that will draw the drop highlight between the rows. - Sublcasses can override this to return a custom view to draw their drop highlight - @param theUpperRowIndex the index of the upper row - @param theLowerRowIndex the index of the lower row -*/ -- (CPView)viewForDropHighlightBetweenUpperRow:(int)theUpperRowIndex andLowerRow:(int)theLowerRowIndex -{ - return [[_CPDropOperationDrawView alloc] initWithFrame: - [self rectForDropHighlightViewBetweenUpperRow:theUpperRowIndex andLowerRow:theLowerRowIndex]]; -} - - (CPDragOperation)draggingUpdated:(id)sender { var location = [self convertPoint:[sender draggingLocation] fromView:nil], - dropOperation = [self _proposedDropOperationAtPoint:location], + dropOperation = [self _proposedDropOperation], numberOfRows = [self numberOfRows]; var row = [self _proposedRowAtPoint:location], @@ -2680,29 +2613,11 @@ CPTableViewFirstColumnOnlyAutoresizingStyle = 5; rowRect = _CGRectMake(_CGRectGetMinX(exposedClipRect), rowRect.origin.y, visibleWidth, rowRect.size.height); - // Ask for the feedback view and cache it so we can remove it from the view hierarchy later - var dropOperationFeedbackView = nil; - - // Get the correct drop feedback view and add it to the view hierarchy - if (dropOperation === CPTableViewDropAbove) - { - dropOperationFeedbackView = [self viewForDropHighlightBetweenUpperRow:row - 1 andLowerRow:row]; - [self addSubview:dropOperationFeedbackView positioned:CPWindowAbove relativeTo:nil]; - } - else if (dropOperation === CPTableViewDropOn) - { - dropOperationFeedbackView = [self viewForDropHighlightOnRow:row]; - - // FIXME: this doesn't work for tableviews that have alternating row background colors - [self addSubview:dropOperationFeedbackView positioned:CPWindowBelow relativeTo:nil]; - } - - [self _setDropOperationFeedbackView:dropOperationFeedbackView]; - - if (CGRectIsNull([[self _dropOperationFeedbackView] frame])) - [[self _dropOperationFeedbackView] setFrame:rowRect]; - - [[self _dropOperationFeedbackView] setHidden:NO]; + [_dropOperationFeedbackView setDropOperation:dropOperation]; + [_dropOperationFeedbackView setHidden:(dragOperation == CPDragOperationNone)]; + [_dropOperationFeedbackView setFrame:rowRect]; + [_dropOperationFeedbackView setCurrentRow:row]; + [self addSubview:_dropOperationFeedbackView]; // FIXME : Maybe we should do this in a timer outside this method. Problem: we don't know when the scroll ends and neighter when the next -draggingUpdated is called. Which one will come first ? if (row > 0 && location.y - CGRectGetMinY(exposedClipRect) < _rowHeight) @@ -2720,6 +2635,8 @@ CPTableViewFirstColumnOnlyAutoresizingStyle = 5; { // FIX ME: is there anything else that needs to happen here? // actual validation is called in dragginUpdated: + [_dropOperationFeedbackView setHidden:YES]; + return (_implementedDataSourceMethods & CPTableViewDataSource_tableView_validateDrop_proposedRow_proposedDropOperation_); } @@ -2729,7 +2646,7 @@ CPTableViewFirstColumnOnlyAutoresizingStyle = 5; - (BOOL)performDragOperation:(id)sender { var location = [self convertPoint:[sender draggingLocation] fromView:nil]; - operation = [self _proposedDropOperationAtPoint:location]; + operation = [self _proposedDropOperation]; if(_retargetedDropRow !== nil) var row = _retargetedDropRow; @@ -3110,26 +3027,78 @@ var CPTableViewDataSourceKey = @"CPTableViewDataSourceKey", @end -@implementation _CPDropOperationDrawView : CPView +@implementation _dropOperationDrawingView : CPView { + unsigned dropOperation @accessors; + CPTableView tableView @accessors; + int currentRow @accessors; } - (void)drawRect:(CGRect)aRect { - var context = [[CPGraphicsContext currentContext] graphicsPort], - rect = [self bounds]; + if(tableView._destinationDragStyle === CPTableViewDraggingDestinationFeedbackStyleNone) + return; - CGContextSetStrokeColor(context, [CPColor selectionColor]); - CGContextSetLineWidth(context, 3.0); + var context = [[CPGraphicsContext currentContext] graphicsPort]; - // We want the ellipse to fit in a square so we make sure the width and the height of the ellipse are equal - var ellipesRect = CPRectMake(rect.origin.x + 2.5, rect.origin.y + 2.5, rect.size.height - 4.0, rect.size.height - 4.0); - CGContextStrokeEllipseInRect(context, ellipesRect); - - CGContextBeginPath(context); - CGContextMoveToPoint(context, CPRectGetMaxX(ellipesRect), CPRectGetMidY(ellipesRect)); - CGContextAddLineToPoint(context, CPRectGetMaxX(rect) - CPRectGetMaxX(ellipesRect), CPRectGetMidY(ellipesRect)); - CGContextClosePath(context); - CGContextStrokePath(context); + CGContextSetStrokeColor(context, [CPColor colorWithHexString:@"4886ca"]); + CGContextSetLineWidth(context, 3); + + if(dropOperation === CPTableViewDropOn) + { + //if row is selected don't fill and stroke white + var selectedRows = [tableView selectedRowIndexes]; + var newRect = _CGRectMake(aRect.origin.x + 2, aRect.origin.y + 2, aRect.size.width - 4, aRect.size.height - 5); + if([selectedRows containsIndex:currentRow]) + { + CGContextSetLineWidth(context, 2); + CGContextSetStrokeColor(context, [CPColor whiteColor]); + } + else + { + CGContextSetFillColor(context, [CPColor colorWithRed:72/255 green:134/255 blue:202/255 alpha:0.25]); + CGContextFillRoundedRectangleInRect(context, newRect, 8, YES, YES, YES, YES); + } + CGContextStrokeRoundedRectangleInRect(context, newRect, 8, YES, YES, YES, YES); + + } + + + if(dropOperation === CPTableViewDropAbove) + { + + + //reposition the view up a tad + [self setFrameOrigin:CGPointMake(_frame.origin.x, _frame.origin.y - 8)]; + + var selectedRows = [tableView selectedRowIndexes]; + + if([selectedRows containsIndex:currentRow - 1] || [selectedRows containsIndex:currentRow]) + { + CGContextSetStrokeColor(context, [CPColor whiteColor]); + CGContextSetLineWidth(context, 4); + //draw the circle thing + CGContextStrokeEllipseInRect(context, _CGRectMake(aRect.origin.x + 4, aRect.origin.y + 4, 8, 8)); + //then draw the line + CGContextBeginPath(context); + CGContextMoveToPoint(context, 10, aRect.origin.y + 8); + CGContextAddLineToPoint(context, aRect.size.width - aRect.origin.y - 8, aRect.origin.y + 8); + CGContextClosePath(context); + CGContextStrokePath(context); + + CGContextSetStrokeColor(context, [CPColor colorWithHexString:@"4886ca"]); + CGContextSetLineWidth(context, 3); + } + + //draw the circle thing + CGContextStrokeEllipseInRect(context, _CGRectMake(aRect.origin.x + 4, aRect.origin.y + 4, 8, 8)); + //then draw the line + CGContextBeginPath(context); + CGContextMoveToPoint(context, 10, aRect.origin.y + 8); + CGContextAddLineToPoint(context, aRect.size.width - aRect.origin.y - 8, aRect.origin.y + 8); + CGContextClosePath(context); + CGContextStrokePath(context); + //CGContextStrokeLineSegments(context, [aRect.origin.x + 8, aRect.origin.y + 8, 300 , aRect.origin.y + 8]); + } } @end From 117ec9970c5219cfc844c68c4335f99660d1b7c7 Mon Sep 17 00:00:00 2001 From: Klaas Pieter Annema Date: Thu, 4 Feb 2010 14:20:12 +0100 Subject: [PATCH 31/58] - reduced the number of rows on the tableview sample so it works with the variable row heights - made CPTableView ask for the rect of the drop highlight so CPOutlineView can adjust this - re factored some stuff in CPOutlineView's table delegate --- AppKit/CPOutlineView.j | 122 ++++++++++++------ AppKit/CPTableView.j | 7 +- .../Manual/CPOutlineViewTest/AppController.j | 39 ++---- Tests/Manual/TableTest/AppController.j | 2 +- 4 files changed, 101 insertions(+), 69 deletions(-) diff --git a/AppKit/CPOutlineView.j b/AppKit/CPOutlineView.j index aee074e09..363fe96b7 100644 --- a/AppKit/CPOutlineView.j +++ b/AppKit/CPOutlineView.j @@ -500,11 +500,11 @@ var CPOutlineViewDelegate_outlineView_dataViewForTableColumn_item_ return [super frameOfDataViewAtColumn:aColumn row:aRow]; } -- (CPRect)rectForDropHighlightViewBetweenUpperRow:(int)theUpperRowIndex andLowerRow:(int)theLowerRowIndex +- (CPRect)_rectForDropHighlightViewBetweenUpperRow:(int)theUpperRowIndex andLowerRow:(int)theLowerRowIndex offset:(float)theXOffset { // Just call super and update the x to reflect the current indentation level - var level = [self levelForRow:theLowerRowIndex], - rect = [super rectForDropHighlightViewBetweenUpperRow:theUpperRowIndex andLowerRow:theLowerRowIndex]; + var level = [self levelForRow:theUpperRowIndex], + rect = [super _rectForDropHighlightViewBetweenUpperRow:theUpperRowIndex andLowerRow:theLowerRowIndex offset:theXOffset]; rect.origin.x = level * [self indentationPerLevel]; return rect; @@ -826,33 +826,68 @@ var _loadItemInfoForItem = function(/*CPOutlineView*/ anOutlineView, /*id*/ anIt return [_outlineView._outlineViewDataSource outlineView:_outlineView writeItems:items toPasteboard:thePasteboard]; } +- (int)_childIndexForDropOperation:(CPTableViewDropOperation)theDropOperation item:(id)theItem +{ + var parentItem = [_outlineView parentForItem:theItem], + childIndex = CPNotFound; + + if (theDropOperation === CPTableViewDropAbove) + { + var itemInfo = (parentItem !== nil) ? _outlineView._itemInfosForItems[[parentItem UID]] : _outlineView._rootItemInfo, + children = itemInfo.children; + + childIndex = [children indexOfObject:theItem]; + + // When no child is found the index we want to add the item below all it's children + // Think about dragging an item below the collectionview + if (childIndex === -1) + childIndex = [children count]; + } + else if (theOperation === CPTableViewDropOn) + childIndex = -1; + + return childIndex; +} + +- (void)_parentItemForDropOperation:(CPTableViewDropOperation)theDropOperation item:(id)theItem +{ + if (theDropOperation === CPTableViewDropAbove) + return [_outlineView parentForItem:theItem]; + + else + return theItem; +} + - (CPDragOperation)tableView:(CPTableView)aTableView validateDrop:(id < CPDraggingInfo >)theInfo proposedRow:(int)theRow proposedDropOperation:(CPTableViewDropOperation)theOperation { if (!(_outlineView._implementedOutlineViewDataSourceMethods & CPOutlineViewDataSource_outlineView_validateDrop_proposedItem_proposedChildIndex_)) return CPDragOperationNone; - var droppedItem = [_outlineView itemAtRow:theRow], - parentItem = [_outlineView parentForItem:droppedItem]; - childIndex = CPNotFound; - - if (theOperation === CPTableViewDropAbove) - { - var itemInfo = (parentItem != nil) ? _outlineView._itemInfosForItems[[parentItem UID]] : _outlineView._rootItemInfo, - children = itemInfo.children, - - childIndex = [children indexOfObject:droppedItem]; - - // When no child is found the index we want to add the item below all it's children - // Think about dragging an item below the collectionview - if (childIndex === -1) - childIndex = [children count]; - } - else if (theOperation === CPTableViewDropOn) - { - parentItem = droppedItem; - childIndex = -1; - } + var childIndex = [self _childIndexForDropOperation:theOperation item:[_outlineView itemAtRow:theRow]], + parentItem = [self _parentItemForDropOperation:theOperation item:[_outlineView itemAtRow:theRow]]; + + // var droppedItem = [_outlineView itemAtRow:theRow], + // parentItem = [_outlineView parentForItem:droppedItem]; + // childIndex = CPNotFound; + // + // if (theOperation === CPTableViewDropAbove) + // { + // var itemInfo = (parentItem != nil) ? _outlineView._itemInfosForItems[[parentItem UID]] : _outlineView._rootItemInfo, + // children = itemInfo.children, + // + // childIndex = [children indexOfObject:droppedItem]; + // + // // When no child is found the index we want to add the item below all it's children + // // Think about dragging an item below the collectionview + // if (childIndex === -1) + // childIndex = [children count]; + // } + // else if (theOperation === CPTableViewDropOn) + // { + // parentItem = droppedItem; + // childIndex = -1; + // } return [_outlineView._outlineViewDataSource outlineView:_outlineView validateDrop:theInfo proposedItem:parentItem proposedChildIndex:childIndex]; } @@ -862,22 +897,29 @@ var _loadItemInfoForItem = function(/*CPOutlineView*/ anOutlineView, /*id*/ anIt if (!(_outlineView._implementedOutlineViewDataSourceMethods & CPOutlineViewDataSource_outlineView_acceptDrop_item_childIndex_)) return NO; - var droppedItem = [_outlineView itemAtRow:theRow], - parentItem = [_outlineView parentForItem:droppedItem]; - childIndex = CPNotFound; - - if (theOperation === CPTableViewDropAbove) - { - var itemInfo = (parentItem != nil) ? _outlineView._itemInfosForItems[[parentItem UID]] : _outlineView._rootItemInfo, - children = itemInfo.children, - - childIndex = [children indexOfObject:droppedItem]; - } - else if (theOperation === CPTableViewDropOn) - { - parentItem = droppedItem; - childIndex = -1; - } + // var droppedItem = [_outlineView itemAtRow:theRow], + // parentItem = [_outlineView parentForItem:droppedItem]; + // childIndex = CPNotFound; + // + // if (theOperation === CPTableViewDropAbove) + // { + // var itemInfo = (parentItem != nil) ? _outlineView._itemInfosForItems[[parentItem UID]] : _outlineView._rootItemInfo, + // children = itemInfo.children, + // + // childIndex = [children indexOfObject:droppedItem]; + // + // // When no child is found the index we want to add the item below all it's children + // // Think about dragging an item below the collectionview + // if (childIndex === -1) + // childIndex = [children count]; + // } + // else if (theOperation === CPTableViewDropOn) + // { + // parentItem = droppedItem; + // childIndex = -1; + // } + var childIndex = [self _childIndexForDropOperation:theOperation item:[_outlineView itemAtRow:theRow]], + parentItem = [self _parentItemForDropOperation:theOperation item:[_outlineView itemAtRow:theRow]]; return [_outlineView._outlineViewDataSource outlineView:_outlineView acceptDrop:theInfo item:parentItem childIndex:childIndex]; } diff --git a/AppKit/CPTableView.j b/AppKit/CPTableView.j index 36e6d402f..dd4a86256 100644 --- a/AppKit/CPTableView.j +++ b/AppKit/CPTableView.j @@ -2589,6 +2589,11 @@ CPTableViewFirstColumnOnlyAutoresizingStyle = 5; return CPDragOperationNone; } +- (CPRect)_rectForDropHighlightViewBetweenUpperRow:(int)theUpperRowIndex andLowerRow:(int)theLowerRowIndex offset:(float)theXOffset +{ + return [self rectOfRow:theUpperRowIndex]; +} + - (CPDragOperation)draggingUpdated:(id)sender { var location = [self convertPoint:[sender draggingLocation] fromView:nil], @@ -2615,7 +2620,7 @@ CPTableViewFirstColumnOnlyAutoresizingStyle = 5; [_dropOperationFeedbackView setDropOperation:dropOperation]; [_dropOperationFeedbackView setHidden:(dragOperation == CPDragOperationNone)]; - [_dropOperationFeedbackView setFrame:rowRect]; + [_dropOperationFeedbackView setFrame:[self _rectForDropHighlightViewBetweenUpperRow:row andLowerRow:row + 1 offset:location.x]]; [_dropOperationFeedbackView setCurrentRow:row]; [self addSubview:_dropOperationFeedbackView]; diff --git a/Tests/Manual/CPOutlineViewTest/AppController.j b/Tests/Manual/CPOutlineViewTest/AppController.j index 78287f661..b0506a96a 100644 --- a/Tests/Manual/CPOutlineViewTest/AppController.j +++ b/Tests/Manual/CPOutlineViewTest/AppController.j @@ -49,22 +49,12 @@ CustomOutlineViewDragType = @"CustomOutlineViewDragType"; - (CPString)description { - return [self descriptionWithChildren:YES]; -} - -- (CPString)descriptionWithChildren:(BOOL)showChildren -{ - var description = [super description] + @" " + [self title]; - - if (showChildren && [[self children] count] > 0) - description = @"\n" + [description stringByAppendingFormat:@" children: %@", [self children]]; - - return description; + return [self title]; } - (void)insertSubmenu:(Menu)theItem atIndex:(int)theIndex { - CPLog.debug(@"insert menu: %@ in menu: %@ at index: %i", [theItem descriptionWithChildren:NO], [self descriptionWithChildren:NO], theIndex); + CPLog.debug(@"insert menu: %@ in menu: %@ at index: %i", theItem, self, theIndex); if ([[self children] containsObject:theItem]) return; @@ -78,7 +68,7 @@ CustomOutlineViewDragType = @"CustomOutlineViewDragType"; - (void)removeFromMenu { - CPLog.debug(@"remove menu: %@ from menu: %@", [self descriptionWithChildren:NO], [[self menu] descriptionWithChildren:NO]); + CPLog.debug(@"remove menu: %@ from menu: %@", self, [self menu]); [[[self menu] children] removeObject:self]; @@ -193,27 +183,15 @@ CustomOutlineViewDragType = @"CustomOutlineViewDragType"; [_outlineView setDataSource:self]; [_outlineView setAllowsMultipleSelection:YES]; + [_outlineView expandItem:nil expandChildren:YES]; // [_outlineView setIntercellSpacing:CPSizeMake(0.0, 0.0)] // [scrollView setDocumentView:_outlineView]; [theWindow setContentView:_outlineView]; - [self expandItem:[self menu]]; - [theWindow orderFront:self]; } -- (void)expandItem:(Menu)item -{ - var children = [item children], - childIndex = [children count]; - - while (childIndex--) - [self expandItem:[children objectAtIndex:childIndex]]; - - [_outlineView expandItem:item]; -} - - (id)outlineView:(CPOutlineView)theOutlineView child:(int)theIndex ofItem:(id)theItem { if (theItem === nil) @@ -265,6 +243,11 @@ CustomOutlineViewDragType = @"CustomOutlineViewDragType"; - (CPDragOperation)outlineView:(CPOutlineView)anOutlineView validateDrop:(id < CPDraggingInfo >)theInfo proposedItem:(id)theItem proposedChildIndex:(int)theIndex { + if (theItem === nil) + theItem = [self menu]; + + CPLog.debug(@"validate item: %@ at index: %i", theItem, theIndex); + return CPDragOperationEvery; } @@ -272,6 +255,8 @@ CustomOutlineViewDragType = @"CustomOutlineViewDragType"; { if (theItem === nil) theItem = [self menu]; + + CPLog.debug(@"drop item: %@ at index: %i", theItem, theIndex); var menuIndex = [_draggedItems count]; while (menuIndex--) @@ -285,7 +270,7 @@ CustomOutlineViewDragType = @"CustomOutlineViewDragType"; theIndex += 1; } - CPLog.debug([[self menu] descriptionWithChildren:YES]); + CPLog.debug([self menu]); return YES; } diff --git a/Tests/Manual/TableTest/AppController.j b/Tests/Manual/TableTest/AppController.j index c8a24f961..d80b96eb1 100644 --- a/Tests/Manual/TableTest/AppController.j +++ b/Tests/Manual/TableTest/AppController.j @@ -22,7 +22,7 @@ CPLogRegister(CPLogConsole); dataSet1 = [], dataSet2 = []; - for(var i = 1; i < 500000; i++) + for(var i = 1; i < 100; i++) { dataSet1[i - 1] = i; dataSet2[i - 1] = i + 10; From 7720200679554f41f39f05366534b72acf6da3f2 Mon Sep 17 00:00:00 2001 From: Klaas Pieter Annema Date: Thu, 4 Feb 2010 16:56:48 +0100 Subject: [PATCH 32/58] - improved the CPOutlineView drag & drop support in cases where more than 1 parent is possible - improved the outline view test project --- AppKit/CPOutlineView.j | 128 +++++++----------- AppKit/CPTableView.j | 47 ++++--- .../Manual/CPOutlineViewTest/AppController.j | 48 ++++--- Tests/Manual/TableTest/AppController.j | 68 +++++----- 4 files changed, 138 insertions(+), 153 deletions(-) diff --git a/AppKit/CPOutlineView.j b/AppKit/CPOutlineView.j index 363fe96b7..f83d15721 100644 --- a/AppKit/CPOutlineView.j +++ b/AppKit/CPOutlineView.j @@ -500,13 +500,27 @@ var CPOutlineViewDelegate_outlineView_dataViewForTableColumn_item_ return [super frameOfDataViewAtColumn:aColumn row:aRow]; } +- (id)_parentItemForRow:(int)theLowerRow andUpperRow:(int)theUpperRow atMouseOffset:(float)theXOffset +{ + var level = [self levelForRow:theLowerRow], + upperLevel = [self levelForRow:theUpperRow]; + + if (upperLevel > level) + if (theXOffset > (level + 1) * [self indentationPerLevel]) + return [self parentForItem:[self itemAtRow:theUpperRow]]; + + return [self parentForItem:[self itemAtRow:theLowerRow]]; +} + - (CPRect)_rectForDropHighlightViewBetweenUpperRow:(int)theUpperRowIndex andLowerRow:(int)theLowerRowIndex offset:(float)theXOffset { - // Just call super and update the x to reflect the current indentation level - var level = [self levelForRow:theUpperRowIndex], - rect = [super _rectForDropHighlightViewBetweenUpperRow:theUpperRowIndex andLowerRow:theLowerRowIndex offset:theXOffset]; - - rect.origin.x = level * [self indentationPerLevel]; + // Call super and the x to reflect the current indentation level + var rect = [super _rectForDropHighlightViewBetweenUpperRow:theUpperRowIndex andLowerRow:theLowerRowIndex offset:theXOffset], + parentItem = [self _parentItemForRow:theLowerRowIndex andUpperRow:theUpperRowIndex atMouseOffset:theXOffset], + level = [self levelForItem:parentItem]; + + rect.origin.x = (level + 1) * [self indentationPerLevel]; + return rect; } @@ -826,36 +840,31 @@ var _loadItemInfoForItem = function(/*CPOutlineView*/ anOutlineView, /*id*/ anIt return [_outlineView._outlineViewDataSource outlineView:_outlineView writeItems:items toPasteboard:thePasteboard]; } -- (int)_childIndexForDropOperation:(CPTableViewDropOperation)theDropOperation item:(id)theItem +- (int)_childIndexForDropOperation:(CPTableViewDropOperation)theDropOperation row:(int)theRow offset:(CPPoint)theXOffset { - var parentItem = [_outlineView parentForItem:theItem], - childIndex = CPNotFound; - - if (theDropOperation === CPTableViewDropAbove) - { - var itemInfo = (parentItem !== nil) ? _outlineView._itemInfosForItems[[parentItem UID]] : _outlineView._rootItemInfo, - children = itemInfo.children; - - childIndex = [children indexOfObject:theItem]; - - // When no child is found the index we want to add the item below all it's children - // Think about dragging an item below the collectionview - if (childIndex === -1) - childIndex = [children count]; - } - else if (theOperation === CPTableViewDropOn) - childIndex = -1; - - return childIndex; + var childIndex = CPNotFound; + + if (theDropOperation === CPTableViewDropAbove) + { + var parentItem = [_outlineView _parentItemForRow:theRow andUpperRow:theRow - 1 atMouseOffset:theXOffset], + itemInfo = (parentItem !== nil) ? _outlineView._itemInfosForItems[[parentItem UID]] : _outlineView._rootItemInfo, + children = itemInfo.children; + + childIndex = [children indexOfObject:[_outlineView itemAtRow:theRow]]; + } + else if (theDropOperation === CPTableViewDropOn) + childIndex = -1; + + return childIndex; } -- (void)_parentItemForDropOperation:(CPTableViewDropOperation)theDropOperation item:(id)theItem + +- (void)_parentItemForDropOperation:(CPTableViewDropOperation)theDropOperation row:(int)theRow offset:(CPPoint)theXOffset { - if (theDropOperation === CPTableViewDropAbove) - return [_outlineView parentForItem:theItem]; - - else - return theItem; + if (theDropOperation === CPTableViewDropAbove) + return [_outlineView _parentItemForRow:theRow andUpperRow:theRow - 1 atMouseOffset:theXOffset] + + return [_outlineView itemAtRow:theRow]; } - (CPDragOperation)tableView:(CPTableView)aTableView validateDrop:(id < CPDraggingInfo >)theInfo @@ -863,31 +872,10 @@ var _loadItemInfoForItem = function(/*CPOutlineView*/ anOutlineView, /*id*/ anIt { if (!(_outlineView._implementedOutlineViewDataSourceMethods & CPOutlineViewDataSource_outlineView_validateDrop_proposedItem_proposedChildIndex_)) return CPDragOperationNone; - - var childIndex = [self _childIndexForDropOperation:theOperation item:[_outlineView itemAtRow:theRow]], - parentItem = [self _parentItemForDropOperation:theOperation item:[_outlineView itemAtRow:theRow]]; - - // var droppedItem = [_outlineView itemAtRow:theRow], - // parentItem = [_outlineView parentForItem:droppedItem]; - // childIndex = CPNotFound; - // - // if (theOperation === CPTableViewDropAbove) - // { - // var itemInfo = (parentItem != nil) ? _outlineView._itemInfosForItems[[parentItem UID]] : _outlineView._rootItemInfo, - // children = itemInfo.children, - // - // childIndex = [children indexOfObject:droppedItem]; - // - // // When no child is found the index we want to add the item below all it's children - // // Think about dragging an item below the collectionview - // if (childIndex === -1) - // childIndex = [children count]; - // } - // else if (theOperation === CPTableViewDropOn) - // { - // parentItem = droppedItem; - // childIndex = -1; - // } + + var location = [_outlineView convertPoint:[theInfo draggingLocation] fromView:nil], + childIndex = [self _childIndexForDropOperation:theOperation row:theRow offset:location.x], + parentItem = [self _parentItemForDropOperation:theOperation row:theRow offset:location.x]; return [_outlineView._outlineViewDataSource outlineView:_outlineView validateDrop:theInfo proposedItem:parentItem proposedChildIndex:childIndex]; } @@ -896,30 +884,10 @@ var _loadItemInfoForItem = function(/*CPOutlineView*/ anOutlineView, /*id*/ anIt { if (!(_outlineView._implementedOutlineViewDataSourceMethods & CPOutlineViewDataSource_outlineView_acceptDrop_item_childIndex_)) return NO; - - // var droppedItem = [_outlineView itemAtRow:theRow], - // parentItem = [_outlineView parentForItem:droppedItem]; - // childIndex = CPNotFound; - // - // if (theOperation === CPTableViewDropAbove) - // { - // var itemInfo = (parentItem != nil) ? _outlineView._itemInfosForItems[[parentItem UID]] : _outlineView._rootItemInfo, - // children = itemInfo.children, - // - // childIndex = [children indexOfObject:droppedItem]; - // - // // When no child is found the index we want to add the item below all it's children - // // Think about dragging an item below the collectionview - // if (childIndex === -1) - // childIndex = [children count]; - // } - // else if (theOperation === CPTableViewDropOn) - // { - // parentItem = droppedItem; - // childIndex = -1; - // } - var childIndex = [self _childIndexForDropOperation:theOperation item:[_outlineView itemAtRow:theRow]], - parentItem = [self _parentItemForDropOperation:theOperation item:[_outlineView itemAtRow:theRow]]; + + var location = [_outlineView convertPoint:[theInfo draggingLocation] fromView:nil], + childIndex = [self _childIndexForDropOperation:theOperation row:theRow offset:location.x], + parentItem = [self _parentItemForDropOperation:theOperation row:theRow offset:location.x]; return [_outlineView._outlineViewDataSource outlineView:_outlineView acceptDrop:theInfo item:parentItem childIndex:childIndex]; } diff --git a/AppKit/CPTableView.j b/AppKit/CPTableView.j index dd4a86256..e9dcf41f7 100644 --- a/AppKit/CPTableView.j +++ b/AppKit/CPTableView.j @@ -2498,7 +2498,7 @@ CPTableViewFirstColumnOnlyAutoresizingStyle = 5; - (CPDragOperation)draggingEntered:(id)sender { var location = [self convertPoint:[sender draggingLocation] fromView:nil], - dropOperation = [self _proposedDropOperation], + dropOperation = [self _proposedDropOperationAtPoint:location], row = [self _proposedRowAtPoint:location]; if(_retargetedDropRow !== nil) @@ -2538,7 +2538,7 @@ CPTableViewFirstColumnOnlyAutoresizingStyle = 5; _retargetedDropOperation = nil; _retargetedDropRow = nil; _draggedRowIndexes = [CPIndexSet indexSet]; - [_dropOperationFeedbackView setHidden:YES]; + [_dropOperationFeedbackView setHidden:YES]; } /* @ignore @@ -2551,14 +2551,23 @@ CPTableViewFirstColumnOnlyAutoresizingStyle = 5; /* @ignore */ -- (CPTableViewDropOperation)_proposedDropOperation +- (CPTableViewDropOperation)_proposedDropOperationAtPoint:(CGPoint)theDragPoint { - //check is something is forced... - // otherwise we use the above action by default - if(_retargetedDropOperation !== nil) + if(_retargetedDropOperation !== nil) return _retargetedDropOperation; - else - return CPTableViewDropAbove; + + var row = [self rowAtPoint:theDragPoint], + rowRect = [self rectOfRow:row]; + + // If there is no (the default) or to little inter cell spacing we create some room for the CPTableViewDropAbove indicator + // This probably doesn't work if the row height is smaller than or around 5.0 + if ([self intercellSpacing].height < 5.0) + rowRect = CPRectInset(rowRect, 0.0, 5.0 - [self intercellSpacing].height); + + if (CGRectContainsPoint(rowRect, theDragPoint)) + return CPTableViewDropOn; + + return CPTableViewDropAbove; } /* @@ -2569,14 +2578,9 @@ CPTableViewFirstColumnOnlyAutoresizingStyle = 5; var numberOfRows = [self numberOfRows], row = [self rowAtPoint:dragPoint]; - // cocoa seems to jump to the next row when we approach the below row + // cocoa seems to jump to the next row when we approach the below row dragPoint.y += FLOOR(CPRectGetHeight([self rectOfRow:row]) / 4.0); row = [self rowAtPoint:dragPoint]; - - // Check if we are dragging outside the tableview - // because we want the drag highlight to be below the last row - if (row === -1) - row = numberOfRows + 1; return row; } @@ -2591,13 +2595,13 @@ CPTableViewFirstColumnOnlyAutoresizingStyle = 5; - (CPRect)_rectForDropHighlightViewBetweenUpperRow:(int)theUpperRowIndex andLowerRow:(int)theLowerRowIndex offset:(float)theXOffset { - return [self rectOfRow:theUpperRowIndex]; + return [self rectOfRow:theLowerRowIndex]; } - (CPDragOperation)draggingUpdated:(id)sender { var location = [self convertPoint:[sender draggingLocation] fromView:nil], - dropOperation = [self _proposedDropOperation], + dropOperation = [self _proposedDropOperationAtPoint:location], numberOfRows = [self numberOfRows]; var row = [self _proposedRowAtPoint:location], @@ -2620,7 +2624,7 @@ CPTableViewFirstColumnOnlyAutoresizingStyle = 5; [_dropOperationFeedbackView setDropOperation:dropOperation]; [_dropOperationFeedbackView setHidden:(dragOperation == CPDragOperationNone)]; - [_dropOperationFeedbackView setFrame:[self _rectForDropHighlightViewBetweenUpperRow:row andLowerRow:row + 1 offset:location.x]]; + [_dropOperationFeedbackView setFrame:[self _rectForDropHighlightViewBetweenUpperRow:row - 1 andLowerRow:row offset:location.x]]; [_dropOperationFeedbackView setCurrentRow:row]; [self addSubview:_dropOperationFeedbackView]; @@ -2651,12 +2655,11 @@ CPTableViewFirstColumnOnlyAutoresizingStyle = 5; - (BOOL)performDragOperation:(id)sender { var location = [self convertPoint:[sender draggingLocation] fromView:nil]; - operation = [self _proposedDropOperation]; + operation = [self _proposedDropOperationAtPoint:location], + row = _retargetedDropRow; - if(_retargetedDropRow !== nil) - var row = _retargetedDropRow; - else - var row = [self rowAtPoint:location]; + if(row === nil) + var row = [self _proposedRowAtPoint:location]; return [_dataSource tableView:self acceptDrop:sender row:row dropOperation:operation]; } diff --git a/Tests/Manual/CPOutlineViewTest/AppController.j b/Tests/Manual/CPOutlineViewTest/AppController.j index b0506a96a..70ecefe7f 100644 --- a/Tests/Manual/CPOutlineViewTest/AppController.j +++ b/Tests/Manual/CPOutlineViewTest/AppController.j @@ -49,26 +49,36 @@ CustomOutlineViewDragType = @"CustomOutlineViewDragType"; - (CPString)description { - return [self title]; + return [self title]; } - (void)insertSubmenu:(Menu)theItem atIndex:(int)theIndex { - CPLog.debug(@"insert menu: %@ in menu: %@ at index: %i", theItem, self, theIndex); + // CPLog.debug(@"insert menu: %@ in menu: %@ at index: %i", theItem, self, theIndex); if ([[self children] containsObject:theItem]) return; if ([theItem menu]) [theItem removeFromMenu]; - + [theItem setMenu:self]; - [[self children] insertObject:theItem atIndex:theIndex]; + + if (theIndex === -1) + { + [[self children] addObject:theItem]; + } + else + { + [[self children] insertObject:theItem atIndex:theIndex]; + } + + // CPLog.debug(@"%@ children: %@", self, [self children]); } - (void)removeFromMenu { - CPLog.debug(@"remove menu: %@ from menu: %@", self, [self menu]); + // CPLog.debug(@"remove menu: %@ from menu: %@", self, [self menu]); [[[self menu] children] removeObject:self]; @@ -79,6 +89,9 @@ CustomOutlineViewDragType = @"CustomOutlineViewDragType"; - (void)setChildren:(CPArray)theChildren { + if (theChildren === nil) + theChildren = []; + if (_children === theChildren) return; @@ -88,7 +101,7 @@ CustomOutlineViewDragType = @"CustomOutlineViewDragType"; var child = theChildren[childIndex]; [child setMenu:self]; } - + _children = theChildren; } @@ -183,11 +196,11 @@ CustomOutlineViewDragType = @"CustomOutlineViewDragType"; [_outlineView setDataSource:self]; [_outlineView setAllowsMultipleSelection:YES]; - [_outlineView expandItem:nil expandChildren:YES]; + [_outlineView expandItem:nil expandChildren:YES]; // [_outlineView setIntercellSpacing:CPSizeMake(0.0, 0.0)] // [scrollView setDocumentView:_outlineView]; - [theWindow setContentView:_outlineView]; + [theWindow setContentView:_outlineView]; [theWindow orderFront:self]; } @@ -243,11 +256,11 @@ CustomOutlineViewDragType = @"CustomOutlineViewDragType"; - (CPDragOperation)outlineView:(CPOutlineView)anOutlineView validateDrop:(id < CPDraggingInfo >)theInfo proposedItem:(id)theItem proposedChildIndex:(int)theIndex { - if (theItem === nil) - theItem = [self menu]; - - CPLog.debug(@"validate item: %@ at index: %i", theItem, theIndex); - + if (theItem === nil) + theItem = [self menu]; + + CPLog.debug(@"validate item: %@ at index: %i", theItem, theIndex); + return CPDragOperationEvery; } @@ -255,8 +268,8 @@ CustomOutlineViewDragType = @"CustomOutlineViewDragType"; { if (theItem === nil) theItem = [self menu]; - - CPLog.debug(@"drop item: %@ at index: %i", theItem, theIndex); + + CPLog.debug(@"drop item: %@ at index: %i", theItem, theIndex); var menuIndex = [_draggedItems count]; while (menuIndex--) @@ -265,13 +278,14 @@ CustomOutlineViewDragType = @"CustomOutlineViewDragType"; // CPLog.debug(@"move item: %@ to: %@ index: %@", menu, theItem, theIndex); + if (menu === theItem) + continue; + [menu removeFromMenu]; [theItem insertSubmenu:menu atIndex:theIndex]; theIndex += 1; } - CPLog.debug([self menu]); - return YES; } diff --git a/Tests/Manual/TableTest/AppController.j b/Tests/Manual/TableTest/AppController.j index d80b96eb1..0ca646c09 100644 --- a/Tests/Manual/TableTest/AppController.j +++ b/Tests/Manual/TableTest/AppController.j @@ -66,7 +66,7 @@ CPLogRegister(CPLogConsole); // [textDataView setValue:CGInsetMake(0, 0, 0, 0) forThemeAttribute:@"focus-inset" inState:CPThemeStateBezeled|CPThemeStateEditing]; //[textDataView setValue:CGSizeMake(1,1) forThemeAttribute:@"text-shadow-offset"]; - //[textDataView setValue:[CPColor blackColor] forThemeAttribute:@"text-shadow-color" inState:CPThemeStateHighlighted]; + //[textDataView setValue:[CPColor blackColor] forThemeAttribute:@"text-shadow-color" inState:CPThemeStateHighlighted]; // [textDataView setBackgroundColor:[[CPColor redColor] colorWithAlphaComponent:0.5]]; @@ -149,7 +149,7 @@ CPLogRegister(CPLogConsole); [textDataView setValue:[CPFont systemFontOfSize:12] forThemeAttribute:@"font" inState:CPThemeStateHighlighted]; //[textDataView setValue:CGSizeMake(1,1) forThemeAttribute:@"text-shadow-offset"]; - //[textDataView setValue:[CPColor blackColor] forThemeAttribute:@"text-shadow-color" inState:CPThemeStateHighlighted]; + //[textDataView setValue:[CPColor blackColor] forThemeAttribute:@"text-shadow-color" inState:CPThemeStateHighlighted]; // [textDataView setBackgroundColor:[[CPColor redColor] colorWithAlphaComponent:0.5]]; @@ -224,30 +224,30 @@ CPLogRegister(CPLogConsole); //- (void)tableViewSelectionIsChanging:(CPNotification)aNotification //{ -// CPLog.debug(@"changing! %@", [aNotification description]); +// CPLog.debug(@"changing! %@", [aNotification description]); //} // //- (void)tableViewSelectionDidChange:(CPNotification)aNotification //{ -// CPLog.debug(@"did change! %@", [aNotification description]); +// CPLog.debug(@"did change! %@", [aNotification description]); //} - (BOOL)tableView:(CPTableView)aTableView shouldSelectRow:(int)rowIndex { - //CPLog.debug(@"shouldSelectRow %d", rowIndex); - //for (var i = 2, sqrt = SQRT(rowIndex+1); i <= sqrt; i++) - // if ((rowIndex+1) % i === 0) - //return false; + //CPLog.debug(@"shouldSelectRow %d", rowIndex); + //for (var i = 2, sqrt = SQRT(rowIndex+1); i <= sqrt; i++) + // if ((rowIndex+1) % i === 0) + //return false; // if(rowIndex % 2 == 1) - // return true; + // return true; // else return true; } - (BOOL)selectionShouldChangeInTableView:(CPTableView)aTableView { - //CPLog.debug(@"selectionShouldChangeInTableView"); - return YES; + //CPLog.debug(@"selectionShouldChangeInTableView"); + return YES; } - (void)tableViewSelectionDidChange:(id)notification @@ -267,8 +267,8 @@ CPLogRegister(CPLogConsole); //- (CPIndexSet)tableView:(CPTableView)tableView selectionIndexesForProposedSelection:(CPIndexSet)proposedSelectionIndexes //{ -// CPLog.debug(@"selectionIndexesForProposedSelection %@", [proposedSelectionIndexes description]); -// return proposedSelectionIndexes; +// CPLog.debug(@"selectionIndexesForProposedSelection %@", [proposedSelectionIndexes description]); +// return proposedSelectionIndexes; //} @@ -371,28 +371,28 @@ CPLogRegister(CPLogConsole); var aboveCount = 0, object, removeIndex; - - var index = [indexes lastIndex]; - + + var index = [indexes lastIndex]; + while (index != CPNotFound) - { - if (index >= insertIndex) - { - removeIndex = index + aboveCount; - aboveCount ++; - } - else - { - removeIndex = index; - insertIndex --; - } - - object = [self objectAtIndex:removeIndex]; - [self removeObjectAtIndex:removeIndex]; - [self insertObject:object atIndex:insertIndex]; - - index = [indexes indexLessThanIndex:index]; - } + { + if (index >= insertIndex) + { + removeIndex = index + aboveCount; + aboveCount ++; + } + else + { + removeIndex = index; + insertIndex --; + } + + object = [self objectAtIndex:removeIndex]; + [self removeObjectAtIndex:removeIndex]; + [self insertObject:object atIndex:insertIndex]; + + index = [indexes indexLessThanIndex:index]; + } } @end From 0696fb405eccdd7d32e45788b008e9325cab862e Mon Sep 17 00:00:00 2001 From: Klaas Pieter Annema Date: Fri, 5 Feb 2010 11:41:20 +0100 Subject: [PATCH 33/58] improved CPTableView's drop row logic for the lowest possible row --- AppKit/CPOutlineView.j | 27 ++++- AppKit/CPTableView.j | 111 +++++++++++------- .../Manual/CPOutlineViewTest/AppController.j | 16 ++- Tests/Manual/TableTest/AppController.j | 21 +++- 4 files changed, 118 insertions(+), 57 deletions(-) diff --git a/AppKit/CPOutlineView.j b/AppKit/CPOutlineView.j index f83d15721..141b7dbe8 100644 --- a/AppKit/CPOutlineView.j +++ b/AppKit/CPOutlineView.j @@ -504,11 +504,25 @@ var CPOutlineViewDelegate_outlineView_dataViewForTableColumn_item_ { var level = [self levelForRow:theLowerRow], upperLevel = [self levelForRow:theUpperRow]; - + + // If the row above us has a higher level the item can be added to multiple parent items + // Determine which one by looping through all possible parents and return the first one + // which indentation level is larger than the current x offset if (upperLevel > level) - if (theXOffset > (level + 1) * [self indentationPerLevel]) - return [self parentForItem:[self itemAtRow:theUpperRow]]; + { + while (level !== 0) + { + level = [self levelForRow:theUpperRow]; + // See if this item's indentation level matches the mouse offset + if (theXOffset > (level + 1) * [self indentationPerLevel]) + return [self parentForItem:[self itemAtRow:theUpperRow]]; + + // Check the next parent + theUpperRow = [self rowForItem:[self parentForItem:[self itemAtRow:theUpperRow]]]; + } + } + return [self parentForItem:[self itemAtRow:theLowerRow]]; } @@ -518,7 +532,7 @@ var CPOutlineViewDelegate_outlineView_dataViewForTableColumn_item_ var rect = [super _rectForDropHighlightViewBetweenUpperRow:theUpperRowIndex andLowerRow:theLowerRowIndex offset:theXOffset], parentItem = [self _parentItemForRow:theLowerRowIndex andUpperRow:theUpperRowIndex atMouseOffset:theXOffset], level = [self levelForItem:parentItem]; - + rect.origin.x = (level + 1) * [self indentationPerLevel]; return rect; @@ -851,6 +865,9 @@ var _loadItemInfoForItem = function(/*CPOutlineView*/ anOutlineView, /*id*/ anIt children = itemInfo.children; childIndex = [children indexOfObject:[_outlineView itemAtRow:theRow]]; + + if (childIndex === CPNotFound) + childIndex = children.length; } else if (theDropOperation === CPTableViewDropOn) childIndex = -1; @@ -936,7 +953,7 @@ var _loadItemInfoForItem = function(/*CPOutlineView*/ anOutlineView, /*id*/ anIt { if ((_outlineView._implementedOutlineViewDelegateMethods & CPOutlineViewDelegate_outlineView_heightOfRowByItem_)) return [_outlineView._outlineViewDelegate outlineView:_outlineView heightOfRowByItem:[_outlineView itemAtRow:theRow]]; - + return [theTableView rowHeight]; } diff --git a/AppKit/CPTableView.j b/AppKit/CPTableView.j index e9dcf41f7..46abde0b4 100644 --- a/AppKit/CPTableView.j +++ b/AppKit/CPTableView.j @@ -1048,14 +1048,15 @@ CPTableViewFirstColumnOnlyAutoresizingStyle = 5; if ((_implementedDelegateMethods & CPTableViewDelegate_tableView_heightOfRow_)) { rowHeight = [_delegate tableView:self heightOfRow:aRowIndex]; - _hasVariableRowHeight = YES; + + if (rowHeight !== _rowHeight) + _hasVariableRowHeight = YES; } else _hasVariableRowHeight = NO; // FIXME: WRONG: ASK TABLE COLUMN RANGE var previousRowRect = [self rectOfRow:aRowIndex - 1]; - return CPRectMake(0.0, CPRectGetMaxY(previousRowRect) + _intercellSpacing.height, CPRectGetWidth([self bounds]), _rowHeight); } @@ -1174,14 +1175,13 @@ CPTableViewFirstColumnOnlyAutoresizingStyle = 5; - (CPInteger)rowAtPoint:(CGPoint)aPoint { var row = -1; - - // Check if we are using variable sized rows - // to determine if we can use the quicker way to determine the row at point + + // Check if we are using variable sized rows so we can use the quicker way to determine the row at point if (!_hasVariableRowHeight) row = FLOOR(aPoint.y / (_rowHeight + _intercellSpacing.height)); else { - // We are using variable sized rows so we'll have to loop over all the rows and determine if it's at the current point + // We are using variable sized rows so we'll have to loop over all the rows and determine if it's at the point var rowArray = []; [_exposedRows getIndexes:rowArray maxCount:-1 inIndexRange:nil]; @@ -1193,15 +1193,15 @@ CPTableViewFirstColumnOnlyAutoresizingStyle = 5; if (CPRectContainsPoint([self rectOfRow:row], aPoint)) break; - - // Make sure that the row is not found if we exit the loop without breaking - row = -1; } - } - if (row >= _numberOfRows) + // Make sure we return -1 if we could not find a row row = -1; - + } + + if (row > [self numberOfRows]) + return -1; + return row; } @@ -1665,11 +1665,15 @@ CPTableViewFirstColumnOnlyAutoresizingStyle = 5; */ - (void)setDropRow:(CPInteger)row dropOperation:(CPTableViewDropOperation)operation { - if(row < 0 && operation === CPTableViewDropAbove) - row = 0; - - if(row >= [self numberOfRows] && operation === CPTableViewDropOn) - [[CPException exceptionWithName:@"Error" reason:@"Attempt to set dropRow="+ row +", dropOperation=CPTableViewDropOn when [0 - "+ [self numberOfRows] +"] is valid range of rows." userInfo:nil] raise]; + if(row > [self numberOfRows] && operation === CPTableViewDropOn) + { + var numberOfRows = [self numberOfRows] + 1; + var reason = @"Attempt to set dropRow=" + row + + " dropOperation=CPTableViewDropOn when [0 - " + numberOfRows + "] is valid range of rows." + + [[CPException exceptionWithName:@"Error" reason:reason userInfo:nil] raise]; + } + _retargetedDropRow = row; _retargetedDropOperation = operation; @@ -2575,13 +2579,12 @@ CPTableViewFirstColumnOnlyAutoresizingStyle = 5; */ - (CPInteger)_proposedRowAtPoint:(CGPoint)dragPoint { - var numberOfRows = [self numberOfRows], - row = [self rowAtPoint:dragPoint]; - + var row = [self rowAtPoint:dragPoint]; + // cocoa seems to jump to the next row when we approach the below row dragPoint.y += FLOOR(CPRectGetHeight([self rectOfRow:row]) / 4.0); row = [self rowAtPoint:dragPoint]; - + return row; } @@ -2593,8 +2596,19 @@ CPTableViewFirstColumnOnlyAutoresizingStyle = 5; return CPDragOperationNone; } +- (CPRect)_rectForDropHighlightViewOnRow:(int)theRowIndex +{ + if (theRowIndex >= [self numberOfRows]) + theRowIndex = [self numberOfRows] - 1; + + return [self rectOfRow:theRowIndex]; +} + - (CPRect)_rectForDropHighlightViewBetweenUpperRow:(int)theUpperRowIndex andLowerRow:(int)theLowerRowIndex offset:(float)theXOffset { + if (theLowerRowIndex > [self numberOfRows]) + theLowerRowIndex = [self numberOfRows]; + return [self rectOfRow:theLowerRowIndex]; } @@ -2606,28 +2620,39 @@ CPTableViewFirstColumnOnlyAutoresizingStyle = 5; var row = [self _proposedRowAtPoint:location], dragOperation = [self _validateDrop:sender proposedRow:row proposedDropOperation:dropOperation]; + exposedClipRect = [self exposedClipRect]; if(_retargetedDropRow !== nil) row = _retargetedDropRow; - - //if the user forces -1 then we should highlight the whole tableview - var rowRect = CPRectMakeZero(); - if(_retargetedDropRow === -1) - rowRect = [self exposedClipRect]; - else - rowRect = [self rectOfRow:row]; - var exposedClipRect = [self exposedClipRect], - visibleWidth = _CGRectGetWidth(exposedClipRect); + //if the user forces -1 then we should highlight the whole tableview + // var rowRect = CPRectMakeZero(); + // if(_retargetedDropRow === -1 || row === -1) + // rowRect = [self exposedClipRect]; + // else + // rowRect = [self rectOfRow:row]; + // + // visibleWidth = _CGRectGetWidth(exposedClipRect); + // + // rowRect = _CGRectMake(_CGRectGetMinX(exposedClipRect), rowRect.origin.y, visibleWidth, rowRect.size.height); - rowRect = _CGRectMake(_CGRectGetMinX(exposedClipRect), rowRect.origin.y, visibleWidth, rowRect.size.height); + var rect = CPRectMakeZero(); + + if (row === -1) + rect = exposedClipRect; - [_dropOperationFeedbackView setDropOperation:dropOperation]; + else if (dropOperation === CPTableViewDropAbove) + rect = [self _rectForDropHighlightViewBetweenUpperRow:row - 1 andLowerRow:row offset:location.x]; + + else + rect = [self _rectForDropHighlightViewOnRow:row]; + + [_dropOperationFeedbackView setDropOperation:row !== -1 ? dropOperation : CPDragOperationNone]; [_dropOperationFeedbackView setHidden:(dragOperation == CPDragOperationNone)]; - [_dropOperationFeedbackView setFrame:[self _rectForDropHighlightViewBetweenUpperRow:row - 1 andLowerRow:row offset:location.x]]; + [_dropOperationFeedbackView setFrame:rect]; [_dropOperationFeedbackView setCurrentRow:row]; [self addSubview:_dropOperationFeedbackView]; - + // FIXME : Maybe we should do this in a timer outside this method. Problem: we don't know when the scroll ends and neighter when the next -draggingUpdated is called. Which one will come first ? if (row > 0 && location.y - CGRectGetMinY(exposedClipRect) < _rowHeight) [self scrollRowToVisible:row - 1]; @@ -3046,13 +3071,16 @@ var CPTableViewDataSourceKey = @"CPTableViewDataSourceKey", { if(tableView._destinationDragStyle === CPTableViewDraggingDestinationFeedbackStyleNone) return; - + var context = [[CPGraphicsContext currentContext] graphicsPort]; CGContextSetStrokeColor(context, [CPColor colorWithHexString:@"4886ca"]); CGContextSetLineWidth(context, 3); - - if(dropOperation === CPTableViewDropOn) + + if (currentRow === -1) + CGContextStrokeRect(context, [self bounds]); + + else if(dropOperation === CPTableViewDropOn) { //if row is selected don't fill and stroke white var selectedRows = [tableView selectedRowIndexes]; @@ -3069,13 +3097,9 @@ var CPTableViewDataSourceKey = @"CPTableViewDataSourceKey", } CGContextStrokeRoundedRectangleInRect(context, newRect, 8, YES, YES, YES, YES); - } - - - if(dropOperation === CPTableViewDropAbove) + } + else if (dropOperation === CPTableViewDropAbove) { - - //reposition the view up a tad [self setFrameOrigin:CGPointMake(_frame.origin.x, _frame.origin.y - 8)]; @@ -3108,5 +3132,6 @@ var CPTableViewDataSourceKey = @"CPTableViewDataSourceKey", CGContextStrokePath(context); //CGContextStrokeLineSegments(context, [aRect.origin.x + 8, aRect.origin.y + 8, 300 , aRect.origin.y + 8]); } + } @end diff --git a/Tests/Manual/CPOutlineViewTest/AppController.j b/Tests/Manual/CPOutlineViewTest/AppController.j index 70ecefe7f..9683b8846 100644 --- a/Tests/Manual/CPOutlineViewTest/AppController.j +++ b/Tests/Manual/CPOutlineViewTest/AppController.j @@ -146,7 +146,11 @@ CustomOutlineViewDragType = @"CustomOutlineViewDragType"; [Menu menuWithTitle:@"1.1.2"], ]], [Menu menuWithTitle:@"1.2" children:[ - [Menu menuWithTitle:@"1.2.1"], + [Menu menuWithTitle:@"1.2.1" children:[ + [Menu menuWithTitle:@"1.2.1.1"], + [Menu menuWithTitle:@"1.2.1.2"], + [Menu menuWithTitle:@"1.2.1.3"], + ]], [Menu menuWithTitle:@"1.2.2"], [Menu menuWithTitle:@"1.2.3"] ]] @@ -188,6 +192,8 @@ CustomOutlineViewDragType = @"CustomOutlineViewDragType"; _outlineView = [[CPOutlineView alloc] initWithFrame:[contentView bounds]]; + + [_outlineView setBackgroundColor:[CPColor greenColor]]; var column = [[CPTableColumn alloc] initWithIdentifier:@""]; [_outlineView addTableColumn:column]; @@ -199,10 +205,14 @@ CustomOutlineViewDragType = @"CustomOutlineViewDragType"; [_outlineView expandItem:nil expandChildren:YES]; // [_outlineView setIntercellSpacing:CPSizeMake(0.0, 0.0)] - // [scrollView setDocumentView:_outlineView]; - [theWindow setContentView:_outlineView]; + [scrollView setDocumentView:_outlineView]; + [theWindow setContentView:scrollView]; + + // [theWindow setContentView:_outlineView]; [theWindow orderFront:self]; + + [column setWidth:CPRectGetWidth([_outlineView bounds])]; } - (id)outlineView:(CPOutlineView)theOutlineView child:(int)theIndex ofItem:(id)theItem diff --git a/Tests/Manual/TableTest/AppController.j b/Tests/Manual/TableTest/AppController.j index 0ca646c09..e75efcb41 100644 --- a/Tests/Manual/TableTest/AppController.j +++ b/Tests/Manual/TableTest/AppController.j @@ -22,7 +22,7 @@ CPLogRegister(CPLogConsole); dataSet1 = [], dataSet2 = []; - for(var i = 1; i < 100; i++) + for(var i = 1; i < 5; i++) { dataSet1[i - 1] = i; dataSet2[i - 1] = i + 10; @@ -217,10 +217,10 @@ CPLogRegister(CPLogConsole); } } -- (id)tableView:(CPTableView)tableView heightOfRow:(int)row -{ - return 50; -} +// - (id)tableView:(CPTableView)tableView heightOfRow:(int)row +// { +// return 50; +// } //- (void)tableViewSelectionIsChanging:(CPNotification)aNotification //{ @@ -301,10 +301,19 @@ CPLogRegister(CPLogConsole); // console.log([aTableView rectOfRow:0]); //console.log(row) + CPLog.debug(@"proposed row: %i", row); + [[aTableView window] orderFront:nil]; - if(aTableView === tableView) + if(aTableView === tableView) + { + // This is actually the behavior in Cocoa + if (row >= [aTableView numberOfRows]) + row = [aTableView numberOfRows] - 1; + [aTableView setDropRow:row dropOperation:CPTableViewDropOn]; + } + else [aTableView setDropRow:row dropOperation:CPTableViewDropAbove]; From ed1a7a4bc92007cf65307770b3411069efefda2c Mon Sep 17 00:00:00 2001 From: Klaas Pieter Annema Date: Fri, 5 Feb 2010 12:05:46 +0100 Subject: [PATCH 34/58] - removed variable row heights from CPTableView (can be found in variabletableview branch) - fixed a bug where it was not possible to drag unselectable rows #445 --- AppKit/CPTableView.j | 66 +++++++------------------- Tests/Manual/TableTest/AppController.j | 2 +- 2 files changed, 18 insertions(+), 50 deletions(-) diff --git a/AppKit/CPTableView.j b/AppKit/CPTableView.j index 36e6d402f..1573ada4f 100644 --- a/AppKit/CPTableView.j +++ b/AppKit/CPTableView.j @@ -161,8 +161,6 @@ CPTableViewFirstColumnOnlyAutoresizingStyle = 5; CGSize _intercellSpacing; float _rowHeight; - BOOL _hasVariableRowHeight; - BOOL _usesAlternatingRowBackgroundColors; CPArray _alternatingRowBackgroundColors; @@ -1040,23 +1038,11 @@ CPTableViewFirstColumnOnlyAutoresizingStyle = 5; - (CGRect)rectOfRow:(CPInteger)aRowIndex { - if (aRowIndex < 0) - return CPRectMakeZero(); - - var rowHeight = _rowHeight; - - if ((_implementedDelegateMethods & CPTableViewDelegate_tableView_heightOfRow_)) - { - rowHeight = [_delegate tableView:self heightOfRow:aRowIndex]; - _hasVariableRowHeight = YES; - } - else - _hasVariableRowHeight = NO; - - // FIXME: WRONG: ASK TABLE COLUMN RANGE - var previousRowRect = [self rectOfRow:aRowIndex - 1]; + if (NO) + return NULL; - return CPRectMake(0.0, CPRectGetMaxY(previousRowRect) + _intercellSpacing.height, CPRectGetWidth([self bounds]), _rowHeight); + // FIXME: WRONG: ASK TABLE COLUMN RANGE + return _CGRectMake(0.0, (aRowIndex * (_rowHeight + _intercellSpacing.height)), _CGRectGetWidth([self bounds]), _rowHeight); } // Complexity: @@ -1173,34 +1159,12 @@ CPTableViewFirstColumnOnlyAutoresizingStyle = 5; - (CPInteger)rowAtPoint:(CGPoint)aPoint { - var row = -1; - - // Check if we are using variable sized rows - // to determine if we can use the quicker way to determine the row at point - if (!_hasVariableRowHeight) - row = FLOOR(aPoint.y / (_rowHeight + _intercellSpacing.height)); - else - { - // We are using variable sized rows so we'll have to loop over all the rows and determine if it's at the current point - var rowArray = []; - [_exposedRows getIndexes:rowArray maxCount:-1 inIndexRange:nil]; - - var rowIndex = [rowArray count]; - - while (rowIndex--) - { - row = [rowArray objectAtIndex:rowIndex]; - - if (CPRectContainsPoint([self rectOfRow:row], aPoint)) - break; - - // Make sure that the row is not found if we exit the loop without breaking - row = -1; - } - } + var y = aPoint.y; + + var row = FLOOR(y / (_rowHeight + _intercellSpacing.height)); if (row >= _numberOfRows) - row = -1; + return -1; return row; } @@ -2355,17 +2319,21 @@ CPTableViewFirstColumnOnlyAutoresizingStyle = 5; */ - (BOOL)continueTracking:(CGPoint)lastPoint at:(CGPoint)aPoint { - var row = [self rowAtPoint:aPoint]; + var row = [self rowAtPoint:aPoint], + canSelect = YES; + + if ((_implementedDelegateMethods & CPTableViewDelegate_tableView_shouldSelectRow_)) + canSelect = [_delegate tableView:self shouldSelectRow:row]; // begin the drag is the datasource lets us, we've move at least +-3px vertical or horizontal, or we're dragging from selected rows and we haven't begun a drag session if ( - !_isSelectingSession && + !canSelect || (!_isSelectingSession && (_implementedDataSourceMethods & CPTableViewDataSource_tableView_writeRowsWithIndexes_toPasteboard_) && ( (lastPoint.x - aPoint.x > 3 || (_verticalMotionCanDrag && ABS(lastPoint.y - aPoint.y) > 3)) || ([_selectedRowIndexes containsIndex:row]) - ) + )) ) { if ([_selectedRowIndexes containsIndex:row]) @@ -2538,7 +2506,7 @@ CPTableViewFirstColumnOnlyAutoresizingStyle = 5; _retargetedDropOperation = nil; _retargetedDropRow = nil; _draggedRowIndexes = [CPIndexSet indexSet]; - [_dropOperationFeedbackView setHidden:YES]; + [_dropOperationFeedbackView setHidden:YES]; } /* @ignore @@ -2569,7 +2537,7 @@ CPTableViewFirstColumnOnlyAutoresizingStyle = 5; var numberOfRows = [self numberOfRows], row = [self rowAtPoint:dragPoint]; - // cocoa seems to jump to the next row when we approach the below row + // cocoa seems to jump to the next row when we approach the below row dragPoint.y += FLOOR(CPRectGetHeight([self rectOfRow:row]) / 4.0); row = [self rowAtPoint:dragPoint]; diff --git a/Tests/Manual/TableTest/AppController.j b/Tests/Manual/TableTest/AppController.j index c8a24f961..1ca6428ab 100644 --- a/Tests/Manual/TableTest/AppController.j +++ b/Tests/Manual/TableTest/AppController.j @@ -241,7 +241,7 @@ CPLogRegister(CPLogConsole); // if(rowIndex % 2 == 1) // return true; // else - return true; + return NO; } - (BOOL)selectionShouldChangeInTableView:(CPTableView)aTableView From 8759b175bdb1781e813fbed60a292ee6fa266ea3 Mon Sep 17 00:00:00 2001 From: Klaas Pieter Annema Date: Mon, 8 Feb 2010 11:14:03 +0100 Subject: [PATCH 35/58] various fixes to outline view drag & drop --- AppKit/CPOutlineView.j | 65 ++++++++++++++++--- AppKit/CPTableView.j | 37 +++++------ .../Manual/CPOutlineViewTest/AppController.j | 1 + Tests/Manual/TableTest/AppController.j | 1 + 4 files changed, 73 insertions(+), 31 deletions(-) diff --git a/AppKit/CPOutlineView.j b/AppKit/CPOutlineView.j index 141b7dbe8..eb057f470 100644 --- a/AppKit/CPOutlineView.j +++ b/AppKit/CPOutlineView.j @@ -55,7 +55,7 @@ var CPOutlineViewDelegate_outlineView_dataViewForTableColumn_item_ CPOutlineViewDelegate_outlineView_shouldSelectItem_ = 1 << 2; CPOutlineViewDelegate_outlineView_heightOfRowByItem_ = 1 << 3; - +CPOutlineViewDropOnItemIndex = -1; @implementation CPOutlineView : CPTableView { @@ -342,7 +342,13 @@ var CPOutlineViewDelegate_outlineView_dataViewForTableColumn_item_ if (!itemInfo) return nil; - return itemInfo.parent; + var parent = itemInfo.parent; + + // Check if the parent is the root item because we never return the actual root item + if (itemInfo[[parent UID]] === _rootItemInfo) + parent = nil; + + return parent; } - (CGRect)frameOfOutlineDataViewAtColumn:(CPInteger)aColumn row:(CPInteger)aRow @@ -500,14 +506,52 @@ var CPOutlineViewDelegate_outlineView_dataViewForTableColumn_item_ return [super frameOfDataViewAtColumn:aColumn row:aRow]; } +- (void)setDropItem:(id)theItem dropChildIndex:(int)theIndex +{ + // var dropRow = [self rowForItem:theItem], + // dropOperation = CPTableViewDropOn; + // + // if (theIndex !== CPOutlineViewDropOnItemIndex) + // { + // dropOperation = CPTableViewDropAbove; + // + // var itemInfo = _itemInfosForItems[[theItem UID]]; + // + // if (!itemInfo) + // itemInfo = _rootItemInfo; + // + // var children = itemInfo.children; + // + // if (theIndex < [children count]) + // { + // childItem = [children objectAtIndex:theIndex]; + // itemInfo = _itemInfosForItems[[childItem UID]]; + // dropRow = itemInfo.row; + // } + // else + // { + // // We dropped outside of the range of children for this item + // // Determine the tableviews dropped row indexes by asking for the row index of the last item + 1 + // dropRow = [self rowForItem:[children lastObject]] + 1; + // } + // + // // CPLog.debug(@"changed drop operation: %i", dropOperation); + // } + // + // CPLog.debug(@"set drop row: %i operation: %i", dropRow, dropOperation); + // + // [self setDropRow:dropRow dropOperation:dropOperation]; + +} + - (id)_parentItemForRow:(int)theLowerRow andUpperRow:(int)theUpperRow atMouseOffset:(float)theXOffset { var level = [self levelForRow:theLowerRow], upperLevel = [self levelForRow:theUpperRow]; // If the row above us has a higher level the item can be added to multiple parent items - // Determine which one by looping through all possible parents and return the first one - // which indentation level is larger than the current x offset + // Determine which one by looping through all possible parents and return the first + // of which the indentation level is larger than the current x offset if (upperLevel > level) { while (level !== 0) @@ -516,7 +560,10 @@ var CPOutlineViewDelegate_outlineView_dataViewForTableColumn_item_ // See if this item's indentation level matches the mouse offset if (theXOffset > (level + 1) * [self indentationPerLevel]) + { + // CPLog.debug(@"parent for item: %@ : %@", anItem, parent); return [self parentForItem:[self itemAtRow:theUpperRow]]; + } // Check the next parent theUpperRow = [self rowForItem:[self parentForItem:[self itemAtRow:theUpperRow]]]; @@ -863,15 +910,15 @@ var _loadItemInfoForItem = function(/*CPOutlineView*/ anOutlineView, /*id*/ anIt var parentItem = [_outlineView _parentItemForRow:theRow andUpperRow:theRow - 1 atMouseOffset:theXOffset], itemInfo = (parentItem !== nil) ? _outlineView._itemInfosForItems[[parentItem UID]] : _outlineView._rootItemInfo, children = itemInfo.children; - - childIndex = [children indexOfObject:[_outlineView itemAtRow:theRow]]; + + childIndex = [children indexOfObject:[_outlineView itemAtRow:theRow]]; if (childIndex === CPNotFound) childIndex = children.length; } else if (theDropOperation === CPTableViewDropOn) childIndex = -1; - + return childIndex; } @@ -889,11 +936,11 @@ var _loadItemInfoForItem = function(/*CPOutlineView*/ anOutlineView, /*id*/ anIt { if (!(_outlineView._implementedOutlineViewDataSourceMethods & CPOutlineViewDataSource_outlineView_validateDrop_proposedItem_proposedChildIndex_)) return CPDragOperationNone; - + var location = [_outlineView convertPoint:[theInfo draggingLocation] fromView:nil], childIndex = [self _childIndexForDropOperation:theOperation row:theRow offset:location.x], parentItem = [self _parentItemForDropOperation:theOperation row:theRow offset:location.x]; - + return [_outlineView._outlineViewDataSource outlineView:_outlineView validateDrop:theInfo proposedItem:parentItem proposedChildIndex:childIndex]; } diff --git a/AppKit/CPTableView.j b/AppKit/CPTableView.j index e8c7deee3..d5568a72e 100644 --- a/AppKit/CPTableView.j +++ b/AppKit/CPTableView.j @@ -1163,7 +1163,7 @@ CPTableViewFirstColumnOnlyAutoresizingStyle = 5; var row = FLOOR(y / (_rowHeight + _intercellSpacing.height)); - if (row >= _numberOfRows) + if (row > _numberOfRows) return -1; return row; @@ -2332,7 +2332,7 @@ CPTableViewFirstColumnOnlyAutoresizingStyle = 5; // begin the drag is the datasource lets us, we've move at least +-3px vertical or horizontal, or we're dragging from selected rows and we haven't begun a drag session if ( - !canSelect || (!_isSelectingSession && + (!_isSelectingSession && (_implementedDataSourceMethods & CPTableViewDataSource_tableView_writeRowsWithIndexes_toPasteboard_) && ( (lastPoint.x - aPoint.x > 3 || (_verticalMotionCanDrag && ABS(lastPoint.y - aPoint.y) > 3)) @@ -2530,12 +2530,12 @@ CPTableViewFirstColumnOnlyAutoresizingStyle = 5; var row = [self rowAtPoint:theDragPoint], rowRect = [self rectOfRow:row]; - + // If there is no (the default) or to little inter cell spacing we create some room for the CPTableViewDropAbove indicator // This probably doesn't work if the row height is smaller than or around 5.0 if ([self intercellSpacing].height < 5.0) rowRect = CPRectInset(rowRect, 0.0, 5.0 - [self intercellSpacing].height); - + if (CGRectContainsPoint(rowRect, theDragPoint)) return CPTableViewDropOn; @@ -2576,7 +2576,7 @@ CPTableViewFirstColumnOnlyAutoresizingStyle = 5; { if (theLowerRowIndex > [self numberOfRows]) theLowerRowIndex = [self numberOfRows]; - + return [self rectOfRow:theLowerRowIndex]; } @@ -2589,20 +2589,9 @@ CPTableViewFirstColumnOnlyAutoresizingStyle = 5; var row = [self _proposedRowAtPoint:location], dragOperation = [self _validateDrop:sender proposedRow:row proposedDropOperation:dropOperation]; exposedClipRect = [self exposedClipRect]; - + if(_retargetedDropRow !== nil) row = _retargetedDropRow; - - //if the user forces -1 then we should highlight the whole tableview - // var rowRect = CPRectMakeZero(); - // if(_retargetedDropRow === -1 || row === -1) - // rowRect = [self exposedClipRect]; - // else - // rowRect = [self rectOfRow:row]; - // - // visibleWidth = _CGRectGetWidth(exposedClipRect); - // - // rowRect = _CGRectMake(_CGRectGetMinX(exposedClipRect), rowRect.origin.y, visibleWidth, rowRect.size.height); var rect = CPRectMakeZero(); @@ -2615,6 +2604,7 @@ CPTableViewFirstColumnOnlyAutoresizingStyle = 5; else rect = [self _rectForDropHighlightViewOnRow:row]; + CPLog.debug(@"dropped row: %i", row); [_dropOperationFeedbackView setDropOperation:row !== -1 ? dropOperation : CPDragOperationNone]; [_dropOperationFeedbackView setHidden:(dragOperation == CPDragOperationNone)]; [_dropOperationFeedbackView setFrame:rect]; @@ -3044,11 +3034,13 @@ var CPTableViewDataSourceKey = @"CPTableViewDataSourceKey", CGContextSetStrokeColor(context, [CPColor colorWithHexString:@"4886ca"]); CGContextSetLineWidth(context, 3); - - if (currentRow === -1) - CGContextStrokeRect(context, [self bounds]); - - else if(dropOperation === CPTableViewDropOn) + + if (currentRow === -1) + { + CGContextStrokeRect(context, [self bounds]); + } + + else if (dropOperation === CPTableViewDropOn) { //if row is selected don't fill and stroke white var selectedRows = [tableView selectedRowIndexes]; @@ -3100,6 +3092,7 @@ var CPTableViewDataSourceKey = @"CPTableViewDataSourceKey", CGContextStrokePath(context); //CGContextStrokeLineSegments(context, [aRect.origin.x + 8, aRect.origin.y + 8, 300 , aRect.origin.y + 8]); } + } @end diff --git a/Tests/Manual/CPOutlineViewTest/AppController.j b/Tests/Manual/CPOutlineViewTest/AppController.j index 9683b8846..314d6783a 100644 --- a/Tests/Manual/CPOutlineViewTest/AppController.j +++ b/Tests/Manual/CPOutlineViewTest/AppController.j @@ -270,6 +270,7 @@ CustomOutlineViewDragType = @"CustomOutlineViewDragType"; theItem = [self menu]; CPLog.debug(@"validate item: %@ at index: %i", theItem, theIndex); + [anOutlineView setDropItem:theItem dropChildIndex:theIndex]; return CPDragOperationEvery; } diff --git a/Tests/Manual/TableTest/AppController.j b/Tests/Manual/TableTest/AppController.j index 74d949c1b..59617ce2e 100644 --- a/Tests/Manual/TableTest/AppController.j +++ b/Tests/Manual/TableTest/AppController.j @@ -55,6 +55,7 @@ CPLogRegister(CPLogConsole); [iconColumn setDataView:iconView]; [tableView addTableColumn:iconColumn]; + [tableView setVerticalMotionCanBeginDrag:YES]; iconImage = [[CPImage alloc] initWithContentsOfFile:"http://cappuccino.org/images/favicon.png" size:CGSizeMake(16,16)]; From 57ef2d22295cade53235d1f4c533470555733c9d Mon Sep 17 00:00:00 2001 From: Klaas Pieter Annema Date: Mon, 8 Feb 2010 11:14:50 +0100 Subject: [PATCH 36/58] removed log statements --- AppKit/CPOutlineView.j | 88 +++++++++---------- AppKit/CPTableView.j | 15 ++-- .../Manual/CPOutlineViewTest/AppController.j | 2 +- Tests/Manual/TableTest/AppController.j | 2 +- 4 files changed, 53 insertions(+), 54 deletions(-) diff --git a/AppKit/CPOutlineView.j b/AppKit/CPOutlineView.j index eb057f470..717d6d944 100644 --- a/AppKit/CPOutlineView.j +++ b/AppKit/CPOutlineView.j @@ -342,11 +342,11 @@ CPOutlineViewDropOnItemIndex = -1; if (!itemInfo) return nil; - var parent = itemInfo.parent; - - // Check if the parent is the root item because we never return the actual root item - if (itemInfo[[parent UID]] === _rootItemInfo) - parent = nil; + var parent = itemInfo.parent; + + // Check if the parent is the root item because we never return the actual root item + if (itemInfo[[parent UID]] === _rootItemInfo) + parent = nil; return parent; } @@ -508,40 +508,40 @@ CPOutlineViewDropOnItemIndex = -1; - (void)setDropItem:(id)theItem dropChildIndex:(int)theIndex { - // var dropRow = [self rowForItem:theItem], - // dropOperation = CPTableViewDropOn; - // - // if (theIndex !== CPOutlineViewDropOnItemIndex) - // { - // dropOperation = CPTableViewDropAbove; - // - // var itemInfo = _itemInfosForItems[[theItem UID]]; - // - // if (!itemInfo) - // itemInfo = _rootItemInfo; - // - // var children = itemInfo.children; - // - // if (theIndex < [children count]) - // { - // childItem = [children objectAtIndex:theIndex]; - // itemInfo = _itemInfosForItems[[childItem UID]]; - // dropRow = itemInfo.row; - // } - // else - // { - // // We dropped outside of the range of children for this item - // // Determine the tableviews dropped row indexes by asking for the row index of the last item + 1 - // dropRow = [self rowForItem:[children lastObject]] + 1; - // } - // - // // CPLog.debug(@"changed drop operation: %i", dropOperation); - // } - // - // CPLog.debug(@"set drop row: %i operation: %i", dropRow, dropOperation); - // - // [self setDropRow:dropRow dropOperation:dropOperation]; - + // var dropRow = [self rowForItem:theItem], + // dropOperation = CPTableViewDropOn; + // + // if (theIndex !== CPOutlineViewDropOnItemIndex) + // { + // dropOperation = CPTableViewDropAbove; + // + // var itemInfo = _itemInfosForItems[[theItem UID]]; + // + // if (!itemInfo) + // itemInfo = _rootItemInfo; + // + // var children = itemInfo.children; + // + // if (theIndex < [children count]) + // { + // childItem = [children objectAtIndex:theIndex]; + // itemInfo = _itemInfosForItems[[childItem UID]]; + // dropRow = itemInfo.row; + // } + // else + // { + // // We dropped outside of the range of children for this item + // // Determine the tableviews dropped row indexes by asking for the row index of the last item + 1 + // dropRow = [self rowForItem:[children lastObject]] + 1; + // } + // + // // CPLog.debug(@"changed drop operation: %i", dropOperation); + // } + // + // CPLog.debug(@"set drop row: %i operation: %i", dropRow, dropOperation); + // + // [self setDropRow:dropRow dropOperation:dropOperation]; + } - (id)_parentItemForRow:(int)theLowerRow andUpperRow:(int)theUpperRow atMouseOffset:(float)theXOffset @@ -560,10 +560,10 @@ CPOutlineViewDropOnItemIndex = -1; // See if this item's indentation level matches the mouse offset if (theXOffset > (level + 1) * [self indentationPerLevel]) - { - // CPLog.debug(@"parent for item: %@ : %@", anItem, parent); + { + // CPLog.debug(@"parent for item: %@ : %@", anItem, parent); return [self parentForItem:[self itemAtRow:theUpperRow]]; - } + } // Check the next parent theUpperRow = [self rowForItem:[self parentForItem:[self itemAtRow:theUpperRow]]]; @@ -911,7 +911,7 @@ var _loadItemInfoForItem = function(/*CPOutlineView*/ anOutlineView, /*id*/ anIt itemInfo = (parentItem !== nil) ? _outlineView._itemInfosForItems[[parentItem UID]] : _outlineView._rootItemInfo, children = itemInfo.children; - childIndex = [children indexOfObject:[_outlineView itemAtRow:theRow]]; + childIndex = [children indexOfObject:[_outlineView itemAtRow:theRow]]; if (childIndex === CPNotFound) childIndex = children.length; @@ -936,7 +936,7 @@ var _loadItemInfoForItem = function(/*CPOutlineView*/ anOutlineView, /*id*/ anIt { if (!(_outlineView._implementedOutlineViewDataSourceMethods & CPOutlineViewDataSource_outlineView_validateDrop_proposedItem_proposedChildIndex_)) return CPDragOperationNone; - + var location = [_outlineView convertPoint:[theInfo draggingLocation] fromView:nil], childIndex = [self _childIndexForDropOperation:theOperation row:theRow offset:location.x], parentItem = [self _parentItemForDropOperation:theOperation row:theRow offset:location.x]; diff --git a/AppKit/CPTableView.j b/AppKit/CPTableView.j index d5568a72e..53447782e 100644 --- a/AppKit/CPTableView.j +++ b/AppKit/CPTableView.j @@ -2604,7 +2604,6 @@ CPTableViewFirstColumnOnlyAutoresizingStyle = 5; else rect = [self _rectForDropHighlightViewOnRow:row]; - CPLog.debug(@"dropped row: %i", row); [_dropOperationFeedbackView setDropOperation:row !== -1 ? dropOperation : CPDragOperationNone]; [_dropOperationFeedbackView setHidden:(dragOperation == CPDragOperationNone)]; [_dropOperationFeedbackView setFrame:rect]; @@ -3034,13 +3033,13 @@ var CPTableViewDataSourceKey = @"CPTableViewDataSourceKey", CGContextSetStrokeColor(context, [CPColor colorWithHexString:@"4886ca"]); CGContextSetLineWidth(context, 3); - - if (currentRow === -1) - { - CGContextStrokeRect(context, [self bounds]); - } - - else if (dropOperation === CPTableViewDropOn) + + if (currentRow === -1) + { + CGContextStrokeRect(context, [self bounds]); + } + + else if (dropOperation === CPTableViewDropOn) { //if row is selected don't fill and stroke white var selectedRows = [tableView selectedRowIndexes]; diff --git a/Tests/Manual/CPOutlineViewTest/AppController.j b/Tests/Manual/CPOutlineViewTest/AppController.j index 314d6783a..df76f1648 100644 --- a/Tests/Manual/CPOutlineViewTest/AppController.j +++ b/Tests/Manual/CPOutlineViewTest/AppController.j @@ -270,7 +270,7 @@ CustomOutlineViewDragType = @"CustomOutlineViewDragType"; theItem = [self menu]; CPLog.debug(@"validate item: %@ at index: %i", theItem, theIndex); - [anOutlineView setDropItem:theItem dropChildIndex:theIndex]; + [anOutlineView setDropItem:theItem dropChildIndex:theIndex]; return CPDragOperationEvery; } diff --git a/Tests/Manual/TableTest/AppController.j b/Tests/Manual/TableTest/AppController.j index 59617ce2e..313b286c7 100644 --- a/Tests/Manual/TableTest/AppController.j +++ b/Tests/Manual/TableTest/AppController.j @@ -55,7 +55,7 @@ CPLogRegister(CPLogConsole); [iconColumn setDataView:iconView]; [tableView addTableColumn:iconColumn]; - [tableView setVerticalMotionCanBeginDrag:YES]; + [tableView setVerticalMotionCanBeginDrag:YES]; iconImage = [[CPImage alloc] initWithContentsOfFile:"http://cappuccino.org/images/favicon.png" size:CGSizeMake(16,16)]; From 65ceb96e4f69d965bc52708c60fda45ce33d9ed7 Mon Sep 17 00:00:00 2001 From: Klaas Pieter Annema Date: Mon, 8 Feb 2010 11:18:44 +0100 Subject: [PATCH 37/58] Merge branch 'jake' of git://github.com/280north/cappuccino into jake Conflicts: AppKit/CPTableColumn.j AppKit/CPTableView.j --- AppKit/CPTableColumn.j | 57 ++++--- AppKit/CPTableHeaderView.j | 207 ++++++++++++++++++++----- AppKit/CPTableView.j | 181 +++++++++++++-------- Tests/Manual/TableTest/AppController.j | 7 +- 4 files changed, 327 insertions(+), 125 deletions(-) diff --git a/AppKit/CPTableColumn.j b/AppKit/CPTableColumn.j index 044c1d141..557212519 100644 --- a/AppKit/CPTableColumn.j +++ b/AppKit/CPTableColumn.j @@ -30,8 +30,8 @@ #include "CoreGraphics/CGGeometry.h" CPTableColumnNoResizing = 0; -CPTableColumnAutoresizingMask = 1; -CPTableColumnUserResizingMask = 2; +CPTableColumnAutoresizingMask = 1 << 0; +CPTableColumnUserResizingMask = 1 << 1; @implementation CPTableColumn : CPObject { @@ -50,6 +50,8 @@ CPTableColumnUserResizingMask = 2; CPSortDescriptor _sortDescriptorPrototype; BOOL _isHidden; CPString _headerToolTip; + + BOOL _disableResizingPosting @accessors(property=disableResizingPosting); } - (id)init @@ -68,7 +70,9 @@ CPTableColumnUserResizingMask = 2; _width = 100.0; _minWidth = 10.0; _maxWidth = 1000000.0; - + _resizingMask = CPTableColumnAutoresizingMask | CPTableColumnUserResizingMask; + _disableResizingPosting = NO; + [self setIdentifier:anIdentifier]; var header = [[_CPTableColumnHeaderView alloc] initWithFrame:CGRectMakeZero()]; @@ -79,6 +83,7 @@ CPTableColumnUserResizingMask = 2; [textDataView setValue:[CPColor whiteColor] forThemeAttribute:@"text-color" inState:CPThemeStateHighlighted]; [textDataView setValue:[CPFont boldSystemFontOfSize:12] forThemeAttribute:@"font" inState:CPThemeStateHighlighted]; [textDataView setValue:CPCenterVerticalTextAlignment forThemeAttribute:@"vertical-alignment"]; + [textDataView setValue:CGInsetMake(4.0, 8.0, 0.0, 8.0) forThemeAttribute:@"content-inset"]; [self setDataView:textDataView]; } @@ -116,18 +121,23 @@ CPTableColumnUserResizingMask = 2; if (tableView) { - var index = [[tableView tableColumns] indexOfObjectIdenticalTo:self]; - - // FIXME: THIS IS HORRIBLE. Don't just reload everything when a table column changes, just relayout the changed widths. - tableView._reloadAllRows = YES; - tableView._dirtyTableColumnRangeIndex = tableView._dirtyTableColumnRangeIndex < 0 ? index : MIN(index, tableView._dirtyTableColumnRangeIndex); - + var index = [[tableView tableColumns] indexOfObjectIdenticalTo:self], + dirtyTableColumnRangeIndex = tableView._dirtyTableColumnRangeIndex; + + if (dirtyTableColumnRangeIndex < 0) + tableView._dirtyTableColumnRangeIndex = index; + else + tableView._dirtyTableColumnRangeIndex = MIN(index, tableView._dirtyTableColumnRangeIndex); + + var rows = tableView._exposedRows, + columns = [CPIndexSet indexSetWithIndexesInRange:CPMakeRange(index, [tableView._exposedColumns lastIndex] - index + 1)]; + + // FIXME: Would be faster with some sort of -setNeedsDisplayInColumns: that updates a dirtyTableColumnForDisplay cache; then marked columns would relayout their data views at display time. + [tableView _layoutDataViewsInRows:rows columns:columns]; [tableView tile]; - - [[CPNotificationCenter defaultCenter] - postNotificationName:CPTableViewColumnDidResizeNotification - object:tableView - userInfo:[CPDictionary dictionaryWithObjects:[self, oldWidth] forKeys:[@"CPTableColumn", "CPOldWidth"]]]; + + if (!_disableResizingPosting) + [self _postDidResizeNotificationWithOldWidth:oldWidth]; } } @@ -183,7 +193,7 @@ CPTableColumnUserResizingMask = 2; _resizingMask = aResizingMask; } -- (float)resizingMask +- (unsigned)resizingMask { return _resizingMask; } @@ -255,9 +265,9 @@ CPTableColumnUserResizingMask = 2; var dataView = [self dataViewForRow:aRowIndex], dataViewUID = [dataView UID]; -var x = [self tableView]._cachedDataViews[dataViewUID]; -if (x && x.length) -return x.pop(); + var x = [self tableView]._cachedDataViews[dataViewUID]; + if (x && x.length) + return x.pop(); // if we haven't cached an archive of the data view, do it now if (!_dataViewData[dataViewUID]) @@ -265,7 +275,8 @@ return x.pop(); // unarchive the data view cache var newDataView = [CPKeyedUnarchiver unarchiveObjectWithData:_dataViewData[dataViewUID]]; -newDataView.identifier = dataViewUID; + newDataView.identifier = dataViewUID; + return newDataView; } @@ -345,6 +356,14 @@ newDataView.identifier = dataViewUID; return _headerToolTip; } +- (void)_postDidResizeNotificationWithOldWidth:(float)oldWidth +{ + [[CPNotificationCenter defaultCenter] + postNotificationName:CPTableViewColumnDidResizeNotification + object:[self tableView] + userInfo:[CPDictionary dictionaryWithObjects:[self, oldWidth] forKeys:[@"CPTableColumn", "CPOldWidth"]]]; +} + @end var CPTableColumnIdentifierKey = @"CPTableColumnIdentifierKey", diff --git a/AppKit/CPTableHeaderView.j b/AppKit/CPTableHeaderView.j index 79ebf6c49..2feda8741 100644 --- a/AppKit/CPTableHeaderView.j +++ b/AppKit/CPTableHeaderView.j @@ -36,7 +36,7 @@ var CPThemeStatePressed = CPThemeState("pressed"); self = [super initWithFrame:frame]; if (self) { - _textField = [[CPTextField alloc] initWithFrame:[self bounds]]; + _textField = [[CPTextField alloc] initWithFrame:CGRectMake(5, 1, CGRectGetWidth([self bounds]) - 5, CGRectGetHeight([self bounds]) - 1)]; [_textField setAutoresizingMask:CPViewWidthSizable|CPViewHeightSizable]; [_textField setTextColor: [CPColor colorWithHexString: @"333333"]]; [_textField setValue:[CPFont boldSystemFontOfSize:12.0] forThemeAttribute:@"font"]; @@ -99,6 +99,8 @@ var CPThemeStatePressed = CPThemeState("pressed"); int _pressedColumn @accessors(readonly, property=pressedColumn); float _draggedDistance @accessors(readonly, property=draggedDistance); + float _lastLocation; + float _columnOldWidth; CPTableView _tableView @accessors(property=tableView); } @@ -113,6 +115,9 @@ var CPThemeStatePressed = CPThemeState("pressed"); _draggedColumn = CPNotFound; _pressedColumn = CPNotFound; _draggedDistance = 0.0; + _lastLocation = nil; + _columnOldWidth = nil; + [self setBackgroundColor:[CPColor colorWithPatternImage:CPAppKitImage("tableview-headerview.png", CGSizeMake(1.0, 22.0))]]; } @@ -156,16 +161,22 @@ var CPThemeStatePressed = CPThemeState("pressed"); if (aColumnIndex < 0 || aColumnIndex > [tableColumns count]) [CPException raise:"invalid" reason:"tried to get headerRectOfColumn: on invalid column"]; - bounds.size.width = [tableColumns[aColumnIndex] width] + tableSpacing.width; - - while (--aColumnIndex >= 0) - bounds.origin.x += [tableColumns[aColumnIndex] width] + tableSpacing.width; - + // UPDATE COLUMN RANGES ? + if (_tableView._dirtyTableColumnRangeIndex !== CPNotFound) + [_tableView _recalculateTableColumnRanges]; + + var tableRange = _tableView._tableColumnRanges[aColumnIndex]; + bounds.origin.x = tableRange.location; + bounds.size.width = tableRange.length; + return bounds; } - (CPRect)_resizeRectBeforeColumn:(CPInteger)column { + if (!([_tableView._tableColumns[column] resizingMask] & CPTableColumnUserResizingMask)) + return CGRectMakeZero(); + var rect = [self headerRectOfColumn:column]; rect.origin.x -= 10; @@ -193,52 +204,168 @@ var CPThemeStatePressed = CPThemeState("pressed"); - (void)mouseDown:(CPEvent)theEvent { - var location = [self convertPoint:[theEvent locationInWindow] fromView:nil], - aPoint = CGPointMakeCopy(location), - clickedColumn = [self columnAtPoint:aPoint]; + var mouseLocation = [self convertPoint:[theEvent locationInWindow] fromView:nil], + clickedColumn = [self columnAtPoint:mouseLocation]; if (clickedColumn == -1) return; - - // Error, can't find var CPTableViewDelegate_tableView_mouseDownInHeaderOfTableColumn_ !? - if (_tableView._implementedDelegateMethods & (1 << 6)) - [[_tableView delegate] tableView:_tableView - mouseDownInHeaderOfTableColumn:[[_tableView tableColumns] objectAtIndex:clickedColumn]]; - [self _setPressedColumn:clickedColumn]; + [_tableView _sendDelegateDidMouseDownInHeader:clickedColumn]; + + var resizeLocation = CGPointMake(mouseLocation.x + 10, mouseLocation.y), + resizedColumn = [self columnAtPoint:resizeLocation] - 1; + + // 2 different tracking methods: one for resizing/stop-resizing, another one for selection/reordering + if ([_tableView allowsColumnResizing] + && resizedColumn >= 0 + && CGRectContainsPoint([self _resizeRectBeforeColumn:(resizedColumn + 1)], mouseLocation)) + { + _resizedColumn = resizedColumn; + [_tableView._tableColumns[_resizedColumn] setDisableResizingPosting:YES]; + [self trackResizeWithEvent:theEvent]; + } + else + { + [self _setPressedColumn:clickedColumn]; + [self trackMouseWithEvent:theEvent]; + } } -- (void)mouseUp:(CPEvent)theEvent +- (void)trackMouseWithEvent:(CPEvent)theEvent { - var location = [self convertPoint:[theEvent locationInWindow] fromView:nil], - clickedColumn = [self columnAtPoint:location]; + var type = [theEvent type]; + + if (type == CPLeftMouseUp) + { + var location = [self convertPoint:[theEvent locationInWindow] fromView:nil], + clickedColumn = [self columnAtPoint:location]; - [self _setPressedColumn:CPNotFound]; - - if (clickedColumn == -1) - return; - - if ([_tableView allowsColumnSelection]) - { - if ([theEvent modifierFlags] & CPCommandKeyMask) - { - if ([_tableView isColumnSelected:clickedColumn]) - [_tableView deselectColumn:clickedColumn]; - else if ([_tableView allowsMultipleSelection] == YES) - [_tableView selectColumnIndexes:[CPIndexSet indexSetWithIndex:clickedColumn] byExtendingSelection:YES]; - } - else if ([theEvent modifierFlags] & CPShiftKeyMask) - { - // should be from clickedColumn to lastClickedColum with extending:(direction == previous selection) - var selectedIndexes = [_tableView selectedColumnIndexes], - startColumn = MIN(clickedColumn, [selectedIndexes lastIndex]), - endColumn = MAX(clickedColumn, [selectedIndexes firstIndex]); + [self _setPressedColumn:CPNotFound]; - [_tableView selectColumnIndexes:[CPIndexSet indexSetWithIndexesInRange:CPMakeRange(startColumn, endColumn - startColumn + 1)] byExtendingSelection:YES]; + if (clickedColumn == -1) + return; + + [_tableView _sendDelegateDidClickColumn:clickedColumn]; + + if ([_tableView allowsColumnSelection]) + { + if ([theEvent modifierFlags] & CPCommandKeyMask) + { + if ([_tableView isColumnSelected:clickedColumn]) + [_tableView deselectColumn:clickedColumn]; + else if ([_tableView allowsMultipleSelection] == YES) + [_tableView selectColumnIndexes:[CPIndexSet indexSetWithIndex:clickedColumn] byExtendingSelection:YES]; + } + else if ([theEvent modifierFlags] & CPShiftKeyMask) + { + // should be from clickedColumn to lastClickedColum with extending:(direction == previous selection) + var selectedIndexes = [_tableView selectedColumnIndexes], + startColumn = MIN(clickedColumn, [selectedIndexes lastIndex]), + endColumn = MAX(clickedColumn, [selectedIndexes firstIndex]); + + [_tableView selectColumnIndexes:[CPIndexSet indexSetWithIndexesInRange:CPMakeRange(startColumn, endColumn - startColumn + 1)] byExtendingSelection:YES]; + } + else + [_tableView selectColumnIndexes:[CPIndexSet indexSetWithIndex:clickedColumn] byExtendingSelection:NO]; + } + return; + } +/* + else if (type & CPLeftMouseDragged && [_tableView allowsColumnREordering]) + { + // Start dragging here + [[CPCursor closedHandCursor] set]; + return; + } +*/ + [CPApp setTarget:self selector:@selector(trackMouseWithEvent:) forNextEventMatchingMask:CPLeftMouseDraggedMask | CPLeftMouseUpMask | CPLeftMouseDownMask untilDate:nil inMode:nil dequeue:YES]; +} + +- (void)trackResizeWithEvent:(CPEvent)anEvent +{ + var location = [self convertPoint:[anEvent locationInWindow] fromView:nil], + tableColumn = [[_tableView tableColumns] objectAtIndex:_resizedColumn], + type = [anEvent type]; + + if (_lastLocation == nil) _lastLocation = location; + if (_columnOldWidth == nil) _columnOldWidth = [tableColumn width]; + + if (type === CPLeftMouseUp) + { + [self _updateResizeCursor:anEvent]; + + [tableColumn _postDidResizeNotificationWithOldWidth:_columnOldWidth]; + [tableColumn setDisableResizingPosting:NO]; + + _resizedColumn = CPNotFound; + _lastLocation = nil; + _columnOldWidth = nil; + return; + } + else if (type === CPLeftMouseDragged) + { + var newWidth = [tableColumn width] + location.x - _lastLocation.x; + + if (newWidth >= [tableColumn minWidth]) + { + [tableColumn setWidth:newWidth]; + // FIXME: there has to be a better way to do this... + // We should refactor the auto resizing crap. + // We need to figure out the exact cocoa behavior here though. + [_tableView resizeWithOldSuperviewSize:[_tableView bounds]]; + _lastLocation = location; + + [[CPCursor resizeLeftRightCursor] set]; + [self setNeedsLayout]; + [self setNeedsDisplay:YES]; } else - [_tableView selectColumnIndexes:[CPIndexSet indexSetWithIndex:clickedColumn] byExtendingSelection:NO]; + [[CPCursor resizeRightCursor] set]; } + + [CPApp setTarget:self selector:@selector(trackResizeWithEvent:) forNextEventMatchingMask:CPLeftMouseDraggedMask | CPLeftMouseUpMask untilDate:nil inMode:nil dequeue:YES]; +} + +- (void)_updateResizeCursor:(CPEvent)theEvent +{ + var mouseLocation = [self convertPoint:[theEvent locationInWindow] fromView:nil]; + + var mouseOverLocation = CGPointMake(mouseLocation.x + 10, mouseLocation.y), + overColumn = [self columnAtPoint:mouseOverLocation]; + + var isInside = (overColumn > 0 && CGRectContainsPoint([self _resizeRectBeforeColumn:overColumn], mouseLocation)); + if (isInside) + { + var column = [[_tableView tableColumns] objectAtIndex:overColumn - 1]; + if ([column width] == [column minWidth]) + [[CPCursor resizeRightCursor] set]; + else + [[CPCursor resizeLeftRightCursor] set]; + } + else + [[CPCursor arrowCursor] set]; +} + +- (void)viewDidMoveToWindow +{ + if ([_tableView allowsColumnResizing]) + [[self window] setAcceptsMouseMovedEvents:YES]; +} + +- (void)mouseEntered:(CPEvent)theEvent +{ + [self _updateResizeCursor:theEvent]; +} + +- (void)mouseMoved:(CPEvent)theEvent +{ + [self _updateResizeCursor:theEvent]; +} + +- (void)mouseExited:(CPEvent)theEvent +{ + // FIXME: we should use CPCursor push/pop (if previous currentCursor != arrow). + [[CPCursor arrowCursor] set]; } - (void)layoutSubviews diff --git a/AppKit/CPTableView.j b/AppKit/CPTableView.j index 1573ada4f..2ad1cddfd 100644 --- a/AppKit/CPTableView.j +++ b/AppKit/CPTableView.j @@ -190,6 +190,7 @@ CPTableViewFirstColumnOnlyAutoresizingStyle = 5; SEL _doubleAction; unsigned _columnAutoResizingStyle; + CGPoint _originalMouseDownPoint; BOOL _verticalMotionCanDrag; unsigned _destinationDragStyle; BOOL _isSelectingSession; @@ -219,7 +220,7 @@ CPTableViewFirstColumnOnlyAutoresizingStyle = 5; _selectionHighlightMask = CPTableViewSelectionHighlightStyleRegular; [self setUsesAlternatingRowBackgroundColors:NO]; - [self setAlternatingRowBackgroundColors:[[CPColor whiteColor], [CPColor colorWithHexString:@"e4e7ff"]]]; + [self setAlternatingRowBackgroundColors:[[CPColor whiteColor], /*[CPColor colorWithHexString:@"e4e7ff"]*/ [CPColor colorWithHexString:@"f5f9fc"]]]; _tableColumns = []; _tableColumnRanges = []; @@ -237,7 +238,7 @@ CPTableViewFirstColumnOnlyAutoresizingStyle = 5; _rowHeight = 23.0; [self setSelectionHightlightColor:[CPColor selectionColor]]; - [self setGridColor:[CPColor grayColor]]; + [self setGridColor:[CPColor colorWithHexString:@"dce0e2"]]; [self setGridStyleMask:CPTableViewGridNone]; _headerView = [[CPTableHeaderView alloc] initWithFrame:CGRectMake(0, 0, [self bounds].size.width, _rowHeight)]; @@ -1179,6 +1180,7 @@ CPTableViewFirstColumnOnlyAutoresizingStyle = 5; return _CGRectMake(tableColumnRange.location, _CGRectGetMinY(rectOfRow), tableColumnRange.length, _CGRectGetHeight(rectOfRow)); } +//FIX ME: We should refactor this! - (void)resizeWithOldSuperviewSize:(CGSize)aSize { [super resizeWithOldSuperviewSize:aSize]; @@ -1528,6 +1530,24 @@ CPTableViewFirstColumnOnlyAutoresizingStyle = 5; return _delegate; } +- (void)_sendDelegateDidClickColumn:(int)column +{ + if (_implementedDelegateMethods & CPTableViewDelegate_tableView_didClickTableColumn_) + [_delegate tableView:self didClickTableColumn:_tableColumns[column]]; +} + +- (void)_sendDelegateDidDragColumn:(int)column +{ + if (_implementedDelegateMethods & CPTableViewDelegate_tableView_didDragTableColumn_) + [_delegate tableView:self didDragTableColumn:_tableColumns[column]]; +} + +- (void)_sendDelegateDidMouseDownInHeader:(int)column +{ + if (_implementedDelegateMethods & CPTableViewDelegate_tableView_mouseDownInHeaderOfTableColumn_) + [_delegate tableView:self mouseDownInHeaderOfTableColumn:_tableColumns[column]]; +} + //Highlightable Column Headers /* - (CPTableColumn)highlightedTableColumn @@ -1901,6 +1921,45 @@ CPTableViewFirstColumnOnlyAutoresizingStyle = 5; } } +- (void)_layoutDataViewsInRows:(CPIndexSet)rows columns:(CPIndexSet)columns +{ + var rowArray = [], + rowRects = [], + columnArray = []; + + [rows getIndexes:rowArray maxCount:-1 inIndexRange:nil]; + [columns getIndexes:columnArray maxCount:-1 inIndexRange:nil]; + + UPDATE_COLUMN_RANGES_IF_NECESSARY(); + + var columnIndex = 0, + columnsCount = columnArray.length; + + for (; columnIndex < columnsCount; ++columnIndex) + { + var column = columnArray[columnIndex], + tableColumn = _tableColumns[column], + tableColumnUID = [tableColumn UID], + dataViewsForTableColumn = _dataViewsForTableColumns[tableColumnUID], + columnRange = _tableColumnRanges[column]; + + var rowIndex = 0, + rowsCount = rowArray.length; + + for (; rowIndex < rowsCount; ++rowIndex) + { + var row = rowArray[rowIndex], + dataView = dataViewsForTableColumn[row], + frame = [dataView frame]; + + frame.origin.x = columnRange.location; + frame.size.width = columnRange.length; + + [dataView setFrame:frame]; + } + } +} + - (void)_commitDataViewObjectValue:(CPTextView)sender { [_dataSource tableView:self @@ -2192,7 +2251,7 @@ CPTableViewFirstColumnOnlyAutoresizingStyle = 5; } CGContextClosePath(context); - CGContextSetStrokeColor(context, [CPColor whiteColor]); + CGContextSetStrokeColor(context, [CPColor colorWithHexString:@"e5e5e5"]); CGContextStrokePath(context); } @@ -2285,17 +2344,17 @@ CPTableViewFirstColumnOnlyAutoresizingStyle = 5; else _selectionAnchorRow = row; + + //set ivars for startTrackingPoint and time... + _startTrackingPoint = aPoint; + _startTrackingTimestamp = new Date(); - - if (_implementedDataSourceMethods & CPTableViewDataSource_tableView_setObjectValue_forTableColumn_row_) { - _startTrackingPoint = aPoint; - _startTrackingTimestamp = new Date(); + if (_implementedDataSourceMethods & CPTableViewDataSource_tableView_setObjectValue_forTableColumn_row_) _trackingPointMovedOutOfClickSlop = NO; - } // if the table has drag support then we use mouseUp to select a single row. // otherwise it uses mouse down. - if(!(_implementedDataSourceMethods & CPTableViewDataSource_tableView_writeRowsWithIndexes_toPasteboard_)) + if (!(_implementedDataSourceMethods & CPTableViewDataSource_tableView_writeRowsWithIndexes_toPasteboard_)) [self _updateSelectionWithMouseAtRow:row]; [[self window] makeFirstResponder:self]; @@ -2319,62 +2378,58 @@ CPTableViewFirstColumnOnlyAutoresizingStyle = 5; */ - (BOOL)continueTracking:(CGPoint)lastPoint at:(CGPoint)aPoint { - var row = [self rowAtPoint:aPoint], - canSelect = YES; - - if ((_implementedDelegateMethods & CPTableViewDelegate_tableView_shouldSelectRow_)) - canSelect = [_delegate tableView:self shouldSelectRow:row]; - + var row = [self rowAtPoint:aPoint]; // begin the drag is the datasource lets us, we've move at least +-3px vertical or horizontal, or we're dragging from selected rows and we haven't begun a drag session - if - ( - !canSelect || (!_isSelectingSession && - (_implementedDataSourceMethods & CPTableViewDataSource_tableView_writeRowsWithIndexes_toPasteboard_) && - ( - (lastPoint.x - aPoint.x > 3 || (_verticalMotionCanDrag && ABS(lastPoint.y - aPoint.y) > 3)) - || ([_selectedRowIndexes containsIndex:row]) - )) - ) + if(!_isSelectingSession && _implementedDataSourceMethods & CPTableViewDataSource_tableView_writeRowsWithIndexes_toPasteboard_) { - if ([_selectedRowIndexes containsIndex:row]) - _draggedRowIndexes = [[CPIndexSet alloc] initWithIndexSet:_selectedRowIndexes]; - else - _draggedRowIndexes = [CPIndexSet indexSetWithIndex:row]; - - - //ask the datasource for the data - var pboard = [CPPasteboard pasteboardWithName:CPDragPboard]; - - if ([self canDragRowsWithIndexes:_draggedRowIndexes atPoint:aPoint] && [_dataSource tableView:self writeRowsWithIndexes:_draggedRowIndexes toPasteboard:pboard]) + if ( + (ABS(_startTrackingPoint.x - aPoint.x) > 4 || (_verticalMotionCanDrag && ABS(_startTrackingPoint.y - aPoint.y) > 4)) || + ([_selectedRowIndexes containsIndex:row]) + ) { - var currentEvent = [CPApp currentEvent], - offset = CPPointMakeZero(), - tableColumns = [_tableColumns objectsAtIndexes:_exposedColumns]; - - // We deviate from the default Cocoa implementation here by asking for a view in stead of an image - // We support both, but the view prefered over the image because we can mimic the rows we are dragging - // by re-creating the data views for the dragged rows - var view = [self dragViewForRowsWithIndexes:_draggedRowIndexes - tableColumns:tableColumns - event:currentEvent - offset:offset]; - - if (!view) + if ([_selectedRowIndexes containsIndex:row]) + _draggedRowIndexes = [[CPIndexSet alloc] initWithIndexSet:_selectedRowIndexes]; + else + _draggedRowIndexes = [CPIndexSet indexSetWithIndex:row]; + + + //ask the datasource for the data + var pboard = [CPPasteboard pasteboardWithName:CPDragPboard]; + + if ([self canDragRowsWithIndexes:_draggedRowIndexes atPoint:aPoint] && [_dataSource tableView:self writeRowsWithIndexes:_draggedRowIndexes toPasteboard:pboard]) { - var image = [self dragImageForRowsWithIndexes:_draggedRowIndexes - tableColumns:tableColumns - event:currentEvent - offset:offset]; - view = [[CPImageView alloc] initWithFrame:CPMakeRect(0, 0, [image size].width, [image size].height)]; - [view setImage:image]; + var currentEvent = [CPApp currentEvent], + offset = CPPointMakeZero(), + tableColumns = [_tableColumns objectsAtIndexes:_exposedColumns]; + + // We deviate from the default Cocoa implementation here by asking for a view in stead of an image + // We support both, but the view prefered over the image because we can mimic the rows we are dragging + // by re-creating the data views for the dragged rows + var view = [self dragViewForRowsWithIndexes:_draggedRowIndexes + tableColumns:tableColumns + event:currentEvent + offset:offset]; + + if (!view) + { + var image = [self dragImageForRowsWithIndexes:_draggedRowIndexes + tableColumns:tableColumns + event:currentEvent + offset:offset]; + view = [[CPImageView alloc] initWithFrame:CPMakeRect(0, 0, [image size].width, [image size].height)]; + [view setImage:image]; + } + + var bounds = [view bounds]; + var viewLocation = CPPointMake(aPoint.x - CGRectGetWidth(bounds)/2 + offset.x, aPoint.y - CGRectGetHeight(bounds)/2 + offset.y); + [self dragView:view at:viewLocation offset:CPPointMakeZero() event:[CPApp currentEvent] pasteboard:pboard source:self slideBack:YES]; + _startTrackingPoint = nil; + + return NO; } - - var bounds = [view bounds]; - var viewLocation = CPPointMake(aPoint.x - CGRectGetWidth(bounds)/2 + offset.x, aPoint.y - CGRectGetHeight(bounds)/2 + offset.y); - [self dragView:view at:viewLocation offset:CPPointMakeZero() event:[CPApp currentEvent] pasteboard:pboard source:self slideBack:YES]; - - return NO; } + else if (ABS(_startTrackingPoint.x - aPoint.x) < 5 && ABS(_startTrackingPoint.y - aPoint.y) < 5) + return YES; } _isSelectingSession = YES; @@ -2801,10 +2856,8 @@ CPTableViewFirstColumnOnlyAutoresizingStyle = 5; [self selectRowIndexes:[CPIndexSet indexSetWithIndex:i] byExtendingSelection:extend]; - if(i) - { + if(i >= 0) [self scrollRowToVisible:i]; - } } - (void)moveUp:(id)sender @@ -2850,10 +2903,8 @@ CPTableViewFirstColumnOnlyAutoresizingStyle = 5; [self selectRowIndexes:[CPIndexSet indexSetWithIndex:i] byExtendingSelection:extend]; - if(i) - { + if(i >= 0) [self scrollRowToVisible:i]; - } } - (void)deleteBackward:(id)sender diff --git a/Tests/Manual/TableTest/AppController.j b/Tests/Manual/TableTest/AppController.j index 1ca6428ab..cbfc912e6 100644 --- a/Tests/Manual/TableTest/AppController.j +++ b/Tests/Manual/TableTest/AppController.j @@ -241,7 +241,7 @@ CPLogRegister(CPLogConsole); // if(rowIndex % 2 == 1) // return true; // else - return NO; + return YES; } - (BOOL)selectionShouldChangeInTableView:(CPTableView)aTableView @@ -277,6 +277,11 @@ CPLogRegister(CPLogConsole); return NO; } +- (void)tableView:(CPTableView)aTableView willDisplayView:(CPView)aView forTableColumn:(CPTableColumn)tableColumn row:(int)row +{ + CPLogConsole(_cmd + " column: " + [tableColumn identifier] + " row:" + row) +} + - (void)tableView:(CPTableView)aTableView setObjectValue:(id)aValue forTableColumn:(CPTableColumn)tableColumn row:(int)row { From 0375e7a88108e9ff04b1b297adbc5d925adf9cca Mon Sep 17 00:00:00 2001 From: Klaas Pieter Annema Date: Mon, 8 Feb 2010 14:44:21 +0100 Subject: [PATCH 38/58] - further improved outline view drag & drop for multiple parent situations --- AppKit/CPOutlineView.j | 71 +++++++++---------- AppKit/CPTableView.j | 6 +- .../Manual/CPOutlineViewTest/AppController.j | 18 +++-- 3 files changed, 49 insertions(+), 46 deletions(-) diff --git a/AppKit/CPOutlineView.j b/AppKit/CPOutlineView.j index 717d6d944..dd0c6719f 100644 --- a/AppKit/CPOutlineView.j +++ b/AppKit/CPOutlineView.j @@ -508,6 +508,7 @@ CPOutlineViewDropOnItemIndex = -1; - (void)setDropItem:(id)theItem dropChildIndex:(int)theIndex { + [self doesNotRecognizeSelector:_cmd]; // var dropRow = [self rowForItem:theItem], // dropOperation = CPTableViewDropOn; // @@ -544,44 +545,40 @@ CPOutlineViewDropOnItemIndex = -1; } -- (id)_parentItemForRow:(int)theLowerRow andUpperRow:(int)theUpperRow atMouseOffset:(float)theXOffset +- (id)_parentItemForUpperRow:(int)theUpperRowIndex andLowerRow:(int)theLowerRowIndex atMouseOffset:(CPPoint)theOffset { - var level = [self levelForRow:theLowerRow], - upperLevel = [self levelForRow:theUpperRow]; - + var lowerLevel = [self levelForRow:theLowerRowIndex] + upperItem = [self itemAtRow:theUpperRowIndex]; + upperLevel = [self levelForItem:upperItem]; + // If the row above us has a higher level the item can be added to multiple parent items // Determine which one by looping through all possible parents and return the first // of which the indentation level is larger than the current x offset - if (upperLevel > level) - { - while (level !== 0) - { - level = [self levelForRow:theUpperRow]; - - // See if this item's indentation level matches the mouse offset - if (theXOffset > (level + 1) * [self indentationPerLevel]) - { - // CPLog.debug(@"parent for item: %@ : %@", anItem, parent); - return [self parentForItem:[self itemAtRow:theUpperRow]]; - } - - // Check the next parent - theUpperRow = [self rowForItem:[self parentForItem:[self itemAtRow:theUpperRow]]]; - } - } + while (upperLevel > lowerLevel) + { + upperLevel = [self levelForItem:upperItem]; + + // See if this item's indentation level matches the mouse offset + if (theOffset.x > (upperLevel + 1) * [self indentationPerLevel]) + return [self parentForItem:upperItem]; + + // Check the next parent + upperItem = [self parentForItem:upperItem]; + } - return [self parentForItem:[self itemAtRow:theLowerRow]]; + return [self parentForItem:[self itemAtRow:theLowerRowIndex]]; } -- (CPRect)_rectForDropHighlightViewBetweenUpperRow:(int)theUpperRowIndex andLowerRow:(int)theLowerRowIndex offset:(float)theXOffset +- (CPRect)_rectForDropHighlightViewBetweenUpperRow:(int)theUpperRowIndex andLowerRow:(int)theLowerRowIndex offset:(CPPoint)theOffset { - // Call super and the x to reflect the current indentation level - var rect = [super _rectForDropHighlightViewBetweenUpperRow:theUpperRowIndex andLowerRow:theLowerRowIndex offset:theXOffset], - parentItem = [self _parentItemForRow:theLowerRowIndex andUpperRow:theUpperRowIndex atMouseOffset:theXOffset], + // Call super and the update x to reflect the current indentation level + var rect = [super _rectForDropHighlightViewBetweenUpperRow:theUpperRowIndex andLowerRow:theLowerRowIndex offset:theOffset], + parentItem = [self _parentItemForUpperRow:theUpperRowIndex andLowerRow:theLowerRowIndex atMouseOffset:theOffset], level = [self levelForItem:parentItem]; - - rect.origin.x = (level + 1) * [self indentationPerLevel]; - + + rect.origin.x = (level + 1) * [self indentationPerLevel]; + rect.size.width -= rect.origin.x; // This assumes that the x returned by super is zero + return rect; } @@ -901,13 +898,13 @@ var _loadItemInfoForItem = function(/*CPOutlineView*/ anOutlineView, /*id*/ anIt return [_outlineView._outlineViewDataSource outlineView:_outlineView writeItems:items toPasteboard:thePasteboard]; } -- (int)_childIndexForDropOperation:(CPTableViewDropOperation)theDropOperation row:(int)theRow offset:(CPPoint)theXOffset +- (int)_childIndexForDropOperation:(CPTableViewDropOperation)theDropOperation row:(int)theRow offset:(CPPoint)theOffset { var childIndex = CPNotFound; if (theDropOperation === CPTableViewDropAbove) { - var parentItem = [_outlineView _parentItemForRow:theRow andUpperRow:theRow - 1 atMouseOffset:theXOffset], + var parentItem = [_outlineView _parentItemForUpperRow:theRow - 1 andLowerRow:theRow atMouseOffset:theOffset], itemInfo = (parentItem !== nil) ? _outlineView._itemInfosForItems[[parentItem UID]] : _outlineView._rootItemInfo, children = itemInfo.children; @@ -923,10 +920,10 @@ var _loadItemInfoForItem = function(/*CPOutlineView*/ anOutlineView, /*id*/ anIt } -- (void)_parentItemForDropOperation:(CPTableViewDropOperation)theDropOperation row:(int)theRow offset:(CPPoint)theXOffset +- (void)_parentItemForDropOperation:(CPTableViewDropOperation)theDropOperation row:(int)theRow offset:(CPPoint)theOffset { if (theDropOperation === CPTableViewDropAbove) - return [_outlineView _parentItemForRow:theRow andUpperRow:theRow - 1 atMouseOffset:theXOffset] + return [_outlineView _parentItemForUpperRow:theRow - 1 andLowerRow:theRow atMouseOffset:theOffset] return [_outlineView itemAtRow:theRow]; } @@ -938,8 +935,8 @@ var _loadItemInfoForItem = function(/*CPOutlineView*/ anOutlineView, /*id*/ anIt return CPDragOperationNone; var location = [_outlineView convertPoint:[theInfo draggingLocation] fromView:nil], - childIndex = [self _childIndexForDropOperation:theOperation row:theRow offset:location.x], - parentItem = [self _parentItemForDropOperation:theOperation row:theRow offset:location.x]; + childIndex = [self _childIndexForDropOperation:theOperation row:theRow offset:location], + parentItem = [self _parentItemForDropOperation:theOperation row:theRow offset:location]; return [_outlineView._outlineViewDataSource outlineView:_outlineView validateDrop:theInfo proposedItem:parentItem proposedChildIndex:childIndex]; } @@ -950,8 +947,8 @@ var _loadItemInfoForItem = function(/*CPOutlineView*/ anOutlineView, /*id*/ anIt return NO; var location = [_outlineView convertPoint:[theInfo draggingLocation] fromView:nil], - childIndex = [self _childIndexForDropOperation:theOperation row:theRow offset:location.x], - parentItem = [self _parentItemForDropOperation:theOperation row:theRow offset:location.x]; + childIndex = [self _childIndexForDropOperation:theOperation row:theRow offset:location], + parentItem = [self _parentItemForDropOperation:theOperation row:theRow offset:location]; return [_outlineView._outlineViewDataSource outlineView:_outlineView acceptDrop:theInfo item:parentItem childIndex:childIndex]; } diff --git a/AppKit/CPTableView.j b/AppKit/CPTableView.j index 702bd313b..f9aec55bf 100644 --- a/AppKit/CPTableView.j +++ b/AppKit/CPTableView.j @@ -2627,7 +2627,7 @@ CPTableViewFirstColumnOnlyAutoresizingStyle = 5; return [self rectOfRow:theRowIndex]; } -- (CPRect)_rectForDropHighlightViewBetweenUpperRow:(int)theUpperRowIndex andLowerRow:(int)theLowerRowIndex offset:(float)theXOffset +- (CPRect)_rectForDropHighlightViewBetweenUpperRow:(int)theUpperRowIndex andLowerRow:(int)theLowerRowIndex offset:(CPPoint)theOffset { if (theLowerRowIndex > [self numberOfRows]) theLowerRowIndex = [self numberOfRows]; @@ -2641,6 +2641,8 @@ CPTableViewFirstColumnOnlyAutoresizingStyle = 5; dropOperation = [self _proposedDropOperationAtPoint:location], numberOfRows = [self numberOfRows]; + // CPLog.debug(@"offset: %@", CPStringFromPoint(location)); + var row = [self _proposedRowAtPoint:location], dragOperation = [self _validateDrop:sender proposedRow:row proposedDropOperation:dropOperation]; exposedClipRect = [self exposedClipRect]; @@ -2654,7 +2656,7 @@ CPTableViewFirstColumnOnlyAutoresizingStyle = 5; rect = exposedClipRect; else if (dropOperation === CPTableViewDropAbove) - rect = [self _rectForDropHighlightViewBetweenUpperRow:row - 1 andLowerRow:row offset:location.x]; + rect = [self _rectForDropHighlightViewBetweenUpperRow:row - 1 andLowerRow:row offset:location]; else rect = [self _rectForDropHighlightViewOnRow:row]; diff --git a/Tests/Manual/CPOutlineViewTest/AppController.j b/Tests/Manual/CPOutlineViewTest/AppController.j index df76f1648..795036e6e 100644 --- a/Tests/Manual/CPOutlineViewTest/AppController.j +++ b/Tests/Manual/CPOutlineViewTest/AppController.j @@ -192,12 +192,13 @@ CustomOutlineViewDragType = @"CustomOutlineViewDragType"; _outlineView = [[CPOutlineView alloc] initWithFrame:[contentView bounds]]; - - [_outlineView setBackgroundColor:[CPColor greenColor]]; - var column = [[CPTableColumn alloc] initWithIdentifier:@""]; + var column = [[CPTableColumn alloc] initWithIdentifier:@"One"]; [_outlineView addTableColumn:column]; [_outlineView setOutlineTableColumn:column]; + + [_outlineView addTableColumn:[[CPTableColumn alloc] initWithIdentifier:@"Two"]]; + [_outlineView registerForDraggedTypes:[CustomOutlineViewDragType]]; [_outlineView setDataSource:self]; @@ -246,7 +247,10 @@ CustomOutlineViewDragType = @"CustomOutlineViewDragType"; } - (id)outlineView:(CPOutlineView)anOutlineView objectValueForTableColumn:(CPTableColumn)theColumn byItem:(id)theItem -{ +{ + // if ([theColumn identifier] === @"Two") + // return @"Two"; + if (theItem === nil) theItem = [self menu]; @@ -269,8 +273,8 @@ CustomOutlineViewDragType = @"CustomOutlineViewDragType"; if (theItem === nil) theItem = [self menu]; - CPLog.debug(@"validate item: %@ at index: %i", theItem, theIndex); - [anOutlineView setDropItem:theItem dropChildIndex:theIndex]; + // CPLog.debug(@"validate item: %@ at index: %i", theItem, theIndex); + // [anOutlineView setDropItem:theItem dropChildIndex:theIndex]; return CPDragOperationEvery; } @@ -280,7 +284,7 @@ CustomOutlineViewDragType = @"CustomOutlineViewDragType"; if (theItem === nil) theItem = [self menu]; - CPLog.debug(@"drop item: %@ at index: %i", theItem, theIndex); + // CPLog.debug(@"drop item: %@ at index: %i", theItem, theIndex); var menuIndex = [_draggedItems count]; while (menuIndex--) From 78b4bbb06e8e0d5b25e954db84217f2193f69c34 Mon Sep 17 00:00:00 2001 From: Klaas Pieter Annema Date: Mon, 8 Feb 2010 16:49:07 +0100 Subject: [PATCH 39/58] implement setDropItem:dropChildIndex on CPOutlineView --- AppKit/CPOutlineView.j | 92 +++++++++---------- AppKit/CPTableView.j | 2 - .../Manual/CPOutlineViewTest/AppController.j | 16 ++-- 3 files changed, 53 insertions(+), 57 deletions(-) diff --git a/AppKit/CPOutlineView.j b/AppKit/CPOutlineView.j index dd0c6719f..d51a1a78b 100644 --- a/AppKit/CPOutlineView.j +++ b/AppKit/CPOutlineView.j @@ -201,6 +201,9 @@ CPOutlineViewDropOnItemIndex = -1; itemInfo = _rootItemInfo; else itemInfo = _itemInfosForItems[[anItem UID]]; + + if (!itemInfo) + return; itemInfo.isExpanded = YES; [self reloadItem:anItem reloadChildren:YES]; @@ -508,63 +511,58 @@ CPOutlineViewDropOnItemIndex = -1; - (void)setDropItem:(id)theItem dropChildIndex:(int)theIndex { - [self doesNotRecognizeSelector:_cmd]; - // var dropRow = [self rowForItem:theItem], - // dropOperation = CPTableViewDropOn; - // - // if (theIndex !== CPOutlineViewDropOnItemIndex) - // { - // dropOperation = CPTableViewDropAbove; - // - // var itemInfo = _itemInfosForItems[[theItem UID]]; - // - // if (!itemInfo) - // itemInfo = _rootItemInfo; - // - // var children = itemInfo.children; - // - // if (theIndex < [children count]) - // { - // childItem = [children objectAtIndex:theIndex]; - // itemInfo = _itemInfosForItems[[childItem UID]]; - // dropRow = itemInfo.row; - // } - // else - // { - // // We dropped outside of the range of children for this item - // // Determine the tableviews dropped row indexes by asking for the row index of the last item + 1 - // dropRow = [self rowForItem:[children lastObject]] + 1; - // } - // - // // CPLog.debug(@"changed drop operation: %i", dropOperation); - // } - // - // CPLog.debug(@"set drop row: %i operation: %i", dropRow, dropOperation); - // - // [self setDropRow:dropRow dropOperation:dropOperation]; + var dropRow = [self rowForItem:theItem], + dropOperation = CPTableViewDropOn; + + if (theIndex !== CPOutlineViewDropOnItemIndex) + { + dropOperation = CPTableViewDropAbove; + + var itemInfo = nil; + if (!theItem) + itemInfo = _rootItemInfo; + else + itemInfo = _itemInfosForItems[[theItem UID]]; + var children = itemInfo.children; + + if (theIndex < [children count]) + { + childItem = [children objectAtIndex:theIndex]; + itemInfo = _itemInfosForItems[[childItem UID]]; + dropRow = itemInfo.row; + } + else + { + // We dropped outside of the range of children for this item + // Determine the tableviews dropped row indexes by asking for the row index of the last item + 1 + dropRow = [self rowForItem:[children lastObject]] + 1; + } + } + + [self setDropRow:dropRow dropOperation:dropOperation]; } - (id)_parentItemForUpperRow:(int)theUpperRowIndex andLowerRow:(int)theLowerRowIndex atMouseOffset:(CPPoint)theOffset { var lowerLevel = [self levelForRow:theLowerRowIndex] - upperItem = [self itemAtRow:theUpperRowIndex]; + upperItem = [self itemAtRow:theUpperRowIndex]; upperLevel = [self levelForItem:upperItem]; // If the row above us has a higher level the item can be added to multiple parent items // Determine which one by looping through all possible parents and return the first // of which the indentation level is larger than the current x offset - while (upperLevel > lowerLevel) - { - upperLevel = [self levelForItem:upperItem]; + while (upperLevel > lowerLevel) + { + upperLevel = [self levelForItem:upperItem]; - // See if this item's indentation level matches the mouse offset - if (theOffset.x > (upperLevel + 1) * [self indentationPerLevel]) - return [self parentForItem:upperItem]; + // See if this item's indentation level matches the mouse offset + if (theOffset.x > (upperLevel + 1) * [self indentationPerLevel]) + return [self parentForItem:upperItem]; - // Check the next parent - upperItem = [self parentForItem:upperItem]; - } + // Check the next parent + upperItem = [self parentForItem:upperItem]; + } return [self parentForItem:[self itemAtRow:theLowerRowIndex]]; } @@ -575,10 +573,10 @@ CPOutlineViewDropOnItemIndex = -1; var rect = [super _rectForDropHighlightViewBetweenUpperRow:theUpperRowIndex andLowerRow:theLowerRowIndex offset:theOffset], parentItem = [self _parentItemForUpperRow:theUpperRowIndex andLowerRow:theLowerRowIndex atMouseOffset:theOffset], level = [self levelForItem:parentItem]; - + rect.origin.x = (level + 1) * [self indentationPerLevel]; - rect.size.width -= rect.origin.x; // This assumes that the x returned by super is zero - + rect.size.width -= rect.origin.x; // This assumes that the x returned by super is zero + return rect; } diff --git a/AppKit/CPTableView.j b/AppKit/CPTableView.j index f9aec55bf..7b2234990 100644 --- a/AppKit/CPTableView.j +++ b/AppKit/CPTableView.j @@ -2641,8 +2641,6 @@ CPTableViewFirstColumnOnlyAutoresizingStyle = 5; dropOperation = [self _proposedDropOperationAtPoint:location], numberOfRows = [self numberOfRows]; - // CPLog.debug(@"offset: %@", CPStringFromPoint(location)); - var row = [self _proposedRowAtPoint:location], dragOperation = [self _validateDrop:sender proposedRow:row proposedDropOperation:dropOperation]; exposedClipRect = [self exposedClipRect]; diff --git a/Tests/Manual/CPOutlineViewTest/AppController.j b/Tests/Manual/CPOutlineViewTest/AppController.j index 795036e6e..0df7b4991 100644 --- a/Tests/Manual/CPOutlineViewTest/AppController.j +++ b/Tests/Manual/CPOutlineViewTest/AppController.j @@ -196,8 +196,8 @@ CustomOutlineViewDragType = @"CustomOutlineViewDragType"; var column = [[CPTableColumn alloc] initWithIdentifier:@"One"]; [_outlineView addTableColumn:column]; [_outlineView setOutlineTableColumn:column]; - - [_outlineView addTableColumn:[[CPTableColumn alloc] initWithIdentifier:@"Two"]]; + + [_outlineView addTableColumn:[[CPTableColumn alloc] initWithIdentifier:@"Two"]]; [_outlineView registerForDraggedTypes:[CustomOutlineViewDragType]]; @@ -248,9 +248,9 @@ CustomOutlineViewDragType = @"CustomOutlineViewDragType"; - (id)outlineView:(CPOutlineView)anOutlineView objectValueForTableColumn:(CPTableColumn)theColumn byItem:(id)theItem { - // if ([theColumn identifier] === @"Two") - // return @"Two"; - + // if ([theColumn identifier] === @"Two") + // return @"Two"; + if (theItem === nil) theItem = [self menu]; @@ -271,11 +271,11 @@ CustomOutlineViewDragType = @"CustomOutlineViewDragType"; - (CPDragOperation)outlineView:(CPOutlineView)anOutlineView validateDrop:(id < CPDraggingInfo >)theInfo proposedItem:(id)theItem proposedChildIndex:(int)theIndex { if (theItem === nil) - theItem = [self menu]; + [anOutlineView setDropItem:nil dropChildIndex:theIndex]; // CPLog.debug(@"validate item: %@ at index: %i", theItem, theIndex); - // [anOutlineView setDropItem:theItem dropChildIndex:theIndex]; - + [anOutlineView setDropItem:theItem dropChildIndex:theIndex]; + return CPDragOperationEvery; } From c8437895dc79d8a8b0223ce7bb5646d4cd7b46ab Mon Sep 17 00:00:00 2001 From: Klaas Pieter Annema Date: Tue, 9 Feb 2010 14:42:11 +0100 Subject: [PATCH 40/58] fixed setDropItem:dropChildIndex behavior --- AppKit/CPOutlineView.j | 85 +++++++++++++++++++++++------------------- 1 file changed, 46 insertions(+), 39 deletions(-) diff --git a/AppKit/CPOutlineView.j b/AppKit/CPOutlineView.j index d51a1a78b..f293dcccc 100644 --- a/AppKit/CPOutlineView.j +++ b/AppKit/CPOutlineView.j @@ -77,6 +77,12 @@ CPOutlineViewDropOnItemIndex = -1; CPArray _disclosureControlsForRows; CPData _disclosureControlData; CPArray _disclosureControlQueue; + + BOOL _shouldRetargetItem; + id _retargetedItem; + + BOOL _shouldRetargetChildIndex; + CPInteger _retargedChildIndex; } - (id)initWithFrame:(CGRect)aFrame @@ -92,6 +98,12 @@ CPOutlineViewDropOnItemIndex = -1; _itemInfosForItems = { }; _disclosureControlsForRows = []; + _retargetedItem = nil; + _shouldRetargetItem = NO; + + _retargedChildIndex = nil; + _shouldRetargetChildIndex = NO; + [self setIndentationPerLevel:16.0]; [self setIndentationMarkerFollowsDataView:YES]; @@ -511,40 +523,20 @@ CPOutlineViewDropOnItemIndex = -1; - (void)setDropItem:(id)theItem dropChildIndex:(int)theIndex { - var dropRow = [self rowForItem:theItem], - dropOperation = CPTableViewDropOn; - - if (theIndex !== CPOutlineViewDropOnItemIndex) - { - dropOperation = CPTableViewDropAbove; - - var itemInfo = nil; - if (!theItem) - itemInfo = _rootItemInfo; - else - itemInfo = _itemInfosForItems[[theItem UID]]; - - var children = itemInfo.children; - - if (theIndex < [children count]) - { - childItem = [children objectAtIndex:theIndex]; - itemInfo = _itemInfosForItems[[childItem UID]]; - dropRow = itemInfo.row; - } - else - { - // We dropped outside of the range of children for this item - // Determine the tableviews dropped row indexes by asking for the row index of the last item + 1 - dropRow = [self rowForItem:[children lastObject]] + 1; - } - } - - [self setDropRow:dropRow dropOperation:dropOperation]; + CPLog.debug(@"set drop item: %@ index: %i", theItem, theIndex); + + _retargetedItem = theItem; + _shouldRetargetItem = YES; + + _retargedChildIndex = theIndex; + _shouldRetargetChildIndex = YES; } - (id)_parentItemForUpperRow:(int)theUpperRowIndex andLowerRow:(int)theLowerRowIndex atMouseOffset:(CPPoint)theOffset { + if (_shouldRetargetItem) + return _retargetedItem; + var lowerLevel = [self levelForRow:theLowerRowIndex] upperItem = [self itemAtRow:theUpperRowIndex]; upperLevel = [self levelForItem:upperItem]; @@ -898,6 +890,9 @@ var _loadItemInfoForItem = function(/*CPOutlineView*/ anOutlineView, /*id*/ anIt - (int)_childIndexForDropOperation:(CPTableViewDropOperation)theDropOperation row:(int)theRow offset:(CPPoint)theOffset { + if (_outlineView._shouldRetargetChildIndex) + return _outlineView._retargedChildIndex; + var childIndex = CPNotFound; if (theDropOperation === CPTableViewDropAbove) @@ -917,7 +912,6 @@ var _loadItemInfoForItem = function(/*CPOutlineView*/ anOutlineView, /*id*/ anIt return childIndex; } - - (void)_parentItemForDropOperation:(CPTableViewDropOperation)theDropOperation row:(int)theRow offset:(CPPoint)theOffset { if (theDropOperation === CPTableViewDropAbove) @@ -931,12 +925,19 @@ var _loadItemInfoForItem = function(/*CPOutlineView*/ anOutlineView, /*id*/ anIt { if (!(_outlineView._implementedOutlineViewDataSourceMethods & CPOutlineViewDataSource_outlineView_validateDrop_proposedItem_proposedChildIndex_)) return CPDragOperationNone; - - var location = [_outlineView convertPoint:[theInfo draggingLocation] fromView:nil], - childIndex = [self _childIndexForDropOperation:theOperation row:theRow offset:location], - parentItem = [self _parentItemForDropOperation:theOperation row:theRow offset:location]; - return [_outlineView._outlineViewDataSource outlineView:_outlineView validateDrop:theInfo proposedItem:parentItem proposedChildIndex:childIndex]; + // Make sure the retargeted item and index are reset + _outlineView._retargetedItem = nil; + _outlineView._shouldRetargetItem = NO; + + _outlineView._retargedChildIndex = nil; + _outlineView._shouldRetargetChildIndex = NO; + + var location = [_outlineView convertPoint:[theInfo draggingLocation] fromView:nil], + parentItem = [self _parentItemForDropOperation:theOperation row:theRow offset:location]; + childIndex = [self _childIndexForDropOperation:theOperation row:theRow offset:location]; + + return [_outlineView._outlineViewDataSource outlineView:_outlineView validateDrop:theInfo proposedItem:parentItem proposedChildIndex:childIndex]; } - (BOOL)tableView:(CPTableView)aTableView acceptDrop:(id )theInfo row:(int)theRow dropOperation:(CPTableViewDropOperation)theOperation @@ -944,10 +945,16 @@ var _loadItemInfoForItem = function(/*CPOutlineView*/ anOutlineView, /*id*/ anIt if (!(_outlineView._implementedOutlineViewDataSourceMethods & CPOutlineViewDataSource_outlineView_acceptDrop_item_childIndex_)) return NO; - var location = [_outlineView convertPoint:[theInfo draggingLocation] fromView:nil], - childIndex = [self _childIndexForDropOperation:theOperation row:theRow offset:location], - parentItem = [self _parentItemForDropOperation:theOperation row:theRow offset:location]; + var location = [_outlineView convertPoint:[theInfo draggingLocation] fromView:nil], + parentItem = [self _parentItemForDropOperation:theOperation row:theRow offset:location]; + childIndex = [self _childIndexForDropOperation:theOperation row:theRow offset:location]; + _outlineView._retargetedItem = nil; + _outlineView._shouldRetargetItem = NO; + + _outlineView._retargedChildIndex = nil; + _outlineView._shouldRetargetChildIndex = NO; + return [_outlineView._outlineViewDataSource outlineView:_outlineView acceptDrop:theInfo item:parentItem childIndex:childIndex]; } From d96e939eed606a161e174106925e5cf0904968fa Mon Sep 17 00:00:00 2001 From: Klaas Pieter Annema Date: Tue, 9 Feb 2010 14:43:02 +0100 Subject: [PATCH 41/58] made sure the dragserver doesn't call prepareDrag if the last drag update returned CPDragOperationNone --- AppKit/CPDragServer.j | 25 +++++++++++++++++-------- 1 file changed, 17 insertions(+), 8 deletions(-) diff --git a/AppKit/CPDragServer.j b/AppKit/CPDragServer.j index 811ec8593..c0438d3af 100644 --- a/AppKit/CPDragServer.j +++ b/AppKit/CPDragServer.j @@ -150,6 +150,10 @@ var CPDraggingSource_draggedImage_movedTo_ = 1 << 0, CGPoint _draggingLocation; id _draggingDestination; + + CGPoint _startDragLocation; + BOOL _shouldSlideBack; + unsigned _dragOperation; } /* @@ -254,10 +258,10 @@ var CPDraggingSource_draggedImage_movedTo_ = 1 << 0, - (void)draggingEndedInPlatformWindow:(CPPlatformWindow)aPlatformWindow globalLocation:(CGPoint)aLocation operation:(CPDragOperation)anOperation { [_draggedView removeFromSuperview]; - + if (![CPPlatform supportsDragAndDrop]) [_draggedWindow orderOut:self]; - + if (_implementedDraggingSourceMethods & CPDraggingSource_draggedImage_endAt_operation_) [_draggingSource draggedImage:[_draggedView image] endedAt:aLocation operation:anOperation]; @@ -296,6 +300,7 @@ var CPDraggingSource_draggedImage_movedTo_ = 1 << 0, _draggingPasteboard = aPasteboard || [CPPasteboard pasteboardWithName:CPDragPboard]; _draggingSource = aSourceObject; _draggingDestination = nil; + _shouldSlideBack = slideBack; // The offset is based on the distance from where we want the view to be initially from where the mouse is initially // Hence the use of mouseDownEvent's location and view's location in global coordinates. @@ -320,9 +325,10 @@ var CPDraggingSource_draggedImage_movedTo_ = 1 << 0, var mouseLocation = [CPEvent mouseLocation]; // Place it where the mouse pointer is. - [_draggedWindow setFrameOrigin:_CGPointMake(mouseLocation.x - _draggingOffset.width, mouseLocation.y - _draggingOffset.height)]; + _startDragLocation = _CGPointMake(mouseLocation.x - _draggingOffset.width, mouseLocation.y - _draggingOffset.height); + [_draggedWindow setFrameOrigin:_startDragLocation]; [_draggedWindow setFrameSize:[aView frame].size]; - + [[_draggedWindow contentView] addSubview:aView]; _implementedDraggingSourceMethods = 0; @@ -385,15 +391,18 @@ var CPDraggingSource_draggedImage_movedTo_ = 1 << 0, if (type === CPLeftMouseUp) { - [self performDragOperationInPlatformWindow:platformWindow]; - [self draggingEndedInPlatformWindow:platformWindow globalLocation:platformWindowLocation operation:CPDragOperationNone]; - + // Make sure we do not finalize (cancel) the drag if the last drag update was disallowed + if (_dragOperation !== CPDragOperationNone) + [self performDragOperationInPlatformWindow:platformWindow]; + + [self draggingEndedInPlatformWindow:platformWindow globalLocation:platformWindowLocation operation:_dragOperation]; + // Stop tracking events. return; } [self draggingSourceUpdatedWithGlobalLocation:platformWindowLocation]; - [self draggingUpdatedInPlatformWindow:platformWindow location:platformWindowLocation]; + _dragOperation = [self draggingUpdatedInPlatformWindow:platformWindow location:platformWindowLocation]; // If we're not a mouse up, then we're going to want to grab the next event. [CPApp setTarget:self selector:@selector(trackDragging:) From 669d18b218982f43c1a879109ab11c633b3aaa55 Mon Sep 17 00:00:00 2001 From: Klaas Pieter Annema Date: Wed, 10 Feb 2010 11:46:40 +0100 Subject: [PATCH 42/58] added missing exception when a viewcontroller has no view after loadView --- AppKit/CPViewController.j | 10 ++++++++-- 1 file changed, 8 insertions(+), 2 deletions(-) diff --git a/AppKit/CPViewController.j b/AppKit/CPViewController.j index c66f021f8..748e2140e 100644 --- a/AppKit/CPViewController.j +++ b/AppKit/CPViewController.j @@ -138,8 +138,6 @@ var CPViewControllerCachedCibs; Returns the view that the controller manages. If this property is nil, the controller sends loadView to itself to create the view that it manages. Subclasses should override the loadView method to create any custom views. The default value is nil. - - Note: An error will not be thrown if after -loadView, the view property is still nil. -view will simply return nil, but will continue to call -loadView on subsequent calls. */ - (CPView)view { @@ -155,6 +153,14 @@ var CPViewControllerCachedCibs; if (_view === nil && [cibOwner isKindOfClass:[CPDocument class]]) [self setView:[cibOwner valueForKey:@"view"]]; + if (!_view) + { + var reason = [CPString stringWithFormat:@"View for %@ could not be loaded from Cib or no view specified. \ + Override loadView to load the view manually.", self]; + + [CPException raise:CPInternalInconsistencyException reason:reason]; + } + if ([cibOwner respondsToSelector:@selector(viewControllerDidLoadCib:)]) [cibOwner viewControllerDidLoadCib:self]; } From 90cd519916bda0f38dcdfb39542d8b6101365f5e Mon Sep 17 00:00:00 2001 From: Klaas Pieter Annema Date: Wed, 10 Feb 2010 12:13:17 +0100 Subject: [PATCH 43/58] added viewDidLoad to CPViewController --- AppKit/CPViewController.j | 16 ++++++++++++++-- 1 file changed, 14 insertions(+), 2 deletions(-) diff --git a/AppKit/CPViewController.j b/AppKit/CPViewController.j index 748e2140e..3fffe261d 100644 --- a/AppKit/CPViewController.j +++ b/AppKit/CPViewController.j @@ -155,20 +155,32 @@ var CPViewControllerCachedCibs; if (!_view) { - var reason = [CPString stringWithFormat:@"View for %@ could not be loaded from Cib or no view specified. \ - Override loadView to load the view manually.", self]; + var reason = [CPString stringWithFormat:@"View for %@ could not be loaded from Cib or no view specified. Override loadView to load the view manually.", self]; [CPException raise:CPInternalInconsistencyException reason:reason]; } if ([cibOwner respondsToSelector:@selector(viewControllerDidLoadCib:)]) [cibOwner viewControllerDidLoadCib:self]; + + [self viewDidLoad]; } return _view; } +/*! + This method is called after the view controller has loaded its associated views into memory. + This method is called regardless of whether the views were stored in a nib file or created programmatically in the loadView method. + This method is most commonly used to perform additional initialization steps on views that are loaded from nib files. +*/ +- (void)viewDidLoad +{ + +} + + /*! Manually sets the view that the controller manages. Setting to nil will cause -loadView to be called on all subsequent calls of -view. From ea47baa1fc0fcfc0e65f616c1fab17188d1652d7 Mon Sep 17 00:00:00 2001 From: Klaas Pieter Annema Date: Wed, 10 Feb 2010 16:19:51 +0100 Subject: [PATCH 44/58] implemented imageDimsWhenDisabled on CPButton --- AppKit/CPButton.j | 1 + AppKit/_CPImageAndTextView.j | 18 ++++++++++++++++++ 2 files changed, 19 insertions(+) diff --git a/AppKit/CPButton.j b/AppKit/CPButton.j index 57b15195b..2cbcbf519 100644 --- a/AppKit/CPButton.j +++ b/AppKit/CPButton.j @@ -554,6 +554,7 @@ CPButtonStateMixed = CPThemeState("mixed"); [contentView setTextShadowOffset:[self currentValueForThemeAttribute:@"text-shadow-offset"]]; [contentView setImagePosition:[self currentValueForThemeAttribute:@"image-position"]]; [contentView setImageScaling:[self currentValueForThemeAttribute:@"image-scaling"]]; + [contentView setDimsImage:[self hasThemeState:CPThemeStateDisabled] && _imageDimsWhenDisabled]; } } diff --git a/AppKit/_CPImageAndTextView.j b/AppKit/_CPImageAndTextView.j index d5755c60d..85ba77333 100644 --- a/AppKit/_CPImageAndTextView.j +++ b/AppKit/_CPImageAndTextView.j @@ -68,6 +68,7 @@ var HORIZONTAL_MARGIN = 3.0, CPCellImagePosition _imagePosition; CPImageScaling _imageScaling; + BOOL _shouldDimImage; CPImage _image; CPString _text; @@ -216,6 +217,16 @@ var HORIZONTAL_MARGIN = 3.0, return _imageScaling; } +- (void)setDimsImage:(BOOL)shouldDimImage +{ + var shouldDimImage = !!shouldDimImage; + if (_shouldDimImage !== shouldDimImage) + { + _shouldDimImage = shouldDimImage; + [self setNeedsLayout]; + } +} + - (void)setTextColor:(CPColor)aTextColor { if (_textColor === aTextColor) @@ -577,6 +588,13 @@ var HORIZONTAL_MARGIN = 3.0, imageHeight *= scale; } +#if PLATFORM(DOM) + if (CPFeatureIsCompatible(CPOpacityRequiresFilterFeature)) + _DOMElement.style.filter = @"alpha(opacity=" + _shouldDimImage ? 50 : 100 + ")"; + else + _DOMElement.style.opacity = _shouldDimImage ? 0.5 : 1.0; +#endif + #if PLATFORM(DOM) _DOMImageElement.width = imageWidth; _DOMImageElement.height = imageHeight; From bf691fa552649091dcebd54c940e93321dce3086 Mon Sep 17 00:00:00 2001 From: Klaas Pieter Annema Date: Thu, 11 Feb 2010 12:47:27 +0100 Subject: [PATCH 45/58] removed incorrect implementation of imageDimsWhenDisabled --- AppKit/CPButton.j | 1 - AppKit/_CPImageAndTextView.j | 18 ------------------ 2 files changed, 19 deletions(-) diff --git a/AppKit/CPButton.j b/AppKit/CPButton.j index 2cbcbf519..57b15195b 100644 --- a/AppKit/CPButton.j +++ b/AppKit/CPButton.j @@ -554,7 +554,6 @@ CPButtonStateMixed = CPThemeState("mixed"); [contentView setTextShadowOffset:[self currentValueForThemeAttribute:@"text-shadow-offset"]]; [contentView setImagePosition:[self currentValueForThemeAttribute:@"image-position"]]; [contentView setImageScaling:[self currentValueForThemeAttribute:@"image-scaling"]]; - [contentView setDimsImage:[self hasThemeState:CPThemeStateDisabled] && _imageDimsWhenDisabled]; } } diff --git a/AppKit/_CPImageAndTextView.j b/AppKit/_CPImageAndTextView.j index 85ba77333..d5755c60d 100644 --- a/AppKit/_CPImageAndTextView.j +++ b/AppKit/_CPImageAndTextView.j @@ -68,7 +68,6 @@ var HORIZONTAL_MARGIN = 3.0, CPCellImagePosition _imagePosition; CPImageScaling _imageScaling; - BOOL _shouldDimImage; CPImage _image; CPString _text; @@ -217,16 +216,6 @@ var HORIZONTAL_MARGIN = 3.0, return _imageScaling; } -- (void)setDimsImage:(BOOL)shouldDimImage -{ - var shouldDimImage = !!shouldDimImage; - if (_shouldDimImage !== shouldDimImage) - { - _shouldDimImage = shouldDimImage; - [self setNeedsLayout]; - } -} - - (void)setTextColor:(CPColor)aTextColor { if (_textColor === aTextColor) @@ -588,13 +577,6 @@ var HORIZONTAL_MARGIN = 3.0, imageHeight *= scale; } -#if PLATFORM(DOM) - if (CPFeatureIsCompatible(CPOpacityRequiresFilterFeature)) - _DOMElement.style.filter = @"alpha(opacity=" + _shouldDimImage ? 50 : 100 + ")"; - else - _DOMElement.style.opacity = _shouldDimImage ? 0.5 : 1.0; -#endif - #if PLATFORM(DOM) _DOMImageElement.width = imageWidth; _DOMImageElement.height = imageHeight; From bc07bd16bd796ede66fc334daceea14531d99950 Mon Sep 17 00:00:00 2001 From: Klaas Pieter Annema Date: Thu, 11 Feb 2010 16:47:49 +0100 Subject: [PATCH 46/58] implemented outlineView:willDisplayView:forTableColumn:row delegate method --- AppKit/CPOutlineView.j | 93 ++++++++++++++++++++++++------------------ 1 file changed, 53 insertions(+), 40 deletions(-) diff --git a/AppKit/CPOutlineView.j b/AppKit/CPOutlineView.j index f293dcccc..7771b576b 100644 --- a/AppKit/CPOutlineView.j +++ b/AppKit/CPOutlineView.j @@ -53,7 +53,8 @@ var CPOutlineViewDataSource_outlineView_setObjectValue_forTableColumn_byItem_ var CPOutlineViewDelegate_outlineView_dataViewForTableColumn_item_ = 1 << 1, CPOutlineViewDelegate_outlineView_shouldSelectItem_ = 1 << 2; - CPOutlineViewDelegate_outlineView_heightOfRowByItem_ = 1 << 3; + CPOutlineViewDelegate_outlineView_heightOfRowByItem_ = 1 << 3, + CPOutlineViewDelegate_outlineView_willDisplayView_forTableColumn_item_ = 1 << 4; CPOutlineViewDropOnItemIndex = -1; @@ -77,12 +78,12 @@ CPOutlineViewDropOnItemIndex = -1; CPArray _disclosureControlsForRows; CPData _disclosureControlData; CPArray _disclosureControlQueue; - - BOOL _shouldRetargetItem; - id _retargetedItem; - - BOOL _shouldRetargetChildIndex; - CPInteger _retargedChildIndex; + + BOOL _shouldRetargetItem; + id _retargetedItem; + + BOOL _shouldRetargetChildIndex; + CPInteger _retargedChildIndex; } - (id)initWithFrame:(CGRect)aFrame @@ -98,11 +99,11 @@ CPOutlineViewDropOnItemIndex = -1; _itemInfosForItems = { }; _disclosureControlsForRows = []; - _retargetedItem = nil; - _shouldRetargetItem = NO; - - _retargedChildIndex = nil; - _shouldRetargetChildIndex = NO; + _retargetedItem = nil; + _shouldRetargetItem = NO; + + _retargedChildIndex = nil; + _shouldRetargetChildIndex = NO; [self setIndentationPerLevel:16.0]; [self setIndentationMarkerFollowsDataView:YES]; @@ -462,6 +463,9 @@ CPOutlineViewDropOnItemIndex = -1; if ([_outlineViewDelegate respondsToSelector:@selector(outlineView:heightOfRowByItem:)]) _implementedOutlineViewDelegateMethods |= CPOutlineViewDelegate_outlineView_heightOfRowByItem_; + if ([_outlineViewDelegate respondsToSelector:@selector(outlineView:willDisplayView:forTableColumn:item:)]) + _implementedOutlineViewDelegateMethods |= CPOutlineViewDelegate_outlineView_willDisplayView_forTableColumn_item_; + if ([_outlineViewDelegate respondsToSelector:@selector(outlineViewColumnDidMove:)]) [defaultCenter addObserver:_outlineViewDelegate @@ -523,20 +527,18 @@ CPOutlineViewDropOnItemIndex = -1; - (void)setDropItem:(id)theItem dropChildIndex:(int)theIndex { - CPLog.debug(@"set drop item: %@ index: %i", theItem, theIndex); - - _retargetedItem = theItem; - _shouldRetargetItem = YES; - - _retargedChildIndex = theIndex; - _shouldRetargetChildIndex = YES; + _retargetedItem = theItem; + _shouldRetargetItem = YES; + + _retargedChildIndex = theIndex; + _shouldRetargetChildIndex = YES; } - (id)_parentItemForUpperRow:(int)theUpperRowIndex andLowerRow:(int)theLowerRowIndex atMouseOffset:(CPPoint)theOffset { - if (_shouldRetargetItem) - return _retargetedItem; - + if (_shouldRetargetItem) + return _retargetedItem; + var lowerLevel = [self levelForRow:theLowerRowIndex] upperItem = [self itemAtRow:theUpperRowIndex]; upperLevel = [self levelForItem:upperItem]; @@ -890,9 +892,9 @@ var _loadItemInfoForItem = function(/*CPOutlineView*/ anOutlineView, /*id*/ anIt - (int)_childIndexForDropOperation:(CPTableViewDropOperation)theDropOperation row:(int)theRow offset:(CPPoint)theOffset { - if (_outlineView._shouldRetargetChildIndex) - return _outlineView._retargedChildIndex; - + if (_outlineView._shouldRetargetChildIndex) + return _outlineView._retargedChildIndex; + var childIndex = CPNotFound; if (theDropOperation === CPTableViewDropAbove) @@ -926,18 +928,18 @@ var _loadItemInfoForItem = function(/*CPOutlineView*/ anOutlineView, /*id*/ anIt if (!(_outlineView._implementedOutlineViewDataSourceMethods & CPOutlineViewDataSource_outlineView_validateDrop_proposedItem_proposedChildIndex_)) return CPDragOperationNone; - // Make sure the retargeted item and index are reset - _outlineView._retargetedItem = nil; - _outlineView._shouldRetargetItem = NO; + // Make sure the retargeted item and index are reset + _outlineView._retargetedItem = nil; + _outlineView._shouldRetargetItem = NO; - _outlineView._retargedChildIndex = nil; - _outlineView._shouldRetargetChildIndex = NO; + _outlineView._retargedChildIndex = nil; + _outlineView._shouldRetargetChildIndex = NO; var location = [_outlineView convertPoint:[theInfo draggingLocation] fromView:nil], - parentItem = [self _parentItemForDropOperation:theOperation row:theRow offset:location]; - childIndex = [self _childIndexForDropOperation:theOperation row:theRow offset:location]; + parentItem = [self _parentItemForDropOperation:theOperation row:theRow offset:location]; + childIndex = [self _childIndexForDropOperation:theOperation row:theRow offset:location]; - return [_outlineView._outlineViewDataSource outlineView:_outlineView validateDrop:theInfo proposedItem:parentItem proposedChildIndex:childIndex]; + return [_outlineView._outlineViewDataSource outlineView:_outlineView validateDrop:theInfo proposedItem:parentItem proposedChildIndex:childIndex]; } - (BOOL)tableView:(CPTableView)aTableView acceptDrop:(id )theInfo row:(int)theRow dropOperation:(CPTableViewDropOperation)theOperation @@ -945,15 +947,15 @@ var _loadItemInfoForItem = function(/*CPOutlineView*/ anOutlineView, /*id*/ anIt if (!(_outlineView._implementedOutlineViewDataSourceMethods & CPOutlineViewDataSource_outlineView_acceptDrop_item_childIndex_)) return NO; - var location = [_outlineView convertPoint:[theInfo draggingLocation] fromView:nil], - parentItem = [self _parentItemForDropOperation:theOperation row:theRow offset:location]; - childIndex = [self _childIndexForDropOperation:theOperation row:theRow offset:location]; + var location = [_outlineView convertPoint:[theInfo draggingLocation] fromView:nil], + parentItem = [self _parentItemForDropOperation:theOperation row:theRow offset:location]; + childIndex = [self _childIndexForDropOperation:theOperation row:theRow offset:location]; - _outlineView._retargetedItem = nil; - _outlineView._shouldRetargetItem = NO; + _outlineView._retargetedItem = nil; + _outlineView._shouldRetargetItem = NO; - _outlineView._retargedChildIndex = nil; - _outlineView._shouldRetargetChildIndex = NO; + _outlineView._retargedChildIndex = nil; + _outlineView._shouldRetargetChildIndex = NO; return [_outlineView._outlineViewDataSource outlineView:_outlineView acceptDrop:theInfo item:parentItem childIndex:childIndex]; } @@ -1006,6 +1008,17 @@ var _loadItemInfoForItem = function(/*CPOutlineView*/ anOutlineView, /*id*/ anIt return [theTableView rowHeight]; } +- (void)tableView:(CPTableView)aTableView willDisplayView:(id)aView forTableColumn:(CPTableColumn)aTableColumn row:(int)aRowIndex +{ + if ((_outlineView._implementedOutlineViewDelegateMethods & CPOutlineViewDelegate_outlineView_willDisplayView_forTableColumn_item_)) + { + var item = [_outlineView itemAtRow:aRowIndex]; + [_outlineView._outlineViewDelegate outlineView:_outlineView willDisplayView:aView forTableColumn:aTableColumn item:item]; + } +} + + + @end @implementation CPDisclosureButton : CPButton From 65051855ee1751f38f532da1fcac2de65723de1b Mon Sep 17 00:00:00 2001 From: Klaas Pieter Annema Date: Fri, 12 Feb 2010 13:02:55 +0100 Subject: [PATCH 47/58] fixed a bug where the tableview would draw a row to many --- AppKit/CPTableView.j | 41 +++++++++++++++++++++++------------------ 1 file changed, 23 insertions(+), 18 deletions(-) diff --git a/AppKit/CPTableView.j b/AppKit/CPTableView.j index 7b2234990..880525d2a 100644 --- a/AppKit/CPTableView.j +++ b/AppKit/CPTableView.j @@ -1164,7 +1164,7 @@ CPTableViewFirstColumnOnlyAutoresizingStyle = 5; var row = FLOOR(y / (_rowHeight + _intercellSpacing.height)); - if (row > _numberOfRows) + if (row >= _numberOfRows) return -1; return row; @@ -2583,15 +2583,18 @@ CPTableViewFirstColumnOnlyAutoresizingStyle = 5; if(_retargetedDropOperation !== nil) return _retargetedDropOperation; - var row = [self rowAtPoint:theDragPoint], + var row = [self _proposedRowAtPoint:theDragPoint], rowRect = [self rectOfRow:row]; - + // If there is no (the default) or to little inter cell spacing we create some room for the CPTableViewDropAbove indicator // This probably doesn't work if the row height is smaller than or around 5.0 if ([self intercellSpacing].height < 5.0) - rowRect = CPRectInset(rowRect, 0.0, 5.0 - [self intercellSpacing].height); + rowRect = CPRectInset(rowRect, 0.0, 5.0 - [self intercellSpacing].height); - if (CGRectContainsPoint(rowRect, theDragPoint)) + // If the altered row rect contains the drag point we show the drop on + // We don't show the drop on indicator if we are dragging below the last row + // in that case we always want to show the drop above indicator + if (CGRectContainsPoint(rowRect, theDragPoint) && row < _numberOfRows) return CPTableViewDropOn; return CPTableViewDropAbove; @@ -2602,13 +2605,18 @@ CPTableViewFirstColumnOnlyAutoresizingStyle = 5; */ - (CPInteger)_proposedRowAtPoint:(CGPoint)dragPoint { - var row = [self rowAtPoint:dragPoint]; - - // cocoa seems to jump to the next row when we approach the below row - dragPoint.y += FLOOR(CPRectGetHeight([self rectOfRow:row]) / 4.0); - row = [self rowAtPoint:dragPoint]; - - return row; + // We don't use rowAtPoint here because the drag indicator can appear below the last row + // and rowAtPoint doesn't return rows that are larger than numberOfRows + var row = FLOOR(dragPoint.y / _rowHeight + _intercellSpacing.height); + dragPoint.y += FLOOR(CPRectGetHeight([self rectOfRow:row]) / 4.0); + + // cocoa seems to jump to the next row when we approach the below row + row = FLOOR(dragPoint.y / _rowHeight + _intercellSpacing.height); + + if (row > _numberOfRows) + return -1; + + return row; } - (void)_validateDrop:(id)info proposedRow:(CPInteger)row proposedDropOperation:(CPTableViewDropOperation)dropOperation @@ -2629,10 +2637,7 @@ CPTableViewFirstColumnOnlyAutoresizingStyle = 5; - (CPRect)_rectForDropHighlightViewBetweenUpperRow:(int)theUpperRowIndex andLowerRow:(int)theLowerRowIndex offset:(CPPoint)theOffset { - if (theLowerRowIndex > [self numberOfRows]) - theLowerRowIndex = [self numberOfRows]; - - return [self rectOfRow:theLowerRowIndex]; + return [self rectOfRow:theLowerRowIndex]; } - (CPDragOperation)draggingUpdated:(id)sender @@ -2645,8 +2650,8 @@ CPTableViewFirstColumnOnlyAutoresizingStyle = 5; dragOperation = [self _validateDrop:sender proposedRow:row proposedDropOperation:dropOperation]; exposedClipRect = [self exposedClipRect]; - if(_retargetedDropRow !== nil) - row = _retargetedDropRow; + // if(_retargetedDropRow !== nil) + // row = _retargetedDropRow; var rect = CPRectMakeZero(); From 20f6a57b3a9c556d6c50577708f18dfb755026a3 Mon Sep 17 00:00:00 2001 From: Klaas Pieter Annema Date: Tue, 16 Feb 2010 07:45:19 +0100 Subject: [PATCH 48/58] - made the proposed drag row calculations more accurate when a tableview has non-default row height or inter-cell spacing - fixed a bug in the dragged row at point calculation --- AppKit/CPTableView.j | 21 ++++++++++--------- .../Manual/CPOutlineViewTest/AppController.j | 6 ++++-- 2 files changed, 15 insertions(+), 12 deletions(-) diff --git a/AppKit/CPTableView.j b/AppKit/CPTableView.j index 880525d2a..13cd805d2 100644 --- a/AppKit/CPTableView.j +++ b/AppKit/CPTableView.j @@ -2607,15 +2607,16 @@ CPTableViewFirstColumnOnlyAutoresizingStyle = 5; { // We don't use rowAtPoint here because the drag indicator can appear below the last row // and rowAtPoint doesn't return rows that are larger than numberOfRows - var row = FLOOR(dragPoint.y / _rowHeight + _intercellSpacing.height); - dragPoint.y += FLOOR(CPRectGetHeight([self rectOfRow:row]) / 4.0); + var row = FLOOR(dragPoint.y / ( _rowHeight + _intercellSpacing.height )); - // cocoa seems to jump to the next row when we approach the below row - row = FLOOR(dragPoint.y / _rowHeight + _intercellSpacing.height); - - if (row > _numberOfRows) - return -1; + // Determine if the mouse is currently closer to this row or the row below it + var lowerRow = row + 1, + rect = [self rectOfRow:row], + lowerRect = [self rectOfRow:lowerRow]; + if (ABS(CPRectGetMinY(lowerRect) - dragPoint.y) < ABS(dragPoint.y - CPRectGetMinY(rect))) + row = lowerRow; + return row; } @@ -2649,9 +2650,9 @@ CPTableViewFirstColumnOnlyAutoresizingStyle = 5; var row = [self _proposedRowAtPoint:location], dragOperation = [self _validateDrop:sender proposedRow:row proposedDropOperation:dropOperation]; exposedClipRect = [self exposedClipRect]; - - // if(_retargetedDropRow !== nil) - // row = _retargetedDropRow; + + if(_retargetedDropRow !== nil) + row = _retargetedDropRow; var rect = CPRectMakeZero(); diff --git a/Tests/Manual/CPOutlineViewTest/AppController.j b/Tests/Manual/CPOutlineViewTest/AppController.j index 0df7b4991..36e1ea605 100644 --- a/Tests/Manual/CPOutlineViewTest/AppController.j +++ b/Tests/Manual/CPOutlineViewTest/AppController.j @@ -204,7 +204,8 @@ CustomOutlineViewDragType = @"CustomOutlineViewDragType"; [_outlineView setDataSource:self]; [_outlineView setAllowsMultipleSelection:YES]; [_outlineView expandItem:nil expandChildren:YES]; - // [_outlineView setIntercellSpacing:CPSizeMake(0.0, 0.0)] + // [_outlineView setRowHeight:50.0]; + // [_outlineView setIntercellSpacing:CPSizeMake(0.0, 10.0)] [scrollView setDocumentView:_outlineView]; [theWindow setContentView:scrollView]; @@ -270,10 +271,11 @@ CustomOutlineViewDragType = @"CustomOutlineViewDragType"; - (CPDragOperation)outlineView:(CPOutlineView)anOutlineView validateDrop:(id < CPDraggingInfo >)theInfo proposedItem:(id)theItem proposedChildIndex:(int)theIndex { + CPLog.debug(@"validate item: %@ at index: %i", theItem, theIndex); + if (theItem === nil) [anOutlineView setDropItem:nil dropChildIndex:theIndex]; - // CPLog.debug(@"validate item: %@ at index: %i", theItem, theIndex); [anOutlineView setDropItem:theItem dropChildIndex:theIndex]; return CPDragOperationEvery; From 4a43e4fda6c47cec0fd951b2e2ede5373d7779c6 Mon Sep 17 00:00:00 2001 From: Ross Boucher Date: Tue, 2 Mar 2010 15:16:10 -0800 Subject: [PATCH 49/58] Overhaul of the key/main window status, esp. with respect to assigning new values after a window closes or after a window is minimized, and with app activation/deactivation. --- AppKit/CPApplication.j | 138 +++++++++++++++++++++ AppKit/CPCursor.j | 2 - AppKit/CPWindow/CPWindow.j | 135 ++++++++++++++++---- AppKit/Platform/CPPlatform.j | 4 + AppKit/Platform/DOM/CPPlatform.j | 6 + AppKit/Platform/DOM/CPPlatformWindow+DOM.j | 52 ++++---- 6 files changed, 287 insertions(+), 50 deletions(-) diff --git a/AppKit/CPApplication.j b/AppKit/CPApplication.j index f276ebd74..7e5b948f1 100644 --- a/AppKit/CPApplication.j +++ b/AppKit/CPApplication.j @@ -40,6 +40,10 @@ CPApp = nil; CPApplicationWillFinishLaunchingNotification = @"CPApplicationWillFinishLaunchingNotification"; CPApplicationDidFinishLaunchingNotification = @"CPApplicationDidFinishLaunchingNotification"; CPApplicationWillTerminateNotification = @"CPApplicationWillTerminateNotification"; +CPApplicationWillBecomeActiveNotification = @"CPApplicationWillBecomeActiveNotification"; +CPApplicationDidBecomeActiveNotification = @"CPApplicationDidBecomeActiveNotification"; +CPApplicationWillResignActiveNotification = @"CPApplicationWillResignActiveNotification"; +CPApplicationDidResignActiveNotification = @"CPApplicationDidResignActiveNotification"; CPTerminateNow = YES; CPTerminateCancel = NO; @@ -83,6 +87,8 @@ CPRunContinuesResponse = -1002; CPArray _windows; CPWindow _keyWindow; CPWindow _mainWindow; + CPWindow _previousKeyWindow; + CPWindow _previousMainWindow; CPMenu _mainMenu; CPDocumentController _documentController; @@ -92,6 +98,7 @@ CPRunContinuesResponse = -1002; // id _delegate; BOOL _finishedLaunching; + BOOL _isActive; CPDictionary _namedArgs; CPArray _args; @@ -219,6 +226,26 @@ CPRunContinuesResponse = -1002; removeObserver:_delegate name:CPApplicationDidFinishLaunchingNotification object:self]; + + [defaultCenter + removeObserver:_delegate + name:CPApplicationWillBecomeActiveNotification + object:self]; + + [defaultCenter + removeObserver:_delegate + name:CPApplicationDidBecomeActiveNotification + object:self]; + + [defaultCenter + removeObserver:_delegate + name:CPApplicationWillResignActiveNotification + object:self]; + + [defaultCenter + removeObserver:_delegate + name:CPApplicationDidResignActiveNotification + object:self]; } _delegate = aDelegate; @@ -236,6 +263,34 @@ CPRunContinuesResponse = -1002; selector:@selector(applicationDidFinishLaunching:) name:CPApplicationDidFinishLaunchingNotification object:self]; + + if ([_delegate respondsToSelector:@selector(applicationWillBecomeActive:)]) + [defaultCenter + addObserver:_delegate + selector:@selector(applicationWillBecomeActive:) + name:CPApplicationWillBecomeActiveNotification + object:self]; + + if ([_delegate respondsToSelector:@selector(applicationDidBecomeActive:)]) + [defaultCenter + addObserver:_delegate + selector:@selector(applicationDidBecomeActive:) + name:CPApplicationDidBecomeActiveNotification + object:self]; + + if ([_delegate respondsToSelector:@selector(applicationWillResignActive:)]) + [defaultCenter + addObserver:_delegate + selector:@selector(applicationWillResignActive:) + name:CPApplicationWillResignActiveNotification + object:self]; + + if ([_delegate respondsToSelector:@selector(applicationDidResignActive:)]) + [defaultCenter + addObserver:_delegate + selector:@selector(applicationDidResignActive:) + name:CPApplicationDidResignActiveNotification + object:self]; } /*! @@ -419,7 +474,27 @@ CPRunContinuesResponse = -1002; - (void)activateIgnoringOtherApps:(BOOL)shouldIgnoreOtherApps { + [self _willBecomeActive]; + [CPPlatform activateIgnoringOtherApps:shouldIgnoreOtherApps]; + _isActive = YES; + + [self _willResignActive]; +} + +- (void)deactivate +{ + [self _willResignActive]; + + [CPPlatform deactivate]; + _isActive = NO; + + [self _didResignActive]; +} + +- (void)isActive +{ + return _isActive; } - (void)hideOtherApplications:(id)aSender @@ -624,6 +699,14 @@ CPRunContinuesResponse = -1002; return _windows; } +/*! + Returns an array of visible CPWindow objects, ordered by their front to back order on the screen. +*/ +- (CPArray)orderedWindows +{ + return CPWindowObjectList(); +} + - (void)hide:(id)aSender { [CPPlatform hide:self]; @@ -953,10 +1036,65 @@ CPRunContinuesResponse = -1002; return !![_documentController openDocumentWithContentsOfURL:aURL display:YES error:NULL]; } +- (void)_willBecomeActive +{ + [[CPNotificationCenter defaultCenter] postNotificationName:CPApplicationWillBecomeActiveNotification + object:self + userInfo:nil]; +} + +- (void)_didBecomeActive +{ + if (![self keyWindow] && _previousKeyWindow && + [[self windows] indexOfObjectIdenticalTo:_previousKeyWindow] !== CPNotFound) + [_previousKeyWindow makeKeyWindow]; + + if (![self mainWindow] && _previousMainWindow && + [[self windows] indexOfObjectIdenticalTo:_previousMainWindow] !== CPNotFound) + [_previousMainWindow makeMainWindow]; + + if ([self keyWindow]) + [[self keyWindow] orderFront:self]; + else if ([self mainWindow]) + [[self mainWindow] makeKeyAndOrderFront:self]; + else + [[[self mainMenu] window] makeKeyWindow]; //FIXME this may not actually work + + _previousKeyWindow = nil; + _previousMainWindow = nil; + + [[CPNotificationCenter defaultCenter] postNotificationName:CPApplicationDidBecomeActiveNotification + object:self + userInfo:nil]; +} + +- (void)_willResignActive +{ + [[CPNotificationCenter defaultCenter] postNotificationName:CPApplicationWillResignActiveNotification + object:self + userInfo:nil]; +} + - (void)_didResignActive { if (self._activeMenu) [self._activeMenu cancelTracking]; + + if ([self keyWindow]) + { + _previousKeyWindow = [self keyWindow]; + [_previousKeyWindow resignKeyWindow]; + } + + if ([self mainWindow]) + { + _previousMainWindow = [self mainWindow]; + [_previousMainWindow resignMainWindow]; + } + + [[CPNotificationCenter defaultCenter] postNotificationName:CPApplicationDidResignActiveNotification + object:self + userInfo:nil]; } + (CPString)defaultThemeName diff --git a/AppKit/CPCursor.j b/AppKit/CPCursor.j index f5e67f692..95b1dc79a 100755 --- a/AppKit/CPCursor.j +++ b/AppKit/CPCursor.j @@ -230,8 +230,6 @@ var currentCursor = nil, + (void)_setCursorCSS:(CPString)aString { #if PLATFORM(DOM) - [CPPlatformWindow primaryPlatformWindow]._DOMBodyElement.style.cursor = aString; - var platformWindows = [[CPPlatformWindow visiblePlatformWindows] allObjects]; for (var i = 0, count = [platformWindows count]; i < count; i++) platformWindows[i]._DOMBodyElement.style.cursor = aString; diff --git a/AppKit/CPWindow/CPWindow.j b/AppKit/CPWindow/CPWindow.j index 3f506889d..aec63bb13 100644 --- a/AppKit/CPWindow/CPWindow.j +++ b/AppKit/CPWindow/CPWindow.j @@ -175,6 +175,8 @@ CPWindowBelow = 2; CPWindowWillCloseNotification = @"CPWindowWillCloseNotification"; CPWindowDidBecomeMainNotification = @"CPWindowDidBecomeMainNotification"; CPWindowDidResignMainNotification = @"CPWindowDidResignMainNotification"; +CPWindowDidBecomeKeyNotification = @"CPWindowDidBecomeKeyNotification"; +CPWindowDidResignKeyNotification = @"CPWindowDidResignKeyNotification"; CPWindowDidResizeNotification = @"CPWindowDidResizeNotification"; CPWindowDidMoveNotification = @"CPWindowDidMoveNotification"; CPWindowWillBeginSheetNotification = @"CPWindowWillBeginSheetNotification"; @@ -762,12 +764,7 @@ CPTexturedBackgroundWindowMask [_platformWindow order:CPWindowOut window:self relativeTo:nil]; - if ([CPApp keyWindow] == self) - { - [self resignKeyWindow]; - - CPApp._keyWindow = nil; - } + [self _updateMainAndKeyWindows]; } /*! @@ -1066,13 +1063,31 @@ CPTexturedBackgroundWindowMask */ - (void)setDelegate:(id)aDelegate { - // FIXME: Unregister for notifications! + var defaultCenter = [CPNotificationCenter defaultCenter]; + + [defaultCenter removeObserver:_delegate name:CPWindowDidResignKeyNotification object:self]; + [defaultCenter removeObserver:_delegate name:CPWindowDidBecomeKeyNotification object:self]; + [defaultCenter removeObserver:_delegate name:CPWindowDidBecomeMainNotification object:self]; + [defaultCenter removeObserver:_delegate name:CPWindowDidResignMainNotification object:self]; + [defaultCenter removeObserver:_delegate name:CPWindowDidMoveNotification object:self]; + [defaultCenter removeObserver:_delegate name:CPWindowDidResizeNotification object:self]; _delegate = aDelegate; - _delegateRespondsToWindowWillReturnUndoManagerSelector = [_delegate respondsToSelector:@selector(windowWillReturnUndoManager:)]; - var defaultCenter = [CPNotificationCenter defaultCenter]; + if ([_delegate respondsToSelector:@selector(windowDidResignKey:)]) + [defaultCenter + addObserver:_delegate + selector:@selector(windowDidResignKey:) + name:CPWindowDidResignKeyNotification + object:self]; + + if ([_delegate respondsToSelector:@selector(windowDidBecomeKey:)]) + [defaultCenter + addObserver:_delegate + selector:@selector(windowDidBecomeKey:) + name:CPWindowDidBecomeKeyNotification + object:self]; if ([_delegate respondsToSelector:@selector(windowDidBecomeMain:)]) [defaultCenter @@ -1418,8 +1433,14 @@ CPTexturedBackgroundWindowMask */ - (void)becomeKeyWindow { - if (_firstResponder != self && [_firstResponder respondsToSelector:@selector(becomeKeyWindow)]) + CPApp._keyWindow = self; + + if (_firstResponder !== self && [_firstResponder respondsToSelector:@selector(becomeKeyWindow)]) [_firstResponder becomeKeyWindow]; + + [[CPNotificationCenter defaultCenter] + postNotificationName:CPWindowDidBecomeKeyNotification + object:self]; } /*! @@ -1456,13 +1477,10 @@ CPTexturedBackgroundWindowMask */ - (void)makeKeyWindow { - if (![self canBecomeKeyWindow]) + if ([CPApp keyWindow] === self || ![self canBecomeKeyWindow]) return; - [CPApp._keyWindow resignKeyWindow]; - - CPApp._keyWindow = self; - + [[CPApp keyWindow] resignKeyWindow]; [self becomeKeyWindow]; } @@ -1473,9 +1491,12 @@ CPTexturedBackgroundWindowMask { if (_firstResponder != self && [_firstResponder respondsToSelector:@selector(resignKeyWindow)]) [_firstResponder resignKeyWindow]; - - if ([_delegate respondsToSelector:@selector(windowDidResignKey:)]) - [_delegate windowDidResignKey:self]; + + CPApp._keyWindow = nil; + + [[CPNotificationCenter defaultCenter] + postNotificationName:CPWindowDidResignKeyNotification + object:self]; } /*! @@ -1664,6 +1685,8 @@ CPTexturedBackgroundWindowMask [[self platformWindow] miniaturize:sender]; + [self _lossOfKeyOrMainWindow]; + [[CPNotificationCenter defaultCenter] postNotificationName:CPWindowDidMiniaturizeNotification object:self]; _isMiniaturized = YES; @@ -1799,13 +1822,10 @@ CPTexturedBackgroundWindowMask */ - (void)makeMainWindow { - if (CPApp._mainWindow === self || ![self canBecomeMainWindow]) + if ([CPApp mainWindow] === self || ![self canBecomeMainWindow]) return; - [CPApp._mainWindow resignMainWindow]; - - CPApp._mainWindow = self; - + [[CPApp mainWindow] resignMainWindow]; [self becomeMainWindow]; } @@ -1816,7 +1836,9 @@ CPTexturedBackgroundWindowMask { [self _synchronizeMenuBarTitleWithWindowTitle]; [self _synchronizeSaveMenuWithDocumentSaving]; - + + CPApp._mainWindow = self; + [[CPNotificationCenter defaultCenter] postNotificationName:CPWindowDidBecomeMainNotification object:self]; @@ -1830,6 +1852,71 @@ CPTexturedBackgroundWindowMask [[CPNotificationCenter defaultCenter] postNotificationName:CPWindowDidResignMainNotification object:self]; + + CPApp._mainWindow = nil; +} + +- (void)_updateMainAndKeyWindows +{ + var allWindows = [CPApp orderedWindows], + windowCount = [allWindows count]; + + if (!windowCount) + return; + + if ([self isKeyWindow]) + { + var keyWindow = [CPApp keyWindow]; + [self resignKeyWindow]; + + if (keyWindow && keyWindow !== self && [keyWindow canBecomeKeyWindow]) + [keyWindow makeKeyWindow]; + else + { + var menuWindow = [CPApp mainMenu]._menuWindow; + for (var i = 0; i < windowCount; i++) + { + var currentWindow = allWindows[i]; + if (currentWindow === self || currentWindow === menuWindow) + continue; + + if ([currentWindow isVisible] && [currentWindow canBecomeKeyWindow]) + { + [currentWindow makeKeyWindow]; + break; + } + } + + if (![CPApp keyWindow]) + [keyWindow makeKeyWindow]; + } + } + + + if ([self isMainWindow]) + { + var mainWindow = [CPApp mainWindow]; + [self resignMainWindow]; + + if (mainWindow && mainWindow !== self && [mainWindow canBecomeMainWindow]) + [mainWindow makeMainWindow]; + else + { + var menuWindow = [CPApp mainMenu]._menuWindow; + for (var i = 0; i < windowCount; i++) + { + var currentWindow = allWindows[i]; + if (currentWindow === self || currentWindow === menuWindow) + continue; + + if ([currentWindow isVisible] && [currentWindow canBecomeMainWindow]) + { + [currentWindow makeMainWindow]; + break; + } + } + } + } } // Managing Toolbars diff --git a/AppKit/Platform/CPPlatform.j b/AppKit/Platform/CPPlatform.j index 8bf37856e..db2128810 100644 --- a/AppKit/Platform/CPPlatform.j +++ b/AppKit/Platform/CPPlatform.j @@ -58,6 +58,10 @@ { } ++ (void)deactivate +{ +} + + (void)hideOtherApplications:(id)aSender { } diff --git a/AppKit/Platform/DOM/CPPlatform.j b/AppKit/Platform/DOM/CPPlatform.j index 96c7a30bf..98d7ca02e 100644 --- a/AppKit/Platform/DOM/CPPlatform.j +++ b/AppKit/Platform/DOM/CPPlatform.j @@ -69,6 +69,12 @@ var screenNeedsInitialization = NO, window.cpActivateIgnoringOtherApps(!!shouldIgnoreOtherApps); } ++ (void)deactivate +{ + if (typeof window["cpDeactivate"] === "function") + window.cpDeactivate(); +} + + (void)hideOtherApplications:(id)aSender { if (typeof window["cpHideOtherApplications"] === "function") diff --git a/AppKit/Platform/DOM/CPPlatformWindow+DOM.j b/AppKit/Platform/DOM/CPPlatformWindow+DOM.j index e6cff4912..1e7f8d835 100644 --- a/AppKit/Platform/DOM/CPPlatformWindow+DOM.j +++ b/AppKit/Platform/DOM/CPPlatformWindow+DOM.j @@ -426,7 +426,14 @@ var supportsNativeDragAndDrop = [CPPlatform supportsDragAndDrop]; + (CPSet)visiblePlatformWindows { - return PlatformWindows; + if ([[CPPlatformWindow primaryPlatformWindow] isVisible]) + { + var set = [CPSet setWithSet:PlatformWindows]; + [set addObject:[CPPlatformWindow primaryPlatformWindow]]; + return set; + } + else + return PlatformWindows; } - (void)orderFront:(id)aSender @@ -1374,19 +1381,25 @@ var CPDOMEventStop = function(aDOMEvent, aPlatformWindow) function CPWindowObjectList() { - var platformWindow = [CPPlatformWindow primaryPlatformWindow], - levels = platformWindow._windowLevels, - layers = platformWindow._windowLayers, - levelCount = levels.length, + var platformWindows = [CPPlatformWindow visiblePlatformWindows], + platformWindowEnumerator = [platformWindows objectEnumerator], + platformWindow = nil, windowObjects = []; - while (levelCount--) + while (platformWindow = [platformWindowEnumerator nextObject]) { - var windows = [layers objectForKey:levels[levelCount]]._windows, - windowCount = windows.length; + var levels = platformWindow._windowLevels, + layers = platformWindow._windowLayers, + levelCount = levels.length; - while (windowCount--) - windowObjects.push(windows[windowCount]); + while (levelCount--) + { + var windows = [layers objectForKey:levels[levelCount]]._windows, + windowCount = windows.length; + + while (windowCount--) + windowObjects.push(windows[windowCount]); + } } return windowObjects; @@ -1394,20 +1407,11 @@ function CPWindowObjectList() function CPWindowList() { - var platformWindow = [CPPlatformWindow primaryPlatformWindow], - levels = platformWindow._windowLevels, - layers = platformWindow._windowLayers, - levelCount = levels.length, - windowNumbers = []; + var windowObjectList = CPWindowObjectList(), + windowList = []; - while (levelCount--) - { - var windows = [layers objectForKey:levels[levelCount]]._windows, - windowCount = windows.length; + for (var i = 0, count = [windowObjectList count]; i < count; i++) + windowList.push([windowObjectList[i] windowNumber]); - while (windowCount--) - windowNumbers.push([windows[windowCount] windowNumber]); - } - - return windowNumbers; + return windowList; } From 398d61097c10b109eff7f54f5b360d8867755229 Mon Sep 17 00:00:00 2001 From: Ross Boucher Date: Tue, 2 Mar 2010 15:27:40 -0800 Subject: [PATCH 50/58] Typo in miniaturize: --- AppKit/CPWindow/CPWindow.j | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/AppKit/CPWindow/CPWindow.j b/AppKit/CPWindow/CPWindow.j index aec63bb13..b3275ee6c 100644 --- a/AppKit/CPWindow/CPWindow.j +++ b/AppKit/CPWindow/CPWindow.j @@ -1685,7 +1685,7 @@ CPTexturedBackgroundWindowMask [[self platformWindow] miniaturize:sender]; - [self _lossOfKeyOrMainWindow]; + [self _updateMainAndKeyWindows]; [[CPNotificationCenter defaultCenter] postNotificationName:CPWindowDidMiniaturizeNotification object:self]; From 149308bc89e92405983d4648e766bb24d2681233 Mon Sep 17 00:00:00 2001 From: Ross Boucher Date: Wed, 3 Mar 2010 14:42:15 -0800 Subject: [PATCH 51/58] Revert "fix for scrollviews being drawn below window resize indicator." This reverts commit 18a0deb67860deb4afe3d7589ca43981f8738693. --- AppKit/CPScrollView.j | 19 +++---------------- 1 file changed, 3 insertions(+), 16 deletions(-) diff --git a/AppKit/CPScrollView.j b/AppKit/CPScrollView.j index 55955a4da..73cae512e 100644 --- a/AppKit/CPScrollView.j +++ b/AppKit/CPScrollView.j @@ -229,19 +229,6 @@ if (shouldShowHorizontalScroller) contentFrame.size.height -= horizontalScrollerHeight; - var _window = [self window], - forceCornerSpace = NO; - - if (_window && [_window contentView]) - { - var windowIsResizable = !!(([_window styleMask] & CPResizableWindowMask) || ([_window styleMask] & CPBorderlessBridgeWindowMask)), - relativeFrame = [self convertRect:[[_window contentView] frame] fromView:nil], - maxPoint = CGPointMake(CGRectGetMaxX([self bounds]), CGRectGetMaxY([self bounds])), - isInWindowCorner = CGRectGetMaxX(relativeFrame) >= maxPoint.x && CGRectGetMaxY(relativeFrame) >= maxPoint.y; - - forceCornerSpace = windowIsResizable && isInWindowCorner; - } - var scrollPoint = [_contentView bounds].origin, wasShowingVerticalScroller = ![_verticalScroller isHidden], wasShowingHorizontalScroller = ![_horizontalScroller isHidden]; @@ -251,7 +238,7 @@ var verticalScrollerY = MAX(_CGRectGetHeight([self _cornerViewFrame]), headerClipViewHeight), verticalScrollerHeight = _CGRectGetHeight([self bounds]) - verticalScrollerY; - if (forceCornerSpace || shouldShowHorizontalScroller) + if (shouldShowHorizontalScroller) verticalScrollerHeight -= horizontalScrollerHeight; [_verticalScroller setFloatValue:(difference.height <= 0.0) ? 0.0 : scrollPoint.y / difference.height]; @@ -268,7 +255,7 @@ { [_horizontalScroller setFloatValue:(difference.width <= 0.0) ? 0.0 : scrollPoint.x / difference.width]; [_horizontalScroller setKnobProportion:_CGRectGetWidth(contentFrame) / _CGRectGetWidth(documentFrame)]; - [_horizontalScroller setFrame:_CGRectMake(0.0, _CGRectGetMaxY(contentFrame), _CGRectGetWidth(contentFrame) - ((!shouldShowVerticalScroller && forceCornerSpace) ? verticalScrollerWidth : 0), horizontalScrollerHeight)]; + [_horizontalScroller setFrame:_CGRectMake(0.0, _CGRectGetMaxY(contentFrame), _CGRectGetWidth(contentFrame), horizontalScrollerHeight)]; } else if (wasShowingHorizontalScroller) { @@ -806,4 +793,4 @@ var CPScrollViewContentViewKey = "CPScrollViewContentView", [aCoder encodeObject:_cornerView forKey:CPScrollViewCornerViewKey]; } -@end \ No newline at end of file +@end From 628488f7aa8d1b7aa7353329034c3a06535db59b Mon Sep 17 00:00:00 2001 From: Ross Boucher Date: Wed, 3 Mar 2010 14:42:29 -0800 Subject: [PATCH 52/58] Revert "fix for scroller still being drawn below resize indicator on the first reflect of the clipview." This reverts commit fa63551b42bf41c33537d6ebd7f8fadf434c2903. --- AppKit/CPScrollView.j | 5 ----- 1 file changed, 5 deletions(-) diff --git a/AppKit/CPScrollView.j b/AppKit/CPScrollView.j index 73cae512e..6406c96fb 100644 --- a/AppKit/CPScrollView.j +++ b/AppKit/CPScrollView.j @@ -720,11 +720,6 @@ [_headerClipView scrollToPoint:CGPointMake(contentBounds.origin, 0)]; } -- (void)viewDidMoveToWindow -{ - [self reflectScrolledClipView:_contentView]; -} - @end var CPScrollViewContentViewKey = "CPScrollViewContentView", From d76d9bcfadaff8b31a77ae9ae83cb09f97db24d8 Mon Sep 17 00:00:00 2001 From: Randall Luecke Date: Fri, 5 Mar 2010 03:37:19 -0500 Subject: [PATCH 53/58] Fixed bugs with drag and drop in tableview after outlineview drag and drop merge. --- AppKit/CPTableView.j | 10 ++++++++-- 1 file changed, 8 insertions(+), 2 deletions(-) diff --git a/AppKit/CPTableView.j b/AppKit/CPTableView.j index 9b27819b0..86a4e7a33 100644 --- a/AppKit/CPTableView.j +++ b/AppKit/CPTableView.j @@ -2741,9 +2741,9 @@ CPTableViewFirstColumnOnlyAutoresizingStyle = 5; var draggedTypes = [self registeredDraggedTypes], count = [draggedTypes count], - i; + i = 0; - for (i = 0; i < count; i++) + for (; i < count; i++) { if ([[[sender draggingPasteboard] types] containsObject:[draggedTypes objectAtIndex: i]]) return [self _validateDrop:sender proposedRow:row proposedDropOperation:dropOperation]; @@ -2824,6 +2824,9 @@ CPTableViewFirstColumnOnlyAutoresizingStyle = 5; if (ABS(CPRectGetMinY(lowerRect) - dragPoint.y) < ABS(dragPoint.y - CPRectGetMinY(rect))) row = lowerRow; + + if (row >= [self numberOfRows]) + row = [self numberOfRows]; return row; } @@ -2846,6 +2849,9 @@ CPTableViewFirstColumnOnlyAutoresizingStyle = 5; - (CPRect)_rectForDropHighlightViewBetweenUpperRow:(int)theUpperRowIndex andLowerRow:(int)theLowerRowIndex offset:(CPPoint)theOffset { + if (theLowerRowIndex > [self numberOfRows]) + theLowerRowIndex = [self numberOfRows]; + return [self rectOfRow:theLowerRowIndex]; } From dc7bd3355dd19f668cc387a4edaf4c408a3b0f1b Mon Sep 17 00:00:00 2001 From: Randall Luecke Date: Fri, 5 Mar 2010 03:59:37 -0500 Subject: [PATCH 54/58] Fixed wrong import for outlineview test. --- Tests/Manual/CPOutlineViewTest/AppController.j | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Tests/Manual/CPOutlineViewTest/AppController.j b/Tests/Manual/CPOutlineViewTest/AppController.j index 36e1ea605..8e080afc7 100644 --- a/Tests/Manual/CPOutlineViewTest/AppController.j +++ b/Tests/Manual/CPOutlineViewTest/AppController.j @@ -7,7 +7,7 @@ */ @import -@import "AppKit/CPOutlineView.j" +@import CPLogRegister(CPLogConsole); From 9537a62ab12927d43691007815557233255959de Mon Sep 17 00:00:00 2001 From: saikat Date: Sun, 28 Feb 2010 00:22:47 -0800 Subject: [PATCH 55/58] Fixes calling selectText in the text field's delegate's controlTextDidFocus: method. --- AppKit/CPTextField.j | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/AppKit/CPTextField.j b/AppKit/CPTextField.j index 762e4c9b3..b3c452cc0 100644 --- a/AppKit/CPTextField.j +++ b/AppKit/CPTextField.j @@ -483,6 +483,7 @@ CPTextFieldStatePlaceholder = CPThemeState("placeholder"); window.setTimeout(function() { element.focus(); + [self textDidFocus:[CPNotification notificationWithName:CPTextFieldDidFocusNotification object:self userInfo:nil]]; CPTextFieldInputOwner = self; }, 0.0); @@ -500,8 +501,6 @@ CPTextFieldStatePlaceholder = CPThemeState("placeholder"); [[self window] platformWindow]._DOMBodyElement.ondrag = function () {}; [[self window] platformWindow]._DOMBodyElement.onselectstart = function () {}; } - - [self textDidFocus:[CPNotification notificationWithName:CPTextFieldDidFocusNotification object:self userInfo:nil]]; #endif return YES; From ad5f574fb71e1783a0b2e5475302b2c35f907fc6 Mon Sep 17 00:00:00 2001 From: saikat Date: Sun, 28 Feb 2010 00:52:51 -0800 Subject: [PATCH 56/58] Fix for issue #511 - disabling a menu item in the menu item's action --- AppKit/CPMenuItem/_CPMenuItemMenuBarView.j | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/AppKit/CPMenuItem/_CPMenuItemMenuBarView.j b/AppKit/CPMenuItem/_CPMenuItemMenuBarView.j index 6e232fef8..6342ef99e 100644 --- a/AppKit/CPMenuItem/_CPMenuItemMenuBarView.j +++ b/AppKit/CPMenuItem/_CPMenuItemMenuBarView.j @@ -155,7 +155,7 @@ var SelectionColor = nil, { // FIXME: This should probably be even throw. if (![_menuItem isEnabled]) - return; + shouldHighlight = NO; if (shouldHighlight) { From d0999fa5d57216499fcb8f2a0df2b70b91e04fb3 Mon Sep 17 00:00:00 2001 From: Randall Luecke Date: Fri, 5 Mar 2010 16:20:24 -0500 Subject: [PATCH 57/58] Additional fixes for drag and drop in the TableView after OutlineView merge. --- AppKit/CPTableView.j | 14 +++++++++++--- 1 file changed, 11 insertions(+), 3 deletions(-) diff --git a/AppKit/CPTableView.j b/AppKit/CPTableView.j index 86a4e7a33..c6bc4f64a 100644 --- a/AppKit/CPTableView.j +++ b/AppKit/CPTableView.j @@ -2640,6 +2640,9 @@ CPTableViewFirstColumnOnlyAutoresizingStyle = 5; return NO; } + + // The delegate disallowed the drag so clear the dragged row indexes + _draggedRowIndexes = [CPIndexSet indexSet]; } else if (ABS(_startTrackingPoint.x - aPoint.x) < 5 && ABS(_startTrackingPoint.y - aPoint.y) < 5) return YES; @@ -2735,7 +2738,7 @@ CPTableViewFirstColumnOnlyAutoresizingStyle = 5; var location = [self convertPoint:[sender draggingLocation] fromView:nil], dropOperation = [self _proposedDropOperationAtPoint:location], row = [self _proposedRowAtPoint:location]; - + if(_retargetedDropRow !== nil) row = _retargetedDropRow; @@ -2868,6 +2871,10 @@ CPTableViewFirstColumnOnlyAutoresizingStyle = 5; if(_retargetedDropRow !== nil) row = _retargetedDropRow; + + if (dropOperation === CPTableViewDropOn && row >= [self numberOfRows]) + row = [self numberOfRows] - 1; + var rect = CPRectMakeZero(); if (row === -1) @@ -3339,8 +3346,9 @@ var CPTableViewDataSourceKey = @"CPTableViewDataSourceKey", else if (dropOperation === CPTableViewDropOn) { //if row is selected don't fill and stroke white - var selectedRows = [tableView selectedRowIndexes]; - var newRect = _CGRectMake(aRect.origin.x + 2, aRect.origin.y + 2, aRect.size.width - 4, aRect.size.height - 5); + var selectedRows = [tableView selectedRowIndexes], + newRect = _CGRectMake(aRect.origin.x + 2, aRect.origin.y + 2, aRect.size.width - 4, aRect.size.height - 5); + if([selectedRows containsIndex:currentRow]) { CGContextSetLineWidth(context, 2); From 29a0de3636e3745ebeed2503ffd6e503bf6b80fa Mon Sep 17 00:00:00 2001 From: Ross Boucher Date: Fri, 5 Mar 2010 20:09:23 -0800 Subject: [PATCH 58/58] Fix document title's not being synced properly. --- AppKit/CPWindow/CPWindow.j | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/AppKit/CPWindow/CPWindow.j b/AppKit/CPWindow/CPWindow.j index b3275ee6c..e68c33174 100644 --- a/AppKit/CPWindow/CPWindow.j +++ b/AppKit/CPWindow/CPWindow.j @@ -1834,11 +1834,11 @@ CPTexturedBackgroundWindowMask */ - (void)becomeMainWindow { + CPApp._mainWindow = self; + [self _synchronizeMenuBarTitleWithWindowTitle]; [self _synchronizeSaveMenuWithDocumentSaving]; - CPApp._mainWindow = self; - [[CPNotificationCenter defaultCenter] postNotificationName:CPWindowDidBecomeMainNotification object:self];