The combo halves its height — the symbol picker gives up its padding, not its glyph
The owner's evening review superseded the same day's 4:5-ratio pass: 'reduce vertical size of both pickers by 50%, on symbol picker by reducing padding.' ComboFieldMetrics.height goes back to 1.4 em (18pt at the standard body, exactly half the 4:5 pass's 36) — both combos get this for free, since it's shared. width stops being height's own restatement (widthToHeightRatio is gone); it holds the 4:5 pass's pixel figure as its own em number instead, because re-deriving it at the new height would starve the trigger strip and empty the face zone entirely. SymbolComboControl.drawFace now sizes its glyph off the actual face rect it is handed at draw time rather than the pure ComboFieldMetrics.glyphPointSize (removed, along with its doc — it only ever described the control's intrinsic portrait width, not the stretched-wide shape the card sidebar's row actually proposes). No inset — SF Symbols carry their own margins — with the sizing and overshoot-scaling rules split into two pure static functions so the fit is assertable without a live draw. ComboFieldMetricsTests updated for the new figures and the new actual-rect glyph rule; the superseded 4:5-ratio-at-six-sizes test is replaced by one pinning height/width independently and asserting faceWidth stays positive at every size the old test used. Claude-Session: https://claude.ai/code/session_014PtZdPwqZuqEDLc6wZMtEy
This commit is contained in:
@@ -432,15 +432,25 @@ final class SymbolComboControl: ComboFieldControl {
|
||||
/// draw only ever centred vertically and offset from the leading edge by the swatch's own
|
||||
/// horizontal padding, which read as left-aligned once the glyph was more than a sliver narrower
|
||||
/// than the face. The owner's review named this directly ("for symbol picker center the symbol").
|
||||
///
|
||||
/// **Sized off the actual `rect`, not `ComboFieldMetrics.glyphPointSize`, since the evening
|
||||
/// 2026-08-09 review.** That figure (now removed) was a pure derivation from the *intrinsic*
|
||||
/// portrait width, but `sizeThatFits` obeys any finite width SwiftUI proposes, and the card
|
||||
/// sidebar's row proposes real width — so the control renders wide while a glyph pinned at the
|
||||
/// intrinsic figure stayed small, a glyph floating in visible dead space. That space *was* the
|
||||
/// "padding" the owner's "reduce vertical size … on symbol picker by reducing padding" was naming,
|
||||
/// so the fix reads the point size off the rect the face actually receives, via `glyphPointSize(
|
||||
/// forFace:)` and `fittedSize(for:in:)` below — pure functions, not inlined here, so the sizing
|
||||
/// rule is assertable without an actual draw.
|
||||
override func drawFace(in rect: NSRect) {
|
||||
guard rect.width > 0, rect.height > 0 else { return }
|
||||
let name = ItemSymbol.exists(glyphName) ? glyphName : "questionmark.square.dashed"
|
||||
let config = NSImage.SymbolConfiguration(pointSize: metrics.glyphPointSize, weight: .regular)
|
||||
let config = NSImage.SymbolConfiguration(pointSize: Self.glyphPointSize(forFace: rect), weight: .regular)
|
||||
.applying(.init(paletteColors: [glyphTint ?? .labelColor]))
|
||||
guard let image = NSImage(systemSymbolName: name, accessibilityDescription: nil)?
|
||||
.withSymbolConfiguration(config)
|
||||
else { return }
|
||||
let size = image.size
|
||||
let size = Self.fittedSize(for: image.size, in: rect)
|
||||
image.draw(in: NSRect(
|
||||
x: rect.midX - size.width / 2,
|
||||
y: rect.midY - size.height / 2,
|
||||
@@ -448,6 +458,26 @@ final class SymbolComboControl: ComboFieldControl {
|
||||
height: size.height
|
||||
))
|
||||
}
|
||||
|
||||
/// The glyph's target point size for a face rect — no inset subtracted, so this is simply whichever
|
||||
/// of the rect's own two dimensions is smaller. SF Symbols already carry their own internal
|
||||
/// margins, and the owner's evening review asked for the *dead space around* the glyph gone, not a
|
||||
/// second margin layered on top of the system's own.
|
||||
static func glyphPointSize(forFace rect: NSRect) -> CGFloat {
|
||||
min(rect.width, rect.height)
|
||||
}
|
||||
|
||||
/// `imageSize` unchanged, unless it overshoots `rect` on either axis — a symbol configured at
|
||||
/// `glyphPointSize(forFace:)` can still render wider (or, rarely, taller) than that on its long
|
||||
/// axis, since SF Symbols are not all square glyphs. Scaled down proportionally so the drawn glyph
|
||||
/// stays fully inside its face rather than clipping at the edges, and never scaled up: a glyph
|
||||
/// smaller than its face on both axes is left exactly as configured.
|
||||
static func fittedSize(for imageSize: NSSize, in rect: NSRect) -> NSSize {
|
||||
guard rect.width > 0, rect.height > 0 else { return imageSize }
|
||||
let overshoot = max(imageSize.width / rect.width, imageSize.height / rect.height)
|
||||
guard overshoot > 1 else { return imageSize }
|
||||
return NSSize(width: imageSize.width / overshoot, height: imageSize.height / overshoot)
|
||||
}
|
||||
}
|
||||
|
||||
// MARK: - The popover's content
|
||||
|
||||
Reference in New Issue
Block a user