Refactors the input controller.
This commit is contained in:
parent
6fe2fc59f3
commit
1ad9e23918
|
@ -52,7 +52,7 @@
|
||||||
D44FB74727919D35003C80A6 /* EmacsKeyHelper.swift in Sources */ = {isa = PBXBuildFile; fileRef = D44FB74627919C83003C80A6 /* EmacsKeyHelper.swift */; };
|
D44FB74727919D35003C80A6 /* EmacsKeyHelper.swift in Sources */ = {isa = PBXBuildFile; fileRef = D44FB74627919C83003C80A6 /* EmacsKeyHelper.swift */; };
|
||||||
D44FB74A2791B829003C80A6 /* VXHanConvert in Frameworks */ = {isa = PBXBuildFile; productRef = D44FB7492791B829003C80A6 /* VXHanConvert */; };
|
D44FB74A2791B829003C80A6 /* VXHanConvert in Frameworks */ = {isa = PBXBuildFile; productRef = D44FB7492791B829003C80A6 /* VXHanConvert */; };
|
||||||
D44FB74D2792189A003C80A6 /* PhraseReplacementMap.cpp in Sources */ = {isa = PBXBuildFile; fileRef = D44FB74B2792189A003C80A6 /* PhraseReplacementMap.cpp */; };
|
D44FB74D2792189A003C80A6 /* PhraseReplacementMap.cpp in Sources */ = {isa = PBXBuildFile; fileRef = D44FB74B2792189A003C80A6 /* PhraseReplacementMap.cpp */; };
|
||||||
D456576E279E4F7B00DF6BC9 /* KeyHandler.swift in Sources */ = {isa = PBXBuildFile; fileRef = D456576D279E4F7B00DF6BC9 /* KeyHandler.swift */; };
|
D456576E279E4F7B00DF6BC9 /* KeyHandlerInput.swift in Sources */ = {isa = PBXBuildFile; fileRef = D456576D279E4F7B00DF6BC9 /* KeyHandlerInput.swift */; };
|
||||||
D461B792279DAC010070E734 /* InputState.swift in Sources */ = {isa = PBXBuildFile; fileRef = D461B791279DAC010070E734 /* InputState.swift */; };
|
D461B792279DAC010070E734 /* InputState.swift in Sources */ = {isa = PBXBuildFile; fileRef = D461B791279DAC010070E734 /* InputState.swift */; };
|
||||||
D47B92C027972AD100458394 /* main.swift in Sources */ = {isa = PBXBuildFile; fileRef = D47B92BF27972AC800458394 /* main.swift */; };
|
D47B92C027972AD100458394 /* main.swift in Sources */ = {isa = PBXBuildFile; fileRef = D47B92BF27972AC800458394 /* main.swift */; };
|
||||||
D47F7DCE278BFB57002F9DD7 /* PreferencesWindowController.swift in Sources */ = {isa = PBXBuildFile; fileRef = D47F7DCD278BFB57002F9DD7 /* PreferencesWindowController.swift */; };
|
D47F7DCE278BFB57002F9DD7 /* PreferencesWindowController.swift in Sources */ = {isa = PBXBuildFile; fileRef = D47F7DCD278BFB57002F9DD7 /* PreferencesWindowController.swift */; };
|
||||||
|
@ -206,7 +206,7 @@
|
||||||
D44FB7482791B346003C80A6 /* VXHanConvert */ = {isa = PBXFileReference; lastKnownFileType = wrapper; name = VXHanConvert; path = Packages/VXHanConvert; sourceTree = "<group>"; };
|
D44FB7482791B346003C80A6 /* VXHanConvert */ = {isa = PBXFileReference; lastKnownFileType = wrapper; name = VXHanConvert; path = Packages/VXHanConvert; sourceTree = "<group>"; };
|
||||||
D44FB74B2792189A003C80A6 /* PhraseReplacementMap.cpp */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; path = PhraseReplacementMap.cpp; sourceTree = "<group>"; };
|
D44FB74B2792189A003C80A6 /* PhraseReplacementMap.cpp */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; path = PhraseReplacementMap.cpp; sourceTree = "<group>"; };
|
||||||
D44FB74C2792189A003C80A6 /* PhraseReplacementMap.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = PhraseReplacementMap.h; sourceTree = "<group>"; };
|
D44FB74C2792189A003C80A6 /* PhraseReplacementMap.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = PhraseReplacementMap.h; sourceTree = "<group>"; };
|
||||||
D456576D279E4F7B00DF6BC9 /* KeyHandler.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = KeyHandler.swift; sourceTree = "<group>"; };
|
D456576D279E4F7B00DF6BC9 /* KeyHandlerInput.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = KeyHandlerInput.swift; sourceTree = "<group>"; };
|
||||||
D461B791279DAC010070E734 /* InputState.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = InputState.swift; sourceTree = "<group>"; };
|
D461B791279DAC010070E734 /* InputState.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = InputState.swift; sourceTree = "<group>"; };
|
||||||
D47B92BF27972AC800458394 /* main.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = main.swift; sourceTree = "<group>"; };
|
D47B92BF27972AC800458394 /* main.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = main.swift; sourceTree = "<group>"; };
|
||||||
D47F7DCD278BFB57002F9DD7 /* PreferencesWindowController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = PreferencesWindowController.swift; sourceTree = "<group>"; };
|
D47F7DCD278BFB57002F9DD7 /* PreferencesWindowController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = PreferencesWindowController.swift; sourceTree = "<group>"; };
|
||||||
|
@ -304,13 +304,13 @@
|
||||||
D41355D6278D7409005E5CBD /* LanguageModelManager.h */,
|
D41355D6278D7409005E5CBD /* LanguageModelManager.h */,
|
||||||
D41355D7278D7409005E5CBD /* LanguageModelManager.mm */,
|
D41355D7278D7409005E5CBD /* LanguageModelManager.mm */,
|
||||||
D461B791279DAC010070E734 /* InputState.swift */,
|
D461B791279DAC010070E734 /* InputState.swift */,
|
||||||
D456576D279E4F7B00DF6BC9 /* KeyHandler.swift */,
|
D456576D279E4F7B00DF6BC9 /* KeyHandlerInput.swift */,
|
||||||
D47B92BF27972AC800458394 /* main.swift */,
|
|
||||||
D427F76B278CA1BA004A2160 /* AppDelegate.swift */,
|
D427F76B278CA1BA004A2160 /* AppDelegate.swift */,
|
||||||
D44FB74427915555003C80A6 /* Preferences.swift */,
|
D44FB74427915555003C80A6 /* Preferences.swift */,
|
||||||
D44FB74627919C83003C80A6 /* EmacsKeyHelper.swift */,
|
D44FB74627919C83003C80A6 /* EmacsKeyHelper.swift */,
|
||||||
D47F7DCF278C0897002F9DD7 /* NonModalAlertWindowController.swift */,
|
D47F7DCF278C0897002F9DD7 /* NonModalAlertWindowController.swift */,
|
||||||
D47F7DCD278BFB57002F9DD7 /* PreferencesWindowController.swift */,
|
D47F7DCD278BFB57002F9DD7 /* PreferencesWindowController.swift */,
|
||||||
|
D47B92BF27972AC800458394 /* main.swift */,
|
||||||
6A0D4EF615FC0DA600ABF4B3 /* McBopomofo-Prefix.pch */,
|
6A0D4EF615FC0DA600ABF4B3 /* McBopomofo-Prefix.pch */,
|
||||||
D427A9BF25ED28CC005D43E0 /* McBopomofo-Bridging-Header.h */,
|
D427A9BF25ED28CC005D43E0 /* McBopomofo-Bridging-Header.h */,
|
||||||
);
|
);
|
||||||
|
@ -708,7 +708,7 @@
|
||||||
D44FB74D2792189A003C80A6 /* PhraseReplacementMap.cpp in Sources */,
|
D44FB74D2792189A003C80A6 /* PhraseReplacementMap.cpp in Sources */,
|
||||||
D44FB74527915565003C80A6 /* Preferences.swift in Sources */,
|
D44FB74527915565003C80A6 /* Preferences.swift in Sources */,
|
||||||
D47F7DD0278C0897002F9DD7 /* NonModalAlertWindowController.swift in Sources */,
|
D47F7DD0278C0897002F9DD7 /* NonModalAlertWindowController.swift in Sources */,
|
||||||
D456576E279E4F7B00DF6BC9 /* KeyHandler.swift in Sources */,
|
D456576E279E4F7B00DF6BC9 /* KeyHandlerInput.swift in Sources */,
|
||||||
D47F7DCE278BFB57002F9DD7 /* PreferencesWindowController.swift in Sources */,
|
D47F7DCE278BFB57002F9DD7 /* PreferencesWindowController.swift in Sources */,
|
||||||
6A0D4ED215FC0D6400ABF4B3 /* InputMethodController.mm in Sources */,
|
6A0D4ED215FC0D6400ABF4B3 /* InputMethodController.mm in Sources */,
|
||||||
D41355DB278E6D17005E5CBD /* McBopomofoLM.cpp in Sources */,
|
D41355DB278E6D17005E5CBD /* McBopomofoLM.cpp in Sources */,
|
||||||
|
|
|
@ -53,11 +53,6 @@ namespace Formosa {
|
||||||
void setJoinSeparator(const string& separator);
|
void setJoinSeparator(const string& separator);
|
||||||
const string joinSeparator() const;
|
const string joinSeparator() const;
|
||||||
|
|
||||||
// TODO: Remove these later.
|
|
||||||
size_t markerCursorIndex() const;
|
|
||||||
// TODO: Remove these later.
|
|
||||||
void setMarkerCursorIndex(size_t inNewIndex);
|
|
||||||
|
|
||||||
vector<string> readingsAtRange(size_t begin, size_t end) const;
|
vector<string> readingsAtRange(size_t begin, size_t end) const;
|
||||||
|
|
||||||
Grid& grid();
|
Grid& grid();
|
||||||
|
@ -71,7 +66,6 @@ namespace Formosa {
|
||||||
static const size_t MaximumBuildSpanLength = 6;
|
static const size_t MaximumBuildSpanLength = 6;
|
||||||
|
|
||||||
size_t m_cursorIndex;
|
size_t m_cursorIndex;
|
||||||
size_t m_markerCursorIndex;
|
|
||||||
vector<string> m_readings;
|
vector<string> m_readings;
|
||||||
|
|
||||||
Grid m_grid;
|
Grid m_grid;
|
||||||
|
@ -82,14 +76,12 @@ namespace Formosa {
|
||||||
inline BlockReadingBuilder::BlockReadingBuilder(LanguageModel *inLM)
|
inline BlockReadingBuilder::BlockReadingBuilder(LanguageModel *inLM)
|
||||||
: m_LM(inLM)
|
: m_LM(inLM)
|
||||||
, m_cursorIndex(0)
|
, m_cursorIndex(0)
|
||||||
, m_markerCursorIndex(SIZE_MAX)
|
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
inline void BlockReadingBuilder::clear()
|
inline void BlockReadingBuilder::clear()
|
||||||
{
|
{
|
||||||
m_cursorIndex = 0;
|
m_cursorIndex = 0;
|
||||||
m_markerCursorIndex = SIZE_MAX;
|
|
||||||
m_readings.clear();
|
m_readings.clear();
|
||||||
m_grid.clear();
|
m_grid.clear();
|
||||||
}
|
}
|
||||||
|
@ -109,21 +101,6 @@ namespace Formosa {
|
||||||
m_cursorIndex = inNewIndex > m_readings.size() ? m_readings.size() : inNewIndex;
|
m_cursorIndex = inNewIndex > m_readings.size() ? m_readings.size() : inNewIndex;
|
||||||
}
|
}
|
||||||
|
|
||||||
inline size_t BlockReadingBuilder::markerCursorIndex() const
|
|
||||||
{
|
|
||||||
return m_markerCursorIndex;
|
|
||||||
}
|
|
||||||
|
|
||||||
inline void BlockReadingBuilder::setMarkerCursorIndex(size_t inNewIndex)
|
|
||||||
{
|
|
||||||
if (inNewIndex == SIZE_MAX) {
|
|
||||||
m_markerCursorIndex = SIZE_MAX;
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
m_markerCursorIndex = inNewIndex > m_readings.size() ? m_readings.size() : inNewIndex;
|
|
||||||
}
|
|
||||||
|
|
||||||
inline void BlockReadingBuilder::insertReadingAtCursor(const string& inReading)
|
inline void BlockReadingBuilder::insertReadingAtCursor(const string& inReading)
|
||||||
{
|
{
|
||||||
m_readings.insert(m_readings.begin() + m_cursorIndex, inReading);
|
m_readings.insert(m_readings.begin() + m_cursorIndex, inReading);
|
||||||
|
|
|
@ -27,12 +27,12 @@
|
||||||
#import "Gramambular.h"
|
#import "Gramambular.h"
|
||||||
#import "McBopomofoLM.h"
|
#import "McBopomofoLM.h"
|
||||||
#import "UserOverrideModel.h"
|
#import "UserOverrideModel.h"
|
||||||
|
#import "McBopomofo-Swift.h"
|
||||||
|
|
||||||
@interface McBopomofoInputMethodController : IMKInputController
|
@interface McBopomofoInputMethodController : IMKInputController {
|
||||||
{
|
|
||||||
@private
|
@private
|
||||||
// the reading buffer that takes user input
|
// the reading buffer that takes user input
|
||||||
Formosa::Mandarin::BopomofoReadingBuffer* _bpmfReadingBuffer;
|
Formosa::Mandarin::BopomofoReadingBuffer *_bpmfReadingBuffer;
|
||||||
|
|
||||||
// language model
|
// language model
|
||||||
McBopomofo::McBopomofoLM *_languageModel;
|
McBopomofo::McBopomofoLM *_languageModel;
|
||||||
|
@ -41,26 +41,19 @@
|
||||||
McBopomofo::UserOverrideModel *_userOverrideModel;
|
McBopomofo::UserOverrideModel *_userOverrideModel;
|
||||||
|
|
||||||
// the grid (lattice) builder for the unigrams (and bigrams)
|
// the grid (lattice) builder for the unigrams (and bigrams)
|
||||||
Formosa::Gramambular::BlockReadingBuilder* _builder;
|
Formosa::Gramambular::BlockReadingBuilder *_builder;
|
||||||
|
|
||||||
// latest walked path (trellis) using the Viterbi algorithm
|
// latest walked path (trellis) using the Viterbi algorithm
|
||||||
std::vector<Formosa::Gramambular::NodeAnchor> _walkedNodes;
|
std::vector<Formosa::Gramambular::NodeAnchor> _walkedNodes;
|
||||||
|
|
||||||
// the latest composing buffer that is updated to the foreground app
|
|
||||||
NSMutableString *_composingBuffer;
|
|
||||||
NSInteger _latestReadingCursor;
|
|
||||||
|
|
||||||
// the current text input client; we need to keep this when candidate panel is on
|
|
||||||
id _currentCandidateClient;
|
|
||||||
|
|
||||||
// a special deferred client for Terminal.app fix
|
|
||||||
id _currentDeferredClient;
|
|
||||||
|
|
||||||
// current available candidates
|
|
||||||
NSMutableArray *_candidates;
|
|
||||||
|
|
||||||
// current input mode
|
|
||||||
NSString *_inputMode;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
- (BOOL)handleInput:(KeyHandlerInput *)input
|
||||||
|
state:(InputState *)state
|
||||||
|
stateCallback:(void (^)(InputState *))stateCallback
|
||||||
|
candidateSelectionCallback:(void (^)(void))candidateSelectionCallback
|
||||||
|
errorCallback:(void (^)(void))errorCallback;
|
||||||
|
|
||||||
|
- (void)handleState:(InputState *)newState
|
||||||
|
client:(id)client;
|
||||||
|
|
||||||
@end
|
@end
|
||||||
|
|
File diff suppressed because it is too large
Load Diff
|
@ -1,14 +1,18 @@
|
||||||
import Cocoa
|
import Cocoa
|
||||||
|
|
||||||
|
/// Represents the states for the input controller.
|
||||||
class InputState: NSObject {
|
class InputState: NSObject {
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Represents that the input controller is deactive.
|
||||||
class InputStateDeactive: InputState {
|
class InputStateDeactive: InputState {
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Represents that the composing buffer is empty.
|
||||||
class InputStateEmpty: InputState {
|
class InputStateEmpty: InputState {
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Represents that the input controller is committing text into client app.
|
||||||
class InputStateCommitting: InputState {
|
class InputStateCommitting: InputState {
|
||||||
@objc private(set) var poppedText: String = ""
|
@objc private(set) var poppedText: String = ""
|
||||||
|
|
||||||
|
@ -18,17 +22,28 @@ class InputStateCommitting: InputState {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
class InputStateInputting: InputState {
|
/// Represents that the composing buffer is not empty.
|
||||||
|
class InputStateNotEmpty: InputState {
|
||||||
@objc private(set) var composingBuffer: String = ""
|
@objc private(set) var composingBuffer: String = ""
|
||||||
@objc private(set) var cursorIndex: UInt = 0
|
@objc private(set) var cursorIndex: UInt = 0
|
||||||
@objc var poppedText: String = ""
|
|
||||||
|
|
||||||
@objc init(composingBuffer: String, cursorIndex: UInt) {
|
@objc init(composingBuffer: String, cursorIndex: UInt) {
|
||||||
self.composingBuffer = composingBuffer
|
self.composingBuffer = composingBuffer
|
||||||
self.cursorIndex = cursorIndex
|
self.cursorIndex = cursorIndex
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
@objc var attributedSting: NSAttributedString {
|
/// Represents that the user is inputting text.
|
||||||
|
class InputStateInputting: InputStateNotEmpty {
|
||||||
|
@objc var bpmfReading: String = ""
|
||||||
|
@objc var bpmfReadingCursotIndex: UInt8 = 0
|
||||||
|
@objc var poppedText: String = ""
|
||||||
|
|
||||||
|
@objc override init(composingBuffer: String, cursorIndex: UInt) {
|
||||||
|
super.init(composingBuffer: composingBuffer, cursorIndex: cursorIndex)
|
||||||
|
}
|
||||||
|
|
||||||
|
@objc var attributedString: NSAttributedString {
|
||||||
let attrs: [NSAttributedString.Key : Any] = [
|
let attrs: [NSAttributedString.Key : Any] = [
|
||||||
.underlineStyle: NSUnderlineStyle.single,
|
.underlineStyle: NSUnderlineStyle.single,
|
||||||
.markedClauseSegment: 0
|
.markedClauseSegment: 0
|
||||||
|
@ -38,13 +53,37 @@ class InputStateInputting: InputState {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
class InputStateMarking: InputStateInputting {
|
private let kMinMarkRangeLength = 2
|
||||||
|
private let kMaxMarkRangeLength = 6
|
||||||
|
|
||||||
|
|
||||||
|
/// Represents that the user is marking a range in the composing buffer.
|
||||||
|
class InputStateMarking: InputStateNotEmpty {
|
||||||
|
@objc private(set) var readings: [String] = []
|
||||||
@objc private(set) var markerIndex: UInt = 0
|
@objc private(set) var markerIndex: UInt = 0
|
||||||
@objc private(set) var markedRange: NSRange = NSRange(location: 0, length: 0)
|
@objc private(set) var markedRange: NSRange = NSRange(location: 0, length: 0)
|
||||||
@objc var tooltip: String {
|
@objc var tooltip: String {
|
||||||
|
|
||||||
|
if Preferences.phraseReplacementEnabled {
|
||||||
|
return NSLocalizedString("Phrase replacement mode is on. Not suggested to add phrase in the mode.", comment: "")
|
||||||
|
}
|
||||||
|
if Preferences.chineseConversionStyle == 1 && Preferences.chineseConversionEnabled {
|
||||||
|
return NSLocalizedString("Model based Chinese conversion is on. Not suggested to add phrase in the mode.", comment: "")
|
||||||
|
}
|
||||||
|
if markedRange.length == 0 {
|
||||||
return ""
|
return ""
|
||||||
}
|
}
|
||||||
|
|
||||||
|
let text = (composingBuffer as NSString).substring(with: markedRange)
|
||||||
|
if markedRange.length < kMinMarkRangeLength {
|
||||||
|
return String(format: NSLocalizedString("You are now selecting \"%@\". You can add a phrase with two or more characters.", comment: ""), text)
|
||||||
|
} else if (markedRange.length > kMaxMarkRangeLength) {
|
||||||
|
return String(format: NSLocalizedString("You are now selecting \"%@\". A phrase cannot be longer than %d characters.", comment: ""), text, kMaxMarkRangeLength)
|
||||||
|
}
|
||||||
|
return String(format: NSLocalizedString("You are now selecting \"%@\". Press enter to add a new phrase.", comment: ""), text)
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
@objc init(composingBuffer: String, cursorIndex: UInt, markerIndex: UInt) {
|
@objc init(composingBuffer: String, cursorIndex: UInt, markerIndex: UInt) {
|
||||||
super.init(composingBuffer: composingBuffer, cursorIndex: cursorIndex)
|
super.init(composingBuffer: composingBuffer, cursorIndex: cursorIndex)
|
||||||
self.markerIndex = markerIndex
|
self.markerIndex = markerIndex
|
||||||
|
@ -53,7 +92,7 @@ class InputStateMarking: InputStateInputting {
|
||||||
self.markedRange = NSMakeRange(Int(begin), Int(end - begin))
|
self.markedRange = NSMakeRange(Int(begin), Int(end - begin))
|
||||||
}
|
}
|
||||||
|
|
||||||
@objc override var attributedSting: NSAttributedString {
|
@objc var attributedString: NSAttributedString {
|
||||||
let attributedSting = NSMutableAttributedString(string: composingBuffer)
|
let attributedSting = NSMutableAttributedString(string: composingBuffer)
|
||||||
attributedSting.setAttributes([
|
attributedSting.setAttributes([
|
||||||
NSAttributedString.Key.underlineStyle: NSUnderlineStyle.single,
|
NSAttributedString.Key.underlineStyle: NSUnderlineStyle.single,
|
||||||
|
@ -72,7 +111,23 @@ class InputStateMarking: InputStateInputting {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
class InputStateChoosingCandidate: InputStateInputting {
|
/// Represents that the user is choosing in a candidates list.
|
||||||
var markingRang: NSRange = NSRange(location: 0, length: 0)
|
class InputStateChoosingCandidate: InputStateNotEmpty {
|
||||||
var candidates: [String] = []
|
@objc private(set) var candidates: [String] = []
|
||||||
|
@objc private(set) var useVerticalMode: Bool = false
|
||||||
|
|
||||||
|
@objc init(composingBuffer: String, cursorIndex: UInt, candidates: [String], useVerticalMode: Bool) {
|
||||||
|
self.candidates = candidates
|
||||||
|
self.useVerticalMode = useVerticalMode
|
||||||
|
super.init(composingBuffer: composingBuffer, cursorIndex: cursorIndex)
|
||||||
|
}
|
||||||
|
|
||||||
|
@objc var attributedString: NSAttributedString {
|
||||||
|
let attrs: [NSAttributedString.Key : Any] = [
|
||||||
|
.underlineStyle: NSUnderlineStyle.single,
|
||||||
|
.markedClauseSegment: 0
|
||||||
|
]
|
||||||
|
let attributedSting = NSAttributedString(string: composingBuffer, attributes: attrs)
|
||||||
|
return attributedSting
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,65 +0,0 @@
|
||||||
import Cocoa
|
|
||||||
|
|
||||||
@objc enum KeyCode: UInt16 {
|
|
||||||
case none = 0
|
|
||||||
case enter = 76
|
|
||||||
case up = 126
|
|
||||||
case down = 125
|
|
||||||
case left = 123
|
|
||||||
case right = 124
|
|
||||||
case pageUp = 116
|
|
||||||
case pageDown = 121
|
|
||||||
case home = 115
|
|
||||||
case end = 119
|
|
||||||
case delete = 117
|
|
||||||
}
|
|
||||||
|
|
||||||
class KeyHandlerInput: NSObject {
|
|
||||||
private (set) var event: NSEvent
|
|
||||||
private (set) var useVerticalMode: Bool
|
|
||||||
|
|
||||||
@objc var inputText: String? {
|
|
||||||
event.characters
|
|
||||||
}
|
|
||||||
|
|
||||||
@objc var charCode: UInt16 {
|
|
||||||
guard let inputText = inputText, inputText.count > 0 else {
|
|
||||||
return 0
|
|
||||||
}
|
|
||||||
let first = inputText[inputText.startIndex].utf16.first!
|
|
||||||
return first
|
|
||||||
}
|
|
||||||
|
|
||||||
@objc var keyCode: UInt16 {
|
|
||||||
event.keyCode
|
|
||||||
}
|
|
||||||
|
|
||||||
@objc var flags: NSEvent.ModifierFlags {
|
|
||||||
event.modifierFlags
|
|
||||||
}
|
|
||||||
|
|
||||||
@objc var cursorForwardKey: KeyCode {
|
|
||||||
useVerticalMode ? .down : .right
|
|
||||||
}
|
|
||||||
|
|
||||||
@objc var cursorBackwardKey: KeyCode {
|
|
||||||
useVerticalMode ? .up : .left
|
|
||||||
}
|
|
||||||
|
|
||||||
@objc var extraChooseCandidateKey: KeyCode {
|
|
||||||
useVerticalMode ? .left : .down
|
|
||||||
}
|
|
||||||
|
|
||||||
@objc var absorbedArrowKey: KeyCode {
|
|
||||||
useVerticalMode ? .right : .up
|
|
||||||
}
|
|
||||||
|
|
||||||
@objc var verticalModeOnlyChooseCandidateKey: KeyCode {
|
|
||||||
useVerticalMode ? absorbedArrowKey : .none
|
|
||||||
}
|
|
||||||
|
|
||||||
init(event: NSEvent, isVerticalMode: Bool) {
|
|
||||||
self.event = event
|
|
||||||
self.useVerticalMode = isVerticalMode
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -0,0 +1,61 @@
|
||||||
|
import Cocoa
|
||||||
|
|
||||||
|
@objc enum KeyCode: UInt16 {
|
||||||
|
case none = 0
|
||||||
|
case enter = 76
|
||||||
|
case up = 126
|
||||||
|
case down = 125
|
||||||
|
case left = 123
|
||||||
|
case right = 124
|
||||||
|
case pageUp = 116
|
||||||
|
case pageDown = 121
|
||||||
|
case home = 115
|
||||||
|
case end = 119
|
||||||
|
case delete = 117
|
||||||
|
}
|
||||||
|
|
||||||
|
@objc class KeyHandlerInput: NSObject {
|
||||||
|
@objc private (set) var event: NSEvent
|
||||||
|
@objc private (set) var useVerticalMode: Bool
|
||||||
|
|
||||||
|
@objc var inputText: String? {
|
||||||
|
event.characters
|
||||||
|
}
|
||||||
|
|
||||||
|
@objc var keyCode: UInt16 {
|
||||||
|
event.keyCode
|
||||||
|
}
|
||||||
|
|
||||||
|
@objc var flags: NSEvent.ModifierFlags {
|
||||||
|
event.modifierFlags
|
||||||
|
}
|
||||||
|
|
||||||
|
@objc private (set) var charCode: UInt16
|
||||||
|
@objc private (set) var cursorForwardKey: KeyCode
|
||||||
|
@objc private (set) var cursorBackwardKey: KeyCode
|
||||||
|
@objc private (set) var extraChooseCandidateKey: KeyCode
|
||||||
|
@objc private (set) var absorbedArrowKey: KeyCode
|
||||||
|
@objc private (set) var verticalModeOnlyChooseCandidateKey: KeyCode
|
||||||
|
@objc private (set) var emacsKey: McBopomofoEmacsKey
|
||||||
|
|
||||||
|
@objc init(event: NSEvent, isVerticalMode: Bool) {
|
||||||
|
self.event = event
|
||||||
|
self.useVerticalMode = isVerticalMode
|
||||||
|
let charCode: UInt16 = {
|
||||||
|
guard let inputText = event.characters, inputText.count > 0 else {
|
||||||
|
return 0
|
||||||
|
}
|
||||||
|
let first = inputText[inputText.startIndex].utf16.first!
|
||||||
|
return first
|
||||||
|
}()
|
||||||
|
|
||||||
|
self.charCode = charCode
|
||||||
|
self.emacsKey = EmacsKeyHelper.detect(charCode: charCode, flags: event.modifierFlags)
|
||||||
|
self.cursorForwardKey = useVerticalMode ? .up : .left
|
||||||
|
self.cursorBackwardKey = useVerticalMode ? .up : .left
|
||||||
|
self.extraChooseCandidateKey = useVerticalMode ? .left : .down
|
||||||
|
self.absorbedArrowKey = useVerticalMode ? .right : .up
|
||||||
|
self.verticalModeOnlyChooseCandidateKey = useVerticalMode ? absorbedArrowKey : .none
|
||||||
|
super.init()
|
||||||
|
}
|
||||||
|
}
|
Loading…
Reference in New Issue