How can I set NSTableView column to use monospaced numbers?
Asked Answered
I

4

7

El Capitan introduced San Francisco system font, which has proportional digits by default.

This makes numbers in table columns look jagged and hard to compare:

all are 6-digit numbers

I'd like to enable fixed-width numbers option for the font, but keep using the default system font and keep backwards compatibility with earlier versions of OS X.

In Interface Builder selecting font > Font Panel > Typography > Monospaced Numbers does not affect the font (XIB file remains unchanged).

useless panel

What's the right way to set monospaced numbers in OS X table view columns? (I suspect IB is unusable for this, so a programmatic solution is OK too).

Ingvar answered 27/11, 2015 at 9:46 Comment(3)
how are you populating those cells? bindings or are you using something from NSTableViewDataSource (e.g. 'tableView:objectValueForTableColumn:row:')Louls
@MichaelDautermann I'm using bindings with NSArrayControllerIngvar
I think Johan's answer should be accepted because it doesn't use private API.Condition
V
11

Just use +[NSFont monospacedDigitSystemFontOfSize:weight:] when it's available. It's new in 10.11, but still not in the NSFont docs. It's in the headers and was discussed in the WWDC 2015 videos. So, something like:

if ([NSFont respondsToSelector:@selector(monospacedDigitSystemFontOfSize:weight:)])
    textField.font = [NSFont monospacedDigitSystemFontOfSize:textField.font.pointSize weight:NSFontWeightRegular];
Victorie answered 29/11, 2015 at 13:38 Comment(0)
S
5

Here's a Swift extension that gives you a monospaced digits font with high legibility.

extension NSFont {
    var legibleNumbersVariant: NSFont {
        let features = [
            [NSFontFeatureTypeIdentifierKey: kNumberSpacingType,
             NSFontFeatureSelectorIdentifierKey: kMonospacedNumbersSelector],
            [NSFontFeatureTypeIdentifierKey: kStylisticAlternativesType,
             NSFontFeatureSelectorIdentifierKey: kStylisticAltSixOnSelector]
        ]
        let descriptor = fontDescriptor.addingAttributes([NSFontFeatureSettingsAttribute: features])
        return NSFont(descriptor: descriptor, size: pointSize) ?? self
    }
}

Comparison

Styria answered 7/2, 2017 at 15:29 Comment(0)
R
4

Treat the following as pseudo-code, quickly done, not throughly tested, etc.

Given an NSFont which represents a font which has monospaced numbers as a feature the following method will produce another NSFont with that feature selected:

- (NSFont *) newMonospaceNumbersFont:(NSFont *)font
{
   CTFontDescriptorRef origDesc = CTFontCopyFontDescriptor((__bridge CTFontRef)font);
   CTFontDescriptorRef monoDesc = CTFontDescriptorCreateCopyWithFeature(origDesc, (__bridge CFNumberRef)@(kNumberSpacingType), (__bridge CFNumberRef)@(kMonospacedNumbersSelector));
   CFRelease(origDesc);
   CTFontRef monoFont = CTFontCreateWithFontDescriptor(monoDesc, font.pointSize, NULL);
   CFRelease(monoDesc);
   return (__bridge_transfer NSFont *)monoFont;
}

You can use this, say, to take the current font of a UI element and convert it to one with monospace numbers.

HTH

Variant for Swift

Assuming res is the NSTextField with the number to display:

let origDesc = CTFontCopyFontDescriptor(res.font!)
let monoDesc = CTFontDescriptorCreateCopyWithFeature(origDesc, kNumberSpacingType, kMonospacedNumbersSelector)
let monoFont = CTFontCreateWithFontDescriptor(monoDesc, res.font!.pointSize, nil)
res.font = monoFont
Rubbish answered 28/11, 2015 at 20:10 Comment(0)
L
2

In my experience, the "font panel" functionality isn't well defined and I usually just ignore it whenever I'm messing with a XIB or Storyboard.

What should work is to go back to that "Font" attribute in the Text Field Cell attributes inspector and then select "User Fixed Pitch" from the Font drop down menu (the choice should automatically default to size 11).

Choose your font this way

If you bump the font size up a point, it'll magically switch to Monaco (the default fixed width font).

Louls answered 28/11, 2015 at 15:30 Comment(1)
I'm looking for a solution that uses San Francisco (with mono numbers option)/Helvetica/Lucida Grande appropriately for the system, and using Monaco doesn't cut it.Ingvar

© 2022 - 2024 — McMap. All rights reserved.