A collection of user interface components and drawing routines for building tasteful apps using AppKit.
appkit swift aqua ui mac

Refining the segmented control

+35 -28
+35 -28
Sources/AquaKit/Controls and Views/AquaSegmentedCell.swift
··· 5 5 import AppKit 6 6 7 7 open class AquaSegmentedCell: NSSegmentedCell { 8 + private var highlightedSegment: Int? 9 + 8 10 func swoosh(in rect: NSRect) -> NSBezierPath { 9 11 let d: CGFloat = 20 10 12 let r: CGFloat = 20 ··· 106 108 } 107 109 } 108 110 111 + open func selectionColor(withFrame cellFrame: NSRect, in controlView: NSView) -> NSColor? { 112 + var color = NSColor.selectedControlColor.usingColorSpace(.displayP3)! 113 + var lightGraphite: NSColor { 114 + NSColor.graphiteColor.highlight(withLevel: 0.6)! 115 + } 116 + if color.isGrayscale { 117 + color = lightGraphite 118 + } 119 + if let window = controlView.window, !window.isKeyWindow { 120 + color = lightGraphite 121 + } 122 + color = color.modifyDark { color in 123 + color.withAlphaComponent(0.4) 124 + } 125 + 126 + return color 127 + } 128 + 129 + open override func highlightColor(withFrame cellFrame: NSRect, in controlView: NSView) -> NSColor? { 130 + selectionColor(withFrame: cellFrame, in: controlView).map { color in 131 + color.withAlphaComponent(0.5) 132 + } 133 + } 134 + 109 135 open override func drawSegment(_ segment: Int, inFrame frame: NSRect, with controlView: NSView) { 110 136 if segment == selectedSegment { 111 - var baseColor = NSColor.selectedControlColor.usingColorSpace(.displayP3)! 112 - var lightGraphite: NSColor { 113 - NSColor.graphiteColor.highlight(withLevel: 0.6)! 114 - } 115 - if baseColor.isGrayscale { 116 - baseColor = lightGraphite 117 - } 118 - if let window = controlView.window, !window.isKeyWindow { 119 - baseColor = lightGraphite 120 - } 121 - baseColor = baseColor.modifyDark { color in 122 - color.withAlphaComponent(0.4) 123 - } 137 + selectionColor(withFrame: frame, in: controlView)!.setFill() 138 + frame.fill(using: .multiply) 139 + } 124 140 125 - baseColor.setFill() 141 + if segment == highlightedSegment { 142 + highlightColor(withFrame: frame, in: controlView)!.setFill() 126 143 frame.fill(using: .multiply) 127 144 } 128 145 ··· 133 150 } 134 151 } 135 152 136 - var savedSelectedSegment: Int? 137 - 138 153 func segment(at point: NSPoint, in controlView: NSView) -> Int? { 139 154 for segment in 0..<segmentCount { 140 155 let segmentRect = rect(forSegment: segment, in: controlView.bounds) ··· 147 162 } 148 163 149 164 open override func startTracking(at startPoint: NSPoint, in controlView: NSView) -> Bool { 150 - if let segment = segment(at: startPoint, in: controlView) { 151 - savedSelectedSegment = selectedSegment 152 - selectedSegment = segment 153 - } 154 - 165 + highlightedSegment = segment(at: startPoint, in: controlView) 155 166 return super.startTracking(at: startPoint, in: controlView) 156 167 } 157 168 158 169 open override func continueTracking(last lastPoint: NSPoint, current currentPoint: NSPoint, in controlView: NSView) -> Bool { 159 - if !controlView.bounds.contains(currentPoint), let saved = savedSelectedSegment { 160 - selectedSegment = saved 161 - } else if let segment = segment(at: currentPoint, in: controlView) { 162 - selectedSegment = segment 163 - } 164 - 170 + highlightedSegment = segment(at: currentPoint, in: controlView) 171 + controlView.setNeedsDisplay(controlView.bounds) 165 172 return super.continueTracking(last: lastPoint, current: currentPoint, in: controlView) 166 173 } 167 174 168 175 open override func stopTracking(last lastPoint: NSPoint, current stopPoint: NSPoint, in controlView: NSView, mouseIsUp flag: Bool) { 169 - savedSelectedSegment = nil 176 + highlightedSegment = nil 170 177 super.stopTracking(last: lastPoint, current: stopPoint, in: controlView, mouseIsUp: flag) 171 178 } 172 179 }