From f8d5febadb5e5e5fe46755f66d185f071306c04b Mon Sep 17 00:00:00 2001 From: ShikiSuen Date: Sat, 15 Jan 2022 00:59:34 +0800 Subject: [PATCH] Zonble: Swiftify // AppDelegate - Applied the usage of frmAboutWindow and Hiraku's Notification Center implementation. - Disables auto-update by default since this feature is not finished for vChewing. Co-Authored-By: Hiraku --- Source/AppDelegate.h | 61 ------ Source/AppDelegate.m | 296 ----------------------------- Source/AppDelegate.swift | 251 ++++++++++++++++++++++++ Source/InputMethodController.mm | 1 - Source/vChewing-Bridging-Header.h | 2 + vChewing.xcodeproj/project.pbxproj | 10 +- 6 files changed, 257 insertions(+), 364 deletions(-) delete mode 100644 Source/AppDelegate.h delete mode 100644 Source/AppDelegate.m create mode 100644 Source/AppDelegate.swift diff --git a/Source/AppDelegate.h b/Source/AppDelegate.h deleted file mode 100644 index a2c01108..00000000 --- a/Source/AppDelegate.h +++ /dev/null @@ -1,61 +0,0 @@ -// -// AppDelegate.h -// -// Copyright (c) 2021-2022 The vChewing Project. -// Copyright (c) 2011-2022 The OpenVanilla Project. -// -// Contributors: -// Mengjuei Hsieh (@mjhsieh) @ OpenVanilla -// Weizhong Yang (@zonble) @ OpenVanilla -// Lukhnos Liu (@lukhnos) @ OpenVanilla -// Hiraku Wang (@hirakujira) @ vChewing -// Shiki Suen (@ShikiSuen) @ vChewing -// -// 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 -#import "frmAboutWindow.h" - -@class PreferencesWindowController; - -@interface AppDelegate : NSObject -{ -@private - NSURLConnection *_updateCheckConnection; - BOOL _currentUpdateCheckIsForced; - NSMutableData *_receivingData; - NSURL *_updateNextStepURL; - PreferencesWindowController *_preferencesWindowController; - frmAboutWindow *_aboutWindowController; -} - -- (void)checkForUpdate; -- (void)checkForUpdateForced:(BOOL)forced; -- (void)showPreferences; -- (void)showAbout; - -@property (weak, nonatomic) IBOutlet NSWindow *window; -@end diff --git a/Source/AppDelegate.m b/Source/AppDelegate.m deleted file mode 100644 index 25248418..00000000 --- a/Source/AppDelegate.m +++ /dev/null @@ -1,296 +0,0 @@ -// -// AppDelegate.m -// -// Copyright (c) 2021-2022 The vChewing Project. -// Copyright (c) 2011-2022 The OpenVanilla Project. -// -// Contributors: -// Mengjuei Hsieh (@mjhsieh) @ OpenVanilla -// Weizhong Yang (@zonble) @ OpenVanilla -// Lukhnos Liu (@lukhnos) @ OpenVanilla -// Hiraku Wang (@hirakujira) @ vChewing -// Shiki Suen (@ShikiSuen) @ vChewing -// -// 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 "AppDelegate.h" -#import "vChewing-Swift.h" -#import "frmAboutWindow.h" - -extern void LTLoadLanguageModel(void); -extern void LTLoadUserLanguageModelFile(void); - -static NSString *kCheckUpdateAutomatically = @"CheckUpdateAutomatically"; -static NSString *kNextUpdateCheckDateKey = @"NextUpdateCheckDate"; -static NSString *kUpdateInfoEndpointKey = @"UpdateInfoEndpoint"; -static NSString *kUpdateInfoSiteKey = @"UpdateInfoSite"; -static const NSTimeInterval kNextCheckInterval = 86400.0; -static const NSTimeInterval kTimeoutInterval = 60.0; - -@interface AppDelegate () -@end - -@implementation AppDelegate -@synthesize window = _window; - -- (void)dealloc -{ - _preferencesWindowController = nil; - _aboutWindowController = nil; - _updateCheckConnection = nil; -} - -- (void)applicationDidFinishLaunching:(NSNotification *)inNotification -{ - LTLoadLanguageModel(); - LTLoadUserLanguageModelFile(); - - if (![[NSUserDefaults standardUserDefaults] objectForKey:kCheckUpdateAutomatically]) { - [[NSUserDefaults standardUserDefaults] setBool:YES forKey:kCheckUpdateAutomatically]; - [[NSUserDefaults standardUserDefaults] synchronize]; - } - - [self checkForUpdate]; - [[NSUserNotificationCenter defaultUserNotificationCenter] setDelegate:self]; -} - -- (void)checkForUpdate -{ - [self checkForUpdateForced:NO]; -} - -- (void)checkForUpdateForced:(BOOL)forced -{ - if (_updateCheckConnection) { - // busy - return; - } - - _currentUpdateCheckIsForced = forced; - - // time for update? - if (!forced) { - if (![[NSUserDefaults standardUserDefaults] boolForKey:kCheckUpdateAutomatically]) { - return; - } - - NSDate *now = [NSDate date]; - NSDate *date = [[NSUserDefaults standardUserDefaults] objectForKey:kNextUpdateCheckDateKey]; - if (![date isKindOfClass:[NSDate class]]) { - date = now; - } - - if ([now compare:date] == NSOrderedAscending) { - return; - } - } - - NSDate *nextUpdateDate = [NSDate dateWithTimeInterval:kNextCheckInterval sinceDate:[NSDate date]]; - [[NSUserDefaults standardUserDefaults] setObject:nextUpdateDate forKey:kNextUpdateCheckDateKey]; - - NSDictionary *infoDict = [[NSBundle mainBundle] infoDictionary]; - NSString *updateInfoURLString = [infoDict objectForKey:kUpdateInfoEndpointKey]; - if (![updateInfoURLString length]) { - return; - } - - NSURL *updateInfoURL = [NSURL URLWithString:updateInfoURLString]; - if (!updateInfoURL) { - return; - } - - NSURLRequest *request = [NSURLRequest requestWithURL:updateInfoURL cachePolicy:NSURLRequestReloadIgnoringLocalCacheData timeoutInterval:kTimeoutInterval]; - if (!request) { - return; - } -#if DEBUG - NSLog(@"about to request update url %@ ",updateInfoURL); -#endif - - if (_receivingData) { - _receivingData = nil; - } - - // create a new data buffer and connection - _receivingData = [[NSMutableData alloc] init]; - _updateCheckConnection = [[NSURLConnection alloc] initWithRequest:request delegate:self]; - [_updateCheckConnection start]; -} - -- (void)showPreferences -{ - if (!_preferencesWindowController) { - _preferencesWindowController = [[PreferencesWindowController alloc] initWithWindowNibName:@"preferences"]; - } - [[_preferencesWindowController window] center]; - [[_preferencesWindowController window] orderFront:self]; -} - -- (void)connection:(NSURLConnection *)connection didFailWithError:(NSError *)error -{ - BOOL isForcedCheck = _currentUpdateCheckIsForced; - - _receivingData = nil; - _updateCheckConnection = nil; - _currentUpdateCheckIsForced = NO; - - if (isForcedCheck) { - [[NonModalAlertWindowController sharedInstance] showWithTitle:NSLocalizedString(@"Update Check Failed", nil) content:[NSString stringWithFormat:NSLocalizedString(@"There may be no internet connection or the server failed to respond.\n\nError message: %@", nil), [error localizedDescription]] confirmButtonTitle:NSLocalizedString(@"Dismiss", nil) cancelButtonTitle:nil cancelAsDefault:NO delegate:nil]; - } -} - -- (void)showNoUpdateAvailableAlert -{ - [[NonModalAlertWindowController sharedInstance] showWithTitle:NSLocalizedString(@"Check for Update Completed", nil) content:NSLocalizedString(@"You are already using the latest version of vChewing.", nil) confirmButtonTitle:NSLocalizedString(@"OK", nil) cancelButtonTitle:nil cancelAsDefault:NO delegate:nil]; -} - -- (void)connectionDidFinishLoading:(NSURLConnection *)connection -{ - id plist = [NSPropertyListSerialization propertyListWithData:_receivingData options:NSPropertyListImmutable format:NULL error:NULL]; -#if DEBUG - NSLog(@"plist %@",plist); -#endif - - BOOL isForcedCheck = _currentUpdateCheckIsForced; - - _receivingData = nil; - _updateCheckConnection = nil; - _currentUpdateCheckIsForced = NO; - - if (!plist) { - if (isForcedCheck) { - [self showNoUpdateAvailableAlert]; - } - return; - } - - NSString *remoteVersion = [plist objectForKey:(id)kCFBundleVersionKey]; -#if DEBUG - NSLog(@"the remoteversion is %@",remoteVersion); -#endif - if (!remoteVersion) { - if (isForcedCheck) { - [self showNoUpdateAvailableAlert]; - } - return; - } - - // TODO: Validate info (e.g. bundle identifier) - // TODO: Use HTML to display change log, need a new key like UpdateInfoChangeLogURL for this - - NSDictionary *infoDict = [[NSBundle mainBundle] infoDictionary]; - NSString *currentVersion = [infoDict objectForKey:(id)kCFBundleVersionKey]; - NSComparisonResult result = [currentVersion compare:remoteVersion options:NSNumericSearch]; - - if (result != NSOrderedAscending) { - if (isForcedCheck) { - [self showNoUpdateAvailableAlert]; - } - return; - } - - - NSString *siteInfoURLString = [plist objectForKey:kUpdateInfoSiteKey]; - if (!siteInfoURLString) { - if (isForcedCheck) { - [self showNoUpdateAvailableAlert]; - } - return; - } - - NSURL *siteInfoURL = [NSURL URLWithString:siteInfoURLString]; - if (!siteInfoURL) { - if (isForcedCheck) { - [self showNoUpdateAvailableAlert]; - } - return; - } - _updateNextStepURL = siteInfoURL; - - NSDictionary *versionDescriptions = [plist objectForKey:@"Description"]; - NSString *versionDescription = @""; - if ([versionDescriptions isKindOfClass:[NSDictionary class]]) { - NSString *locale = @"en"; - NSArray *supportedLocales = [NSArray arrayWithObjects:@"en", @"zh-Hant", @"zh-Hans", nil]; - NSArray *preferredTags = [NSBundle preferredLocalizationsFromArray:supportedLocales]; - if ([preferredTags count]) { - locale = [preferredTags objectAtIndex:0]; - } - versionDescription = [versionDescriptions objectForKey:locale]; - if (!versionDescription) { - versionDescription = [versionDescriptions objectForKey:@"en"]; - } - - if (!versionDescription) { - versionDescription = @""; - } - else { - versionDescription = [@"\n\n" stringByAppendingString:versionDescription]; - } - } - - NSString *content = [NSString stringWithFormat:NSLocalizedString(@"You're currently using vChewing %@ (%@), a new version %@ (%@) is now available. Do you want to visit vChewing's website to download the version?%@", nil), [infoDict objectForKey:@"CFBundleShortVersionString"], currentVersion, [plist objectForKey:@"CFBundleShortVersionString"], remoteVersion, versionDescription]; - - [[NonModalAlertWindowController sharedInstance] showWithTitle:NSLocalizedString(@"New Version Available", nil) content:content confirmButtonTitle:NSLocalizedString(@"Visit Website", nil) cancelButtonTitle:NSLocalizedString(@"Not Now", nil) cancelAsDefault:NO delegate:self]; -} - -- (void)connection:(NSURLConnection *)connection didReceiveData:(NSData *)data -{ - [_receivingData appendData:data]; -} - -- (void)nonModalAlertWindowControllerDidConfirm:(NonModalAlertWindowController *)controller -{ - if (_updateNextStepURL) { - [[NSWorkspace sharedWorkspace] openURL:_updateNextStepURL]; - } - - _updateNextStepURL = nil; -} - -- (void)nonModalAlertWindowControllerDidCancel:(NonModalAlertWindowController *)controller -{ - _updateNextStepURL = nil; -} - -- (BOOL)userNotificationCenter:(NSUserNotificationCenter *)center shouldPresentNotification:(NSUserNotification *)notification{ - return YES; -} - -- (void)showAbout { - if (!_aboutWindowController) { - _aboutWindowController = [[frmAboutWindow alloc] initWithWindowNibName:@"frmAboutWindow"]; - } - [[_aboutWindowController window] center]; - [[_aboutWindowController window] orderFrontRegardless]; -} - -- (IBAction) about:(id)sender { - [(AppDelegate *)[NSApp delegate] showAbout]; - [[NSApplication sharedApplication] activateIgnoringOtherApps:YES]; -} - -@end diff --git a/Source/AppDelegate.swift b/Source/AppDelegate.swift new file mode 100644 index 00000000..96364162 --- /dev/null +++ b/Source/AppDelegate.swift @@ -0,0 +1,251 @@ +// +// AppDelegate.swift +// +// Copyright (c) 2021-2022 The vChewing Project. +// Copyright (c) 2011-2022 The OpenVanilla Project. +// +// Contributors: +// Mengjuei Hsieh (@mjhsieh) @ OpenVanilla +// Weizhong Yang (@zonble) @ OpenVanilla +// Lukhnos Liu (@lukhnos) @ OpenVanilla +// Hiraku Wang (@hirakujira) @ vChewing +// Shiki Suen (@ShikiSuen) @ vChewing +// +// 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 +import InputMethodKit + +private let kCheckUpdateAutomatically = "CheckUpdateAutomatically" +private let kNextUpdateCheckDateKey = "NextUpdateCheckDate" +private let kUpdateInfoEndpointKey = "UpdateInfoEndpoint" +private let kUpdateInfoSiteKey = "UpdateInfoSite" +private let kNextCheckInterval: TimeInterval = 86400.0 +private let kTimeoutInterval: TimeInterval = 60.0 + +@objc (AppDelegate) +class AppDelegate: NSObject, NSApplicationDelegate, + NSUserNotificationCenterDelegate, // Hiraku PR#1 + NonModalAlertWindowControllerDelegate { + + @IBOutlet weak var window: NSWindow? + private var preferencesWindowController: PreferencesWindowController? + private var aboutWindowController: frmAboutWindow? // New About Window + private var checkTask: URLSessionTask? + private var updateNextStepURL: URL? + + // 補上 dealloc + deinit { + preferencesWindowController = nil + aboutWindowController = nil + checkTask = nil + updateNextStepURL = nil + } + + func applicationDidFinishLaunching(_ notification: Notification) { + LTLoadLanguageModel() + LTLoadUserLanguageModelFile(); + + if UserDefaults.standard.object(forKey: kCheckUpdateAutomatically) == nil { + UserDefaults.standard.set(false, forKey: kCheckUpdateAutomatically) + UserDefaults.standard.synchronize() + } + checkForUpdate() + NSUserNotificationCenter.default.delegate = self // Hiraku PR#1 + } + + @objc func showPreferences() { + if (preferencesWindowController == nil) { + preferencesWindowController = PreferencesWindowController(windowNibName: "preferences") + } + preferencesWindowController?.window?.center() + preferencesWindowController?.window?.orderFrontRegardless() // 逼著屬性視窗往最前方顯示 + } + + // New About Window + @objc func showAbout() { + if (aboutWindowController == nil) { + aboutWindowController = frmAboutWindow.init(windowNibName: "frmAboutWindow") + } + aboutWindowController?.window?.center() + aboutWindowController?.window?.orderFrontRegardless() // 逼著關於視窗往最前方顯示 + } + + @objc (checkForUpdate) + func checkForUpdate() { + checkForUpdate(forced: false) + } + + @objc (checkForUpdateForced:) + func checkForUpdate(forced: Bool) { + + if checkTask != nil { + // busy + return + } + + // time for update? + if !forced { + if UserDefaults.standard.bool(forKey: kCheckUpdateAutomatically) == false { + return + } + let now = Date() + let date = UserDefaults.standard.object(forKey: kNextUpdateCheckDateKey) as? Date ?? now + if now.compare(date) == .orderedAscending { + return + } + } + + let nextUpdateDate = Date(timeInterval: kNextCheckInterval, since: Date()) + UserDefaults.standard.set(nextUpdateDate, forKey: kNextUpdateCheckDateKey) + + guard let infoDict = Bundle.main.infoDictionary, + let updateInfoURLString = infoDict[kUpdateInfoEndpointKey] as? String, + let updateInfoURL = URL(string: updateInfoURLString) else { + return + } + + let request = URLRequest(url: updateInfoURL, cachePolicy: .reloadIgnoringLocalCacheData, timeoutInterval: kTimeoutInterval) + + func showNoUpdateAvailableAlert() { + NonModalAlertWindowController.shared.show(title: NSLocalizedString("Check for Update Completed", comment: ""), content: NSLocalizedString("You are already using the latest version of vChewing.", comment: ""), confirmButtonTitle: NSLocalizedString("OK", comment: ""), cancelButtonTitle: nil, cancelAsDefault: false, delegate: nil) + } + + let task = URLSession.shared.dataTask(with: request) { data, response, error in + defer { + self.checkTask = nil + } + + if let error = error { + if forced { + let title = NSLocalizedString("Update Check Failed", comment: "") + let content = String(format: NSLocalizedString("There may be no internet connection or the server failed to respond.\n\nError message: %@", comment: ""), error.localizedDescription) + let buttonTitle = NSLocalizedString("Dismiss", comment: "") + + DispatchQueue.main.async { + NonModalAlertWindowController.shared.show(title: title , content: content, confirmButtonTitle: buttonTitle, cancelButtonTitle: nil, cancelAsDefault: false, delegate: nil) + } + } + return + } + + do { + guard let plist = try PropertyListSerialization.propertyList(from: data ?? Data(), options: [], format: nil) as? [AnyHashable: Any], + let remoteVersion = plist[kCFBundleVersionKey] as? String, + let infoDict = Bundle.main.infoDictionary + else { + if forced { + DispatchQueue.main.async { + showNoUpdateAvailableAlert() + } + } + return + } + + // TODO: Validate info (e.g. bundle identifier) + // TODO: Use HTML to display change log, need a new key like UpdateInfoChangeLogURL for this + let currentVersion = infoDict[kCFBundleVersionKey as String] as? String ?? "" + let result = currentVersion.compare(remoteVersion, options: .numeric, range: nil, locale: nil) + + if result != .orderedAscending { + if forced { + DispatchQueue.main.async { + showNoUpdateAvailableAlert() + } + } + } + + guard let siteInfoURLString = plist[kUpdateInfoSiteKey] as? String, + let siteInfoURL = URL(string: siteInfoURLString) else { + if forced { + DispatchQueue.main.async { + showNoUpdateAvailableAlert() + } + } + return + } + + self.updateNextStepURL = siteInfoURL + + var versionDescription = "" + let versionDescriptions = plist["Description"] as? [AnyHashable: Any] + if let versionDescriptions = versionDescriptions { + var locale = "en" + let supportedLocales = ["en", "zh-Hant", "zh-Hans"] + let preferredTags = Bundle.preferredLocalizations(from: supportedLocales) + if let first = preferredTags.first { + locale = first + } + versionDescription = versionDescriptions[locale] as? String ?? versionDescriptions["en"] as? String ?? "" + if !versionDescription.isEmpty { + versionDescription = "\n\n" + versionDescription + } + } + + let content = String(format: NSLocalizedString("You're currently using vChewing %@ (%@), a new version %@ (%@) is now available. Do you want to visit vChewing's website to download the version?%@", comment: ""), + infoDict["CFBundleShortVersionString"] as? String ?? "", + currentVersion, + plist["CFBundleShortVersionString"] as? String ?? "", + remoteVersion, + versionDescription) + DispatchQueue.main.async { + NonModalAlertWindowController.shared.show(title: NSLocalizedString("New Version Available", comment: "") , content: content, confirmButtonTitle: NSLocalizedString("Visit Website", comment: ""), cancelButtonTitle: NSLocalizedString("Not Now", comment: ""), cancelAsDefault: false, delegate: self) + } + + } catch { + if forced { + DispatchQueue.main.async { + showNoUpdateAvailableAlert() + } + } + } + } + checkTask = task + task.resume() + } + + func nonModalAlertWindowControllerDidConfirm(_ controller: NonModalAlertWindowController) { + if let updateNextStepURL = updateNextStepURL { + NSWorkspace.shared.open(updateNextStepURL) + } + updateNextStepURL = nil + } + + func nonModalAlertWindowControllerDidCancel(_ controller: NonModalAlertWindowController) { + updateNextStepURL = nil + } + + // Hiraku PR#1 + func userNotificationCenter(_ center: NSUserNotificationCenter, shouldPresent notification: NSUserNotification) -> Bool { + return true + } + + // New About Window + @IBAction func about(_ sender: Any) { + (NSApp.delegate as? AppDelegate)?.showAbout() + NSApplication.shared.activate(ignoringOtherApps: true) + } +} diff --git a/Source/InputMethodController.mm b/Source/InputMethodController.mm index e8e1adba..023292dc 100644 --- a/Source/InputMethodController.mm +++ b/Source/InputMethodController.mm @@ -42,7 +42,6 @@ #import #import "OVStringHelper.h" #import "OVUTF8Helper.h" -#import "AppDelegate.h" #import "vChewing-Swift.h" diff --git a/Source/vChewing-Bridging-Header.h b/Source/vChewing-Bridging-Header.h index 1b2cb5d6..1fa833cc 100644 --- a/Source/vChewing-Bridging-Header.h +++ b/Source/vChewing-Bridging-Header.h @@ -2,3 +2,5 @@ // Use this file to import your target's public headers that you would like to expose to Swift. // +extern void LTLoadLanguageModel(void); +extern void LTLoadUserLanguageModelFile(void); diff --git a/vChewing.xcodeproj/project.pbxproj b/vChewing.xcodeproj/project.pbxproj index 0ae003b0..7910062d 100644 --- a/vChewing.xcodeproj/project.pbxproj +++ b/vChewing.xcodeproj/project.pbxproj @@ -20,11 +20,11 @@ 5BDF2CFF2791BECC00838ADB /* InputSourceHelper.swift in Sources */ = {isa = PBXBuildFile; fileRef = 5BDF2CFD2791BE4400838ADB /* InputSourceHelper.swift */; }; 5BDF2D012791C03B00838ADB /* PreferencesWindowController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 5BDF2D002791C03B00838ADB /* PreferencesWindowController.swift */; }; 5BDF2D032791C71200838ADB /* NonModalAlertWindowController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 5BDF2D022791C71200838ADB /* NonModalAlertWindowController.swift */; }; + 5BDF2D062791DFF200838ADB /* AppDelegate.swift in Sources */ = {isa = PBXBuildFile; fileRef = 5BDF2D052791DA6700838ADB /* AppDelegate.swift */; }; 5BF4A6FE27844738007DC6E7 /* frmAboutWindow.m in Sources */ = {isa = PBXBuildFile; fileRef = 5BF4A6FC27844738007DC6E7 /* frmAboutWindow.m */; }; 5BF4A70027844DC5007DC6E7 /* frmAboutWindow.xib in Resources */ = {isa = PBXBuildFile; fileRef = 5BF4A70227844DC5007DC6E7 /* frmAboutWindow.xib */; }; 6A0421A815FEF3F50061ED63 /* FastLM.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 6A0421A615FEF3F50061ED63 /* FastLM.cpp */; }; 6A0D4EA715FC0D2D00ABF4B3 /* Cocoa.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 6A0D4EA615FC0D2D00ABF4B3 /* Cocoa.framework */; }; - 6A0D4ED015FC0D6400ABF4B3 /* AppDelegate.m in Sources */ = {isa = PBXBuildFile; fileRef = 6A0D4EC415FC0D6400ABF4B3 /* AppDelegate.m */; }; 6A0D4ED215FC0D6400ABF4B3 /* InputMethodController.mm in Sources */ = {isa = PBXBuildFile; fileRef = 6A0D4EC715FC0D6400ABF4B3 /* InputMethodController.mm */; }; 6A0D4ED315FC0D6400ABF4B3 /* main.m in Sources */ = {isa = PBXBuildFile; fileRef = 6A0D4EC815FC0D6400ABF4B3 /* main.m */; }; 6A0D4F0815FC0DA600ABF4B3 /* Bopomofo.tiff in Resources */ = {isa = PBXBuildFile; fileRef = 6A0D4EEF15FC0DA600ABF4B3 /* Bopomofo.tiff */; }; @@ -96,6 +96,7 @@ 5BDF2CFD2791BE4400838ADB /* InputSourceHelper.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = InputSourceHelper.swift; sourceTree = ""; }; 5BDF2D002791C03B00838ADB /* PreferencesWindowController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = PreferencesWindowController.swift; sourceTree = ""; }; 5BDF2D022791C71200838ADB /* NonModalAlertWindowController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = NonModalAlertWindowController.swift; sourceTree = ""; }; + 5BDF2D052791DA6700838ADB /* AppDelegate.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AppDelegate.swift; sourceTree = ""; }; 5BF4A6FB27844738007DC6E7 /* frmAboutWindow.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = frmAboutWindow.h; sourceTree = ""; }; 5BF4A6FC27844738007DC6E7 /* frmAboutWindow.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = frmAboutWindow.m; sourceTree = ""; }; 5BF4A70327844DD0007DC6E7 /* Base */ = {isa = PBXFileReference; lastKnownFileType = file.xib; name = Base; path = Base.lproj/frmAboutWindow.xib; sourceTree = ""; }; @@ -108,8 +109,6 @@ 6A0D4EA615FC0D2D00ABF4B3 /* Cocoa.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = Cocoa.framework; path = System/Library/Frameworks/Cocoa.framework; sourceTree = SDKROOT; }; 6A0D4EA915FC0D2D00ABF4B3 /* AppKit.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = AppKit.framework; path = System/Library/Frameworks/AppKit.framework; sourceTree = SDKROOT; }; 6A0D4EAB15FC0D2D00ABF4B3 /* Foundation.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = Foundation.framework; path = System/Library/Frameworks/Foundation.framework; sourceTree = SDKROOT; }; - 6A0D4EC315FC0D6400ABF4B3 /* AppDelegate.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = AppDelegate.h; sourceTree = ""; }; - 6A0D4EC415FC0D6400ABF4B3 /* AppDelegate.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = AppDelegate.m; sourceTree = ""; }; 6A0D4EC615FC0D6400ABF4B3 /* InputMethodController.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = InputMethodController.h; sourceTree = ""; }; 6A0D4EC715FC0D6400ABF4B3 /* InputMethodController.mm */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.objcpp; path = InputMethodController.mm; sourceTree = ""; }; 6A0D4EC815FC0D6400ABF4B3 /* main.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = main.m; sourceTree = ""; }; @@ -268,8 +267,7 @@ 6A0D4F1215FC0EB100ABF4B3 /* Engine */, 6ACA41E715FC1D9000935EF6 /* Installer */, 6A0D4F4715FC0EB900ABF4B3 /* Resources */, - 6A0D4EC315FC0D6400ABF4B3 /* AppDelegate.h */, - 6A0D4EC415FC0D6400ABF4B3 /* AppDelegate.m */, + 5BDF2D052791DA6700838ADB /* AppDelegate.swift */, 5BF4A6FB27844738007DC6E7 /* frmAboutWindow.h */, 5BF4A6FC27844738007DC6E7 /* frmAboutWindow.m */, 6A0D4EC615FC0D6400ABF4B3 /* InputMethodController.h */, @@ -619,11 +617,11 @@ isa = PBXSourcesBuildPhase; buildActionMask = 2147483647; files = ( - 6A0D4ED015FC0D6400ABF4B3 /* AppDelegate.m in Sources */, 5BDF2CFE2791BE4400838ADB /* InputSourceHelper.swift in Sources */, 6A0D4ED215FC0D6400ABF4B3 /* InputMethodController.mm in Sources */, 6A0D4ED315FC0D6400ABF4B3 /* main.m in Sources */, 5BF4A6FE27844738007DC6E7 /* frmAboutWindow.m in Sources */, + 5BDF2D062791DFF200838ADB /* AppDelegate.swift in Sources */, 5BC3EE1B278FC48C00F5E44C /* VerticalCandidateController.swift in Sources */, 5B42B64027876FDC00BB9B9F /* UserOverrideModel.cpp in Sources */, D427A9C125ED28CC005D43E0 /* OpenCCBridge.swift in Sources */,