5
votes

I'm using an NSOutlineView with source list style, and using the view based (rather than cell based) outline view.

I would like to be able to make some rows bold. However, my attempts to change the font (manually in IB, through code in viewForTableColumn:…, or through the Font Bold binding) have so far been ignored.

From this message, it appears that this is because the source list style for NSOutlineView takes over managing the text field's appearance:

I'm guessing that you've hooked up your text field to the textField outlet of the NSTableCellView? If so, I think you might be running into NSTableView's automatic management of appearance for source lists.

Try disconnecting the text field from the textField outlet and see if your custom font sticks.

If I disconnect the textField outlet, the appearance does come under my control, and my emboldening works.

However, now I can't get it to look like the automatic one. By which I mean, when NSOutlineView was managing the text field's appearance, the font was bold and gained a drop shadow when any item was selected, but when I'm managing it manually this is not the case.

Can anyone answer either of these questions:

  1. How can I get the Font Bold binding to work when NSOutlineView is managing the appearance of my text field
  2. If I don't have NSOutlineView manage the appearance of my text field, how can I make it look and behave like it would if I did have it manage it?
2
Any insights gained since the questions was asked? I have a similar problem :(Max Seelemann
I think I gave up and used an icon rather than changing the font. It might be possible, but I never found out how.Amy Worrall

2 Answers

7
votes

I think I found the solution:

NSTableCellView manages the appearance of it's textField outlet by setting the backgroundStyle property on cells of contained controls. Setting this to NSBackgroundStyleDark triggers a special path in NSTextFieldCell which essentially sets an attributedStringValue, changing the text color and adding an shadow via NSShadowAttributeName.

What you could do is two things:

  • Set the backgroundStyle on your own in a custom row or cell view subclass.
  • Use a custom NSTextFieldCell in the cell's text field and change the behavior/drawing.

We did the latter since we needed a different look for a themed (differently colored) table view. The most convenient (albeit surely not most efficient) location we found for this was to override - drawInteriorWithFrame:inView: and modify the cell's attributed string before calling super, restoring the original afterwards:

- (void)drawInteriorWithFrame:(NSRect)cellFrame inView:(NSView *)controlView
{
    NSAttributedString *originalString = self.attributedStringValue;

    // Customize string as you like
    if (/* whatever */)
        [self setAttributedStringValue: /* some string */];

    // Regular drawing
    [super drawInteriorWithFrame:cellFrame inView:controlView];

    // Reset string
    if (self.attributedStringValue != originalString)
        self.attributedStringValue = originalString;
}

In the hope this may help others in similar situations.

0
votes

Not sure if I have missed anything in your question but changing the font using the following works for me. ReminderTableCellView is just a subclass of NSTableCellView with an additional dateField added.

- (NSView *)outlineView:(NSOutlineView *)outlineView viewForTableColumn:(NSTableColumn *)tableColumn item:(id)item {
    //LOG(@"viewForTableColumn called");
    // For the groups, we just return a regular text view.
    if ([_topLevelItems containsObject:item]) {
        //LOG(@" top level");
        NSTableCellView *result = [outlineView makeViewWithIdentifier:@"HeaderCell" owner:self];
        // Uppercase the string value, but don't set anything else. NSOutlineView automatically applies attributes as necessary
        NSString *value = [item uppercaseString];
        [result.textField setStringValue:value];
        //[result.textField setFont:[NSFont systemFontOfSize:[NSFont smallSystemFontSize]]];
        return result;
    } else  {
        //LOG(@" menu item");
        // The cell is setup in IB. The textField and imageView outlets are properly setup.
        // Special attributes are automatically applied by NSTableView/NSOutlineView for the source list
        ReminderTableCellView *result = [outlineView makeViewWithIdentifier:@"DataCell" owner:self];
        if ([item isKindOfClass:[OSTreeNode class]]) {
            [result.textField setFont:[NSFont boldSystemFontOfSize:13]];
            result.textField.stringValue = [item displayName];
            result.dateField.stringValue = [item nextReminderDateAsString];
        }
        else
            result.textField.stringValue = [item description];
        if (_loading)
            result.textField.textColor = [NSColor grayColor];
        else
            result.textField.textColor = [NSColor textColor];
        NSImage *image = [NSImage imageNamed:@"ReminderMenuIcon.png"];
        [image setSize:NSMakeSize(16,16)];
        [result.imageView setImage:image];
        //[result.imageView setImage:nil];
        return result;
    }
}

Resulting view is shown below. Note this is is an NSOutlineView with Source Listing option selected but I can't see why this would'nt work for a normal outlineView.

enter image description here