Подтвердить что ты не робот

Нарисуйте линии сетки в NSTableView только для заполненных строк?

Как рисовать линии сетки в NSTableView только для заполненных строк? Когда я устанавливаю маску стиля сетки в NSTableViewSolidHorizontalGridStyleMask, она рисует линии сетки для всех строк, заполненных или нет.

Я ищу несколько примеров кода для этого.

4b9b3361

Ответ 1

В Swift 3.1 это все, что вам нужно:

import Cocoa

class GridClipTableView: NSTableView {

    override func drawGrid(inClipRect clipRect: NSRect) { }

}

Ответ 2

То, что я считаю лучшим для меня до сих пор, - это следующий код. Просто обманите исходный код рисования сетки, чтобы рисовать только по заполняемым строкам.

Подкласс 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];
}

Ответ 3

Я думаю, вам придется подклассом 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; каждая клетка могла бы нарисовать специальную рамку вокруг себя, если бы имела контент. Это не нарисовало бы линию во всей строке, хотя, если бы в ячейке были несколько ячеек.

Ответ 4

По какой-то причине ни одно из перечисленных здесь решений не сработало. Вместо этого я сделал:

  1. Подкласс NSTableView и переопределить rectOfColumn: (см. ниже).
  2. Включите поддержку слоев для табличного представления, его представления клипа и его представления прокрутки (это необходимо для работы этого решения).

В моих тестах это работало с 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;
}