Repo // Introducing ctlCandidateProtocol.
This commit is contained in:
parent
bdb7736f4c
commit
e0762339ef
|
@ -34,10 +34,10 @@ import Cocoa
|
|||
|
||||
/// KeyHandler 委任協定
|
||||
protocol KeyHandlerDelegate {
|
||||
func ctlCandidate() -> ctlCandidate
|
||||
func ctlCandidate() -> ctlCandidateProtocol
|
||||
func keyHandler(
|
||||
_: KeyHandler, didSelectCandidateAt index: Int,
|
||||
ctlCandidate controller: ctlCandidate
|
||||
ctlCandidate controller: ctlCandidateProtocol
|
||||
)
|
||||
func keyHandler(_ keyHandler: KeyHandler, didRequestWriteUserPhraseWith state: InputStateProtocol)
|
||||
-> Bool
|
||||
|
|
|
@ -46,7 +46,7 @@ extension KeyHandler {
|
|||
) -> Bool {
|
||||
let inputText = input.inputText
|
||||
let charCode: UniChar = input.charCode
|
||||
guard let ctlCandidateCurrent = delegate?.ctlCandidate() else {
|
||||
guard var ctlCandidateCurrent = delegate?.ctlCandidate() else {
|
||||
IME.prtDebugIntel("06661F6E")
|
||||
errorCallback()
|
||||
return true
|
||||
|
|
|
@ -41,7 +41,7 @@ class ctlInputMethod: IMKInputController {
|
|||
static var areWeDeleting = false
|
||||
|
||||
/// 目前在用的的選字窗副本。
|
||||
static var ctlCandidateCurrent = ctlCandidateUniversal.init(.horizontal)
|
||||
static var ctlCandidateCurrent: ctlCandidateProtocol = ctlCandidateUniversal.init(.horizontal)
|
||||
|
||||
/// 工具提示視窗的副本。
|
||||
static let tooltipController = TooltipController()
|
||||
|
@ -236,4 +236,30 @@ class ctlInputMethod: IMKInputController {
|
|||
_ = sender // 防止格式整理工具毀掉與此對應的參數。
|
||||
resetKeyHandler()
|
||||
}
|
||||
|
||||
/// 生成 IMK 選字窗專用的候選字串陣列。
|
||||
/// - Parameter sender: 呼叫了該函式的客體(無須使用)。
|
||||
/// - Returns: IMK 選字窗專用的候選字串陣列。
|
||||
override func candidates(_ sender: Any!) -> [Any]! {
|
||||
_ = sender // 防止格式整理工具毀掉與此對應的參數。
|
||||
if let state = state as? InputState.AssociatedPhrases {
|
||||
return state.candidates.map { theCandidate -> String in
|
||||
let theConverted = IME.kanjiConversionIfRequired(theCandidate.1)
|
||||
return (theCandidate.1 == theConverted) ? theCandidate.1 : "\(theConverted)(\(theCandidate.1))"
|
||||
}
|
||||
}
|
||||
if let state = state as? InputState.ChoosingCandidate {
|
||||
return state.candidates.map { theCandidate -> String in
|
||||
let theConverted = IME.kanjiConversionIfRequired(theCandidate.1)
|
||||
return (theCandidate.1 == theConverted) ? theCandidate.1 : "\(theConverted)(\(theCandidate.1))"
|
||||
}
|
||||
}
|
||||
if let state = state as? InputState.SymbolTable {
|
||||
return state.candidates.map { theCandidate -> String in
|
||||
let theConverted = IME.kanjiConversionIfRequired(theCandidate.1)
|
||||
return (theCandidate.1 == theConverted) ? theCandidate.1 : "\(theConverted)(\(theCandidate.1))"
|
||||
}
|
||||
}
|
||||
return .init()
|
||||
}
|
||||
}
|
||||
|
|
|
@ -29,11 +29,11 @@ import Foundation
|
|||
// MARK: - KeyHandler Delegate
|
||||
|
||||
extension ctlInputMethod: KeyHandlerDelegate {
|
||||
func ctlCandidate() -> ctlCandidate { ctlInputMethod.ctlCandidateCurrent }
|
||||
func ctlCandidate() -> ctlCandidateProtocol { ctlInputMethod.ctlCandidateCurrent }
|
||||
|
||||
func keyHandler(
|
||||
_: KeyHandler, didSelectCandidateAt index: Int,
|
||||
ctlCandidate controller: ctlCandidate
|
||||
ctlCandidate controller: ctlCandidateProtocol
|
||||
) {
|
||||
ctlCandidate(controller, didSelectCandidateAtIndex: index)
|
||||
}
|
||||
|
@ -70,7 +70,7 @@ extension ctlInputMethod: KeyHandlerDelegate {
|
|||
// MARK: - Candidate Controller Delegate
|
||||
|
||||
extension ctlInputMethod: ctlCandidateDelegate {
|
||||
func candidateCountForController(_ controller: ctlCandidate) -> Int {
|
||||
func candidateCountForController(_ controller: ctlCandidateProtocol) -> Int {
|
||||
_ = controller // 防止格式整理工具毀掉與此對應的參數。
|
||||
if let state = state as? InputState.ChoosingCandidate {
|
||||
return state.candidates.count
|
||||
|
@ -80,7 +80,20 @@ extension ctlInputMethod: ctlCandidateDelegate {
|
|||
return 0
|
||||
}
|
||||
|
||||
func ctlCandidate(_ controller: ctlCandidate, candidateAtIndex index: Int)
|
||||
/// 直接給出全部的候選字詞的字音配對陣列
|
||||
/// - Parameter controller: 對應的控制器。因為有唯一解,所以填錯了也不會有影響。
|
||||
/// - Returns: 候選字詞陣列(字音配對)。
|
||||
func candidatesForController(_ controller: ctlCandidateProtocol) -> [(String, String)] {
|
||||
_ = controller // 防止格式整理工具毀掉與此對應的參數。
|
||||
if let state = state as? InputState.ChoosingCandidate {
|
||||
return state.candidates
|
||||
} else if let state = state as? InputState.AssociatedPhrases {
|
||||
return state.candidates
|
||||
}
|
||||
return .init()
|
||||
}
|
||||
|
||||
func ctlCandidate(_ controller: ctlCandidateProtocol, candidateAtIndex index: Int)
|
||||
-> (String, String)
|
||||
{
|
||||
_ = controller // 防止格式整理工具毀掉與此對應的參數。
|
||||
|
@ -92,7 +105,7 @@ extension ctlInputMethod: ctlCandidateDelegate {
|
|||
return ("", "")
|
||||
}
|
||||
|
||||
func ctlCandidate(_ controller: ctlCandidate, didSelectCandidateAtIndex index: Int) {
|
||||
func ctlCandidate(_ controller: ctlCandidateProtocol, didSelectCandidateAtIndex index: Int) {
|
||||
_ = controller // 防止格式整理工具毀掉與此對應的參數。
|
||||
|
||||
if let state = state as? InputState.SymbolTable,
|
||||
|
|
|
@ -81,11 +81,11 @@ extension ctlInputMethod {
|
|||
/// 該問題徹底解決的價值並不大,直接等到 macOS 10.x 全線淘汰之後用 SwiftUI 重寫選字窗吧。
|
||||
|
||||
if isCandidateWindowVertical { // 縱排輸入時強制使用縱排選字窗
|
||||
ctlInputMethod.ctlCandidateCurrent = .init(.vertical)
|
||||
ctlInputMethod.ctlCandidateCurrent = ctlCandidateUniversal.init(.vertical)
|
||||
} else if mgrPrefs.useHorizontalCandidateList {
|
||||
ctlInputMethod.ctlCandidateCurrent = .init(.horizontal)
|
||||
ctlInputMethod.ctlCandidateCurrent = ctlCandidateUniversal.init(.horizontal)
|
||||
} else {
|
||||
ctlInputMethod.ctlCandidateCurrent = .init(.vertical)
|
||||
ctlInputMethod.ctlCandidateCurrent = ctlCandidateUniversal.init(.vertical)
|
||||
}
|
||||
|
||||
// set the attributes for the candidate panel (which uses NSAttributedString)
|
||||
|
|
|
@ -26,6 +26,11 @@ CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
|||
|
||||
import Cocoa
|
||||
|
||||
public enum CandidateLayout {
|
||||
case horizontal
|
||||
case vertical
|
||||
}
|
||||
|
||||
public class CandidateKeyLabel: NSObject {
|
||||
public private(set) var key: String
|
||||
public private(set) var displayedText: String
|
||||
|
@ -38,21 +43,38 @@ public class CandidateKeyLabel: NSObject {
|
|||
}
|
||||
|
||||
public protocol ctlCandidateDelegate: AnyObject {
|
||||
func candidateCountForController(_ controller: ctlCandidate) -> Int
|
||||
func ctlCandidate(_ controller: ctlCandidate, candidateAtIndex index: Int)
|
||||
func candidateCountForController(_ controller: ctlCandidateProtocol) -> Int
|
||||
func candidatesForController(_ controller: ctlCandidateProtocol) -> [(String, String)]
|
||||
func ctlCandidate(_ controller: ctlCandidateProtocol, candidateAtIndex index: Int)
|
||||
-> (String, String)
|
||||
func ctlCandidate(
|
||||
_ controller: ctlCandidate, didSelectCandidateAtIndex index: Int
|
||||
_ controller: ctlCandidateProtocol, didSelectCandidateAtIndex index: Int
|
||||
)
|
||||
}
|
||||
|
||||
public class ctlCandidate: NSWindowController {
|
||||
public enum Layout {
|
||||
case horizontal
|
||||
case vertical
|
||||
}
|
||||
public protocol ctlCandidateProtocol {
|
||||
var currentLayout: CandidateLayout { get set }
|
||||
var delegate: ctlCandidateDelegate? { get set }
|
||||
var selectedCandidateIndex: Int { get set }
|
||||
var visible: Bool { get set }
|
||||
var windowTopLeftPoint: NSPoint { get set }
|
||||
var keyLabels: [CandidateKeyLabel] { get set }
|
||||
var keyLabelFont: NSFont { get set }
|
||||
var candidateFont: NSFont { get set }
|
||||
var tooltip: String { get set }
|
||||
|
||||
public var currentLayout: Layout = .horizontal
|
||||
init(_ layout: CandidateLayout)
|
||||
func reloadData()
|
||||
func showNextPage() -> Bool
|
||||
func showPreviousPage() -> Bool
|
||||
func highlightNextCandidate() -> Bool
|
||||
func highlightPreviousCandidate() -> Bool
|
||||
func candidateIndexAtKeyLabelIndex(_: Int) -> Int
|
||||
func set(windowTopLeftPoint: NSPoint, bottomOutOfScreenAdjustmentHeight height: CGFloat)
|
||||
}
|
||||
|
||||
public class ctlCandidate: NSWindowController, ctlCandidateProtocol {
|
||||
public var currentLayout: CandidateLayout = .horizontal
|
||||
public weak var delegate: ctlCandidateDelegate? {
|
||||
didSet {
|
||||
reloadData()
|
||||
|
@ -85,6 +107,15 @@ public class ctlCandidate: NSWindowController {
|
|||
}
|
||||
}
|
||||
|
||||
required public init(_ layout: CandidateLayout = .horizontal) {
|
||||
super.init(window: .init())
|
||||
visible = false
|
||||
}
|
||||
|
||||
required init?(coder: NSCoder) {
|
||||
fatalError("init(coder:) has not been implemented")
|
||||
}
|
||||
|
||||
public var keyLabels: [CandidateKeyLabel] = ["1", "2", "3", "4", "5", "6", "7", "8", "9"]
|
||||
.map {
|
||||
CandidateKeyLabel(key: $0, displayedText: $0)
|
||||
|
|
|
@ -370,7 +370,7 @@ public class ctlCandidateUniversal: ctlCandidate {
|
|||
private var nextPageButton: NSButton
|
||||
private var pageCounterLabel: NSTextField
|
||||
private var currentPageIndex: Int = 0
|
||||
override public var currentLayout: Layout {
|
||||
override public var currentLayout: CandidateLayout {
|
||||
get { candidateView.isVerticalLayout ? .vertical : .horizontal }
|
||||
set {
|
||||
switch newValue {
|
||||
|
@ -380,7 +380,7 @@ public class ctlCandidateUniversal: ctlCandidate {
|
|||
}
|
||||
}
|
||||
|
||||
public init(_ layout: Layout = .horizontal) {
|
||||
required public init(_ layout: CandidateLayout = .horizontal) {
|
||||
var contentRect = NSRect(x: 128.0, y: 128.0, width: 0.0, height: 0.0)
|
||||
let styleMask: NSWindow.StyleMask = [.nonactivatingPanel]
|
||||
let panel = NSPanel(
|
||||
|
@ -448,7 +448,8 @@ public class ctlCandidateUniversal: ctlCandidate {
|
|||
|
||||
// MARK: Post-Init()
|
||||
|
||||
super.init(window: panel)
|
||||
super.init(layout)
|
||||
self.window = panel
|
||||
currentLayout = layout
|
||||
|
||||
candidateView.target = self
|
||||
|
|
Loading…
Reference in New Issue