Ответ 1
В Swift 3.1 это все, что вам нужно:
import Cocoa
class GridClipTableView: NSTableView {
override func drawGrid(inClipRect clipRect: NSRect) { }
}
Как рисовать линии сетки в NSTableView только для заполненных строк? Когда я устанавливаю маску стиля сетки в NSTableViewSolidHorizontalGridStyleMask, она рисует линии сетки для всех строк, заполненных или нет.
Я ищу несколько примеров кода для этого.
В Swift 3.1 это все, что вам нужно:
import Cocoa
class GridClipTableView: NSTableView {
override func drawGrid(inClipRect clipRect: NSRect) { }
}
То, что я считаю лучшим для меня до сих пор, - это следующий код. Просто обманите исходный код рисования сетки, чтобы рисовать только по заполняемым строкам.
Подкласс NSTableView, если необходимо, и переопределите drawGridInClipRect: (NSRect) clipRect следующим образом:
- (void)drawGridInClipRect:(NSRect)clipRect
{
NSRect lastRowRect = [self rectOfRow:[self numberOfRows]-1];
NSRect myClipRect = NSMakeRect(0, 0, lastRowRect.size.width, NSMaxY(lastRowRect));
NSRect finalClipRect = NSIntersectionRect(clipRect, myClipRect);
[super drawGridInClipRect:finalClipRect];
}
Я думаю, вам придется подклассом NSTableView
и переопределить drawRow:clipRect:
. Другая возможность - переопределить drawGridInClipRect:
, но это немного более громоздко, потому что вам придется вручную выделять строки.
Это поможет вам двигаться в правильном направлении:
- (void)drawRow:(NSInteger)rowIndex clipRect:(NSRect)clipRect {
// First do the default drawing
[super drawRow:rowIndex clipRect:clipRect];
// Check if there content in any of the cells in this row
BOOL doesHaveContent = NO;
int numCols = [self numberOfColumns];
int colIndex;
for( colIndex = 0; colIndex < numCols; colIndex++ ){
NSCell * cell = [self preparedCellAtColumn:colIndex
row:rowIndex];
if( [cell objectValue] != nil ){
doesHaveContent = YES;
break;
}
}
if( doesHaveContent ){
NSRect rowRect = [self rectOfRow:rowIndex];
NSBezierPath * gridPath = [NSBezierPath bezierPath];
// Ignoring clipRect because this isn't a lot of drawing
[gridPath moveToPoint:rowRect.origin];
[gridPath lineToPoint:NSMakePoint(rowRect.origin.x + rowRect.size.width,
rowRect.origin.y)];
[gridPath moveToPoint:NSMakePoint(rowRect.origin.x,
rowRect.origin.y + rowRect.size.height)];
[gridPath lineToPoint:NSMakePoint(rowRect.origin.x + rowRect.size.width,
rowRect.origin.y + rowRect.size.height)];
[myGridColor set];
[gridPath stroke];
// You could also just do:
// [myGridColor set];
// [[NSBezierPath bezierPathWithRect:rowRect] stroke];
}
}
Еще одна возможность - создать пользовательский NSCell
; каждая клетка могла бы нарисовать специальную рамку вокруг себя, если бы имела контент. Это не нарисовало бы линию во всей строке, хотя, если бы в ячейке были несколько ячеек.
По какой-то причине ни одно из перечисленных здесь решений не сработало. Вместо этого я сделал:
NSTableView
и переопределить rectOfColumn:
(см. ниже).В моих тестах это работало с macOS 10.9 до 10.15.
- (NSRect)rectOfColumn:(NSInteger)column
{
NSRect value = [super rectOfColumn:column];
NSInteger numberOfRows = [self numberOfRows];
if (numberOfRows == 0) {
value.size.height = 0;
} else {
NSRect firstRect = [self rectOfRow:0];
NSRect lastRect = [self rectOfRow:numberOfRows - 1];
value.size.height = NSMaxY(lastRect) - NSMinY(firstRect);
}
return value;
}