vChewing-macOS/Packages/vChewing_CandidateWindow/Sources/CandidateWindow/CtlCandidate.swift

149 lines
4.5 KiB
Swift
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

// (c) 2021 and onwards The vChewing Project (MIT-NTL License).
// ====================
// This code is released under the MIT license (SPDX-License-Identifier: MIT)
// ... with NTL restriction stating that:
// No trademark license is granted to use the trade names, trademarks, service
// marks, or product names of Contributor, except as required to fulfill notice
// requirements defined in MIT License.
import Cocoa
import Shared
open class CtlCandidate: NSWindowController, CtlCandidateProtocol {
open var tooltip: String = ""
open var currentLayout: NSUserInterfaceLayoutOrientation = .horizontal
open var locale: String = ""
open var useLangIdentifier: Bool = false
open func highlightedColor() -> NSColor {
var result = NSColor.alternateSelectedControlColor
var colorBlendAmount: Double = NSApplication.isDarkMode ? 0.3 : 0.0
if #available(macOS 10.14, *), !NSApplication.isDarkMode, locale == "zh-Hant" {
colorBlendAmount = 0.15
}
//
switch locale {
case "zh-Hans":
result = NSColor.systemRed
case "zh-Hant":
result = NSColor.systemBlue
case "ja":
result = NSColor.systemBrown
default: break
}
var blendingAgainstTarget: NSColor = NSApplication.isDarkMode ? NSColor.black : NSColor.white
if #unavailable(macOS 10.14) {
colorBlendAmount = 0.3
blendingAgainstTarget = NSColor.white
}
return result.blended(withFraction: colorBlendAmount, of: blendingAgainstTarget)!
}
open weak var delegate: CtlCandidateDelegate? {
didSet {
reloadData()
}
}
open var windowTopLeftPoint: NSPoint {
get {
guard let frameRect = window?.frame else { return NSPoint.zero }
return NSPoint(x: frameRect.minX, y: frameRect.maxY)
}
set {
DispatchQueue.main.async {
self.set(windowTopLeftPoint: newValue, bottomOutOfScreenAdjustmentHeight: 0)
}
}
}
open var selectedCandidateIndex: Int = .max
open var visible = false {
didSet {
NSObject.cancelPreviousPerformRequests(withTarget: self)
DispatchQueue.main.async { [self] in
_ = visible ? window?.orderFront(self) : window?.orderOut(self)
}
}
}
public required init(_: NSUserInterfaceLayoutOrientation = .horizontal) {
super.init(window: .init())
visible = false
}
///
///
/// 使
///
/// - Parameters:
/// - windowTopLeftPoint:
/// - heightDelta:
public func set(windowTopLeftPoint: NSPoint, bottomOutOfScreenAdjustmentHeight heightDelta: Double) {
DispatchQueue.main.async { [self] in
guard let window = window, var screenFrame = NSScreen.main?.visibleFrame else { return }
let windowSize = window.frame.size
var adjustedPoint = windowTopLeftPoint
var delta = heightDelta
for frame in NSScreen.screens.map(\.visibleFrame).filter({ $0.contains(windowTopLeftPoint) }) {
screenFrame = frame
break
}
if delta > screenFrame.size.height / 2.0 { delta = 0.0 }
if adjustedPoint.y < screenFrame.minY + windowSize.height {
adjustedPoint.y = windowTopLeftPoint.y + windowSize.height + delta
}
adjustedPoint.y = min(adjustedPoint.y, screenFrame.maxY - 1.0)
adjustedPoint.x = min(max(adjustedPoint.x, screenFrame.minX), screenFrame.maxX - windowSize.width - 1.0)
window.setFrameTopLeftPoint(adjustedPoint)
}
}
// MARK: -
@available(*, unavailable)
public required init?(coder _: NSCoder) {
fatalError("init(coder:) has not been implemented")
}
open var candidateFont = NSFont.systemFont(
ofSize: min(196, max(12, Double(UserDefaults.standard.integer(forKey: "CandidateListTextSize"))))
)
@discardableResult open func showNextLine() -> Bool {
false
}
@discardableResult open func showPreviousLine() -> Bool {
false
}
@discardableResult open func highlightNextCandidate() -> Bool {
false
}
@discardableResult open func highlightPreviousCandidate() -> Bool {
false
}
@discardableResult open func showNextPage() -> Bool {
false
}
@discardableResult open func showPreviousPage() -> Bool {
false
}
open func candidateIndexAtKeyLabelIndex(_: Int) -> Int {
Int.max
}
open func reloadData() {}
open func updateDisplay() {}
}