From 5fbc2fb728ac656fd2813a4fcec9c7add5e5c5aa Mon Sep 17 00:00:00 2001 From: ShikiSuen Date: Mon, 24 Oct 2022 10:06:51 +0800 Subject: [PATCH] TDKCandidates // UI accommodation with long reverse-lookup results. - Use array to handle reverse-lookup UI representation. - Remove SessionCtl.annotate(). --- .../CandidateWindow/CtlCandidate.swift | 2 +- .../TDKCandidates/CtlCandidateTDK.swift | 2 +- .../VwrCandidateHorizontal.swift | 31 +++++++++++++----- .../VwrCandidateVertical.swift | 28 ++++++++++++---- .../VwrCandidateHorizontalBackports.swift | 32 +++++++++++++------ .../VwrCandidateVerticalBackports.swift | 29 ++++++++++++----- .../Protocols/CtlCandidateProtocol.swift | 5 +-- Source/Modules/SessionCtl_Delegates.swift | 19 +++++++---- .../CandidateUI/IMKCandidatesImpl.swift | 2 +- 9 files changed, 106 insertions(+), 44 deletions(-) diff --git a/Packages/vChewing_CandidateWindow/Sources/CandidateWindow/CtlCandidate.swift b/Packages/vChewing_CandidateWindow/Sources/CandidateWindow/CtlCandidate.swift index 6cbf7cc3..338ddda9 100644 --- a/Packages/vChewing_CandidateWindow/Sources/CandidateWindow/CtlCandidate.swift +++ b/Packages/vChewing_CandidateWindow/Sources/CandidateWindow/CtlCandidate.swift @@ -14,7 +14,7 @@ open class CtlCandidate: NSWindowController, CtlCandidateProtocol { open var currentLayout: NSUserInterfaceLayoutOrientation = .horizontal open var locale: String = "" open var useLangIdentifier: Bool = false - open var reverseLookupResult: String = "" + open var reverseLookupResult: [String] = [] open func highlightedColor() -> NSColor { var result = NSColor.alternateSelectedControlColor diff --git a/Packages/vChewing_CandidateWindow/Sources/CandidateWindow/TDKCandidates/CtlCandidateTDK.swift b/Packages/vChewing_CandidateWindow/Sources/CandidateWindow/TDKCandidates/CtlCandidateTDK.swift index 15b2d244..491f2088 100644 --- a/Packages/vChewing_CandidateWindow/Sources/CandidateWindow/TDKCandidates/CtlCandidateTDK.swift +++ b/Packages/vChewing_CandidateWindow/Sources/CandidateWindow/TDKCandidates/CtlCandidateTDK.swift @@ -117,7 +117,7 @@ public class CtlCandidateTDK: CtlCandidate { override open func updateDisplay() { guard let window = window else { return } - reverseLookupResult = delegate?.annotate(for: currentSelectedCandidateText) ?? "" + reverseLookupResult = delegate?.reverseLookup(for: currentSelectedCandidateText) ?? [] switch currentLayout { case .horizontal: DispatchQueue.main.async { [self] in diff --git a/Packages/vChewing_CandidateWindow/Sources/CandidateWindow/TDKCandidates/VwrCandidateTDK/VwrCandidateHorizontal.swift b/Packages/vChewing_CandidateWindow/Sources/CandidateWindow/TDKCandidates/VwrCandidateTDK/VwrCandidateHorizontal.swift index 8f9bbf7b..ef8d755b 100644 --- a/Packages/vChewing_CandidateWindow/Sources/CandidateWindow/TDKCandidates/VwrCandidateTDK/VwrCandidateHorizontal.swift +++ b/Packages/vChewing_CandidateWindow/Sources/CandidateWindow/TDKCandidates/VwrCandidateTDK/VwrCandidateHorizontal.swift @@ -36,9 +36,10 @@ struct CandidatePoolViewUIHorizontal_Previews: PreviewProvider { @available(macOS 12, *) public struct VwrCandidateHorizontal: View { public var controller: CtlCandidateTDK + @Environment(\.colorScheme) var colorScheme @State public var thePool: CandidatePool @State public var tooltip: String = "" - @State public var reverseLookupResult: String = "" + @State public var reverseLookupResult: [String] = ["MLGB"] private var positionLabel: String { (thePool.highlightedIndex + 1).description + "/" + thePool.candidateDataAll.count.description @@ -90,20 +91,33 @@ public struct VwrCandidateHorizontal: View { } } } - .fixedSize(horizontal: false, vertical: true).padding(5) - .background(Color(nsColor: NSColor.controlBackgroundColor).ignoresSafeArea()) + .fixedSize(horizontal: false, vertical: true) + .padding([.horizontal], 5).padding([.top], 5).padding([.bottom], -1) + if controller.delegate?.showReverseLookupResult ?? true { + ZStack(alignment: .leading) { + Color(white: colorScheme == .dark ? 0.15 : 0.97) + HStack(alignment: .center, spacing: 4) { + Text("→") + ForEach(reverseLookupResult, id: \.self) { currentResult in + ZStack(alignment: .center) { + Color(white: colorScheme == .dark ? 0.3 : 0.9).cornerRadius(3) + Text(" \(currentResult) ").lineLimit(1) + }.fixedSize() + } + } + .font(.system(size: max(CandidateCellData.unifiedSize * 0.6, 9))) + .padding([.horizontal], 4).padding([.vertical], 4) + .foregroundColor(colorScheme == .light ? Color(white: 0.1) : Color(white: 0.9)) + } + } ZStack(alignment: .trailing) { Color(nsColor: tooltip.isEmpty ? .windowBackgroundColor : CandidateCellData.highlightBackground) .ignoresSafeArea() - HStack(alignment: .bottom) { + HStack(alignment: .center) { if !tooltip.isEmpty { Text(tooltip).lineLimit(1) Spacer() } - if !reverseLookupResult.isEmpty, !(controller.delegate?.isVerticalTyping ?? true) { - Text(reverseLookupResult).lineLimit(1) - Spacer() - } Text(positionLabel).lineLimit(1) } .font(.system(size: max(CandidateCellData.unifiedSize * 0.7, 11), weight: .bold)) @@ -114,6 +128,7 @@ public struct VwrCandidateHorizontal: View { .fixedSize(horizontal: false, vertical: true) } .frame(minWidth: thePool.maxWindowWidth, maxWidth: thePool.maxWindowWidth) + .background(Color(nsColor: NSColor.controlBackgroundColor).ignoresSafeArea()) .overlay( RoundedRectangle(cornerRadius: 10).stroke(.white.opacity(0.2), lineWidth: 1) ) diff --git a/Packages/vChewing_CandidateWindow/Sources/CandidateWindow/TDKCandidates/VwrCandidateTDK/VwrCandidateVertical.swift b/Packages/vChewing_CandidateWindow/Sources/CandidateWindow/TDKCandidates/VwrCandidateTDK/VwrCandidateVertical.swift index bc69d663..0131f9f1 100644 --- a/Packages/vChewing_CandidateWindow/Sources/CandidateWindow/TDKCandidates/VwrCandidateTDK/VwrCandidateVertical.swift +++ b/Packages/vChewing_CandidateWindow/Sources/CandidateWindow/TDKCandidates/VwrCandidateTDK/VwrCandidateVertical.swift @@ -35,9 +35,10 @@ struct CandidatePoolViewUIVertical_Previews: PreviewProvider { @available(macOS 12, *) public struct VwrCandidateVertical: View { public var controller: CtlCandidateTDK + @Environment(\.colorScheme) var colorScheme @State public var thePool: CandidatePool @State public var tooltip: String = "" - @State public var reverseLookupResult: String = "" + @State public var reverseLookupResult: [String] = ["MLGB"] private var positionLabel: String { (thePool.highlightedIndex + 1).description + "/" + thePool.candidateDataAll.count.description @@ -99,19 +100,31 @@ public struct VwrCandidateVertical: View { } } .fixedSize(horizontal: true, vertical: false).padding(5) - .background(Color(nsColor: NSColor.controlBackgroundColor).ignoresSafeArea()) + if controller.delegate?.showReverseLookupResult ?? true { + ZStack(alignment: .leading) { + Color(white: colorScheme == .dark ? 0.15 : 0.97) + HStack(alignment: .center, spacing: 4) { + Text("→") + ForEach(reverseLookupResult, id: \.self) { currentResult in + ZStack(alignment: .center) { + Color(white: colorScheme == .dark ? 0.3 : 0.9).cornerRadius(3) + Text(" \(currentResult) ").lineLimit(1) + }.fixedSize() + } + } + .font(.system(size: max(CandidateCellData.unifiedSize * 0.6, 9))) + .padding([.horizontal], 4).padding([.vertical], 4) + .foregroundColor(colorScheme == .light ? Color(white: 0.1) : Color(white: 0.9)) + } + } ZStack(alignment: .trailing) { Color(nsColor: tooltip.isEmpty ? .windowBackgroundColor : CandidateCellData.highlightBackground) .ignoresSafeArea() - HStack(alignment: .bottom) { + HStack(alignment: .center) { if !tooltip.isEmpty { Text(tooltip).lineLimit(1) Spacer() } - if !reverseLookupResult.isEmpty, !(controller.delegate?.isVerticalTyping ?? true) { - Text(reverseLookupResult).lineLimit(1) - Spacer() - } Text(positionLabel).lineLimit(1) } .font(.system(size: max(CandidateCellData.unifiedSize * 0.7, 11), weight: .bold)) @@ -121,6 +134,7 @@ public struct VwrCandidateVertical: View { } .fixedSize(horizontal: false, vertical: true) } + .background(Color(nsColor: NSColor.controlBackgroundColor).ignoresSafeArea()) .overlay( RoundedRectangle(cornerRadius: 10).stroke(.white.opacity(0.2), lineWidth: 1) ) diff --git a/Packages/vChewing_CandidateWindow/Sources/CandidateWindow/TDKCandidates/VwrCandidateTDK_Backports/VwrCandidateHorizontalBackports.swift b/Packages/vChewing_CandidateWindow/Sources/CandidateWindow/TDKCandidates/VwrCandidateTDK_Backports/VwrCandidateHorizontalBackports.swift index e7e5bd1a..8fd28340 100644 --- a/Packages/vChewing_CandidateWindow/Sources/CandidateWindow/TDKCandidates/VwrCandidateTDK_Backports/VwrCandidateHorizontalBackports.swift +++ b/Packages/vChewing_CandidateWindow/Sources/CandidateWindow/TDKCandidates/VwrCandidateTDK_Backports/VwrCandidateHorizontalBackports.swift @@ -36,11 +36,11 @@ struct CandidatePoolViewUIHorizontalBackports_Previews: PreviewProvider { @available(macOS 10.15, *) public struct VwrCandidateHorizontalBackports: View { - @Environment(\.colorScheme) var colorScheme public var controller: CtlCandidateTDK + @Environment(\.colorScheme) var colorScheme @State public var thePool: CandidatePool @State public var tooltip: String = "" - @State public var reverseLookupResult: String = "" + @State public var reverseLookupResult: [String] = ["MLGB"] private var positionLabel: String { (thePool.highlightedIndex + 1).description + "/" + thePool.candidateDataAll.count.description @@ -92,8 +92,25 @@ public struct VwrCandidateHorizontalBackports: View { } } } - .fixedSize(horizontal: false, vertical: true).padding(5) - .background(Color(white: colorScheme == .dark ? 0.1 : 1)) + .fixedSize(horizontal: false, vertical: true) + .padding([.horizontal], 5).padding([.top], 5).padding([.bottom], -1) + if controller.delegate?.showReverseLookupResult ?? true { + ZStack(alignment: .leading) { + Color(white: colorScheme == .dark ? 0.15 : 0.97) + HStack(alignment: .center, spacing: 4) { + Text("→") + ForEach(reverseLookupResult, id: \.self) { currentResult in + ZStack(alignment: .center) { + Color(white: colorScheme == .dark ? 0.3 : 0.9).cornerRadius(3) + Text(" \(currentResult) ").lineLimit(1) + }.fixedSize() + } + } + .font(.system(size: max(CandidateCellData.unifiedSize * 0.6, 9))) + .padding([.horizontal], 4).padding([.vertical], 4) + .foregroundColor(colorScheme == .light ? Color(white: 0.1) : Color(white: 0.9)) + } + } ZStack(alignment: .trailing) { if tooltip.isEmpty { Color(white: colorScheme == .dark ? 0.2 : 0.9) @@ -101,15 +118,11 @@ public struct VwrCandidateHorizontalBackports: View { Color(white: colorScheme == .dark ? 0.0 : 1) controller.highlightedColorUIBackports } - HStack(alignment: .bottom) { + HStack(alignment: .center) { if !tooltip.isEmpty { Text(tooltip).lineLimit(1) Spacer() } - if !reverseLookupResult.isEmpty, !(controller.delegate?.isVerticalTyping ?? true) { - Text(reverseLookupResult).lineLimit(1) - Spacer() - } Text(positionLabel).lineLimit(1) } .font(.system(size: max(CandidateCellData.unifiedSize * 0.7, 11), weight: .bold)) @@ -120,6 +133,7 @@ public struct VwrCandidateHorizontalBackports: View { .fixedSize(horizontal: false, vertical: true) } .frame(minWidth: thePool.maxWindowWidth, maxWidth: thePool.maxWindowWidth) + .background(Color(white: colorScheme == .dark ? 0.1 : 1)) .overlay( RoundedRectangle(cornerRadius: 10).stroke(.white.opacity(0.2), lineWidth: 1) ) diff --git a/Packages/vChewing_CandidateWindow/Sources/CandidateWindow/TDKCandidates/VwrCandidateTDK_Backports/VwrCandidateVerticalBackports.swift b/Packages/vChewing_CandidateWindow/Sources/CandidateWindow/TDKCandidates/VwrCandidateTDK_Backports/VwrCandidateVerticalBackports.swift index 88b1c1c4..0b8ffcbf 100644 --- a/Packages/vChewing_CandidateWindow/Sources/CandidateWindow/TDKCandidates/VwrCandidateTDK_Backports/VwrCandidateVerticalBackports.swift +++ b/Packages/vChewing_CandidateWindow/Sources/CandidateWindow/TDKCandidates/VwrCandidateTDK_Backports/VwrCandidateVerticalBackports.swift @@ -35,11 +35,11 @@ struct CandidatePoolViewUIVerticalBackports_Previews: PreviewProvider { @available(macOS 10.15, *) public struct VwrCandidateVerticalBackports: View { - @Environment(\.colorScheme) var colorScheme public var controller: CtlCandidateTDK + @Environment(\.colorScheme) var colorScheme @State public var thePool: CandidatePool @State public var tooltip: String = "" - @State public var reverseLookupResult: String = "" + @State public var reverseLookupResult: [String] = ["MLGB"] private var positionLabel: String { (thePool.highlightedIndex + 1).description + "/" + thePool.candidateDataAll.count.description @@ -101,7 +101,23 @@ public struct VwrCandidateVerticalBackports: View { } } .fixedSize(horizontal: true, vertical: false).padding(5) - .background(Color(white: colorScheme == .dark ? 0.1 : 1)) + if controller.delegate?.showReverseLookupResult ?? true { + ZStack(alignment: .leading) { + Color(white: colorScheme == .dark ? 0.15 : 0.97) + HStack(alignment: .center, spacing: 4) { + Text("→") + ForEach(reverseLookupResult, id: \.self) { currentResult in + ZStack(alignment: .center) { + Color(white: colorScheme == .dark ? 0.3 : 0.9).cornerRadius(3) + Text(" \(currentResult) ").lineLimit(1) + }.fixedSize() + } + } + .font(.system(size: max(CandidateCellData.unifiedSize * 0.6, 9))) + .padding([.horizontal], 4).padding([.vertical], 4) + .foregroundColor(colorScheme == .light ? Color(white: 0.1) : Color(white: 0.9)) + } + } ZStack(alignment: .trailing) { if tooltip.isEmpty { Color(white: colorScheme == .dark ? 0.2 : 0.9) @@ -109,15 +125,11 @@ public struct VwrCandidateVerticalBackports: View { Color(white: colorScheme == .dark ? 0.0 : 1) controller.highlightedColorUIBackports } - HStack(alignment: .bottom) { + HStack(alignment: .center) { if !tooltip.isEmpty { Text(tooltip).lineLimit(1) Spacer() } - if !reverseLookupResult.isEmpty, !(controller.delegate?.isVerticalTyping ?? true) { - Text(reverseLookupResult).lineLimit(1) - Spacer() - } Text(positionLabel).lineLimit(1) } .font(.system(size: max(CandidateCellData.unifiedSize * 0.7, 11), weight: .bold)) @@ -127,6 +139,7 @@ public struct VwrCandidateVerticalBackports: View { } .fixedSize(horizontal: false, vertical: true) } + .background(Color(white: colorScheme == .dark ? 0.1 : 1)) .overlay( RoundedRectangle(cornerRadius: 10).stroke(.white.opacity(0.2), lineWidth: 1) ) diff --git a/Packages/vChewing_Shared/Sources/Shared/Protocols/CtlCandidateProtocol.swift b/Packages/vChewing_Shared/Sources/Shared/Protocols/CtlCandidateProtocol.swift index 717e85cf..5e673391 100644 --- a/Packages/vChewing_Shared/Sources/Shared/Protocols/CtlCandidateProtocol.swift +++ b/Packages/vChewing_Shared/Sources/Shared/Protocols/CtlCandidateProtocol.swift @@ -12,14 +12,15 @@ public protocol CtlCandidateDelegate { func candidatePairs(conv: Bool) -> [(String, String)] func candidatePairSelected(at index: Int) func candidates(_ sender: Any!) -> [Any]! - @discardableResult func annotate(for value: String) -> String + @discardableResult func reverseLookup(for value: String) -> [String] var selectionKeys: String { get } var isVerticalTyping: Bool { get } + var showReverseLookupResult: Bool { get } } public protocol CtlCandidateProtocol { var tooltip: String { get set } - var reverseLookupResult: String { get set } + var reverseLookupResult: [String] { get set } var locale: String { get set } var currentLayout: NSUserInterfaceLayoutOrientation { get set } var delegate: CtlCandidateDelegate? { get set } diff --git a/Source/Modules/SessionCtl_Delegates.swift b/Source/Modules/SessionCtl_Delegates.swift index 6e1f908d..939c3d25 100644 --- a/Source/Modules/SessionCtl_Delegates.swift +++ b/Source/Modules/SessionCtl_Delegates.swift @@ -56,14 +56,19 @@ extension SessionCtl: InputHandlerDelegate { // MARK: - Candidate Controller Delegate extension SessionCtl: CtlCandidateDelegate { - @discardableResult public func annotate(for value: String) -> String { + public var showReverseLookupResult: Bool { + !isVerticalTyping && PrefMgr.shared.showReverseLookupInCandidateUI + } + + @discardableResult public func reverseLookup(for value: String) -> [String] { + let blankResult: [String] = [] // 這一段專門處理「反查」。 - if !PrefMgr.shared.showReverseLookupInCandidateUI { return "" } - if isVerticalTyping { return "" } // 縱排輸入的場合,選字窗沒那個空間顯示反查結果。 - if value.isEmpty { return "" } // 空字串沒有需要反查的東西。 - if value.contains("_") { return "" } - guard let lookupResult = LMMgr.currentLM.currentCassette.reverseLookupMap[value] else { return "" } - return lookupResult.stableSort(by: { $0.count < $1.count }).joined(separator: " ") + if !PrefMgr.shared.showReverseLookupInCandidateUI { return blankResult } + if isVerticalTyping { return blankResult } // 縱排輸入的場合,選字窗沒有足夠的空間顯示反查結果。 + if value.isEmpty { return blankResult } // 空字串沒有需要反查的東西。 + if value.contains("_") { return blankResult } + guard let lookupResult = LMMgr.currentLM.currentCassette.reverseLookupMap[value] else { return blankResult } + return lookupResult.stableSort(by: { $0.count < $1.count }) } public var selectionKeys: String { diff --git a/Source/Modules/UIModules/CandidateUI/IMKCandidatesImpl.swift b/Source/Modules/UIModules/CandidateUI/IMKCandidatesImpl.swift index 04bec7e5..85bcb9c6 100644 --- a/Source/Modules/UIModules/CandidateUI/IMKCandidatesImpl.swift +++ b/Source/Modules/UIModules/CandidateUI/IMKCandidatesImpl.swift @@ -12,7 +12,7 @@ import Shared /// 威注音自用的 IMKCandidates 型別。因為有用到 bridging header,所以無法弄成 Swift Package。 public class CtlCandidateIMK: IMKCandidates, CtlCandidateProtocol { public var tooltip: String = "" - public var reverseLookupResult: String = "" + public var reverseLookupResult: [String] = [] public var locale: String = "" public var useLangIdentifier: Bool = false public var currentLayout: NSUserInterfaceLayoutOrientation = .horizontal