Change the font, font color and background color of an NSTableView at runtime using NSFontPanel?

3.1k Views Asked by At

I'd like to enable the user to change the font of an view-based NSTableView. I'm using Cocoa bindings and Core Data. In my test code, I do have a changeFont: method that does get called as soon as I press a font-related key combination, like cmd-I or cmd-B, but I've had no luck so far in changing the actual font of the table view:

- (void)changeFont:(id)sender
{
    NSFont *oldFont = [self.airportTableView font];
    NSFont *newFont = [sender convertFont:oldFont];
    NSLog(@"sender: %@ oldfont: %@, newFont: %@ fontmanager selected: %@, font panel selected: %@",
             sender, oldFont, newFont, [sender selectedFont], [sender convertFont:[sender selectedFont]]);
    [self.airportTableView setFont:newFont];
}

produces the following output:

sender: <NSFontManager: 0x6080000b4580> oldfont: (null), newFont: (null) fontmanager selected: (null), font panel selected: (null)

Even this trivial code:

font = [NSFont boldSystemFontOfSize:12];
[self.airportTableView setFont:font];
NSFont *oldFont = [self.airportTableView font];
NSLog(@"oldfont: %@",oldFont);

only results in:

oldfont: (null)

Can any kind soul provide some code that allows the user to change the font of an NSTableView?

2

There are 2 best solutions below

3
bvogelzang On

You have to set the font of the cell. Not the tableview. Use the following delegate method:

- (NSCell *)tableView:(NSTableView *)tableView dataCellForTableColumn:(NSTableColumn *)tableColumn row:(NSInteger)row {
    NSTextFieldCell *cell = [tableColumn dataCell];
    [cell setFont:[NSFont systemFontOfSize:11]];
    [cell setTextColor: [NSColor lightGrayColor]];

    return cell;
}
0
Mojo66 On

Using the power of the internets, I was able to put together the following code fragment which responds to the NSFontPanel actions for changing font type, font color and background color of an NSTableView:

@interface AppDelegate
{
    NSFont                  *_font;
    NSColor                 *_fontColor;
}

- (void)applicationDidFinishLaunching:(NSNotification *)aNotification {
    [[NSFontManager sharedFontManager] setTarget:self];
    _font      = [NSFont systemFontOfSize:0];
    _fontColor = [NSColor blackColor];
}


- (void)changeFont:(id)sender
{
    _font = [sender convertFont:_font];
    [self.airportTableView reloadData];
}

- (void)setColor:(NSColor *)col forAttribute:(NSString *)attr {
    if ([attr isEqualToString:@"NSDocumentBackgroundColor"]) {
        self.airportTableView.backgroundColor = col;
    } else if ([attr isEqualToString:@"NSColor"]) {
        _fontColor  = col;
        [self.airportTableView reloadData];
    }
}


- (NSView *)tableView:(NSTableView *)tableView viewForTableColumn:(NSTableColumn *)tableColumn row:(NSInteger)row {

    NSTableCellView *cellView   = [tableView makeViewWithIdentifier:[tableColumn identifier] owner:self];
    NSTextField *textField      = [cellView textField];
    textField.font          = _font;
    textField.textColor     = _fontColor;
    return cellView;
}

- (CGFloat)tableView:(NSTableView *)tableView heightOfRow:(NSInteger)row
{
    return _font.boundingRectForFont.size.height + 2.0f;
}

Note the explicit calls to reloadData, otherwise the visible part of the table view won't update. Let me know if there are better solutions.

Also note that -setColor:forAttribute: is undocumented. Apparently, if your class responds to it, -changeAttributes: will not get called.