DnD fixes and cleanups in NSOutlineView.

git-svn-id: svn+ssh://svn.gna.org/svn/gnustep/libs/gui/trunk@18306 72102866-910b-0410-8b05-ffd578937521
This commit is contained in:
ludovic 2004-01-04 03:39:09 +00:00
parent cdb1ad2338
commit c28dd2e585
3 changed files with 140 additions and 136 deletions

View file

@ -1,3 +1,12 @@
2003-01-03 Ludovic Marcotte <ludovic@Sophos.ca>
* Source/NSOutlineView.m: Started to fix the DnD code.
Modified -mouseDown: to not select the row when clicking
only on the expand/collapse image. Rewrote
-noteNumberOfRowsChanged to correctly restore the list
of selected rows after an expand/collapse operation.
Also did some general cleanups. More to come on this class.
2004-01-03 19:00 Gregory John Casamento <greg_casamento@yahoo.com> 2004-01-03 19:00 Gregory John Casamento <greg_casamento@yahoo.com>
* Source/NSBundleAdditions.m: Removed some uneeded includes. * Source/NSBundleAdditions.m: Removed some uneeded includes.

View file

@ -40,6 +40,7 @@
NSMapTable *_itemDict; NSMapTable *_itemDict;
NSMutableArray *_items; NSMutableArray *_items;
NSMutableArray *_expandedItems; NSMutableArray *_expandedItems;
NSMutableArray *_selectedItems;
NSMapTable *_levelOfItems; NSMapTable *_levelOfItems;
BOOL _autoResizesOutlineColumn; BOOL _autoResizesOutlineColumn;
BOOL _indentationMarkerFollowsCell; BOOL _indentationMarkerFollowsCell;

View file

@ -139,12 +139,12 @@ static NSImage *unexpandable = nil;
_itemDict = NSCreateMapTable(NSObjectMapKeyCallBacks, _itemDict = NSCreateMapTable(NSObjectMapKeyCallBacks,
NSObjectMapValueCallBacks, NSObjectMapValueCallBacks,
64); 64);
_items = [NSMutableArray new]; _items = [[NSMutableArray alloc] init];
_expandedItems = [NSMutableArray new]; _expandedItems = [[NSMutableArray alloc] init];
_selectedItems = [[NSMutableArray alloc] init];
_levelOfItems = NSCreateMapTable(NSObjectMapKeyCallBacks, _levelOfItems = NSCreateMapTable(NSObjectMapKeyCallBacks,
NSObjectMapValueCallBacks, NSObjectMapValueCallBacks,
64); 64);
return self; return self;
} }
@ -152,6 +152,8 @@ static NSImage *unexpandable = nil;
{ {
RELEASE(_items); RELEASE(_items);
RELEASE(_expandedItems); RELEASE(_expandedItems);
RELEASE(_selectedItems);
NSFreeMapTable(_itemDict); NSFreeMapTable(_itemDict);
NSFreeMapTable(_levelOfItems); NSFreeMapTable(_levelOfItems);
@ -347,7 +349,9 @@ static NSImage *unexpandable = nil;
if([self isExpandable: item] && [self isItemExpanded: item] && canCollapse) if([self isExpandable: item] && [self isItemExpanded: item] && canCollapse)
{ {
NSMutableDictionary *infoDict = [NSMutableDictionary dictionary]; NSMutableDictionary *infoDict = [NSMutableDictionary dictionary];
int i, count, row;
[infoDict setObject: item forKey: @"NSObject"]; [infoDict setObject: item forKey: @"NSObject"];
// Send out the notification to let observers know that this is about // Send out the notification to let observers know that this is about
@ -356,6 +360,20 @@ static NSImage *unexpandable = nil;
object: self object: self
userInfo: infoDict]; userInfo: infoDict];
// We save the selection
[_selectedItems removeAllObjects];
count = [_selectedRows count];
for (i = 0; i < count; i++)
{
row = [[_selectedRows objectAtIndex: i] intValue];
if ([self itemAtRow: row])
{
[_selectedItems addObject: [self itemAtRow: row]];
}
}
// collapse... // collapse...
[self _closeItem: item]; [self _closeItem: item];
@ -421,6 +439,7 @@ static NSImage *unexpandable = nil;
if(![self isItemExpanded: item] && canExpand) if(![self isItemExpanded: item] && canExpand)
{ {
NSMutableDictionary *infoDict = [NSMutableDictionary dictionary]; NSMutableDictionary *infoDict = [NSMutableDictionary dictionary];
int i, count, row;
[infoDict setObject: item forKey: @"NSObject"]; [infoDict setObject: item forKey: @"NSObject"];
@ -430,6 +449,20 @@ static NSImage *unexpandable = nil;
object: self object: self
userInfo: infoDict]; userInfo: infoDict];
// We save the selection
[_selectedItems removeAllObjects];
count = [_selectedRows count];
for (i = 0; i < count; i++)
{
row = [[_selectedRows objectAtIndex: i] intValue];
if ([self itemAtRow: row])
{
[_selectedItems addObject: [self itemAtRow: row]];
}
}
// insert the root element, if necessary otherwise insert the // insert the root element, if necessary otherwise insert the
// actual object. // actual object.
[self _openItem: item]; [self _openItem: item];
@ -618,7 +651,7 @@ static NSImage *unexpandable = nil;
// release the old array // release the old array
if(_items != nil) if(_items != nil)
{ {
RELEASE(_items); DESTROY(_items);
} }
// regenerate the _items array based on the new dictionary // regenerate the _items array based on the new dictionary
@ -721,72 +754,29 @@ static NSImage *unexpandable = nil;
return YES; return YES;
} }
/** /**
* This method returns the number of rows changed in the data source. * We override the super class's method.
*/ */
- (void) noteNumberOfRowsChanged - (void) noteNumberOfRowsChanged
{ {
_numberOfRows = [_items count]; _numberOfRows = [_items count];
/* If we are selecting rows, we have to check that we have no
selected rows below the new end of the table */
if (!_selectingColumns) if (!_selectingColumns)
{ {
int i, count = [_selectedRows count]; int i, count, row;
int row = -1;
/* Check that all selected rows are in the new range of rows */ /* We restore the selection */
[_selectedRows removeAllObjects];
count = [_selectedItems count];
for (i = 0; i < count; i++) for (i = 0; i < count; i++)
{ {
row = [[_selectedRows objectAtIndex: i] intValue]; row = [self rowForItem: [_selectedItems objectAtIndex: i]];
if (row >= _numberOfRows) if (row >= 0 && row < _numberOfRows)
{ {
break; [_selectedRows addObject: [NSNumber numberWithInt: row]];
}
}
if (i < count && row > -1)
{
/* Some of them are outside the table ! - Remove them */
for (; i < count; i++)
{
[_selectedRows removeLastObject];
}
/* Now if the _selectedRow is outside the table, reset it to be
the last selected row (if any) */
if (_selectedRow >= _numberOfRows)
{
if ([_selectedRows count] > 0)
{
_selectedRow = [[_selectedRows lastObject] intValue];
}
else
{
/* Argh - all selected rows were outside the table */
if (_allowsEmptySelection)
{
_selectedRow = -1;
}
else
{
/* We shouldn't allow empty selection - try
selecting the last row */
int lastRow = _numberOfRows - 1;
if (lastRow > -1)
{
[_selectedRows addObject:
[NSNumber numberWithInt: lastRow]];
_selectedRow = lastRow;
}
else
{
/* problem - there are no rows at all */
_selectedRow = -1;
}
}
}
} }
} }
} }
@ -857,7 +847,7 @@ static NSImage *unexpandable = nil;
} }
// create a new empty one // create a new empty one
_items = RETAIN([NSMutableArray array]); _items = [[NSMutableArray alloc] init];
_itemDict = NSCreateMapTable(NSObjectMapKeyCallBacks, _itemDict = NSCreateMapTable(NSObjectMapKeyCallBacks,
NSObjectMapValueCallBacks, NSObjectMapValueCallBacks,
64); 64);
@ -926,14 +916,12 @@ static NSImage *unexpandable = nil;
_itemDict = NSCreateMapTable(NSObjectMapKeyCallBacks, _itemDict = NSCreateMapTable(NSObjectMapKeyCallBacks,
NSObjectMapValueCallBacks, NSObjectMapValueCallBacks,
64); 64);
_items = [NSMutableArray array]; _items = [[NSMutableArray alloc] init];
_expandedItems = [NSMutableArray array]; _expandedItems = [[NSMutableArray alloc] init];
_selectedItems = [[NSMutableArray alloc] init];
_levelOfItems = NSCreateMapTable(NSObjectMapKeyCallBacks, _levelOfItems = NSCreateMapTable(NSObjectMapKeyCallBacks,
NSObjectMapValueCallBacks, NSObjectMapValueCallBacks,
64); 64);
// Retain items
RETAIN(_items);
RETAIN(_expandedItems);
return self; return self;
} }
@ -941,38 +929,37 @@ static NSImage *unexpandable = nil;
- (void) mouseDown: (NSEvent *)theEvent - (void) mouseDown: (NSEvent *)theEvent
{ {
NSPoint location = [theEvent locationInWindow]; NSPoint location = [theEvent locationInWindow];
NSTableColumn *tb;
NSImage *image = nil;
location = [self convertPoint: location fromView: nil]; location = [self convertPoint: location fromView: nil];
_clickedRow = [self rowAtPoint: location]; _clickedRow = [self rowAtPoint: location];
_clickedColumn = [self columnAtPoint: location]; _clickedColumn = [self columnAtPoint: location];
if([self isItemExpanded: [self itemAtRow: _clickedRow]]) if ([_tableColumns objectAtIndex: _clickedColumn] == _outlineTableColumn)
{
image = expanded;
}
else
{
image = collapsed;
}
tb = [_tableColumns objectAtIndex: _clickedColumn];
if(tb == _outlineTableColumn)
{ {
NSImage *image;
int level = [self levelForRow: _clickedRow]; int level = [self levelForRow: _clickedRow];
int position = 0; int position = 0;
if(_indentationMarkerFollowsCell) if ([self isItemExpanded: [self itemAtRow: _clickedRow]])
{
image = expanded;
}
else
{
image = collapsed;
}
if (_indentationMarkerFollowsCell)
{ {
position = _indentationPerLevel * level; position = _indentationPerLevel * level;
} }
position += _columnOrigins[_clickedColumn]; position += _columnOrigins[_clickedColumn];
if(location.x >= position && location.x <= position + [image size].width) if (location.x >= position && location.x <= position + [image size].width)
{ {
if(![self isItemExpanded: [self itemAtRow: _clickedRow]]) if (![self isItemExpanded: [self itemAtRow: _clickedRow]])
{ {
[self expandItem: [self itemAtRow: _clickedRow]]; [self expandItem: [self itemAtRow: _clickedRow]];
} }
@ -980,6 +967,7 @@ static NSImage *unexpandable = nil;
{ {
[self collapseItem: [self itemAtRow: _clickedRow]]; [self collapseItem: [self itemAtRow: _clickedRow]];
} }
return;
} }
} }
@ -1098,9 +1086,6 @@ static NSImage *unexpandable = nil;
imageRect.origin.x = drawingRect.origin.x; imageRect.origin.x = drawingRect.origin.x;
imageRect.origin.y = drawingRect.origin.y; imageRect.origin.y = drawingRect.origin.y;
} }
imageRect.size.width = [image size].width;
imageRect.size.height = [image size].height;
if ([_delegate respondsToSelector: @selector(outlineView:willDisplayOutlineCell:forTableColumn:item:)]) if ([_delegate respondsToSelector: @selector(outlineView:willDisplayOutlineCell:forTableColumn:item:)])
{ {
@ -1109,16 +1094,26 @@ static NSImage *unexpandable = nil;
forTableColumn: tb forTableColumn: tb
item: item]; item: item];
} }
/* Do not indent if the delegate set the image to nil. */
if ( [imageCell image] )
{
imageRect.size.width = [image size].width;
imageRect.size.height = [image size].height;
[imageCell drawWithFrame: imageRect inView: self];
drawingRect.origin.x += indentationFactor + [image size].width + 5;
drawingRect.size.width -= indentationFactor + [image size].width + 5;
}
else
{
drawingRect.origin.x += indentationFactor;
drawingRect.size.width -= indentationFactor;
}
[imageCell drawWithFrame: imageRect inView: self];
drawingRect.origin.x += indentationFactor + [image size].width + 5;
drawingRect.size.width -= indentationFactor + [image size].width + 5;
RELEASE(imageCell); RELEASE(imageCell);
} }
[cell drawWithFrame: drawingRect inView: self]; [cell drawWithFrame: drawingRect inView: self];
} }
} }
} }
@ -1292,11 +1287,6 @@ static NSImage *unexpandable = nil;
return; return;
} }
if ([self isItemExpanded: item] == NO)
{
return;
}
if (childIndex == NSOutlineViewDropOnItemIndex) if (childIndex == NSOutlineViewDropOnItemIndex)
{ {
currentDropRow = row; currentDropRow = row;
@ -1349,7 +1339,7 @@ static NSImage *unexpandable = nil;
- (unsigned int) draggingEntered: (id <NSDraggingInfo>) sender - (unsigned int) draggingEntered: (id <NSDraggingInfo>) sender
{ {
NSLog(@"draggingEntered"); //NSLog(@"draggingEntered");
currentDropRow = -1; currentDropRow = -1;
// currentDropOperation = -1; // currentDropOperation = -1;
oldDropRow = -1; oldDropRow = -1;
@ -1395,9 +1385,9 @@ static NSImage *unexpandable = nil;
if (row > _numberOfRows) if (row > _numberOfRows)
row = _numberOfRows; row = _numberOfRows;
// NSLog(@"horizontalHalfPosition = %d", horizontalHalfPosition); //NSLog(@"horizontalHalfPosition = %d", horizontalHalfPosition);
// NSLog(@"dropRow %d", row); //NSLog(@"dropRow %d", row);
if (row == 0) if (row == 0)
{ {
@ -1416,16 +1406,13 @@ static NSImage *unexpandable = nil;
levelAfter = [self levelForRow: row]; levelAfter = [self levelForRow: row];
} }
//NSLog(@"horizontalHalfPosition = %d", horizontalHalfPosition);
//NSLog(@"level before = %d", levelBefore);
//NSLog(@"level after = %d", levelAfter);
if (levelBefore < levelAfter) if (levelBefore < levelAfter)
levelBefore = levelAfter; levelBefore = levelAfter;
// NSLog(@"horizontalHalfPosition = %d", horizontalHalfPosition);
// NSLog(@"level before = %d", levelBefore);
// NSLog(@"level after = %d", levelAfter);
if ((lastVerticalQuarterPosition != verticalQuarterPosition) if ((lastVerticalQuarterPosition != verticalQuarterPosition)
|| (lastHorizontalHalfPosition != horizontalHalfPosition)) || (lastHorizontalHalfPosition != horizontalHalfPosition))
{ {
@ -1442,8 +1429,8 @@ static NSImage *unexpandable = nil;
lastVerticalQuarterPosition = verticalQuarterPosition; lastVerticalQuarterPosition = verticalQuarterPosition;
lastHorizontalHalfPosition = horizontalHalfPosition; lastHorizontalHalfPosition = horizontalHalfPosition;
// NSLog(@"horizontalHalfPosition = %d", horizontalHalfPosition); //NSLog(@"horizontalHalfPosition = %d", horizontalHalfPosition);
// NSLog(@"verticalQuarterPosition = %d", verticalQuarterPosition); //NSLog(@"verticalQuarterPosition = %d", verticalQuarterPosition);
currentDropRow = row; currentDropRow = row;
currentDropLevel = level; currentDropLevel = level;
@ -1464,7 +1451,7 @@ static NSImage *unexpandable = nil;
j++; j++;
} }
} }
// NSLog(@"found %d (proposed childIndex = %d)", i, j); //NSLog(@"found %d (proposed childIndex = %d)", i, j);
if (i == -1) if (i == -1)
item = nil; item = nil;
else else
@ -1478,14 +1465,14 @@ static NSImage *unexpandable = nil;
if ([_dataSource respondsToSelector: if ([_dataSource respondsToSelector:
@selector(outlineView:validateDrop:proposedItem:proposedChildIndex:)]) @selector(outlineView:validateDrop:proposedItem:proposedChildIndex:)])
{ {
// NSLog(@"currentDropLevel %d, currentDropRow %d", //NSLog(@"currentDropLevel %d, currentDropRow %d",
// currentDropRow, currentDropLevel); //currentDropLevel, currentDropRow);
[_dataSource outlineView: self [_dataSource outlineView: self
validateDrop: sender validateDrop: sender
proposedItem: item proposedItem: item
proposedChildIndex: childIndex]; proposedChildIndex: childIndex];
// NSLog(@"currentDropLevel %d, currentDropRow %d", //NSLog(@"currentDropLevel %d, currentDropRow %d",
// currentDropRow, currentDropLevel); //currentDropLevel, currentDropRow);
} }
if ((currentDropRow != oldDropRow) || (currentDropLevel != oldDropLevel)) if ((currentDropRow != oldDropRow) || (currentDropLevel != oldDropLevel))
@ -1497,8 +1484,9 @@ static NSImage *unexpandable = nil;
[[NSColor darkGrayColor] set]; [[NSColor darkGrayColor] set];
// NSLog(@"currentDropLevel %d, currentDropRow %d", //NSLog(@"currentDropLevel %d, currentDropRow %d",
// currentDropRow, currentDropLevel); //currentDropLevel, currentDropRow);
if (currentDropLevel != NSOutlineViewDropOnItemIndex) if (currentDropLevel != NSOutlineViewDropOnItemIndex)
{ {
if (currentDropRow == 0) if (currentDropRow == 0)
@ -1578,44 +1566,50 @@ static NSImage *unexpandable = nil;
- (BOOL) performDragOperation: (id<NSDraggingInfo>)sender - (BOOL) performDragOperation: (id<NSDraggingInfo>)sender
{ {
NSLog(@"performDragOperation");
if ([_dataSource if ([_dataSource
respondsToSelector: respondsToSelector:
@selector(outlineView:acceptDrop:item:childIndex:)]) @selector(outlineView:acceptDrop:item:childIndex:)])
{ {
id item; id item;
int childIndex; int childIndex;
int i;
int j = 0; if (currentDropLevel == NSOutlineViewDropOnItemIndex)
int lvl;
for ( i = currentDropRow - 1; i >= 0; i-- )
{ {
lvl = [self levelForRow: i]; item = [self itemAtRow: currentDropRow];
if (lvl == currentDropLevel - 1) childIndex = currentDropLevel;
{
break;
}
else if (lvl == currentDropLevel)
{
j++;
}
} }
if (i == -1)
item = nil;
else else
item = [self itemAtRow: i]; {
int lvl, i, j = 0;
childIndex = j;
for ( i = currentDropRow - 1; i >= 0; i-- )
{
lvl = [self levelForRow: i];
if (lvl == currentDropLevel - 1)
{
break;
}
else if (lvl == currentDropLevel)
{
j++;
}
}
if (i == -1)
item = nil;
else
item = [self itemAtRow: i];
childIndex = j;
}
return [_dataSource return [_dataSource
outlineView: self outlineView: self
acceptDrop: sender acceptDrop: sender
item: item item: item
childIndex: childIndex]; childIndex: childIndex];
} }
else
return NO; return NO;
} }
- (BOOL) prepareForDragOperation: (id<NSDraggingInfo>)sender - (BOOL) prepareForDragOperation: (id<NSDraggingInfo>)sender