refactor: centralize font-relative UI icon sizing
This commit is contained in:
@@ -0,0 +1,50 @@
|
||||
import AppKit
|
||||
import Testing
|
||||
@testable import Conjure
|
||||
|
||||
@Test @MainActor
|
||||
func iconsScaleWithTypographyWithoutEnlargingSymbolsToApplicationSize() throws {
|
||||
_ = NSApplication.shared
|
||||
let artwork = NSImage(size: NSSize(width: 128, height: 128), flipped: false) { rect in
|
||||
NSColor.white.setFill()
|
||||
rect.fill()
|
||||
return true
|
||||
}
|
||||
var rendered: [(application: CGFloat, symbol: CGFloat)] = []
|
||||
for (textSize, expectedApplicationSize): (CGFloat, CGFloat) in [(14, 22), (28, 44)] {
|
||||
let host = NSView(frame: NSRect(x: 0, y: 0, width: 100, height: 100))
|
||||
let icon = IconView(font: .systemFont(ofSize: textSize, weight: .medium))
|
||||
host.addSubview(icon)
|
||||
NSLayoutConstraint.activate([
|
||||
icon.centerXAnchor.constraint(equalTo: host.centerXAnchor),
|
||||
icon.centerYAnchor.constraint(equalTo: host.centerYAnchor)
|
||||
])
|
||||
host.layoutSubtreeIfNeeded()
|
||||
#expect(icon.frame.size == NSSize(width: expectedApplicationSize, height: expectedApplicationSize))
|
||||
func artworkHeight() throws -> CGFloat {
|
||||
let bitmap = try #require(icon.bitmapImageRepForCachingDisplay(in: icon.bounds))
|
||||
icon.cacheDisplay(in: icon.bounds, to: bitmap)
|
||||
var first = bitmap.pixelsHigh
|
||||
var last = -1
|
||||
for y in 0..<bitmap.pixelsHigh {
|
||||
for x in 0..<bitmap.pixelsWide where (bitmap.colorAt(x: x, y: y)?.alphaComponent ?? 0) > 0.5 {
|
||||
first = min(first, y)
|
||||
last = max(last, y)
|
||||
}
|
||||
}
|
||||
return CGFloat(last - first + 1) * icon.bounds.height / CGFloat(bitmap.pixelsHigh)
|
||||
}
|
||||
icon.image = artwork
|
||||
let applicationHeight = try artworkHeight()
|
||||
// Reuse the same slot, as launcher cells do when switching to command/calculator results.
|
||||
icon.image = NSImage(systemSymbolName: "stop.circle", accessibilityDescription: nil)
|
||||
let symbolHeight = try artworkHeight()
|
||||
#expect(applicationHeight == expectedApplicationSize)
|
||||
#expect(symbolHeight > textSize * 0.75 && symbolHeight <= textSize)
|
||||
icon.image = artwork
|
||||
#expect(try artworkHeight() == applicationHeight)
|
||||
rendered.append((applicationHeight, symbolHeight))
|
||||
}
|
||||
#expect(rendered[1].application == rendered[0].application * 2)
|
||||
#expect(abs(rendered[1].symbol - rendered[0].symbol * 2) <= 1)
|
||||
}
|
||||
Reference in New Issue
Block a user