Shiki: Swiftify // Voltaire UI Revamp - Horizontal

This commit is contained in:
ShikiSuen 2022-01-14 22:52:32 +08:00
parent c66f2c10db
commit c4d7007f29
1 changed files with 115 additions and 98 deletions

View File

@ -1,11 +1,16 @@
// //
// HorizontalCandidateController.swift // HorizontalCandidateController.swift
// //
// Copyright (c) 2011 The McBopomofo Project. // Voltaire IME Candidate Controller Module
//
// Copyright (c) 2011-2022 The OpenVanilla Project.
// Beautified by (c) 2021-2022 The vChewing Project.
// //
// Contributors: // Contributors:
// Mengjuei Hsieh (@mjhsieh) // Lukhnos Liu (@lukhnos) @ OpenVanilla // Original Developer
// Weizhong Yang (@zonble) // Weizhong Yang (@zonble) @ OpenVanilla // Rewriter to Swift
// Shiki Suen (ShikiSuen) @ vChewing // Beautification (objC)
// //
// Based on the Syrup Project and the Formosana Library // Based on the Syrup Project and the Formosana Library
// by Lukhnos Liu (@lukhnos). // by Lukhnos Liu (@lukhnos).
@ -38,112 +43,122 @@ fileprivate class HorizontalCandidateView: NSView {
var highlightedIndex: UInt = 0 var highlightedIndex: UInt = 0
var action: Selector? var action: Selector?
weak var target: AnyObject? weak var target: AnyObject?
private var keyLabels: [String] = [] private var keyLabels: [String] = []
private var displayedCandidates: [String] = [] private var displayedCandidates: [String] = []
private var dispCandidatesWithLabels: [String] = []
private var keyLabelHeight: CGFloat = 0 private var keyLabelHeight: CGFloat = 0
private var keyLabelWidth: CGFloat = 0
private var candidateTextHeight: CGFloat = 0 private var candidateTextHeight: CGFloat = 0
private var cellPadding: CGFloat = 0 private var cellPadding: CGFloat = 0
private var keyLabelAttrDict: [NSAttributedString.Key: AnyObject] = [:] private var keyLabelAttrDict: [NSAttributedString.Key: AnyObject] = [:]
private var candidateAttrDict: [NSAttributedString.Key: AnyObject] = [:] private var candidateAttrDict: [NSAttributedString.Key: AnyObject] = [:]
private var candidateWithLabelAttrDict: [NSAttributedString.Key: AnyObject] = [:]
private var elementWidths: [CGFloat] = [] private var elementWidths: [CGFloat] = []
private var trackingHighlightedIndex: UInt = UInt.max private var trackingHighlightedIndex: UInt = UInt.max
override var isFlipped: Bool { override var isFlipped: Bool {
true true
} }
var sizeForView: NSSize { var sizeForView: NSSize {
var result = NSSize.zero var result = NSSize.zero
if !elementWidths.isEmpty { if !elementWidths.isEmpty {
result.width = elementWidths.reduce(0, +) result.width = elementWidths.reduce(0, +)
result.width += CGFloat(elementWidths.count) result.width += CGFloat(elementWidths.count)
result.height = keyLabelHeight + candidateTextHeight + 1.0 // result.height = keyLabelHeight + candidateTextHeight + 1.0
result.height = candidateTextHeight + cellPadding;
} }
return result return result
} }
@objc (setKeyLabels:displayedCandidates:) @objc (setKeyLabels:displayedCandidates:)
func set(keyLabels labels: [String], displayedCandidates candidates: [String]) { func set(keyLabels labels: [String], displayedCandidates candidates: [String]) {
let count = min(labels.count, candidates.count) let count = min(labels.count, candidates.count)
keyLabels = Array(labels[0..<count]) keyLabels = Array(labels[0..<count])
displayedCandidates = Array(candidates[0..<count]) displayedCandidates = Array(candidates[0..<count])
// dispCandidatesWithLabels = keyLabels + displayedCandidates
dispCandidatesWithLabels = zip(keyLabels,displayedCandidates).map() {$0 + $1}
var newWidths = [CGFloat]() var newWidths = [CGFloat]()
let baseSize = NSSize(width: 10240.0, height: 10240.0) let baseSize = NSSize(width: 10240.0, height: 10240.0)
for index in 0..<count { for index in 0..<count {
let labelRect = (keyLabels[index] as NSString).boundingRect(with: baseSize, options: .usesLineFragmentOrigin, attributes: keyLabelAttrDict) let rctCandidate = (dispCandidatesWithLabels[index] as NSString).boundingRect(with: baseSize, options: .usesLineFragmentOrigin, attributes: candidateWithLabelAttrDict)
let candidateRect = (displayedCandidates[index] as NSString).boundingRect(with: baseSize, options: .usesLineFragmentOrigin, attributes: candidateAttrDict) let cellWidth = rctCandidate.size.width + cellPadding;
let cellWidth = max(labelRect.size.width, candidateRect.size.width) + cellPadding;
newWidths.append(cellWidth) newWidths.append(cellWidth)
} }
elementWidths = newWidths elementWidths = newWidths
} }
@objc (setKeyLabelFont:candidateFont:) @objc (setKeyLabelFont:candidateFont:)
func set(keyLabelFont labelFont: NSFont, candidateFont: NSFont) { func set(keyLabelFont labelFont: NSFont, candidateFont: NSFont) {
let paraStyle = NSMutableParagraphStyle() let paraStyle = NSMutableParagraphStyle()
paraStyle.setParagraphStyle(NSParagraphStyle.default) paraStyle.setParagraphStyle(NSParagraphStyle.default)
paraStyle.alignment = .center paraStyle.alignment = .center
candidateWithLabelAttrDict = [.font: candidateFont,
.paragraphStyle: paraStyle,
.foregroundColor: NSColor.labelColor] // We still need this dummy section to make sure the space occupations of the candidates are correct.
keyLabelAttrDict = [.font: labelFont, keyLabelAttrDict = [.font: labelFont,
.paragraphStyle: paraStyle, .paragraphStyle: paraStyle,
.foregroundColor: NSColor.black] .foregroundColor: NSColor.secondaryLabelColor] // Candidate phrase text color
candidateAttrDict = [.font: candidateFont, candidateAttrDict = [.font: candidateFont,
.paragraphStyle: paraStyle, .paragraphStyle: paraStyle,
.foregroundColor: NSColor.textColor] .foregroundColor: NSColor.labelColor] // Candidate index text color
let labelFontSize = labelFont.pointSize let labelFontSize = labelFont.pointSize
let candidateFontSize = candidateFont.pointSize let candidateFontSize = candidateFont.pointSize
let biggestSize = max(labelFontSize, candidateFontSize) let biggestSize = max(labelFontSize, candidateFontSize)
keyLabelWidth = ceil(labelFontSize)
keyLabelHeight = ceil(labelFontSize * 1.20) keyLabelHeight = ceil(labelFontSize * 1.20)
candidateTextHeight = ceil(candidateFontSize * 1.20) candidateTextHeight = ceil(candidateFontSize * 1.20)
cellPadding = ceil(biggestSize / 2.0) cellPadding = ceil(biggestSize / 2.0)
} }
override func draw(_ dirtyRect: NSRect) { override func draw(_ dirtyRect: NSRect) {
let backgroundColor = NSColor.controlBackgroundColor
let darkGray = NSColor(deviceWhite: 0.7, alpha: 1.0) // Give a standalone layer to the candidate list panel
let lightGray = NSColor(deviceWhite: 0.8, alpha: 1.0) self.wantsLayer = true
self.layer?.borderColor = NSColor.selectedMenuItemTextColor.withAlphaComponent(0.30).cgColor
self.layer?.borderWidth = 1.0
self.layer?.cornerRadius = 6.0
let bounds = self.bounds let bounds = self.bounds
backgroundColor.setFill() NSColor.controlBackgroundColor.setFill() // Candidate list panel base background
NSBezierPath.fill(bounds) NSBezierPath.fill(bounds)
if #available(macOS 10.14, *) { if #available(macOS 10.14, *) {
NSColor.separatorColor.setStroke() NSColor.separatorColor.setStroke()
} else { } else {
NSColor.darkGray.setStroke() NSColor.darkGray.setStroke()
} }
NSBezierPath.strokeLine(from: NSPoint(x: bounds.size.width, y: 0.0), to: NSPoint(x: bounds.size.width, y: bounds.size.height)) NSBezierPath.strokeLine(from: NSPoint(x: bounds.size.width, y: 0.0), to: NSPoint(x: bounds.size.width, y: bounds.size.height))
var accuWidth: CGFloat = 0 var accuWidth: CGFloat = 0
for index in 0..<elementWidths.count { for index in 0..<elementWidths.count {
let currentWidth = elementWidths[index] let currentWidth = elementWidths[index]
let labelRect = NSRect(x: accuWidth, y: 0.0, width: currentWidth, height: keyLabelHeight) let rctCandidateArea = NSRect(x: accuWidth, y: 0.0, width: currentWidth + 1.0, height: candidateTextHeight + cellPadding)
let candidateRect = NSRect(x: accuWidth, y: keyLabelHeight + 1.0, width: currentWidth, height: candidateTextHeight) let rctLabel = NSRect(x: accuWidth + cellPadding / 2 - 1, y: cellPadding / 2 , width: keyLabelWidth, height: candidateTextHeight)
(index == highlightedIndex ? darkGray : lightGray).setFill() let rctCandidatePhrase = NSRect(x: accuWidth + keyLabelWidth - 1, y: cellPadding / 2 , width: currentWidth - keyLabelWidth, height: candidateTextHeight)
NSBezierPath.fill(labelRect)
(keyLabels[index] as NSString).draw(in: labelRect, withAttributes: keyLabelAttrDict) var activeCandidateIndexAttr = keyLabelAttrDict
var activeCandidateAttr = candidateAttrDict var activeCandidateAttr = candidateAttrDict
if index == highlightedIndex { if index == highlightedIndex {
NSColor.selectedTextBackgroundColor.setFill() NSColor.alternateSelectedControlColor.setFill() // The background color of the highlightened candidate
activeCandidateAttr = candidateAttrDict activeCandidateIndexAttr[.foregroundColor] = NSColor.selectedMenuItemTextColor.withAlphaComponent(0.84) // The index text color of the highlightened candidate
activeCandidateAttr[.foregroundColor] = NSColor.selectedTextColor activeCandidateAttr[.foregroundColor] = NSColor.selectedMenuItemTextColor // The phrase text color of the highlightened candidate
} else { } else {
backgroundColor.setFill() NSColor.controlBackgroundColor.setFill()
} }
NSBezierPath.fill(rctCandidateArea)
NSBezierPath.fill(candidateRect) (keyLabels[index] as NSString).draw(in: rctLabel, withAttributes: activeCandidateIndexAttr)
(displayedCandidates[index] as NSString).draw(in: candidateRect, withAttributes: activeCandidateAttr) (displayedCandidates[index] as NSString).draw(in: rctCandidatePhrase, withAttributes: activeCandidateAttr)
accuWidth += currentWidth + 1.0 accuWidth += currentWidth + 1.0
} }
} }
private func findHitIndex(event: NSEvent) -> UInt? { private func findHitIndex(event: NSEvent) -> UInt? {
let location = convert(event.locationInWindow, to: nil) let location = convert(event.locationInWindow, to: nil)
if !NSPointInRect(location, self.bounds) { if !NSPointInRect(location, self.bounds) {
@ -152,16 +167,16 @@ fileprivate class HorizontalCandidateView: NSView {
var accuWidth: CGFloat = 0.0 var accuWidth: CGFloat = 0.0
for index in 0..<elementWidths.count { for index in 0..<elementWidths.count {
let currentWidth = elementWidths[index] let currentWidth = elementWidths[index]
if location.x >= accuWidth && location.x <= accuWidth + currentWidth { if location.x >= accuWidth && location.x <= accuWidth + currentWidth {
return UInt(index) return UInt(index)
} }
accuWidth += currentWidth + 1.0 accuWidth += currentWidth + 1.0
} }
return nil return nil
} }
override func mouseUp(with event: NSEvent) { override func mouseUp(with event: NSEvent) {
trackingHighlightedIndex = highlightedIndex trackingHighlightedIndex = highlightedIndex
guard let newIndex = findHitIndex(event: event) else { guard let newIndex = findHitIndex(event: event) else {
@ -170,7 +185,7 @@ fileprivate class HorizontalCandidateView: NSView {
highlightedIndex = newIndex highlightedIndex = newIndex
self.setNeedsDisplay(self.bounds) self.setNeedsDisplay(self.bounds)
} }
override func mouseDown(with event: NSEvent) { override func mouseDown(with event: NSEvent) {
guard let newIndex = findHitIndex(event: event) else { guard let newIndex = findHitIndex(event: event) else {
return return
@ -181,7 +196,7 @@ fileprivate class HorizontalCandidateView: NSView {
} else { } else {
highlightedIndex = trackingHighlightedIndex highlightedIndex = trackingHighlightedIndex
} }
trackingHighlightedIndex = 0 trackingHighlightedIndex = 0
self.setNeedsDisplay(self.bounds) self.setNeedsDisplay(self.bounds)
if triggerAction { if triggerAction {
@ -198,89 +213,99 @@ public class HorizontalCandidateController: CandidateController {
private var prevPageButton: NSButton private var prevPageButton: NSButton
private var nextPageButton: NSButton private var nextPageButton: NSButton
private var currentPage: UInt = 0 private var currentPage: UInt = 0
public init() { public init() {
var contentRect = NSRect(x: 128.0, y: 128.0, width: 0.0, height: 0.0) var contentRect = NSRect(x: 128.0, y: 128.0, width: 0.0, height: 0.0)
let styleMask: NSWindow.StyleMask = [.borderless, .nonactivatingPanel] let styleMask: NSWindow.StyleMask = [.borderless, .nonactivatingPanel]
let panel = NSPanel(contentRect: contentRect, styleMask: styleMask, backing: .buffered, defer: false) let panel = NSPanel(contentRect: contentRect, styleMask: styleMask, backing: .buffered, defer: false)
panel.level = NSWindow.Level(Int(kCGPopUpMenuWindowLevel)) panel.level = NSWindow.Level(Int(kCGPopUpMenuWindowLevel) + 1)
panel.hasShadow = true panel.hasShadow = true
panel.isOpaque = false
panel.backgroundColor = NSColor.clear // Transparentify everything outside of the candidate list panel
contentRect.origin = NSPoint.zero contentRect.origin = NSPoint.zero
candidateView = HorizontalCandidateView(frame: contentRect) candidateView = HorizontalCandidateView(frame: contentRect)
panel.contentView?.addSubview(candidateView) panel.contentView?.addSubview(candidateView)
contentRect.size = NSSize(width: 36.0, height: 20.0) contentRect.size = NSSize(width: 20.0, height: 15.0) // Reduce the button width
nextPageButton = NSButton(frame: contentRect) nextPageButton = NSButton(frame: contentRect)
nextPageButton.setButtonType(.momentaryLight) nextPageButton.setButtonType(.momentaryLight)
nextPageButton.bezelStyle = .smallSquare nextPageButton.bezelStyle = .shadowlessSquare
nextPageButton.title = "»" nextPageButton.wantsLayer = true
nextPageButton.layer?.masksToBounds = true
nextPageButton.layer?.borderColor = NSColor.clear.cgColor // Attempt to remove the system default layer border color - step 1
nextPageButton.layer?.borderWidth = 0.0 // Attempt to remove the system default layer border color - step 2
nextPageButton.layer?.backgroundColor = NSColor.black.cgColor // Button Background Color. Otherwise the button will be half-transparent in macOS Monterey Dark Mode.
nextPageButton.attributedTitle = NSMutableAttributedString(string: "⬇︎") // Next Page Arrow
prevPageButton = NSButton(frame: contentRect) prevPageButton = NSButton(frame: contentRect)
prevPageButton.setButtonType(.momentaryLight) prevPageButton.setButtonType(.momentaryLight)
prevPageButton.bezelStyle = .smallSquare prevPageButton.bezelStyle = .shadowlessSquare
prevPageButton.title = "«" prevPageButton.wantsLayer = true
prevPageButton.layer?.masksToBounds = true
prevPageButton.layer?.borderColor = NSColor.clear.cgColor // Attempt to remove the system default layer border color - step 1
prevPageButton.layer?.borderWidth = 0.0 // Attempt to remove the system default layer border color - step 2
prevPageButton.layer?.backgroundColor = NSColor.black.cgColor // Button Background Color. Otherwise the button will be half-transparent in macOS Monterey Dark Mode.
prevPageButton.attributedTitle = NSMutableAttributedString(string: "⬆︎") // Previous Page Arrow
panel.contentView?.addSubview(nextPageButton) panel.contentView?.addSubview(nextPageButton)
panel.contentView?.addSubview(prevPageButton) panel.contentView?.addSubview(prevPageButton)
super.init(window: panel) super.init(window: panel)
candidateView.target = self candidateView.target = self
candidateView.action = #selector(candidateViewMouseDidClick(_:)) candidateView.action = #selector(candidateViewMouseDidClick(_:))
nextPageButton.target = self nextPageButton.target = self
nextPageButton.action = #selector(pageButtonAction(_:)) nextPageButton.action = #selector(pageButtonAction(_:))
prevPageButton.target = self prevPageButton.target = self
prevPageButton.action = #selector(pageButtonAction(_:)) prevPageButton.action = #selector(pageButtonAction(_:))
} }
required init?(coder: NSCoder) { required init?(coder: NSCoder) {
fatalError("init(coder:) has not been implemented") fatalError("init(coder:) has not been implemented")
} }
public override func reloadData() { public override func reloadData() {
candidateView.highlightedIndex = 0 candidateView.highlightedIndex = 0
currentPage = 0 currentPage = 0
layoutCandidateView() layoutCandidateView()
} }
public override func showNextPage() -> Bool { public override func showNextPage() -> Bool {
guard delegate != nil else { guard delegate != nil else {
return false return false
} }
if currentPage + 1 >= pageCount { if currentPage + 1 >= pageCount {
return false return false
} }
currentPage += 1 currentPage += 1
candidateView.highlightedIndex = 0 candidateView.highlightedIndex = 0
layoutCandidateView() layoutCandidateView()
return true return true
} }
public override func showPreviousPage() -> Bool { public override func showPreviousPage() -> Bool {
guard delegate != nil else { guard delegate != nil else {
return false return false
} }
if currentPage == 0 { if currentPage == 0 {
return false return false
} }
currentPage -= 1 currentPage -= 1
candidateView.highlightedIndex = 0 candidateView.highlightedIndex = 0
layoutCandidateView() layoutCandidateView()
return true return true
} }
public override func highlightNextCandidate() -> Bool { public override func highlightNextCandidate() -> Bool {
guard let delegate = delegate else { guard let delegate = delegate else {
return false return false
} }
let currentIndex = selectedCandidateIndex let currentIndex = selectedCandidateIndex
if currentIndex + 1 >= delegate.candidateCountForController(self) { if currentIndex + 1 >= delegate.candidateCountForController(self) {
return false return false
@ -288,30 +313,30 @@ public class HorizontalCandidateController: CandidateController {
selectedCandidateIndex = currentIndex + 1 selectedCandidateIndex = currentIndex + 1
return true return true
} }
public override func highlightPreviousCandidate() -> Bool { public override func highlightPreviousCandidate() -> Bool {
guard delegate != nil else { guard delegate != nil else {
return false return false
} }
let currentIndex = selectedCandidateIndex let currentIndex = selectedCandidateIndex
if currentIndex == 0 { if currentIndex == 0 {
return false return false
} }
selectedCandidateIndex = currentIndex - 1 selectedCandidateIndex = currentIndex - 1
return true return true
} }
public override func candidateIndexAtKeyLabelIndex(_ index: UInt) -> UInt { public override func candidateIndexAtKeyLabelIndex(_ index: UInt) -> UInt {
guard let delegate = delegate else { guard let delegate = delegate else {
return UInt.max return UInt.max
} }
let result = currentPage * UInt(keyLabels.count) + index let result = currentPage * UInt(keyLabels.count) + index
return result < delegate.candidateCountForController(self) ? result : UInt.max return result < delegate.candidateCountForController(self) ? result : UInt.max
} }
public override var selectedCandidateIndex: UInt { public override var selectedCandidateIndex: UInt {
get { get {
currentPage * UInt(keyLabels.count) + candidateView.highlightedIndex currentPage * UInt(keyLabels.count) + candidateView.highlightedIndex
@ -331,7 +356,7 @@ public class HorizontalCandidateController: CandidateController {
} }
extension HorizontalCandidateController { extension HorizontalCandidateController {
private var pageCount: UInt { private var pageCount: UInt {
guard let delegate = delegate else { guard let delegate = delegate else {
return 0 return 0
@ -340,17 +365,17 @@ extension HorizontalCandidateController {
let keyLabelCount = UInt(keyLabels.count) let keyLabelCount = UInt(keyLabels.count)
return totalCount / keyLabelCount + ((totalCount % keyLabelCount) != 0 ? 1 : 0) return totalCount / keyLabelCount + ((totalCount % keyLabelCount) != 0 ? 1 : 0)
} }
private func layoutCandidateView() { private func layoutCandidateView() {
guard let delegate = delegate else { guard let delegate = delegate else {
return return
} }
candidateView.set(keyLabelFont: keyLabelFont, candidateFont: candidateFont) candidateView.set(keyLabelFont: keyLabelFont, candidateFont: candidateFont)
var candidates = [String]() var candidates = [String]()
let count = delegate.candidateCountForController(self) let count = delegate.candidateCountForController(self)
let keyLabelCount = UInt(keyLabels.count) let keyLabelCount = UInt(keyLabels.count)
let begin = currentPage * keyLabelCount let begin = currentPage * keyLabelCount
for index in begin..<min(begin + keyLabelCount, count) { for index in begin..<min(begin + keyLabelCount, count) {
let candidate = delegate.candidateController(self, candidateAtIndex: index) let candidate = delegate.candidateController(self, candidateAtIndex: index)
@ -361,28 +386,20 @@ extension HorizontalCandidateController {
var frameRect = candidateView.frame var frameRect = candidateView.frame
frameRect.size = newSize frameRect.size = newSize
candidateView.frame = frameRect candidateView.frame = frameRect
if pageCount > 1 { if pageCount > 1 {
var buttonRect = nextPageButton.frame var buttonRect = nextPageButton.frame
var spacing = 0.0 let spacing:CGFloat = 0.0
if newSize.height < 40.0 { buttonRect.size.height = floor(newSize.height / 2)
buttonRect.size.height = floor(newSize.height / 2)
} else {
buttonRect.size.height = 20.0
}
if newSize.height >= 60.0 {
spacing = ceil(newSize.height * 0.1)
}
let buttonOriginY = (newSize.height - (buttonRect.size.height * 2.0 + spacing)) / 2.0 let buttonOriginY = (newSize.height - (buttonRect.size.height * 2.0 + spacing)) / 2.0
buttonRect.origin = NSPoint(x: newSize.width + 8.0, y: buttonOriginY) buttonRect.origin = NSPoint(x: newSize.width + 8.0, y: buttonOriginY)
nextPageButton.frame = buttonRect nextPageButton.frame = buttonRect
buttonRect.origin = NSPoint(x: newSize.width + 8.0, y: buttonOriginY + buttonRect.size.height + spacing) buttonRect.origin = NSPoint(x: newSize.width + 8.0, y: buttonOriginY + buttonRect.size.height + spacing)
prevPageButton.frame = buttonRect prevPageButton.frame = buttonRect
newSize.width += 52.0 newSize.width += 52.0
nextPageButton.isHidden = false nextPageButton.isHidden = false
prevPageButton.isHidden = false prevPageButton.isHidden = false
@ -390,16 +407,16 @@ extension HorizontalCandidateController {
nextPageButton.isHidden = true nextPageButton.isHidden = true
prevPageButton.isHidden = true prevPageButton.isHidden = true
} }
frameRect = window?.frame ?? NSRect.zero frameRect = window?.frame ?? NSRect.zero
let topLeftPoint = NSMakePoint(frameRect.origin.x, frameRect.origin.y + frameRect.size.height) let topLeftPoint = NSMakePoint(frameRect.origin.x, frameRect.origin.y + frameRect.size.height)
frameRect.size = newSize frameRect.size = newSize
frameRect.origin = NSMakePoint(topLeftPoint.x, topLeftPoint.y - frameRect.size.height) frameRect.origin = NSMakePoint(topLeftPoint.x, topLeftPoint.y - frameRect.size.height)
self.window?.setFrame(frameRect, display: false) self.window?.setFrame(frameRect, display: false)
candidateView.setNeedsDisplay(candidateView.bounds) candidateView.setNeedsDisplay(candidateView.bounds)
} }
@objc fileprivate func pageButtonAction(_ sender: Any) { @objc fileprivate func pageButtonAction(_ sender: Any) {
guard let sender = sender as? NSButton else { guard let sender = sender as? NSButton else {
return return
@ -410,9 +427,9 @@ extension HorizontalCandidateController {
_ = showPreviousPage() _ = showPreviousPage()
} }
} }
@objc fileprivate func candidateViewMouseDidClick(_ sender: Any) { @objc fileprivate func candidateViewMouseDidClick(_ sender: Any) {
delegate?.candidateController(self, didSelectCandidateAtIndex: selectedCandidateIndex) delegate?.candidateController(self, didSelectCandidateAtIndex: selectedCandidateIndex)
} }
} }