我有一个关于在NSTableViews / NSOutlineViews中实现一些特定行为的问题。
我正在尝试实现的目标:
我正在尝试创建一个模仿Photoshop图层面板行为的NSOutlineView(除了“图层”列是分层的)。我的outlineview是一个3列表,带有“Layer”列,“Visbility”列和“Lock”列。我已将“visibility”和“lock”列实现为NSImageCells,将“layer”列实现为自定义文本和图像单元格。
具体来说,这是我正在努力实施的行为:
就像Photoshop一样,用户应该能够点击可见性(眼球)图标并向上或向下拖动到不同的行,以根据可见性的“可见性”打开另一行可见性。第一行单击...确切地说Photoshop是如何隐藏和显示图层的。请注意,当表中有许多行时,应支持自动滚动。
就像Photoshop一样,当选择“图层”列中的一行或多行时,可见性/锁定列不应该在它们后面有高亮条(也就是说,行高亮显示不应该通过它们的列)。
在“可见性”或“锁定”列中单击和/或拖动不应更改表格的选择...仅显示上述状态。
我一直在撞墙,试图让它上班一周。我已经阅读过控制器&单元编程指南,表视图编程指南,NSCell的类引用,NSActionCell,NSTableView,NSControl,NSOutlineView,以及NSOutlineViewDelegate和NSOutlineViewDataSource的协议引用......并且整个星期都在尝试不同的方法...而我只是没有搞清楚这个。
有人能引导我朝着正确的方向前进吗?在此先感谢您的帮助!
答案 0 :(得分:2)
通过一些额外的网络搜索和实验,我可以回答我自己的大多数问题:
突出显示NSOUTLINEVIEW中的第一列
通过继承NSOutlineView并实现
,我能够在第一列的选定行上显示选择突出显示- (void)highlightSelectionInClipRect:(NSRect)clipRect
{
NSRange visibleRowIndexes = [self rowsInRect:clipRect];
NSIndexSet *selectedRowIndexes = [self selectedRowIndexes];
NSInteger currentRow = visibleRowIndexes.location;
NSInteger lastRow = currentRow + visibleRowIndexes.length;
NSColor *highlightColor;
//Determine color of selection bar based on key/main/first responder status.
if (self == [[self window] firstResponder] && [[self window] isMainWindow] && [[self window] isKeyWindow]) {
highlightColor = [NSColor colorWithDeviceRed:0.0 green:0.0 blue:0.3 alpha:1.0];
} else
highlightColor = [NSColor lightGrayColor];
}
[highlightColor setFill];
//Get the Rect of only the name column. This is the only column that will be highlighted.
//We'll intersect this rect with the row rect for the area to fill in.
NSInteger nameColumn = [self columnWithIdentifier:@"name"];
NSRect nameColumnRect = [self rectOfColumn:nameColumn];
while (currentRow < lastRow) {
if ([selectedRowIndexes containsIndex:currentRow]) {
NSRect drawRect = NSIntersectionRect([self rectOfRow:currentRow], nameColumnRect);
NSRectFill(drawRect);
}
currentRow++;
}
}
重要的是要注意我必须覆盖我的自定义NSCell子类的drawInteriorWithFrame:inView:方法,以防止它绘制标准高亮,如下所示:
-(void) drawInteriorWithFrame:(NSRect)cellFrame inView:(NSView *)controlView
{
//do drawing here...don't call super.
}
所以对于部分问题有一个解决方案。如果这不是“正确的”方式,请告诉我:)。
在VIS / LOCK列中点击/拖拽不应改变选择 我现在已经确定我应该在
中这样做-(NSIndexSet *) outlineView:(NSOutlineView *)outlineView selectionIndexesForProposedSelection:(NSIndexSet *)proposedSelectionIndexes
方法。如果我处于源于可见性或锁定列的拖动的中间,我只返回当前的selectedRows以保持选择相同。我还没有实现这个,但是一旦我解决了最后的问题就应该很容易(见下文)。
在可见度/锁定列中拖拽或降低状态以改变其状态
我真的很接近这个。在我的自定义NSCell中,我已经覆盖了以下三种方法:-(BOOL) startTrackingAt:(NSPoint)startPoint inView:(NSView *)controlView
-(BOOL) continueTracking:(NSPoint)lastPoint at:(NSPoint)currentPoint inView:(NSView *)controlView
-(void) stopTracking:(NSPoint) lastPoint at:(NSPoint)stopPoint inView:(NSView *)controlView mouseIsUp:(BOOL)flag
我遇到了我的最后一个问题,这就是:我需要知道我何时进入拖动操作以及拖动操作何时完成。我有两种方法可以做到这一点:
如果我不覆盖
+(BOOL) prefersTrackingUntilMouseUp
在我的NSCell子类中(所以它返回默认的NO值),然后我每次离开单元格时都会收到一个stopTracking:at:inView:mouseIsUp:message,并在拖动操作期间转到下一个 /em>...这意味着我无法使用该方法来确定何时完成拖动操作。
如果我做覆盖
+(BOOL) prefersTrackingUntilMouseUp
并返回YES,我得到一个stopTracking:...只在鼠标上调用,这很好......但问题是该表似乎没有更新mouseDown上的单元格的UI或我在电池内拖动。例如,在startTracking:...方法中,如果我将单元格的objectValue设置为nil(以便不再显示其图像),直到鼠标按钮返回或光标离开时才会看到更新细胞。 (当prefersTrackingUntilMouseUp返回NO时,立即更新)。
所以我需要能够立即更新单元格的UI(在mouseDown上),但也有办法知道拖动操作何时完成。这是拼图的最后一部分。有人可以帮忙吗?