Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Restore PR #383 "update the look of the candidate sheet" with an additional fix #385

Merged
merged 2 commits into from
Nov 23, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -97,10 +97,10 @@ fileprivate class HorizontalCandidateView: NSView {

keyLabelAttrDict = [.font: labelFont,
.paragraphStyle: paraStyle,
.foregroundColor: NSColor.black]
.foregroundColor: NSColor.secondaryLabelColor]
candidateAttrDict = [.font: candidateFont,
.paragraphStyle: paraStyle,
.foregroundColor: NSColor.textColor]
.foregroundColor: NSColor.labelColor]

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

override func draw(_ dirtyRect: NSRect) {
let backgroundColor = NSColor.controlBackgroundColor
let darkGray = NSColor(deviceWhite: 0.7, alpha: 1.0)
let lightGray = NSColor(deviceWhite: 0.8, alpha: 1.0)

let bounds = self.bounds
backgroundColor.setFill()
NSBezierPath.fill(bounds)

if #available(macOS 10.14, *) {
NSColor.separatorColor.setStroke()
Expand All @@ -141,20 +137,25 @@ 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)
(index == highlightedIndex ? darkGray : lightGray).setFill()
NSBezierPath.fill(labelRect)
(keyLabels[index] as NSString).draw(in: labelRect, withAttributes: keyLabelAttrDict)
var activeKeyLabelAttrDict = keyLabelAttrDict
if index == highlightedIndex {
NSColor.selectedControlColor.setFill()
NSBezierPath.fill(labelRect)
activeKeyLabelAttrDict[.foregroundColor] = NSColor.selectedControlTextColor
}
(keyLabels[index] as NSString).draw(in: labelRect, withAttributes: activeKeyLabelAttrDict)

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

NSBezierPath.fill(candidateRect)
(displayedCandidates[index] as NSString).draw(in: candidateRect, withAttributes: activeCandidateAttr)
accuWidth += currentWidth + 1.0
}
Expand Down Expand Up @@ -221,6 +222,19 @@ public class HorizontalCandidateController: CandidateController {
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, *) {
effect.material = .popover
} else {
effect.material = .appearanceBased
}
effect.state = .active
effect.maskImage = .mask(withCornerRadius: 4)
panel.contentView = effect

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

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

panel.contentView?.addSubview(nextPageButton)
panel.contentView?.addSubview(prevPageButton)
Expand Down Expand Up @@ -433,3 +449,10 @@ extension HorizontalCandidateController {
}

}

extension String {
func withColor(_ color: NSColor) -> NSAttributedString {
let attrDict: [NSAttributedString.Key: AnyObject] = [.foregroundColor: color]
return NSAttributedString(string: self, attributes: attrDict)
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -35,38 +35,35 @@ fileprivate class VerticalKeyLabelStripView: NSView {

override func draw(_ dirtyRect: NSRect) {
let bounds = self.bounds
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: black,
.foregroundColor: NSColor.secondaryLabelColor,
.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)
var cellRect = NSRect(x: 0.0, y: CGFloat(index) * cellHeight, width: bounds.size.width, height: cellHeight - 1)
let cellRect = NSRect(x: 0.0, y: CGFloat(index) * cellHeight, width: bounds.size.width, height: cellHeight)

if index + 1 >= count {
cellRect.size.height += 1.0
if index == highlightedIndex {
NSColor.selectedControlColor.setFill()
NSBezierPath.fill(cellRect)
}

(index == highlightedIndex ? darkGray : lightGray).setFill()
NSBezierPath.fill(cellRect)
let text = keyLabels[Int(index)]
(text as NSString).draw(in: textRect, withAttributes: textAttr)
(text as NSString).draw(in: textRect, withAttributes: (index == highlightedIndex) ? textAttrHighlighted : textAttr)
}
}
}
Expand All @@ -85,13 +82,6 @@ private let kCandidateTextLeftMargin: CGFloat = 8.0
private let kCandidateTextPaddingWithMandatedTableViewPadding: CGFloat = 18.0
private let kCandidateTextLeftMarginWithMandatedTableViewPadding: CGFloat = 0.0

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 @@ -110,7 +100,19 @@ public class VerticalCandidateController: CandidateController {
let panel = NSPanel(contentRect: contentRect, styleMask: styleMask, backing: .buffered, defer: false)
panel.level = NSWindow.Level(Int(kCGPopUpMenuWindowLevel) + 1)
panel.hasShadow = true
panel.contentView = BackgroundView()
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, *) {
effect.material = .popover
} else {
effect.material = .appearanceBased
}
effect.state = .active
effect.maskImage = .mask(withCornerRadius: 4)
panel.contentView = effect

tooltipView = NSTextField(frame: NSRect.zero)
tooltipView.isEditable = false
Expand All @@ -130,6 +132,8 @@ public class VerticalCandidateController: CandidateController {
scrollViewRect.size.width -= stripRect.size.width
scrollView = NSScrollView(frame: scrollViewRect)
scrollView.verticalScrollElasticity = .none
scrollView.drawsBackground = false
scrollView.contentView.drawsBackground = false

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

if #available(macOS 10.16, *) {
tableView.style = .fullWidth
Expand Down Expand Up @@ -484,3 +489,18 @@ extension VerticalCandidateController: NSTableViewDataSource, NSTableViewDelegat
self.window?.setFrame(frameRect, display: false)
}
}

extension NSImage {
static func mask(withCornerRadius radius: CGFloat) -> NSImage {
let image = NSImage(size: NSSize(width: radius * 2, height: radius * 2), flipped: false) {
NSBezierPath(roundedRect: $0, xRadius: radius, yRadius: radius).fill()
NSColor.black.set()
return true
}

image.capInsets = NSEdgeInsets(top: radius, left: radius, bottom: radius, right: radius)
image.resizingMode = .stretch

return image
}
}