Repo // Move IMEState-related protocols to Shared package.

This commit is contained in:
ShikiSuen 2022-09-23 23:03:12 +08:00
parent cab7eb28f7
commit 1648152b24
10 changed files with 160 additions and 108 deletions

View File

@ -0,0 +1,64 @@
// (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
// IMEState
public protocol IMEStateProtocol {
var type: StateType { get }
var data: StateDataProtocol { get }
var isASCIIMode: Bool { get set }
var isVerticalTyping: Bool { get set }
var isVerticalCandidateWindow: Bool { get set }
var candidates: [(String, String)] { get set }
var hasComposition: Bool { get }
var isCandidateContainer: Bool { get }
var displayedText: String { get }
var displayedTextConverted: String { get }
var textToCommit: String { get set }
var tooltip: String { get set }
var attributedString: NSAttributedString { get }
var convertedToInputting: IMEStateProtocol { get }
var isFilterable: Bool { get }
var isMarkedLengthValid: Bool { get }
var node: CandidateNode { get set }
var displayTextSegments: [String] { get }
var tooltipBackupForInputting: String { get set }
var markedRange: Range<Int> { get }
var u16MarkedRange: Range<Int> { get }
var u16Cursor: Int { get }
var cursor: Int { get set }
var marker: Int { get set }
}
public protocol StateDataProtocol {
var cursor: Int { get set }
var marker: Int { get set }
var markedRange: Range<Int> { get }
var u16MarkedRange: Range<Int> { get }
var u16Cursor: Int { get }
var textToCommit: String { get set }
var markedReadings: [String] { get set }
var displayTextSegments: [String] { get set }
var isFilterable: Bool { get }
var isVerticalTyping: Bool { get set }
var isMarkedLengthValid: Bool { get }
var candidates: [(String, String)] { get set }
var displayedText: String { get set }
var displayedTextConverted: String { get }
var tooltipBackupForInputting: String { get set }
var tooltip: String { get set }
var attributedStringNormal: NSAttributedString { get }
var attributedStringMarking: NSAttributedString { get }
var attributedStringPlaceholder: NSAttributedString { get }
var userPhraseDumped: String { get }
var userPhraseDumpedConverted: String { get }
var doesUserPhraseExist: Bool { get }
var tooltipColorState: TooltipColorState { get set }
mutating func updateTooltipForMarking()
}

View File

@ -103,6 +103,33 @@ public enum UserDef: String, CaseIterable {
}
}
// MARK: - Tooltip Color States
public enum TooltipColorState {
case normal
case redAlert
case warning
case denialOverflow
case denialInsufficiency
case prompt
}
// MARK: - IMEState types.
// enum
public enum StateType: String {
case ofDeactivated = "Deactivated"
case ofEmpty = "Empty"
case ofAbortion = "Abortion" // Empty
case ofCommitting = "Committing"
case ofAssociates = "Associates"
case ofNotEmpty = "NotEmpty"
case ofInputting = "Inputting"
case ofMarking = "Marking"
case ofCandidates = "Candidates"
case ofSymbolTable = "SymbolTable"
}
// MARK: - Parser for Syllable composer
public enum KeyboardParser: Int, CaseIterable {

View File

@ -15,6 +15,7 @@ let package = Package(
dependencies: [
.package(path: "../Fuziki_NSAttributedTextView"),
.package(path: "../vChewing_CocoaExtension"),
.package(path: "../vChewing_Shared"),
],
targets: [
.target(
@ -22,6 +23,7 @@ let package = Package(
dependencies: [
.product(name: "NSAttributedTextView", package: "Fuziki_NSAttributedTextView"),
.product(name: "CocoaExtension", package: "vChewing_CocoaExtension"),
.product(name: "Shared", package: "vChewing_Shared"),
]
)
]

View File

@ -9,17 +9,9 @@
import Cocoa
import CocoaExtension
import NSAttributedTextView
import Shared
public class TooltipUI: NSWindowController {
public enum ColorStates {
case normal
case redAlert
case warning
case denialOverflow
case denialInsufficiency
case prompt
}
private var messageText: NSAttributedTooltipTextView
private var tooltip: String = "" {
didSet {
@ -68,7 +60,7 @@ public class TooltipUI: NSWindowController {
set(windowTopLeftPoint: point, bottomOutOfScreenAdjustmentHeight: heightDelta)
}
public func setColor(state: ColorStates) {
public func setColor(state: TooltipColorState) {
var backgroundColor = NSColor.controlBackgroundColor
var textColor = NSColor.textColor
switch state {

View File

@ -7,47 +7,7 @@
// requirements defined in MIT License.
import LangModelAssembly
// enum
public enum StateType: String {
case ofDeactivated = "Deactivated"
case ofEmpty = "Empty"
case ofAbortion = "Abortion" // Empty
case ofCommitting = "Committing"
case ofAssociates = "Associates"
case ofNotEmpty = "NotEmpty"
case ofInputting = "Inputting"
case ofMarking = "Marking"
case ofCandidates = "Candidates"
case ofSymbolTable = "SymbolTable"
}
// IMEState
public protocol IMEStateProtocol {
var type: StateType { get }
var data: StateData { get }
var isASCIIMode: Bool { get set }
var isVerticalTyping: Bool { get set }
var isVerticalCandidateWindow: Bool { get set }
var candidates: [(String, String)] { get }
var hasComposition: Bool { get }
var isCandidateContainer: Bool { get }
var displayedText: String { get }
var displayedTextConverted: String { get }
var textToCommit: String { get set }
var tooltip: String { get set }
var attributedString: NSAttributedString { get }
var convertedToInputting: IMEState { get }
var isFilterable: Bool { get }
var isMarkedLengthValid: Bool { get }
var node: CandidateNode { get set }
var displayTextSegments: [String] { get }
var tooltipBackupForInputting: String { get set }
var markedRange: Range<Int> { get }
var cursor: Int { get }
var u16MarkedRange: Range<Int> { get }
var u16Cursor: Int { get }
}
import Shared
/// ctlInputMethod
///
@ -82,17 +42,17 @@ public protocol IMEStateProtocol {
/// - .SymbolTable:
public struct IMEState: IMEStateProtocol {
public var type: StateType = .ofEmpty
public var data: StateData = .init()
public var data: StateDataProtocol = StateData() as StateDataProtocol
public var node: CandidateNode = .init(name: "")
public var isASCIIMode = false
public var isVerticalCandidateWindow = false
init(_ data: StateData = .init(), type: StateType = .ofEmpty) {
init(_ data: StateDataProtocol = StateData() as StateDataProtocol, type: StateType = .ofEmpty) {
self.data = data
self.type = type
isVerticalTyping = ctlInputMethod.isVerticalTyping
}
init(_ data: StateData = .init(), type: StateType = .ofEmpty, node: CandidateNode) {
init(_ data: StateDataProtocol = StateData() as StateDataProtocol, type: StateType = .ofEmpty, node: CandidateNode) {
self.data = data
self.type = type
self.node = node
@ -108,14 +68,14 @@ extension IMEState {
public static func ofAbortion() -> IMEState { .init(type: .ofAbortion) }
public static func ofCommitting(textToCommit: String) -> IMEState {
var result = IMEState(type: .ofCommitting)
result.data.textToCommit = textToCommit
result.textToCommit = textToCommit
ChineseConverter.ensureCurrencyNumerals(target: &result.data.textToCommit)
return result
}
public static func ofAssociates(candidates: [(String, String)]) -> IMEState {
var result = IMEState(type: .ofAssociates)
result.data.candidates = candidates
result.candidates = candidates
return result
}
@ -175,15 +135,24 @@ extension IMEState {
extension IMEState {
public var isFilterable: Bool { data.isFilterable }
public var isMarkedLengthValid: Bool { data.isMarkedLengthValid }
public var candidates: [(String, String)] { data.candidates }
public var displayedText: String { data.displayedText }
public var displayedTextConverted: String { data.displayedTextConverted }
public var cursor: Int { data.cursor }
public var displayTextSegments: [String] { data.displayTextSegments }
public var markedRange: Range<Int> { data.markedRange }
public var u16MarkedRange: Range<Int> { data.u16MarkedRange }
public var u16Cursor: Int { data.u16Cursor }
public var convertedToInputting: IMEState {
public var cursor: Int {
get { data.cursor }
set { data.cursor = newValue }
}
public var marker: Int {
get { data.marker }
set { data.marker = newValue }
}
public var convertedToInputting: IMEStateProtocol {
if type == .ofInputting { return self }
var result = IMEState.ofInputting(displayTextSegments: data.displayTextSegments, cursor: data.cursor)
result.tooltip = data.tooltipBackupForInputting
@ -191,22 +160,19 @@ extension IMEState {
return result
}
public var candidates: [(String, String)] {
get { data.candidates }
set { data.candidates = newValue }
}
public var textToCommit: String {
get {
data.textToCommit
}
set {
data.textToCommit = newValue
}
get { data.textToCommit }
set { data.textToCommit = newValue }
}
public var tooltip: String {
get {
data.tooltip
}
set {
data.tooltip = newValue
}
get { data.tooltip }
set { data.tooltip = newValue }
}
public var attributedString: NSAttributedString {
@ -237,11 +203,7 @@ extension IMEState {
}
public var tooltipBackupForInputting: String {
get {
data.tooltipBackupForInputting
}
set {
data.tooltipBackupForInputting = newValue
}
get { data.tooltipBackupForInputting }
set { data.tooltipBackupForInputting = newValue }
}
}

View File

@ -6,10 +6,11 @@
// marks, or product names of Contributor, except as required to fulfill notice
// requirements defined in MIT License.
import Shared
import Tekkon
import TooltipUI
public struct StateData {
public struct StateData: StateDataProtocol {
private static var minCandidateLength: Int {
PrefMgr.shared.allowBoostingSingleKanjiAsUserPhrase ? 1 : 2
}
@ -18,8 +19,8 @@ public struct StateData {
Self.minCandidateLength...PrefMgr.shared.maxCandidateLength
}
var displayedText: String = ""
var displayedTextConverted: String {
public var displayedText: String = ""
public var displayedTextConverted: String {
///
var result = ChineseConverter.kanjiConversionIfRequired(displayedText)
if result.utf16.count != displayedText.utf16.count
@ -32,19 +33,19 @@ public struct StateData {
// MARK: Cursor & Marker & Range for UTF8
var cursor: Int = 0 {
public var cursor: Int = 0 {
didSet {
cursor = min(max(cursor, 0), displayedText.count)
}
}
var marker: Int = 0 {
public var marker: Int = 0 {
didSet {
marker = min(max(marker, 0), displayedText.count)
}
}
var markedRange: Range<Int> {
public var markedRange: Range<Int> {
min(cursor, marker)..<max(cursor, marker)
}
@ -53,58 +54,58 @@ public struct StateData {
/// IMK UTF8 emoji
/// Swift.utf16NSString.length()
///
var u16Cursor: Int {
public var u16Cursor: Int {
displayedText.charComponents[0..<cursor].joined().utf16.count
}
var u16Marker: Int {
public var u16Marker: Int {
displayedText.charComponents[0..<marker].joined().utf16.count
}
var u16MarkedRange: Range<Int> {
public var u16MarkedRange: Range<Int> {
min(u16Cursor, u16Marker)..<max(u16Cursor, u16Marker)
}
// MARK: Other data for non-empty states.
var isVerticalTyping = false
var markedTargetExists: Bool {
public var isVerticalTyping = false
public var markedTargetExists: Bool {
let pair = userPhraseKVPair
return LMMgr.checkIfUserPhraseExist(
userPhrase: pair.1, mode: IMEApp.currentInputMode, key: pair.0
)
}
var displayTextSegments = [String]() {
public var displayTextSegments = [String]() {
didSet {
displayedText = displayTextSegments.joined()
}
}
var reading: String = ""
var markedReadings = [String]()
var candidates = [(String, String)]()
var textToCommit: String = ""
var tooltip: String = ""
var tooltipBackupForInputting: String = ""
var attributedStringPlaceholder: NSAttributedString = .init(
public var reading: String = ""
public var markedReadings = [String]()
public var candidates = [(String, String)]()
public var textToCommit: String = ""
public var tooltip: String = ""
public var tooltipBackupForInputting: String = ""
public var attributedStringPlaceholder: NSAttributedString = .init(
string: " ",
attributes: [
.underlineStyle: NSUnderlineStyle.single.rawValue,
.markedClauseSegment: 0,
]
)
var isFilterable: Bool {
public var isFilterable: Bool {
markedTargetExists ? isMarkedLengthValid : false
}
var isMarkedLengthValid: Bool {
public var isMarkedLengthValid: Bool {
Self.allowedMarkLengthRange.contains(markedRange.count)
}
var tooltipColorState: TooltipUI.ColorStates = .normal
public var tooltipColorState: TooltipColorState = .normal
var attributedStringNormal: NSAttributedString {
public var attributedStringNormal: NSAttributedString {
///
/// JIS
let attributedString = NSMutableAttributedString(string: displayedTextConverted)
@ -122,7 +123,7 @@ public struct StateData {
return attributedString
}
var attributedStringMarking: NSAttributedString {
public var attributedStringMarking: NSAttributedString {
///
/// JIS
let attributedString = NSMutableAttributedString(string: displayedTextConverted)
@ -161,7 +162,7 @@ public struct StateData {
// MARK: - IMEState
extension StateData {
var chkIfUserPhraseExists: Bool {
public var doesUserPhraseExist: Bool {
let text = displayedText.charComponents[markedRange].joined()
let joined = markedReadings.joined(separator: "-")
return LMMgr.checkIfUserPhraseExist(
@ -169,7 +170,7 @@ extension StateData {
)
}
var readingThreadForDisplay: String {
public var readingThreadForDisplay: String {
var arrOutput = [String]()
for neta in markedReadings {
var neta = neta
@ -193,19 +194,19 @@ extension StateData {
return arrOutput.joined(separator: "\u{A0}")
}
var userPhraseKVPair: (String, String) {
public var userPhraseKVPair: (String, String) {
let key = markedReadings.joined(separator: "-")
let value = displayedText.charComponents[markedRange].joined()
return (key, value)
}
var userPhraseDumped: String {
public var userPhraseDumped: String {
let pair = userPhraseKVPair
let nerfedScore = ctlInputMethod.areWeNerfing && markedTargetExists ? " -114.514" : ""
return "\(pair.1) \(pair.0)\(nerfedScore)"
}
var userPhraseDumpedConverted: String {
public var userPhraseDumpedConverted: String {
let pair = userPhraseKVPair
let text = ChineseConverter.crossConvert(pair.1) ?? ""
let nerfedScore = ctlInputMethod.areWeNerfing && markedTargetExists ? " -114.514" : ""
@ -213,7 +214,7 @@ extension StateData {
return "\(text) \(pair.0)\(nerfedScore)\t\(convertedMark)"
}
mutating func updateTooltipForMarking() {
public mutating func updateTooltipForMarking() {
var tooltipForMarking: String {
let pair = userPhraseKVPair
if PrefMgr.shared.phraseReplacementEnabled {

View File

@ -6,6 +6,8 @@
// marks, or product names of Contributor, except as required to fulfill notice
// requirements defined in MIT License.
import Shared
public class ctlPopupCompositionBuffer: NSWindowController {
public var isTypingDirectionVertical = false {
didSet {

View File

@ -32,7 +32,7 @@ extension ctlInputMethod: KeyHandlerDelegate {
(inputMode == .imeModeCHT) ? .imeModeCHS : .imeModeCHT
if !LMMgr.writeUserPhrase(
state.data.userPhraseDumped, inputMode: inputMode,
areWeDuplicating: state.data.chkIfUserPhraseExists,
areWeDuplicating: state.data.doesUserPhraseExist,
areWeDeleting: addToFilter
)
|| !LMMgr.writeUserPhrase(

View File

@ -8,6 +8,8 @@
// marks, or product names of Contributor, except as required to fulfill notice
// requirements defined in MIT License.
import Shared
// MARK: - 調 (State Handling)
extension ctlInputMethod {