improved CPTableView's drop row logic for the lowest possible row

This commit is contained in:
Klaas Pieter Annema
2010-02-05 11:51:06 +01:00
parent 7720200679
commit 0696fb405e
4 changed files with 118 additions and 57 deletions
+22 -5
View File
@@ -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];
}
+68 -43
View File
@@ -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
+13 -3
View File
@@ -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
+15 -6
View File
@@ -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];