Skip to content

Commit

Permalink
Merge pull request #394 from openvanilla/dev/legacy-ui-on-older-os
Browse files Browse the repository at this point in the history
Uses the legacy UI on macOS versions before Big Sur
  • Loading branch information
zonble authored Dec 4, 2023
2 parents 217fcfc + d9f11c5 commit bddbb50
Show file tree
Hide file tree
Showing 2 changed files with 147 additions and 52 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -91,16 +91,30 @@ fileprivate class HorizontalCandidateView: NSView {
}

func set(keyLabelFont labelFont: NSFont, candidateFont: NSFont) {
var bigSurOrHigher = false
if #available(macOS 10.16, *) {
bigSurOrHigher = true
}

let paraStyle = NSMutableParagraphStyle()
paraStyle.setParagraphStyle(NSParagraphStyle.default)
paraStyle.alignment = .center

keyLabelAttrDict = [.font: labelFont,
.paragraphStyle: paraStyle,
.foregroundColor: NSColor.labelColor]
candidateAttrDict = [.font: candidateFont,
.paragraphStyle: paraStyle,
.foregroundColor: NSColor.labelColor]
if bigSurOrHigher {
keyLabelAttrDict = [.font: labelFont,
.paragraphStyle: paraStyle,
.foregroundColor: NSColor.labelColor]
candidateAttrDict = [.font: candidateFont,
.paragraphStyle: paraStyle,
.foregroundColor: NSColor.labelColor]
} else {
keyLabelAttrDict = [.font: labelFont,
.paragraphStyle: paraStyle,
.foregroundColor: NSColor.black]
candidateAttrDict = [.font: candidateFont,
.paragraphStyle: paraStyle,
.foregroundColor: NSColor.textColor]
}

let labelFontSize = labelFont.pointSize
let candidateFontSize = candidateFont.pointSize
Expand All @@ -112,10 +126,21 @@ fileprivate class HorizontalCandidateView: NSView {
}

override func draw(_ dirtyRect: NSRect) {
let lightGray = NSColor(deviceWhite: 0.8, alpha: 1.0)
var bigSurOrHigher = false
if #available(macOS 10.16, *) {
bigSurOrHigher = true
}

let backgroundColor = NSColor.controlBackgroundColor
let lightGray = NSColor(deviceWhite: 0.8, alpha: 1.0)
let darkGray = NSColor(deviceWhite: 0.7, alpha: 1.0)
let bounds = self.bounds

if !bigSurOrHigher {
backgroundColor.setFill()
NSBezierPath.fill(bounds)
}

if #available(macOS 10.14, *) {
NSColor.separatorColor.setStroke()
} else {
Expand All @@ -137,25 +162,40 @@ fileprivate class HorizontalCandidateView: NSView {
let currentWidth = elementWidths[index]
let labelRect = NSRect(x: accuWidth, y: tooltipSize.height, width: currentWidth, height: keyLabelHeight)
let candidateRect = NSRect(x: accuWidth, y: tooltipSize.height + keyLabelHeight + 1.0, width: currentWidth, height: candidateTextHeight)

var activeKeyLabelAttrDict = keyLabelAttrDict
if index == highlightedIndex {
NSColor.selectedControlColor.setFill()
if bigSurOrHigher {
if index == highlightedIndex {
NSColor.selectedControlColor.setFill()
NSBezierPath.fill(labelRect)
activeKeyLabelAttrDict[.foregroundColor] = NSColor.selectedControlTextColor
}
} else {
(index == highlightedIndex ? darkGray : lightGray).setFill()
NSBezierPath.fill(labelRect)
activeKeyLabelAttrDict[.foregroundColor] = NSColor.selectedControlTextColor
}
(keyLabels[index] as NSString).draw(in: labelRect, withAttributes: activeKeyLabelAttrDict)

var activeCandidateAttr = candidateAttrDict
if index == highlightedIndex {
if #available(macOS 10.14, *) {
NSColor.controlAccentColor.setFill()
if bigSurOrHigher {
if index == highlightedIndex {
if #available(macOS 10.14, *) {
NSColor.controlAccentColor.setFill()
} else {
NSColor.selectedControlColor.setFill()
}
NSBezierPath.fill(candidateRect)
activeCandidateAttr[.foregroundColor] = NSColor.white
}
} else {
if index == highlightedIndex {
NSColor.selectedTextBackgroundColor.setFill()
activeCandidateAttr[.foregroundColor] = NSColor.selectedTextColor
} else {
NSColor.selectedControlColor.setFill()
backgroundColor.setFill()
}
NSBezierPath.fill(candidateRect)
activeCandidateAttr[.foregroundColor] = NSColor.white
}

(displayedCandidates[index] as NSString).draw(in: candidateRect, withAttributes: activeCandidateAttr)
accuWidth += currentWidth + 1.0
}
Expand Down Expand Up @@ -217,24 +257,28 @@ public class HorizontalCandidateController: CandidateController {
private var currentPage: UInt = 0

public init() {
var bigSurOrHigher = false
if #available(macOS 10.16, *) {
bigSurOrHigher = true
}

var contentRect = NSRect(x: 128.0, y: 128.0, width: 0.0, height: 0.0)
let styleMask: NSWindow.StyleMask = [.borderless, .nonactivatingPanel]
let panel = NSPanel(contentRect: contentRect, styleMask: styleMask, backing: .buffered, defer: false)
panel.level = NSWindow.Level(Int(kCGPopUpMenuWindowLevel) + 1)
panel.hasShadow = true
panel.backgroundColor = .clear
panel.isOpaque = false

let effect = NSVisualEffectView(frame: NSRect(x: 0, y: 0, width: 0, height: 0))
effect.blendingMode = .behindWindow
if #available(macOS 10.14, *) {
if bigSurOrHigher {
panel.backgroundColor = .clear
panel.isOpaque = false

let effect = NSVisualEffectView(frame: NSRect(x: 0, y: 0, width: 0, height: 0))
effect.blendingMode = .behindWindow
effect.material = .popover
} else {
effect.material = .appearanceBased
effect.state = .active
effect.maskImage = .mask(withCornerRadius: 4)
panel.contentView = effect
}
effect.state = .active
effect.maskImage = .mask(withCornerRadius: 4)
panel.contentView = effect

contentRect.origin = NSPoint.zero
candidateView = HorizontalCandidateView(frame: contentRect)
Expand All @@ -244,14 +288,22 @@ public class HorizontalCandidateController: CandidateController {
nextPageButton = NSButton(frame: contentRect)
nextPageButton.setButtonType(.momentaryLight)
nextPageButton.bezelStyle = .smallSquare
nextPageButton.isBordered = false
nextPageButton.attributedTitle = "»".withColor(.controlTextColor)
if bigSurOrHigher {
nextPageButton.isBordered = false
nextPageButton.attributedTitle = "»".withColor(.controlTextColor)
} else {
nextPageButton.title = "»"
}

prevPageButton = NSButton(frame: contentRect)
prevPageButton.setButtonType(.momentaryLight)
prevPageButton.bezelStyle = .smallSquare
prevPageButton.isBordered = false
prevPageButton.attributedTitle = "«".withColor(.controlTextColor)
if bigSurOrHigher {
prevPageButton.isBordered = false
prevPageButton.attributedTitle = "«".withColor(.controlTextColor)
} else {
prevPageButton.title = "«"
}

panel.contentView?.addSubview(nextPageButton)
panel.contentView?.addSubview(prevPageButton)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -34,36 +34,62 @@ fileprivate class VerticalKeyLabelStripView: NSView {
}

override func draw(_ dirtyRect: NSRect) {
var bigSurOrHigher = false
if #available(macOS 10.16, *) {
bigSurOrHigher = true
}

let bounds = self.bounds
if !bigSurOrHigher {
NSColor.white.setFill()
NSBezierPath.fill(bounds)
}

let count = UInt(keyLabels.count)
if count == 0 {
return
}
let cellHeight: CGFloat = bounds.size.height / CGFloat(count)
let black = NSColor.black
let darkGray = NSColor(deviceWhite: 0.7, alpha: 1.0)
let lightGray = NSColor(deviceWhite: 0.8, alpha: 1.0)

let paraStyle = NSMutableParagraphStyle()
paraStyle.setParagraphStyle(NSParagraphStyle.default)
paraStyle.alignment = .center

let textAttr: [NSAttributedString.Key: AnyObject] = [
.font: keyLabelFont,
.foregroundColor: NSColor.labelColor,
.paragraphStyle: paraStyle]
let textAttr: [NSAttributedString.Key: AnyObject] =
bigSurOrHigher ? [
.font: keyLabelFont,
.foregroundColor: NSColor.labelColor,
.paragraphStyle: paraStyle]
: [
.font: keyLabelFont,
.foregroundColor: black,
.paragraphStyle: paraStyle]
let textAttrHighlighted: [NSAttributedString.Key: AnyObject] = [
.font: keyLabelFont,
.foregroundColor: NSColor.selectedControlTextColor,
.paragraphStyle: paraStyle]
for index in 0..<count {
let textRect = NSRect(x: 0.0, y: CGFloat(index) * cellHeight + labelOffsetY, width: bounds.size.width, height: cellHeight - labelOffsetY)
let cellRect = NSRect(x: 0.0, y: CGFloat(index) * cellHeight, width: bounds.size.width, height: cellHeight)
var cellRect = NSRect(x: 0.0, y: CGFloat(index) * cellHeight, width: bounds.size.width, height: cellHeight)
if !bigSurOrHigher && index + 1 < count {
cellRect.size.height -= 1.0
}

if index == highlightedIndex {
NSColor.selectedControlColor.setFill()
let text = keyLabels[Int(index)]
if bigSurOrHigher {
if index == highlightedIndex {
NSColor.selectedControlColor.setFill()
NSBezierPath.fill(cellRect)
}
(text as NSString).draw(in: textRect, withAttributes: (index == highlightedIndex) ? textAttrHighlighted : textAttr)
} else {
(index == highlightedIndex ? darkGray : lightGray).setFill()
NSBezierPath.fill(cellRect)
(text as NSString).draw(in: textRect, withAttributes: textAttr)
}
let text = keyLabels[Int(index)]
(text as NSString).draw(in: textRect, withAttributes: (index == highlightedIndex) ? textAttrHighlighted : textAttr)
}
}
}
Expand All @@ -73,6 +99,14 @@ private let kCandidateTextLeftMargin: CGFloat = 8.0
private let kCandidateTextPaddingWithMandatedTableViewPadding: CGFloat = 18.0
private let kCandidateTextLeftMarginWithMandatedTableViewPadding: CGFloat = 0.0

// Only used in macOS 10.15 (Catalina) or lower
private class BackgroundView: NSView {
override func draw(_ dirtyRect: NSRect) {
NSColor.windowBackgroundColor.setFill()
NSBezierPath.fill(self.bounds)
}
}

@objc(VTVerticalCandidateController)
public class VerticalCandidateController: CandidateController {
private var keyLabelStripView: VerticalKeyLabelStripView
Expand All @@ -86,24 +120,30 @@ public class VerticalCandidateController: CandidateController {
private var tooltipView: NSTextField

public init() {
var bigSurOrHigher = false
if #available(macOS 10.16, *) {
bigSurOrHigher = true
}

var contentRect = NSRect(x: 128.0, y: 128.0, width: 0.0, height: 0.0)
let styleMask: NSWindow.StyleMask = [.borderless, .nonactivatingPanel]
let panel = NSPanel(contentRect: contentRect, styleMask: styleMask, backing: .buffered, defer: false)
panel.level = NSWindow.Level(Int(kCGPopUpMenuWindowLevel) + 1)
panel.hasShadow = true
panel.backgroundColor = .clear
panel.isOpaque = false

let effect = NSVisualEffectView(frame: NSRect(x: 0, y: 0, width: 0, height: 0))
effect.blendingMode = .behindWindow
if #available(macOS 10.14, *) {
if bigSurOrHigher {
panel.backgroundColor = .clear
panel.isOpaque = false

let effect = NSVisualEffectView(frame: NSRect(x: 0, y: 0, width: 0, height: 0))
effect.blendingMode = .behindWindow
effect.material = .popover
effect.state = .active
effect.maskImage = .mask(withCornerRadius: 4)
panel.contentView = effect
} else {
effect.material = .appearanceBased
panel.contentView = BackgroundView()
}
effect.state = .active
effect.maskImage = .mask(withCornerRadius: 4)
panel.contentView = effect

tooltipView = NSTextField(frame: NSRect.zero)
tooltipView.isEditable = false
Expand All @@ -123,9 +163,11 @@ public class VerticalCandidateController: CandidateController {
scrollViewRect.size.width -= stripRect.size.width
scrollView = NSScrollView(frame: scrollViewRect)
scrollView.verticalScrollElasticity = .none
scrollView.drawsBackground = false
scrollView.contentView.drawsBackground = false
scrollView.contentView.postsBoundsChangedNotifications = true
if bigSurOrHigher {
scrollView.drawsBackground = false
scrollView.contentView.drawsBackground = false
}

tableView = NSTableView(frame: contentRect)
let column = NSTableColumn(identifier: NSUserInterfaceItemIdentifier(rawValue: "candidate"))
Expand All @@ -140,8 +182,9 @@ public class VerticalCandidateController: CandidateController {
tableView.headerView = nil
tableView.allowsMultipleSelection = false
tableView.allowsEmptySelection = false
tableView.backgroundColor = .clear

if bigSurOrHigher {
tableView.backgroundColor = .clear
}
if #available(macOS 10.16, *) {
tableView.style = .fullWidth
candidateTextPadding = kCandidateTextPaddingWithMandatedTableViewPadding
Expand Down

0 comments on commit bddbb50

Please sign in to comment.