Uses property wrappers to manage preferences.
This commit is contained in:
parent
c698c61432
commit
9faed2153f
|
@ -47,6 +47,7 @@
|
||||||
D427F7B4279086DC004A2160 /* InputSourceHelper in Frameworks */ = {isa = PBXBuildFile; productRef = D427F7B3279086DC004A2160 /* InputSourceHelper */; };
|
D427F7B4279086DC004A2160 /* InputSourceHelper in Frameworks */ = {isa = PBXBuildFile; productRef = D427F7B3279086DC004A2160 /* InputSourceHelper */; };
|
||||||
D427F7B6279086F6004A2160 /* InputSourceHelper in Frameworks */ = {isa = PBXBuildFile; productRef = D427F7B5279086F6004A2160 /* InputSourceHelper */; };
|
D427F7B6279086F6004A2160 /* InputSourceHelper in Frameworks */ = {isa = PBXBuildFile; productRef = D427F7B5279086F6004A2160 /* InputSourceHelper */; };
|
||||||
D427F7C127908EFC004A2160 /* OpenCCBridge in Frameworks */ = {isa = PBXBuildFile; productRef = D427F7C027908EFC004A2160 /* OpenCCBridge */; };
|
D427F7C127908EFC004A2160 /* OpenCCBridge in Frameworks */ = {isa = PBXBuildFile; productRef = D427F7C027908EFC004A2160 /* OpenCCBridge */; };
|
||||||
|
D44FB74527915565003C80A6 /* Preferences.swift in Sources */ = {isa = PBXBuildFile; fileRef = D44FB74427915555003C80A6 /* Preferences.swift */; };
|
||||||
D47F7DCE278BFB57002F9DD7 /* PreferencesWindowController.swift in Sources */ = {isa = PBXBuildFile; fileRef = D47F7DCD278BFB57002F9DD7 /* PreferencesWindowController.swift */; };
|
D47F7DCE278BFB57002F9DD7 /* PreferencesWindowController.swift in Sources */ = {isa = PBXBuildFile; fileRef = D47F7DCD278BFB57002F9DD7 /* PreferencesWindowController.swift */; };
|
||||||
D47F7DD0278C0897002F9DD7 /* NonModalAlertWindowController.swift in Sources */ = {isa = PBXBuildFile; fileRef = D47F7DCF278C0897002F9DD7 /* NonModalAlertWindowController.swift */; };
|
D47F7DD0278C0897002F9DD7 /* NonModalAlertWindowController.swift in Sources */ = {isa = PBXBuildFile; fileRef = D47F7DCF278C0897002F9DD7 /* NonModalAlertWindowController.swift */; };
|
||||||
D47F7DD3278C1263002F9DD7 /* UserOverrideModel.cpp in Sources */ = {isa = PBXBuildFile; fileRef = D47F7DD2278C1263002F9DD7 /* UserOverrideModel.cpp */; };
|
D47F7DD3278C1263002F9DD7 /* UserOverrideModel.cpp in Sources */ = {isa = PBXBuildFile; fileRef = D47F7DD2278C1263002F9DD7 /* UserOverrideModel.cpp */; };
|
||||||
|
@ -175,6 +176,7 @@
|
||||||
D427F7AC27907B7E004A2160 /* NotifierUI */ = {isa = PBXFileReference; lastKnownFileType = wrapper; name = NotifierUI; path = Packages/NotifierUI; sourceTree = "<group>"; };
|
D427F7AC27907B7E004A2160 /* NotifierUI */ = {isa = PBXFileReference; lastKnownFileType = wrapper; name = NotifierUI; path = Packages/NotifierUI; sourceTree = "<group>"; };
|
||||||
D427F7B2279086B5004A2160 /* InputSourceHelper */ = {isa = PBXFileReference; lastKnownFileType = wrapper; name = InputSourceHelper; path = Packages/InputSourceHelper; sourceTree = "<group>"; };
|
D427F7B2279086B5004A2160 /* InputSourceHelper */ = {isa = PBXFileReference; lastKnownFileType = wrapper; name = InputSourceHelper; path = Packages/InputSourceHelper; sourceTree = "<group>"; };
|
||||||
D427F7BF27908EAC004A2160 /* OpenCCBridge */ = {isa = PBXFileReference; lastKnownFileType = wrapper; name = OpenCCBridge; path = Packages/OpenCCBridge; sourceTree = "<group>"; };
|
D427F7BF27908EAC004A2160 /* OpenCCBridge */ = {isa = PBXFileReference; lastKnownFileType = wrapper; name = OpenCCBridge; path = Packages/OpenCCBridge; sourceTree = "<group>"; };
|
||||||
|
D44FB74427915555003C80A6 /* Preferences.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Preferences.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>"; };
|
||||||
D47F7DCF278C0897002F9DD7 /* NonModalAlertWindowController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = NonModalAlertWindowController.swift; sourceTree = "<group>"; };
|
D47F7DCF278C0897002F9DD7 /* NonModalAlertWindowController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = NonModalAlertWindowController.swift; sourceTree = "<group>"; };
|
||||||
D47F7DD1278C1263002F9DD7 /* UserOverrideModel.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = UserOverrideModel.h; sourceTree = "<group>"; };
|
D47F7DD1278C1263002F9DD7 /* UserOverrideModel.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = UserOverrideModel.h; sourceTree = "<group>"; };
|
||||||
|
@ -251,6 +253,7 @@
|
||||||
D41355D7278D7409005E5CBD /* LanguageModelManager.mm */,
|
D41355D7278D7409005E5CBD /* LanguageModelManager.mm */,
|
||||||
6A0D4EC815FC0D6400ABF4B3 /* main.m */,
|
6A0D4EC815FC0D6400ABF4B3 /* main.m */,
|
||||||
D427F76B278CA1BA004A2160 /* AppDelegate.swift */,
|
D427F76B278CA1BA004A2160 /* AppDelegate.swift */,
|
||||||
|
D44FB74427915555003C80A6 /* Preferences.swift */,
|
||||||
D47F7DCF278C0897002F9DD7 /* NonModalAlertWindowController.swift */,
|
D47F7DCF278C0897002F9DD7 /* NonModalAlertWindowController.swift */,
|
||||||
D47F7DCD278BFB57002F9DD7 /* PreferencesWindowController.swift */,
|
D47F7DCD278BFB57002F9DD7 /* PreferencesWindowController.swift */,
|
||||||
6A0D4EF615FC0DA600ABF4B3 /* McBopomofo-Prefix.pch */,
|
6A0D4EF615FC0DA600ABF4B3 /* McBopomofo-Prefix.pch */,
|
||||||
|
@ -577,6 +580,7 @@
|
||||||
files = (
|
files = (
|
||||||
D427F76C278CA2B0004A2160 /* AppDelegate.swift in Sources */,
|
D427F76C278CA2B0004A2160 /* AppDelegate.swift in Sources */,
|
||||||
6A0D4ED315FC0D6400ABF4B3 /* main.m in Sources */,
|
6A0D4ED315FC0D6400ABF4B3 /* main.m in Sources */,
|
||||||
|
D44FB74527915565003C80A6 /* Preferences.swift in Sources */,
|
||||||
D47F7DD0278C0897002F9DD7 /* NonModalAlertWindowController.swift in Sources */,
|
D47F7DD0278C0897002F9DD7 /* NonModalAlertWindowController.swift in Sources */,
|
||||||
D47F7DCE278BFB57002F9DD7 /* PreferencesWindowController.swift in Sources */,
|
D47F7DCE278BFB57002F9DD7 /* PreferencesWindowController.swift in Sources */,
|
||||||
6A0D4ED215FC0D6400ABF4B3 /* InputMethodController.mm in Sources */,
|
6A0D4ED215FC0D6400ABF4B3 /* InputMethodController.mm in Sources */,
|
||||||
|
|
|
@ -72,9 +72,6 @@
|
||||||
|
|
||||||
// current input mode
|
// current input mode
|
||||||
NSString *_inputMode;
|
NSString *_inputMode;
|
||||||
|
|
||||||
// if Chinese conversion is enabled
|
|
||||||
BOOL _chineseConversionEnabled;
|
|
||||||
BOOL _halfWidthPunctuationEnabled;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@end
|
@end
|
||||||
|
|
|
@ -53,40 +53,7 @@ using namespace Formosa::Gramambular;
|
||||||
using namespace McBopomofo;
|
using namespace McBopomofo;
|
||||||
using namespace OpenVanilla;
|
using namespace OpenVanilla;
|
||||||
|
|
||||||
// default, min and max candidate list text size
|
|
||||||
static const NSInteger kDefaultCandidateListTextSize = 16;
|
|
||||||
static const NSInteger kMinKeyLabelSize = 10;
|
static const NSInteger kMinKeyLabelSize = 10;
|
||||||
static const NSInteger kMinCandidateListTextSize = 12;
|
|
||||||
static const NSInteger kMaxCandidateListTextSize = 196;
|
|
||||||
|
|
||||||
// default, min and max composing buffer size (in codepoints)
|
|
||||||
// modern Macs can usually work up to 16 codepoints when the builder still
|
|
||||||
// walks the grid with good performance; slower Macs (like old PowerBooks)
|
|
||||||
// will start to sputter beyond 12; such is the algorithmatic complexity
|
|
||||||
// of the Viterbi algorithm used in the builder library (at O(N^2))
|
|
||||||
static const NSInteger kDefaultComposingBufferSize = 10;
|
|
||||||
static const NSInteger kMinComposingBufferSize = 4;
|
|
||||||
static const NSInteger kMaxComposingBufferSize = 20;
|
|
||||||
|
|
||||||
// user defaults (app perferences) key names; in this project we use
|
|
||||||
// NSUserDefaults throughout and do not wrap them in another config object
|
|
||||||
static NSString *const kKeyboardLayoutPreferenceKey = @"KeyboardLayout";
|
|
||||||
static NSString *const kBasisKeyboardLayoutPreferenceKey = @"BasisKeyboardLayout"; // alphanumeric ("ASCII") input basis
|
|
||||||
static NSString *const kFunctionKeyKeyboardLayoutPreferenceKey = @"FunctionKeyKeyboardLayout"; // alphanumeric ("ASCII") input basis
|
|
||||||
static NSString *const kFunctionKeyKeyboardLayoutOverrideIncludeShiftKey = @"FunctionKeyKeyboardLayoutOverrideIncludeShift"; // whether include shift
|
|
||||||
static NSString *const kCandidateListTextSizeKey = @"CandidateListTextSize";
|
|
||||||
static NSString *const kSelectPhraseAfterCursorAsCandidatePreferenceKey = @"SelectPhraseAfterCursorAsCandidate";
|
|
||||||
static NSString *const kUseHorizontalCandidateListPreferenceKey = @"UseHorizontalCandidateList";
|
|
||||||
static NSString *const kComposingBufferSizePreferenceKey = @"ComposingBufferSize";
|
|
||||||
static NSString *const kChooseCandidateUsingSpaceKey = @"ChooseCandidateUsingSpaceKey";
|
|
||||||
static NSString *const kChineseConversionEnabledKey = @"ChineseConversionEnabledKey";
|
|
||||||
static NSString *const kHalfWidthPunctuationEnabledKey = @"HalfWidthPunctuationEnabledKey";
|
|
||||||
static NSString *const kEscToCleanInputBufferKey = @"EscToCleanInputBufferKey";
|
|
||||||
|
|
||||||
// advanced (usually optional) settings
|
|
||||||
static NSString *const kCandidateTextFontName = @"CandidateTextFontName";
|
|
||||||
static NSString *const kCandidateKeyLabelFontName = @"CandidateKeyLabelFontName";
|
|
||||||
static NSString *const kCandidateKeys = @"CandidateKeys";
|
|
||||||
|
|
||||||
// input modes
|
// input modes
|
||||||
static NSString *const kBopomofoModeIdentifier = @"org.openvanilla.inputmethod.McBopomofo.Bopomofo";
|
static NSString *const kBopomofoModeIdentifier = @"org.openvanilla.inputmethod.McBopomofo.Bopomofo";
|
||||||
|
@ -130,12 +97,6 @@ static inline NSString *LocalizationNotNeeded(NSString *s) {
|
||||||
return s;
|
return s;
|
||||||
}
|
}
|
||||||
|
|
||||||
// private methods
|
|
||||||
@interface McBopomofoInputMethodController ()
|
|
||||||
+ (VTHorizontalCandidateController *)horizontalCandidateController;
|
|
||||||
+ (VTVerticalCandidateController *)verticalCandidateController;
|
|
||||||
@end
|
|
||||||
|
|
||||||
@interface McBopomofoInputMethodController (VTCandidateController) <VTCandidateControllerDelegate>
|
@interface McBopomofoInputMethodController (VTCandidateController) <VTCandidateControllerDelegate>
|
||||||
@end
|
@end
|
||||||
|
|
||||||
|
@ -201,8 +162,6 @@ static double FindHighestScore(const vector<NodeAnchor>& nodes, double epsilon)
|
||||||
_composingBuffer = [[NSMutableString alloc] init];
|
_composingBuffer = [[NSMutableString alloc] init];
|
||||||
|
|
||||||
_inputMode = kBopomofoModeIdentifier;
|
_inputMode = kBopomofoModeIdentifier;
|
||||||
_chineseConversionEnabled = [[NSUserDefaults standardUserDefaults] boolForKey:kChineseConversionEnabledKey];
|
|
||||||
_halfWidthPunctuationEnabled = [[NSUserDefaults standardUserDefaults] boolForKey:kHalfWidthPunctuationEnabledKey];
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return self;
|
return self;
|
||||||
|
@ -217,11 +176,11 @@ static double FindHighestScore(const vector<NodeAnchor>& nodes, double epsilon)
|
||||||
|
|
||||||
NSMenuItem *chineseConversionMenuItem = [[NSMenuItem alloc] initWithTitle:NSLocalizedString(@"Chinese Conversion", @"") action:@selector(toggleChineseConverter:) keyEquivalent:@"g"];
|
NSMenuItem *chineseConversionMenuItem = [[NSMenuItem alloc] initWithTitle:NSLocalizedString(@"Chinese Conversion", @"") action:@selector(toggleChineseConverter:) keyEquivalent:@"g"];
|
||||||
chineseConversionMenuItem.keyEquivalentModifierMask = NSEventModifierFlagCommand | NSEventModifierFlagControl;
|
chineseConversionMenuItem.keyEquivalentModifierMask = NSEventModifierFlagCommand | NSEventModifierFlagControl;
|
||||||
chineseConversionMenuItem.state = _chineseConversionEnabled ? NSControlStateValueOn : NSControlStateValueOff;
|
chineseConversionMenuItem.state = Preferences.chineseConversionEnabled ? NSControlStateValueOn : NSControlStateValueOff;
|
||||||
[menu addItem:chineseConversionMenuItem];
|
[menu addItem:chineseConversionMenuItem];
|
||||||
|
|
||||||
NSMenuItem *halfWidthPunctuationMenuItem = [[NSMenuItem alloc] initWithTitle:NSLocalizedString(@"Use Half-Width Punctuations", @"") action:@selector(toggleHalfWidthPunctuation:) keyEquivalent:@""];
|
NSMenuItem *halfWidthPunctuationMenuItem = [[NSMenuItem alloc] initWithTitle:NSLocalizedString(@"Use Half-Width Punctuations", @"") action:@selector(toggleHalfWidthPunctuation:) keyEquivalent:@""];
|
||||||
halfWidthPunctuationMenuItem.state = _halfWidthPunctuationEnabled ? NSControlStateValueOn : NSControlStateValueOff;
|
halfWidthPunctuationMenuItem.state = Preferences.halfWidthPunctuationEnabled ? NSControlStateValueOn : NSControlStateValueOff;
|
||||||
[menu addItem:halfWidthPunctuationMenuItem];
|
[menu addItem:halfWidthPunctuationMenuItem];
|
||||||
|
|
||||||
[menu addItem:[NSMenuItem separatorItem]];
|
[menu addItem:[NSMenuItem separatorItem]];
|
||||||
|
@ -258,10 +217,7 @@ static double FindHighestScore(const vector<NodeAnchor>& nodes, double epsilon)
|
||||||
[[NSUserDefaults standardUserDefaults] synchronize];
|
[[NSUserDefaults standardUserDefaults] synchronize];
|
||||||
|
|
||||||
// Override the keyboard layout. Use US if not set.
|
// Override the keyboard layout. Use US if not set.
|
||||||
NSString *basisKeyboardLayoutID = [[NSUserDefaults standardUserDefaults] stringForKey:kBasisKeyboardLayoutPreferenceKey];
|
NSString *basisKeyboardLayoutID = Preferences.basisKeyboardLayout;
|
||||||
if (!basisKeyboardLayoutID) {
|
|
||||||
basisKeyboardLayoutID = @"com.apple.keylayout.US";
|
|
||||||
}
|
|
||||||
[client overrideKeyboardWithKeyboardNamed:basisKeyboardLayoutID];
|
[client overrideKeyboardWithKeyboardNamed:basisKeyboardLayoutID];
|
||||||
|
|
||||||
// reset the state
|
// reset the state
|
||||||
|
@ -272,7 +228,7 @@ static double FindHighestScore(const vector<NodeAnchor>& nodes, double epsilon)
|
||||||
[_composingBuffer setString:@""];
|
[_composingBuffer setString:@""];
|
||||||
|
|
||||||
// checks and populates the default settings
|
// checks and populates the default settings
|
||||||
NSInteger keyboardLayout = [[NSUserDefaults standardUserDefaults] integerForKey:kKeyboardLayoutPreferenceKey];
|
NSInteger keyboardLayout = Preferences.keyboardLayout;
|
||||||
switch (keyboardLayout) {
|
switch (keyboardLayout) {
|
||||||
case 0:
|
case 0:
|
||||||
_bpmfReadingBuffer->setKeyboardLayout(BopomofoKeyboardLayout::StandardLayout());
|
_bpmfReadingBuffer->setKeyboardLayout(BopomofoKeyboardLayout::StandardLayout());
|
||||||
|
@ -294,27 +250,7 @@ static double FindHighestScore(const vector<NodeAnchor>& nodes, double epsilon)
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
_bpmfReadingBuffer->setKeyboardLayout(BopomofoKeyboardLayout::StandardLayout());
|
_bpmfReadingBuffer->setKeyboardLayout(BopomofoKeyboardLayout::StandardLayout());
|
||||||
[[NSUserDefaults standardUserDefaults] setInteger:0 forKey:kKeyboardLayoutPreferenceKey];
|
Preferences.keyboardLayout = 0;
|
||||||
}
|
|
||||||
|
|
||||||
// set the size
|
|
||||||
NSInteger textSize = [[NSUserDefaults standardUserDefaults] integerForKey:kCandidateListTextSizeKey];
|
|
||||||
NSInteger previousTextSize = textSize;
|
|
||||||
if (textSize == 0) {
|
|
||||||
textSize = kDefaultCandidateListTextSize;
|
|
||||||
}
|
|
||||||
else if (textSize < kMinCandidateListTextSize) {
|
|
||||||
textSize = kMinCandidateListTextSize;
|
|
||||||
}
|
|
||||||
else if (textSize > kMaxCandidateListTextSize) {
|
|
||||||
textSize = kMaxCandidateListTextSize;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (textSize != previousTextSize) {
|
|
||||||
[[NSUserDefaults standardUserDefaults] setInteger:textSize forKey:kCandidateListTextSizeKey];
|
|
||||||
}
|
|
||||||
if (![[NSUserDefaults standardUserDefaults] objectForKey:kChooseCandidateUsingSpaceKey]) {
|
|
||||||
[[NSUserDefaults standardUserDefaults] setBool:YES forKey:kChooseCandidateUsingSpaceKey];
|
|
||||||
}
|
}
|
||||||
|
|
||||||
[(AppDelegate *)[NSApp delegate] checkForUpdate];
|
[(AppDelegate *)[NSApp delegate] checkForUpdate];
|
||||||
|
@ -360,10 +296,7 @@ static double FindHighestScore(const vector<NodeAnchor>& nodes, double epsilon)
|
||||||
[[NSUserDefaults standardUserDefaults] synchronize];
|
[[NSUserDefaults standardUserDefaults] synchronize];
|
||||||
|
|
||||||
// Remember to override the keyboard layout again -- treat this as an activate eventy
|
// Remember to override the keyboard layout again -- treat this as an activate eventy
|
||||||
NSString *basisKeyboardLayoutID = [[NSUserDefaults standardUserDefaults] stringForKey:kBasisKeyboardLayoutPreferenceKey];
|
NSString *basisKeyboardLayoutID = Preferences.basisKeyboardLayout;
|
||||||
if (!basisKeyboardLayoutID) {
|
|
||||||
basisKeyboardLayoutID = @"com.apple.keylayout.US";
|
|
||||||
}
|
|
||||||
[sender overrideKeyboardWithKeyboardNamed:basisKeyboardLayoutID];
|
[sender overrideKeyboardWithKeyboardNamed:basisKeyboardLayoutID];
|
||||||
|
|
||||||
_inputMode = newInputMode;
|
_inputMode = newInputMode;
|
||||||
|
@ -402,8 +335,8 @@ static double FindHighestScore(const vector<NodeAnchor>& nodes, double epsilon)
|
||||||
|
|
||||||
// Chinese conversion.
|
// Chinese conversion.
|
||||||
NSString *buffer = _composingBuffer;
|
NSString *buffer = _composingBuffer;
|
||||||
BOOL chineseConversionEnabled = [[NSUserDefaults standardUserDefaults] boolForKey:kChineseConversionEnabledKey];
|
|
||||||
if (chineseConversionEnabled) {
|
if (Preferences.chineseConversionEnabled) {
|
||||||
buffer = [OpenCCBridge convert:_composingBuffer];
|
buffer = [OpenCCBridge convert:_composingBuffer];
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -544,29 +477,14 @@ NS_INLINE size_t max(size_t a, size_t b) { return a > b ? a : b; }
|
||||||
// the user type along, the already composed text at front will
|
// the user type along, the already composed text at front will
|
||||||
// be popped out
|
// be popped out
|
||||||
|
|
||||||
NSInteger _composingBufferSize = [[NSUserDefaults standardUserDefaults] integerForKey:kComposingBufferSizePreferenceKey];
|
NSInteger composingBufferSize = Preferences.composingBufferSize;
|
||||||
NSInteger previousComposingBufferSize = _composingBufferSize;
|
|
||||||
|
|
||||||
if (_composingBufferSize == 0) {
|
if (_builder->grid().width() > (size_t)composingBufferSize) {
|
||||||
_composingBufferSize = kDefaultComposingBufferSize;
|
|
||||||
}
|
|
||||||
else if (_composingBufferSize < kMinComposingBufferSize) {
|
|
||||||
_composingBufferSize = kMinComposingBufferSize;
|
|
||||||
}
|
|
||||||
else if (_composingBufferSize > kMaxComposingBufferSize) {
|
|
||||||
_composingBufferSize = kMaxComposingBufferSize;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (_composingBufferSize != previousComposingBufferSize) {
|
|
||||||
[[NSUserDefaults standardUserDefaults] setInteger:_composingBufferSize forKey:kComposingBufferSizePreferenceKey];
|
|
||||||
}
|
|
||||||
|
|
||||||
if (_builder->grid().width() > (size_t)_composingBufferSize) {
|
|
||||||
if (_walkedNodes.size() > 0) {
|
if (_walkedNodes.size() > 0) {
|
||||||
NodeAnchor &anchor = _walkedNodes[0];
|
NodeAnchor &anchor = _walkedNodes[0];
|
||||||
NSString *popedText = [NSString stringWithUTF8String:anchor.node->currentKeyValue().value.c_str()];
|
NSString *popedText = [NSString stringWithUTF8String:anchor.node->currentKeyValue().value.c_str()];
|
||||||
// Chinese conversion.
|
// Chinese conversion.
|
||||||
BOOL chineseConversionEnabled = [[NSUserDefaults standardUserDefaults] boolForKey:kChineseConversionEnabledKey];
|
BOOL chineseConversionEnabled = Preferences.chineseConversionEnabled;
|
||||||
if (chineseConversionEnabled) {
|
if (chineseConversionEnabled) {
|
||||||
popedText = [OpenCCBridge convert:popedText];
|
popedText = [OpenCCBridge convert:popedText];
|
||||||
}
|
}
|
||||||
|
@ -586,30 +504,8 @@ NS_INLINE size_t max(size_t a, size_t b) { return a > b ? a : b; }
|
||||||
|
|
||||||
- (string)_currentLayout
|
- (string)_currentLayout
|
||||||
{
|
{
|
||||||
string layout = string("Standard_");;
|
NSString *keyboardLayoutName = Preferences.keyboardLayoutName;
|
||||||
NSInteger keyboardLayout = [[NSUserDefaults standardUserDefaults] integerForKey:kKeyboardLayoutPreferenceKey];
|
string layout = string(keyboardLayoutName.UTF8String) + string("_");
|
||||||
switch (keyboardLayout) {
|
|
||||||
case 0:
|
|
||||||
layout = string("Standard_");
|
|
||||||
break;
|
|
||||||
case 1:
|
|
||||||
layout = string("ETen_");
|
|
||||||
break;
|
|
||||||
case 2:
|
|
||||||
layout = string("ETen26_");
|
|
||||||
break;
|
|
||||||
case 3:
|
|
||||||
layout = string("Hsu_");
|
|
||||||
break;
|
|
||||||
case 4:
|
|
||||||
layout = string("HanyuPinyin_");
|
|
||||||
break;
|
|
||||||
case 5:
|
|
||||||
layout = string("IBM_");
|
|
||||||
break;
|
|
||||||
default:
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
return layout;
|
return layout;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -639,7 +535,6 @@ NS_INLINE size_t max(size_t a, size_t b) { return a > b ? a : b; }
|
||||||
return McBpomofoEmacsKeyNone;
|
return McBpomofoEmacsKeyNone;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
- (BOOL)handleInputText:(NSString*)inputText key:(NSInteger)keyCode modifiers:(NSUInteger)flags client:(id)client
|
- (BOOL)handleInputText:(NSString*)inputText key:(NSInteger)keyCode modifiers:(NSUInteger)flags client:(id)client
|
||||||
{
|
{
|
||||||
NSRect textFrame = NSZeroRect;
|
NSRect textFrame = NSZeroRect;
|
||||||
|
@ -835,7 +730,7 @@ NS_INLINE size_t max(size_t a, size_t b) { return a > b ? a : b; }
|
||||||
if (_bpmfReadingBuffer->isEmpty() && [_composingBuffer length] > 0 && (keyCode == extraChooseCandidateKey || charCode == 32 || (useVerticalMode && (keyCode == verticalModeOnlyChooseCandidateKey)))) {
|
if (_bpmfReadingBuffer->isEmpty() && [_composingBuffer length] > 0 && (keyCode == extraChooseCandidateKey || charCode == 32 || (useVerticalMode && (keyCode == verticalModeOnlyChooseCandidateKey)))) {
|
||||||
if (charCode == 32) {
|
if (charCode == 32) {
|
||||||
// if the spacebar is NOT set to be a selection key
|
// if the spacebar is NOT set to be a selection key
|
||||||
if (![[NSUserDefaults standardUserDefaults] boolForKey:kChooseCandidateUsingSpaceKey]) {
|
if (!Preferences.chooseCandidateUsingSpace) {
|
||||||
if (_builder->cursorIndex() >= _builder->length()) {
|
if (_builder->cursorIndex() >= _builder->length()) {
|
||||||
[_composingBuffer appendString:@" "];
|
[_composingBuffer appendString:@" "];
|
||||||
[self commitComposition:client];
|
[self commitComposition:client];
|
||||||
|
@ -856,7 +751,7 @@ NS_INLINE size_t max(size_t a, size_t b) { return a > b ? a : b; }
|
||||||
|
|
||||||
// Esc
|
// Esc
|
||||||
if (charCode == 27) {
|
if (charCode == 27) {
|
||||||
BOOL escToClearInputBufferEnabled = [[NSUserDefaults standardUserDefaults] boolForKey:kEscToCleanInputBufferKey];
|
BOOL escToClearInputBufferEnabled = Preferences.escToCleanInputBuffer;
|
||||||
|
|
||||||
if (escToClearInputBufferEnabled) {
|
if (escToClearInputBufferEnabled) {
|
||||||
// if the optioon is enabled, we clear everythiong including the composing
|
// if the optioon is enabled, we clear everythiong including the composing
|
||||||
|
@ -1079,7 +974,7 @@ NS_INLINE size_t max(size_t a, size_t b) { return a > b ? a : b; }
|
||||||
|
|
||||||
// if nothing is matched, see if it's a punctuation key for current layout.
|
// if nothing is matched, see if it's a punctuation key for current layout.
|
||||||
string layout = [self _currentLayout];
|
string layout = [self _currentLayout];
|
||||||
string punctuationNamePrefix = (_halfWidthPunctuationEnabled ? string("_half_punctuation_"): string("_punctuation_"));
|
string punctuationNamePrefix = Preferences.halfWidthPunctuationEnabled ? string("_half_punctuation_"): string("_punctuation_");
|
||||||
string customPunctuation = punctuationNamePrefix + layout + string(1, (char)charCode);
|
string customPunctuation = punctuationNamePrefix + layout + string(1, (char)charCode);
|
||||||
if ([self _handlePunctuation:customPunctuation usingVerticalMode:useVerticalMode client:client]) {
|
if ([self _handlePunctuation:customPunctuation usingVerticalMode:useVerticalMode client:client]) {
|
||||||
return YES;
|
return YES;
|
||||||
|
@ -1328,15 +1223,8 @@ NS_INLINE size_t max(size_t a, size_t b) { return a > b ? a : b; }
|
||||||
- (BOOL)handleEvent:(NSEvent *)event client:(id)client
|
- (BOOL)handleEvent:(NSEvent *)event client:(id)client
|
||||||
{
|
{
|
||||||
if ([event type] == NSFlagsChanged) {
|
if ([event type] == NSFlagsChanged) {
|
||||||
NSString *functionKeyKeyboardLayoutID = [[NSUserDefaults standardUserDefaults] stringForKey:kFunctionKeyKeyboardLayoutPreferenceKey];
|
NSString *functionKeyKeyboardLayoutID = Preferences.functionKeyboardLayout;
|
||||||
if (!functionKeyKeyboardLayoutID) {
|
NSString *basisKeyboardLayoutID = Preferences.basisKeyboardLayout;
|
||||||
functionKeyKeyboardLayoutID = @"com.apple.keylayout.US";
|
|
||||||
}
|
|
||||||
|
|
||||||
NSString *basisKeyboardLayoutID = [[NSUserDefaults standardUserDefaults] stringForKey:kBasisKeyboardLayoutPreferenceKey];
|
|
||||||
if (!basisKeyboardLayoutID) {
|
|
||||||
basisKeyboardLayoutID = @"com.apple.keylayout.US";
|
|
||||||
}
|
|
||||||
|
|
||||||
// If no override is needed, just return NO.
|
// If no override is needed, just return NO.
|
||||||
if ([functionKeyKeyboardLayoutID isEqualToString:basisKeyboardLayoutID]) {
|
if ([functionKeyKeyboardLayoutID isEqualToString:basisKeyboardLayoutID]) {
|
||||||
|
@ -1344,7 +1232,7 @@ NS_INLINE size_t max(size_t a, size_t b) { return a > b ? a : b; }
|
||||||
}
|
}
|
||||||
|
|
||||||
// Function key pressed.
|
// Function key pressed.
|
||||||
BOOL includeShift = [[NSUserDefaults standardUserDefaults] boolForKey:kFunctionKeyKeyboardLayoutOverrideIncludeShiftKey];
|
BOOL includeShift = Preferences.functionKeyKeyboardLayoutOverrideIncludeShiftKey;
|
||||||
if (([event modifierFlags] & ~NSShiftKeyMask) || (([event modifierFlags] & NSShiftKeyMask) && includeShift)) {
|
if (([event modifierFlags] & ~NSShiftKeyMask) || (([event modifierFlags] & NSShiftKeyMask) && includeShift)) {
|
||||||
// Override the keyboard layout and let the OS do its thing
|
// Override the keyboard layout and let the OS do its thing
|
||||||
[client overrideKeyboardWithKeyboardNamed:functionKeyKeyboardLayoutID];
|
[client overrideKeyboardWithKeyboardNamed:functionKeyKeyboardLayoutID];
|
||||||
|
@ -1417,10 +1305,7 @@ NS_INLINE size_t max(size_t a, size_t b) { return a > b ? a : b; }
|
||||||
- (size_t)actualCandidateCursorIndex
|
- (size_t)actualCandidateCursorIndex
|
||||||
{
|
{
|
||||||
size_t cursorIndex = _builder->cursorIndex();
|
size_t cursorIndex = _builder->cursorIndex();
|
||||||
|
if (Preferences.selectPhraseAfterCursorAsCandidate) {
|
||||||
BOOL candidatePhraseLocatedAfterCursor = [[NSUserDefaults standardUserDefaults] boolForKey:kSelectPhraseAfterCursorAsCandidatePreferenceKey];
|
|
||||||
|
|
||||||
if (candidatePhraseLocatedAfterCursor) {
|
|
||||||
// MS Phonetics IME style, phrase is *after* the cursor, i.e. cursor is always *before* the phrase
|
// MS Phonetics IME style, phrase is *after* the cursor, i.e. cursor is always *before* the phrase
|
||||||
if (cursorIndex < _builder->length()) {
|
if (cursorIndex < _builder->length()) {
|
||||||
++cursorIndex;
|
++cursorIndex;
|
||||||
|
@ -1438,12 +1323,11 @@ NS_INLINE size_t max(size_t a, size_t b) { return a > b ? a : b; }
|
||||||
- (void)_showCandidateWindowUsingVerticalMode:(BOOL)useVerticalMode client:(id)client
|
- (void)_showCandidateWindowUsingVerticalMode:(BOOL)useVerticalMode client:(id)client
|
||||||
{
|
{
|
||||||
// set the candidate panel style
|
// set the candidate panel style
|
||||||
BOOL useHorizontalCandidateList = [[NSUserDefaults standardUserDefaults] boolForKey:kUseHorizontalCandidateListPreferenceKey];
|
|
||||||
|
|
||||||
if (useVerticalMode) {
|
if (useVerticalMode) {
|
||||||
gCurrentCandidateController = [McBopomofoInputMethodController verticalCandidateController];
|
gCurrentCandidateController = [McBopomofoInputMethodController verticalCandidateController];
|
||||||
}
|
}
|
||||||
else if (useHorizontalCandidateList) {
|
else if (Preferences.useHorizontalCandidateList) {
|
||||||
gCurrentCandidateController = [McBopomofoInputMethodController horizontalCandidateController];
|
gCurrentCandidateController = [McBopomofoInputMethodController horizontalCandidateController];
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
|
@ -1451,16 +1335,16 @@ NS_INLINE size_t max(size_t a, size_t b) { return a > b ? a : b; }
|
||||||
}
|
}
|
||||||
|
|
||||||
// set the attributes for the candidate panel (which uses NSAttributedString)
|
// set the attributes for the candidate panel (which uses NSAttributedString)
|
||||||
NSInteger textSize = [[NSUserDefaults standardUserDefaults] integerForKey:kCandidateListTextSizeKey];
|
NSInteger textSize = Preferences.candidateListTextSize;
|
||||||
|
|
||||||
NSInteger keyLabelSize = textSize / 2;
|
NSInteger keyLabelSize = textSize / 2;
|
||||||
if (keyLabelSize < kMinKeyLabelSize) {
|
if (keyLabelSize < kMinKeyLabelSize) {
|
||||||
keyLabelSize = kMinKeyLabelSize;
|
keyLabelSize = kMinKeyLabelSize;
|
||||||
}
|
}
|
||||||
|
|
||||||
NSString *ctFontName = [[NSUserDefaults standardUserDefaults] stringForKey:kCandidateTextFontName];
|
NSString *ctFontName = Preferences.candidateTextFontName;
|
||||||
NSString *klFontName = [[NSUserDefaults standardUserDefaults] stringForKey:kCandidateKeyLabelFontName];
|
NSString *klFontName = Preferences.candidateKeyLabelFontName;
|
||||||
NSString *ckeys = [[NSUserDefaults standardUserDefaults] stringForKey:kCandidateKeys];
|
NSString *ckeys = Preferences.candidateKeys;
|
||||||
|
|
||||||
gCurrentCandidateController.keyLabelFont = klFontName ? [NSFont fontWithName:klFontName size:keyLabelSize] : [NSFont systemFontOfSize:keyLabelSize];
|
gCurrentCandidateController.keyLabelFont = klFontName ? [NSFont fontWithName:klFontName size:keyLabelSize] : [NSFont systemFontOfSize:keyLabelSize];
|
||||||
gCurrentCandidateController.candidateFont = ctFontName ? [NSFont fontWithName:ctFontName size:textSize] : [NSFont systemFontOfSize:textSize];
|
gCurrentCandidateController.candidateFont = ctFontName ? [NSFont fontWithName:ctFontName size:textSize] : [NSFont systemFontOfSize:textSize];
|
||||||
|
@ -1661,25 +1545,21 @@ NS_INLINE size_t max(size_t a, size_t b) { return a > b ? a : b; }
|
||||||
|
|
||||||
- (void)openUserPhrases:(id)sender
|
- (void)openUserPhrases:(id)sender
|
||||||
{
|
{
|
||||||
NSLog(@"openUserPhrases called");
|
|
||||||
[self _openUserFile:[LanguageModelManager userPhrasesDataPathMcBopomofo]];
|
[self _openUserFile:[LanguageModelManager userPhrasesDataPathMcBopomofo]];
|
||||||
}
|
}
|
||||||
|
|
||||||
- (void)openExcludedPhrasesPlainBopomofo:(id)sender
|
- (void)openExcludedPhrasesPlainBopomofo:(id)sender
|
||||||
{
|
{
|
||||||
NSLog(@"openExcludedPhrasesPlainBopomofo called");
|
|
||||||
[self _openUserFile:[LanguageModelManager excludedPhrasesDataPathPlainBopomofo]];
|
[self _openUserFile:[LanguageModelManager excludedPhrasesDataPathPlainBopomofo]];
|
||||||
}
|
}
|
||||||
|
|
||||||
- (void)openExcludedPhrasesMcBopomofo:(id)sender
|
- (void)openExcludedPhrasesMcBopomofo:(id)sender
|
||||||
{
|
{
|
||||||
NSLog(@"openExcludedPhrasesMcBopomofo called");
|
|
||||||
[self _openUserFile:[LanguageModelManager excludedPhrasesDataPathMcBopomofo]];
|
[self _openUserFile:[LanguageModelManager excludedPhrasesDataPathMcBopomofo]];
|
||||||
}
|
}
|
||||||
|
|
||||||
- (void)reloadUserPhrases:(id)sender
|
- (void)reloadUserPhrases:(id)sender
|
||||||
{
|
{
|
||||||
NSLog(@"reloadUserPhrases called");
|
|
||||||
[LanguageModelManager loadUserPhrasesModel];
|
[LanguageModelManager loadUserPhrasesModel];
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1691,22 +1571,21 @@ NS_INLINE size_t max(size_t a, size_t b) { return a > b ? a : b; }
|
||||||
|
|
||||||
- (void)toggleChineseConverter:(id)sender
|
- (void)toggleChineseConverter:(id)sender
|
||||||
{
|
{
|
||||||
_chineseConversionEnabled = !_chineseConversionEnabled;
|
BOOL chineseConversionEnabled = [Preferences toggleChineseConversionEnabled];
|
||||||
[[NSUserDefaults standardUserDefaults] setBool:_chineseConversionEnabled forKey:kChineseConversionEnabledKey];
|
|
||||||
|
|
||||||
[NotifierController notifyWithMessage:
|
[NotifierController notifyWithMessage:
|
||||||
_chineseConversionEnabled ?
|
chineseConversionEnabled ?
|
||||||
NSLocalizedString(@"Chinese conversion on", @"") :
|
NSLocalizedString(@"Chinese conversion on", @"") :
|
||||||
NSLocalizedString(@"Chinese conversion off", @"") stay:NO];
|
NSLocalizedString(@"Chinese conversion off", @"") stay:NO];
|
||||||
}
|
}
|
||||||
|
|
||||||
- (void)toggleHalfWidthPunctuation:(id)sender
|
- (void)toggleHalfWidthPunctuation:(id)sender
|
||||||
{
|
{
|
||||||
_halfWidthPunctuationEnabled = !_halfWidthPunctuationEnabled;
|
#pragma GCC diagnostic push
|
||||||
[[NSUserDefaults standardUserDefaults] setBool:_halfWidthPunctuationEnabled forKey:kHalfWidthPunctuationEnabledKey];
|
#pragma GCC diagnostic ignored "-Wunused-result"
|
||||||
|
[Preferences toogleHalfWidthPunctuationEnabled];
|
||||||
|
#pragma GCC diagnostic pop
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@end
|
@end
|
||||||
|
|
||||||
#pragma mark -
|
#pragma mark -
|
||||||
|
|
|
@ -0,0 +1,260 @@
|
||||||
|
//
|
||||||
|
// Preferences.swift
|
||||||
|
//
|
||||||
|
// Copyright (c) 2011 The McBopomofo Project.
|
||||||
|
//
|
||||||
|
// Contributors:
|
||||||
|
// Mengjuei Hsieh (@mjhsieh)
|
||||||
|
// Weizhong Yang (@zonble)
|
||||||
|
//
|
||||||
|
// Based on the Syrup Project and the Formosana Library
|
||||||
|
// by Lukhnos Liu (@lukhnos).
|
||||||
|
//
|
||||||
|
// Permission is hereby granted, free of charge, to any person
|
||||||
|
// obtaining a copy of this software and associated documentation
|
||||||
|
// files (the "Software"), to deal in the Software without
|
||||||
|
// restriction, including without limitation the rights to use,
|
||||||
|
// copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||||
|
// copies of the Software, and to permit persons to whom the
|
||||||
|
// Software is furnished to do so, subject to the following
|
||||||
|
// conditions:
|
||||||
|
//
|
||||||
|
// The above copyright notice and this permission notice shall be
|
||||||
|
// included in all copies or substantial portions of the Software.
|
||||||
|
//
|
||||||
|
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
||||||
|
// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
|
||||||
|
// OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
||||||
|
// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
|
||||||
|
// HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
|
||||||
|
// WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
|
||||||
|
// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
|
||||||
|
// OTHER DEALINGS IN THE SOFTWARE.
|
||||||
|
//
|
||||||
|
|
||||||
|
import Cocoa
|
||||||
|
|
||||||
|
private let kKeyboardLayoutPreferenceKey = "KeyboardLayout"
|
||||||
|
private let kBasisKeyboardLayoutPreferenceKey = "BasisKeyboardLayout"; // alphanumeric ("ASCII") input basi
|
||||||
|
private let kFunctionKeyKeyboardLayoutPreferenceKey = "FunctionKeyKeyboardLayout"; // alphanumeric ("ASCII") input basi
|
||||||
|
private let kFunctionKeyKeyboardLayoutOverrideIncludeShiftKey = "FunctionKeyKeyboardLayoutOverrideIncludeShift"; // whether include shif
|
||||||
|
private let kCandidateListTextSizeKey = "CandidateListTextSize"
|
||||||
|
private let kSelectPhraseAfterCursorAsCandidatePreferenceKey = "SelectPhraseAfterCursorAsCandidate"
|
||||||
|
private let kUseHorizontalCandidateListPreferenceKey = "UseHorizontalCandidateList"
|
||||||
|
private let kComposingBufferSizePreferenceKey = "ComposingBufferSize"
|
||||||
|
private let kChooseCandidateUsingSpaceKey = "ChooseCandidateUsingSpaceKey"
|
||||||
|
private let kChineseConversionEnabledKey = "ChineseConversionEnabled"
|
||||||
|
private let kHalfWidthPunctuationEnabledKey = "HalfWidthPunctuationEnable"
|
||||||
|
private let kEscToCleanInputBufferKey = "EscToCleanInputBuffer"
|
||||||
|
|
||||||
|
private let kCandidateTextFontName = "CandidateTextFontName"
|
||||||
|
private let kCandidateKeyLabelFontName = "CandidateKeyLabelFontName"
|
||||||
|
private let kCandidateKeys = "CandidateKeys"
|
||||||
|
|
||||||
|
private let kDefaultCandidateListTextSize: CGFloat = 16
|
||||||
|
private let kMinKeyLabelSize: CGFloat = 10
|
||||||
|
private let kMinCandidateListTextSize: CGFloat = 12
|
||||||
|
private let kMaxCandidateListTextSize: CGFloat = 196
|
||||||
|
|
||||||
|
// default, min and max composing buffer size (in codepoints)
|
||||||
|
// modern Macs can usually work up to 16 codepoints when the builder still
|
||||||
|
// walks the grid with good performance; slower Macs (like old PowerBooks)
|
||||||
|
// will start to sputter beyond 12; such is the algorithmatic complexity
|
||||||
|
// of the Viterbi algorithm used in the builder library (at O(N^2))
|
||||||
|
private let kDefaultComposingBufferSize = 10
|
||||||
|
private let kMinComposingBufferSize = 4
|
||||||
|
private let kMaxComposingBufferSize = 20
|
||||||
|
|
||||||
|
private let kDefaultKeys = "123456789"
|
||||||
|
|
||||||
|
// MARK: Property wrappers
|
||||||
|
|
||||||
|
@propertyWrapper
|
||||||
|
struct UserDefault<Value> {
|
||||||
|
let key: String
|
||||||
|
let defaultValue: Value
|
||||||
|
var container: UserDefaults = .standard
|
||||||
|
|
||||||
|
var wrappedValue: Value {
|
||||||
|
get {
|
||||||
|
return container.object(forKey: key) as? Value ?? defaultValue
|
||||||
|
}
|
||||||
|
set {
|
||||||
|
container.set(newValue, forKey: key)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@propertyWrapper
|
||||||
|
struct CandidateListTextSize {
|
||||||
|
let key: String
|
||||||
|
let defaultValue: CGFloat = kDefaultCandidateListTextSize
|
||||||
|
lazy var container: UserDefault = {
|
||||||
|
UserDefault(key: key, defaultValue: defaultValue) }()
|
||||||
|
|
||||||
|
var wrappedValue: CGFloat {
|
||||||
|
mutating get {
|
||||||
|
var value = container.wrappedValue
|
||||||
|
if value < kMinCandidateListTextSize {
|
||||||
|
value = kMinCandidateListTextSize
|
||||||
|
} else if value > kMaxCandidateListTextSize {
|
||||||
|
value = kMaxCandidateListTextSize
|
||||||
|
}
|
||||||
|
return value
|
||||||
|
}
|
||||||
|
set {
|
||||||
|
var value = newValue
|
||||||
|
if value < kMinCandidateListTextSize {
|
||||||
|
value = kMinCandidateListTextSize
|
||||||
|
} else if value > kMaxCandidateListTextSize {
|
||||||
|
value = kMaxCandidateListTextSize
|
||||||
|
}
|
||||||
|
container.wrappedValue = value
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@propertyWrapper
|
||||||
|
struct ComposingBufferSize {
|
||||||
|
let key: String
|
||||||
|
let defaultValue: Int = kDefaultComposingBufferSize
|
||||||
|
lazy var container: UserDefault = {
|
||||||
|
UserDefault(key: key, defaultValue: defaultValue) }()
|
||||||
|
|
||||||
|
var wrappedValue: Int {
|
||||||
|
mutating get {
|
||||||
|
let currentValue = container.wrappedValue
|
||||||
|
if currentValue < kMinComposingBufferSize {
|
||||||
|
return kMinComposingBufferSize
|
||||||
|
} else if currentValue > kMaxComposingBufferSize {
|
||||||
|
return kMaxComposingBufferSize
|
||||||
|
}
|
||||||
|
return currentValue
|
||||||
|
}
|
||||||
|
set {
|
||||||
|
var value = newValue
|
||||||
|
if value < kMinComposingBufferSize {
|
||||||
|
value = kMinComposingBufferSize
|
||||||
|
} else if value > kMaxComposingBufferSize {
|
||||||
|
value = kMaxComposingBufferSize
|
||||||
|
}
|
||||||
|
container.wrappedValue = value
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@propertyWrapper
|
||||||
|
struct ComposingKeys {
|
||||||
|
let key: String
|
||||||
|
let defaultValue: String? = kCandidateKeys
|
||||||
|
lazy var container: UserDefault = {
|
||||||
|
UserDefault(key: key, defaultValue: defaultValue) }()
|
||||||
|
|
||||||
|
var wrappedValue: String? {
|
||||||
|
mutating get {
|
||||||
|
let value = container.wrappedValue
|
||||||
|
if let value = value {
|
||||||
|
if value.trimmingCharacters(in: .whitespacesAndNewlines).isEmpty {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return value
|
||||||
|
}
|
||||||
|
set {
|
||||||
|
let value = newValue
|
||||||
|
if let value = value {
|
||||||
|
if value.trimmingCharacters(in: .whitespacesAndNewlines).isEmpty {
|
||||||
|
container.wrappedValue = nil
|
||||||
|
return
|
||||||
|
}
|
||||||
|
}
|
||||||
|
container.wrappedValue = value
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// MARK: -
|
||||||
|
|
||||||
|
class Preferences: NSObject {
|
||||||
|
@UserDefault(key: kKeyboardLayoutPreferenceKey, defaultValue: 0)
|
||||||
|
@objc static var keyboardLayout: Int
|
||||||
|
|
||||||
|
@objc static var keyboardLayoutName: String {
|
||||||
|
switch self.keyboardLayout {
|
||||||
|
case 0:
|
||||||
|
return "Standard"
|
||||||
|
case 1:
|
||||||
|
return "ETen"
|
||||||
|
case 2:
|
||||||
|
return "ETen26"
|
||||||
|
case 3:
|
||||||
|
return "Hsu"
|
||||||
|
case 4:
|
||||||
|
return "HanyuPinyin"
|
||||||
|
case 5:
|
||||||
|
return "IBM"
|
||||||
|
default:
|
||||||
|
return "Standard"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@UserDefault(key: kBasisKeyboardLayoutPreferenceKey, defaultValue: "com.apple.keylayout.US")
|
||||||
|
@objc static var basisKeyboardLayout: String
|
||||||
|
|
||||||
|
@UserDefault(key: kFunctionKeyKeyboardLayoutPreferenceKey, defaultValue: "com.apple.keylayout.US")
|
||||||
|
@objc static var functionKeyboardLayout: String
|
||||||
|
|
||||||
|
@UserDefault(key: kFunctionKeyKeyboardLayoutOverrideIncludeShiftKey, defaultValue: false)
|
||||||
|
@objc static var functionKeyKeyboardLayoutOverrideIncludeShiftKey: Bool
|
||||||
|
|
||||||
|
@CandidateListTextSize(key: kCandidateListTextSizeKey)
|
||||||
|
@objc static var candidateListTextSize: CGFloat
|
||||||
|
|
||||||
|
@UserDefault(key: kSelectPhraseAfterCursorAsCandidatePreferenceKey, defaultValue: false)
|
||||||
|
@objc static var selectPhraseAfterCursorAsCandidate: Bool
|
||||||
|
|
||||||
|
@UserDefault(key: kUseHorizontalCandidateListPreferenceKey, defaultValue: false)
|
||||||
|
@objc static var useHorizontalCandidateList: Bool
|
||||||
|
|
||||||
|
@ComposingBufferSize(key: kComposingBufferSizePreferenceKey)
|
||||||
|
@objc static var composingBufferSize: Int
|
||||||
|
|
||||||
|
@UserDefault(key: kChooseCandidateUsingSpaceKey, defaultValue: true)
|
||||||
|
@objc static var chooseCandidateUsingSpace: Bool
|
||||||
|
|
||||||
|
@UserDefault(key: kChineseConversionEnabledKey, defaultValue: true)
|
||||||
|
@objc static var chineseConversionEnabled: Bool
|
||||||
|
|
||||||
|
@objc static func toggleChineseConversionEnabled() -> Bool {
|
||||||
|
chineseConversionEnabled = !chineseConversionEnabled
|
||||||
|
return chineseConversionEnabled
|
||||||
|
}
|
||||||
|
|
||||||
|
@UserDefault(key: kHalfWidthPunctuationEnabledKey, defaultValue: true)
|
||||||
|
@objc static var halfWidthPunctuationEnabled: Bool
|
||||||
|
|
||||||
|
@objc static func toogleHalfWidthPunctuationEnabled() -> Bool {
|
||||||
|
halfWidthPunctuationEnabled = !halfWidthPunctuationEnabled
|
||||||
|
return halfWidthPunctuationEnabled;
|
||||||
|
}
|
||||||
|
|
||||||
|
@UserDefault(key: kEscToCleanInputBufferKey, defaultValue: true)
|
||||||
|
@objc static var escToCleanInputBuffer: Bool
|
||||||
|
|
||||||
|
// MARK: Optional settings
|
||||||
|
|
||||||
|
@UserDefault(key: kCandidateTextFontName, defaultValue: nil)
|
||||||
|
@objc static var candidateTextFontName: String?
|
||||||
|
|
||||||
|
@UserDefault(key: kCandidateKeyLabelFontName, defaultValue: nil)
|
||||||
|
@objc static var candidateKeyLabelFontName: String?
|
||||||
|
|
||||||
|
@ComposingKeys(key: kCandidateKeys)
|
||||||
|
@objc static var candidateKeys: String?
|
||||||
|
|
||||||
|
@objc static var defaultKeys: String {
|
||||||
|
kDefaultKeys
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
|
@ -35,10 +35,6 @@
|
||||||
import Cocoa
|
import Cocoa
|
||||||
import Carbon
|
import Carbon
|
||||||
|
|
||||||
private let kBasisKeyboardLayoutPreferenceKey = "BasisKeyboardLayout"
|
|
||||||
private let kCandidateKeys = "CandidateKeys"
|
|
||||||
private let kDefaultKeys = "123456789"
|
|
||||||
|
|
||||||
// Please note that the class should be exposed as "PreferencesWindowController"
|
// Please note that the class should be exposed as "PreferencesWindowController"
|
||||||
// in Objective-C in order to let IMK to see the same class name as
|
// in Objective-C in order to let IMK to see the same class name as
|
||||||
// the "InputMethodServerPreferencesWindowControllerClass" in Info.plist.
|
// the "InputMethodServerPreferencesWindowControllerClass" in Info.plist.
|
||||||
|
@ -54,7 +50,7 @@ private let kDefaultKeys = "123456789"
|
||||||
|
|
||||||
basisKeyboardLayoutButton.menu?.removeAllItems()
|
basisKeyboardLayoutButton.menu?.removeAllItems()
|
||||||
|
|
||||||
let basisKeyboardLayoutID = UserDefaults.standard.string(forKey: kBasisKeyboardLayoutPreferenceKey)
|
let basisKeyboardLayoutID = Preferences.basisKeyboardLayout
|
||||||
for source in list {
|
for source in list {
|
||||||
if let categoryPtr = TISGetInputSourceProperty(source, kTISPropertyInputSourceCategory) {
|
if let categoryPtr = TISGetInputSourceProperty(source, kTISPropertyInputSourceCategory) {
|
||||||
let category = Unmanaged<CFString>.fromOpaque(categoryPtr).takeUnretainedValue()
|
let category = Unmanaged<CFString>.fromOpaque(categoryPtr).takeUnretainedValue()
|
||||||
|
@ -106,37 +102,36 @@ private let kDefaultKeys = "123456789"
|
||||||
|
|
||||||
basisKeyboardLayoutButton.select(chosenItem ?? usKeyboardLayoutItem)
|
basisKeyboardLayoutButton.select(chosenItem ?? usKeyboardLayoutItem)
|
||||||
selectionKeyComboBox.usesDataSource = false
|
selectionKeyComboBox.usesDataSource = false
|
||||||
selectionKeyComboBox.addItems(withObjectValues: [kDefaultKeys, "asdfghjkl", "asdfzxcvb"])
|
selectionKeyComboBox.addItems(withObjectValues: [Preferences.defaultKeys, "asdfghjkl", "asdfzxcvb"])
|
||||||
|
|
||||||
var candidateSelectionKeys = (UserDefaults.standard.string(forKey: kCandidateKeys) ?? kDefaultKeys)
|
var candidateSelectionKeys = Preferences.candidateKeys ?? Preferences.defaultKeys
|
||||||
.trimmingCharacters(in: CharacterSet.whitespacesAndNewlines)
|
|
||||||
if candidateSelectionKeys.isEmpty {
|
if candidateSelectionKeys.isEmpty {
|
||||||
candidateSelectionKeys = kDefaultKeys
|
candidateSelectionKeys = Preferences.defaultKeys
|
||||||
}
|
}
|
||||||
|
|
||||||
selectionKeyComboBox.stringValue = candidateSelectionKeys
|
selectionKeyComboBox.stringValue = candidateSelectionKeys
|
||||||
}
|
}
|
||||||
|
|
||||||
@IBAction func updateBasisKeyboardLayoutAction(_ sender: Any) {
|
@IBAction func updateBasisKeyboardLayoutAction(_ sender: Any) {
|
||||||
if let sourceID = basisKeyboardLayoutButton.selectedItem?.representedObject {
|
if let sourceID = basisKeyboardLayoutButton.selectedItem?.representedObject as? String {
|
||||||
UserDefaults.standard.set(sourceID, forKey: kBasisKeyboardLayoutPreferenceKey)
|
Preferences.basisKeyboardLayout = sourceID
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@IBAction func changeSelectionKeyAction(_ sender: Any) {
|
@IBAction func changeSelectionKeyAction(_ sender: Any) {
|
||||||
let keys = (sender as AnyObject).stringValue.trimmingCharacters(in: CharacterSet.whitespacesAndNewlines)
|
let keys = (sender as AnyObject).stringValue.trimmingCharacters(in: CharacterSet.whitespacesAndNewlines)
|
||||||
if keys.count != 9 || !keys.canBeConverted(to: .ascii) {
|
if keys.count != 9 || !keys.canBeConverted(to: .ascii) {
|
||||||
selectionKeyComboBox.stringValue = kDefaultKeys
|
selectionKeyComboBox.stringValue = Preferences.defaultKeys
|
||||||
UserDefaults.standard.removeObject(forKey: kCandidateKeys)
|
Preferences.candidateKeys = nil
|
||||||
NSSound.beep()
|
NSSound.beep()
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
selectionKeyComboBox.stringValue = keys
|
selectionKeyComboBox.stringValue = keys
|
||||||
if keys == kDefaultKeys {
|
if keys == Preferences.defaultKeys {
|
||||||
UserDefaults.standard.removeObject(forKey: kCandidateKeys)
|
Preferences.candidateKeys = nil
|
||||||
} else {
|
} else {
|
||||||
UserDefaults.standard.set(keys, forKey: kCandidateKeys)
|
Preferences.candidateKeys = keys
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue