2018-02-20 00:56:15 +01:00
|
|
|
|
//
|
|
|
|
|
// SingleLineTextFieldSizer.swift
|
2018-08-29 07:18:24 +02:00
|
|
|
|
// NetNewsWire
|
2018-02-20 00:56:15 +01:00
|
|
|
|
//
|
|
|
|
|
// Created by Brent Simmons on 2/19/18.
|
|
|
|
|
// Copyright © 2018 Ranchero Software. All rights reserved.
|
|
|
|
|
//
|
|
|
|
|
|
|
|
|
|
import AppKit
|
|
|
|
|
|
|
|
|
|
// Get the size of an NSTextField configured with a specific font with a specific size.
|
|
|
|
|
// Uses a cache.
|
2018-02-20 05:28:00 +01:00
|
|
|
|
// Main thready only.
|
2018-02-20 00:56:15 +01:00
|
|
|
|
|
|
|
|
|
final class SingleLineTextFieldSizer {
|
|
|
|
|
|
|
|
|
|
let font: NSFont
|
|
|
|
|
private let textField: NSTextField
|
|
|
|
|
private var cache = [String: NSSize]()
|
|
|
|
|
|
2019-06-10 01:03:08 +02:00
|
|
|
|
/// Get the NSTextField size for text, given a font.
|
|
|
|
|
static func size(for text: String, font: NSFont) -> NSSize {
|
|
|
|
|
return sizer(for: font).size(for: text)
|
|
|
|
|
}
|
2018-02-20 00:56:15 +01:00
|
|
|
|
|
2019-06-10 01:03:08 +02:00
|
|
|
|
init(font: NSFont) {
|
2018-02-20 00:56:15 +01:00
|
|
|
|
self.textField = NSTextField(labelWithString: "")
|
|
|
|
|
self.textField.font = font
|
|
|
|
|
self.font = font
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
func size(for text: String) -> NSSize {
|
|
|
|
|
if let cachedSize = cache[text] {
|
|
|
|
|
return cachedSize
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
textField.stringValue = text
|
|
|
|
|
var calculatedSize = textField.fittingSize
|
|
|
|
|
calculatedSize.height = ceil(calculatedSize.height)
|
|
|
|
|
calculatedSize.width = ceil(calculatedSize.width)
|
|
|
|
|
|
|
|
|
|
cache[text] = calculatedSize
|
|
|
|
|
return calculatedSize
|
|
|
|
|
}
|
|
|
|
|
|
2019-06-10 01:03:08 +02:00
|
|
|
|
static private var sizers = [SingleLineTextFieldSizer]()
|
|
|
|
|
|
|
|
|
|
static private func sizer(for font: NSFont) -> SingleLineTextFieldSizer {
|
|
|
|
|
// We used to use an [NSFont: SingleLineTextFieldSizer] dictionary —
|
|
|
|
|
// until, in 10.14.5, we started getting crashes with the message:
|
|
|
|
|
// Fatal error: Duplicate keys of type 'NSFont' were found in a Dictionary.
|
|
|
|
|
// This usually means either that the type violates Hashable's requirements, or
|
|
|
|
|
// that members of such a dictionary were mutated after insertion.
|
|
|
|
|
// We use just an array of sizers now — which is totally fine,
|
|
|
|
|
// because there’s only going to be like three of them.
|
2020-04-05 20:06:24 +02:00
|
|
|
|
if let cachedSizer = sizers.first(where: { $0.font == font }) {
|
2018-02-20 00:56:15 +01:00
|
|
|
|
return cachedSizer
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
let newSizer = SingleLineTextFieldSizer(font: font)
|
2019-06-10 01:03:08 +02:00
|
|
|
|
sizers.append(newSizer)
|
2018-02-20 00:56:15 +01:00
|
|
|
|
|
|
|
|
|
return newSizer
|
|
|
|
|
}
|
|
|
|
|
}
|