NSOutlineView: удалить треугольник раскрытия и отступ
Я использую NSOutlineView для проекта и не могу понять две вещи:
- Как удалить треугольник раскрытия для узлов дерева. Такие приложения, как iTunes, могут это сделать:
![alt text]()
Есть ли какой-то метод делегата NSOutlineView, который используется для этого? Или это требует подкласса?
- Как отключить отступы для элементов. Я попытался использовать setIndentationPerLevel: и установить его на 0, а также изменить отступ столбца на 0 в Interface Builder, но он, похоже, не имеет никакого эффекта.
Ответы
Ответ 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