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

NSOutlineView: удалить треугольник раскрытия и отступ

Я использую NSOutlineView для проекта и не могу понять две вещи:

  • Как удалить треугольник раскрытия для узлов дерева. Такие приложения, как iTunes, могут это сделать:

alt text

Есть ли какой-то метод делегата NSOutlineView, который используется для этого? Или это требует подкласса?

  • Как отключить отступы для элементов. Я попытался использовать setIndentationPerLevel: и установить его на 0, а также изменить отступ столбца на 0 в Interface Builder, но он, похоже, не имеет никакого эффекта.
4b9b3361

Ответ 1

Вы попали в нужного человека здесь. Я должен был справиться с этим всего неделю назад.

Удаление треугольника раскрытия: реализуем метод frameOfOutlineCellAtRow: в вашем подклассе NSOutlineView и возвращаем NSZeroRect (только если вы хотите скрыть этот конкретный треугольник строки, конечно.)

- (NSRect)frameOfOutlineCellAtRow:(NSInteger)row {
    return NSZeroRect;
}

Отключить отступы: стандартный макет плана отображает пространство в крайнем левом углу, чтобы нарисовать треугольники, если элемент расширяем. Но вы можете переопределить это для отдельных элементов, указав другой кадр чертежа. Вы также делаете это в своем подклассе, отвечая на это сообщение:

- (NSRect)frameOfCellAtColumn:(NSInteger)column row:(NSInteger)row {
    NSRect superFrame = [super frameOfCellAtColumn:column row:row];


    if ((column == 0) /* && isGroupRow */) {
        return NSMakeRect(0, superFrame.origin.y, [self bounds].size.width, superFrame.size.height);
    }
    return superFrame;
}

Ответ 2

В будущем, самый чистый и самый простой способ скрыть треугольник раскрытия в расширяемых NSOutlineView элементах, реализуя outlineView:shouldShowOutlineCellForItem: метод NSOutlineViewDelegate в вашем делетете:

-(BOOL)outlineView:(NSOutlineView *)outlineView shouldShowOutlineCellForItem:(id)item
{
    // replace this with your logic to determine whether the
    // disclosure triangle should be hidden for a particular item
    return [item hidesDisclosureTriangle];
}

Ответ 3

Мне пришлось объединить два подхода выше, потому что только outlineView:shouldShowOutlineCellForItem: не удаляет пространство, зарезервированное для треугольников раскрытия (оно удаляет сами треугольники).

Делегат:

- (BOOL)outlineView:(NSOutlineView *)outlineView shouldShowOutlineCellForItem:(id)item {
    return NO;
}

Подкласс NSOutlineView:

@implementation ExpandedOutlineView

#define kOutlineCellWidth 11
#define kOutlineMinLeftMargin 6

- (NSRect)frameOfCellAtColumn:(NSInteger)column row:(NSInteger)row {
    NSRect superFrame = [super frameOfCellAtColumn:column row:row];
    if (column == 0) {
        // expand by kOutlineCellWidth to the left to cancel the indent
        CGFloat adjustment = kOutlineCellWidth;

        // ...but be extra defensive because we have no fucking clue what is going on here
        if (superFrame.origin.x - adjustment < kOutlineMinLeftMargin) {
            NSLog(@"%@ adjustment amount is incorrect: adjustment = %f, superFrame = %@, kOutlineMinLeftMargin = %f", NSStringFromClass([self class]), (float)adjustment, NSStringFromRect(superFrame), (float)kOutlineMinLeftMargin);
            adjustment = MAX(0, superFrame.origin.x - kOutlineMinLeftMargin);
        }

        return NSMakeRect(superFrame.origin.x - adjustment, superFrame.origin.y, superFrame.size.width + adjustment, superFrame.size.height);
    }
    return superFrame;
}

@end

Результат:

Screenshot of NSOutlineView with no top-level indentation

Ответ 4

Используйте PXSourceList. Это стиль, который вы ищете с очень приятным апи.

Ответ 5

Я попробовал это в Swift. Это просто работает. Я не знаю, правильно ли это. В Obj-C должен быть эквивалент:

extension NSTableRowView {
    override open func layout() {
        super.layout()
        if let cell = subviews.first as? NSTableCellView, cell.objectValue is <YourHeaderCellClass> {
            subviews.first?.setFrameOrigin(NSZeroPoint)
        }
    }
}

Обязательно верните элемент YourHeaderCellClass в метод источника данных.

func outlineView(_ outlineView: NSOutlineView, child index: Int, ofItem item: Any?) -> Any