From 422fb2670d9f0924c06957607eab1434b0cba3ed Mon Sep 17 00:00:00 2001 From: Virgil Dupras Date: Sat, 22 Jun 2013 21:32:48 -0400 Subject: [PATCH] Added cocoalib as a subtree. --- cocoalib/.gitignore | 15 + cocoalib/.tx/config | 8 + cocoalib/Dialogs.h | 14 + cocoalib/Dialogs.m | 31 ++ cocoalib/HSAboutBox.h | 29 ++ cocoalib/HSAboutBox.m | 42 +++ cocoalib/HSErrorReportWindow.h | 23 ++ cocoalib/HSErrorReportWindow.m | 48 +++ cocoalib/HSFairware.h | 19 ++ cocoalib/HSFairware.m | 150 +++++++++ cocoalib/HSFairwareAboutBox.h | 33 ++ cocoalib/HSFairwareAboutBox.m | 60 ++++ cocoalib/HSFairwareProtocol.h | 20 ++ cocoalib/HSFairwareReminder.h | 46 +++ cocoalib/HSFairwareReminder.m | 115 +++++++ cocoalib/HSGeometry.h | 15 + cocoalib/HSGeometry.m | 71 ++++ cocoalib/HSPyUtil.h | 13 + cocoalib/HSPyUtil.m | 34 ++ cocoalib/HSQuicklook.h | 18 ++ cocoalib/HSQuicklook.m | 36 +++ cocoalib/HSRecentFiles.h | 35 ++ cocoalib/HSRecentFiles.m | 89 +++++ cocoalib/LICENSE | 10 + cocoalib/NSEventAdditions.h | 24 ++ cocoalib/NSEventAdditions.m | 85 +++++ cocoalib/NSImageAdditions.h | 21 ++ cocoalib/NSImageAdditions.m | 114 +++++++ cocoalib/NSNotificationAdditions.h | 10 + cocoalib/NSNotificationAdditions.m | 48 +++ cocoalib/ProgressController.h | 50 +++ cocoalib/ProgressController.m | 160 +++++++++ cocoalib/Sparkle.framework/Headers | 1 + cocoalib/Sparkle.framework/Resources | 1 + cocoalib/Sparkle.framework/Sparkle | 1 + .../Versions/A/Headers/SUAppcast.h | 33 ++ .../Versions/A/Headers/SUAppcastItem.h | 47 +++ .../Versions/A/Headers/SUUpdater.h | 118 +++++++ .../A/Headers/SUVersionComparisonProtocol.h | 27 ++ .../Versions/A/Headers/Sparkle.h | 21 ++ .../Versions/A/Resources/Info.plist | 24 ++ .../Versions/A/Resources/License.txt | 7 + .../A/Resources/SUModelTranslation.plist | 174 ++++++++++ .../A/Resources/SUStatus.nib/classes.nib | 56 ++++ .../A/Resources/SUStatus.nib/info.nib | 20 ++ .../A/Resources/SUStatus.nib/keyedobjects.nib | Bin 0 -> 7344 bytes .../SUAutomaticUpdateAlert.nib/classes.nib | 50 +++ .../SUAutomaticUpdateAlert.nib/info.nib | 20 ++ .../keyedobjects.nib | Bin 0 -> 7148 bytes .../en.lproj/SUUpdateAlert.nib/classes.nib | 67 ++++ .../en.lproj/SUUpdateAlert.nib/info.nib | 20 ++ .../SUUpdateAlert.nib/keyedobjects.nib | Bin 0 -> 10623 bytes .../SUUpdatePermissionPrompt.nib/classes.nib | 59 ++++ .../SUUpdatePermissionPrompt.nib/info.nib | 21 ++ .../keyedobjects.nib | Bin 0 -> 13263 bytes .../A/Resources/en.lproj/Sparkle.strings | Bin 0 -> 8216 bytes .../Versions/A/Resources/relaunch | Bin 0 -> 58924 bytes cocoalib/Sparkle.framework/Versions/A/Sparkle | Bin 0 -> 463540 bytes cocoalib/Sparkle.framework/Versions/Current | 1 + cocoalib/Utils.h | 36 +++ cocoalib/Utils.m | 92 ++++++ cocoalib/ValueTransformers.h | 26 ++ cocoalib/ValueTransformers.m | 79 +++++ cocoalib/Worker.h | 14 + cocoalib/cocoa/CocoaProxy.h | 32 ++ cocoalib/cocoa/CocoaProxy.m | 155 +++++++++ cocoalib/cocoa/__init__.py | 115 +++++++ cocoalib/cocoa/inter.py | 306 ++++++++++++++++++ cocoalib/controllers/HSColumns.h | 38 +++ cocoalib/controllers/HSColumns.m | 198 ++++++++++++ cocoalib/controllers/HSComboBox.h | 25 ++ cocoalib/controllers/HSComboBox.m | 119 +++++++ cocoalib/controllers/HSGUIController.h | 23 ++ cocoalib/controllers/HSGUIController.m | 62 ++++ cocoalib/controllers/HSOutline.h | 44 +++ cocoalib/controllers/HSOutline.m | 280 ++++++++++++++++ cocoalib/controllers/HSPopUpList.h | 23 ++ cocoalib/controllers/HSPopUpList.m | 60 ++++ cocoalib/controllers/HSSelectableList.h | 24 ++ cocoalib/controllers/HSSelectableList.m | 107 ++++++ cocoalib/controllers/HSTable.h | 32 ++ cocoalib/controllers/HSTable.m | 136 ++++++++ cocoalib/controllers/HSTextField.h | 21 ++ cocoalib/controllers/HSTextField.m | 53 +++ cocoalib/en.lproj/cocoalib.strings | 28 ++ cocoalib/locale/cocoalib.pot | 119 +++++++ cocoalib/locale/cs/LC_MESSAGES/cocoalib.po | 125 +++++++ cocoalib/locale/de/LC_MESSAGES/cocoalib.po | 125 +++++++ cocoalib/locale/es/LC_MESSAGES/cocoalib.po | 125 +++++++ cocoalib/locale/fr/LC_MESSAGES/cocoalib.po | 125 +++++++ cocoalib/locale/hy/LC_MESSAGES/cocoalib.po | 125 +++++++ cocoalib/locale/it/LC_MESSAGES/cocoalib.po | 125 +++++++ cocoalib/locale/nl/LC_MESSAGES/cocoalib.po | 125 +++++++ cocoalib/locale/pt_BR/LC_MESSAGES/cocoalib.po | 125 +++++++ cocoalib/locale/ru/LC_MESSAGES/cocoalib.po | 125 +++++++ cocoalib/locale/uk/LC_MESSAGES/cocoalib.po | 125 +++++++ cocoalib/locale/zh_CN/LC_MESSAGES/cocoalib.po | 125 +++++++ cocoalib/ui/about.py | 36 +++ cocoalib/ui/demo_reminder.py | 32 ++ cocoalib/ui/enter_code.py | 52 +++ cocoalib/ui/error_report.py | 33 ++ cocoalib/ui/fairware_about.py | 46 +++ cocoalib/ui/progress.py | 31 ++ cocoalib/views/HSOutlineView.h | 41 +++ cocoalib/views/HSOutlineView.m | 189 +++++++++++ cocoalib/views/HSTableView.h | 31 ++ cocoalib/views/HSTableView.m | 102 ++++++ cocoalib/views/NSIndexPathAdditions.h | 20 ++ cocoalib/views/NSIndexPathAdditions.m | 16 + cocoalib/views/NSTableViewAdditions.h | 24 ++ cocoalib/views/NSTableViewAdditions.m | 118 +++++++ 111 files changed, 6647 insertions(+) create mode 100644 cocoalib/.gitignore create mode 100644 cocoalib/.tx/config create mode 100644 cocoalib/Dialogs.h create mode 100644 cocoalib/Dialogs.m create mode 100644 cocoalib/HSAboutBox.h create mode 100644 cocoalib/HSAboutBox.m create mode 100644 cocoalib/HSErrorReportWindow.h create mode 100644 cocoalib/HSErrorReportWindow.m create mode 100644 cocoalib/HSFairware.h create mode 100644 cocoalib/HSFairware.m create mode 100644 cocoalib/HSFairwareAboutBox.h create mode 100644 cocoalib/HSFairwareAboutBox.m create mode 100644 cocoalib/HSFairwareProtocol.h create mode 100644 cocoalib/HSFairwareReminder.h create mode 100644 cocoalib/HSFairwareReminder.m create mode 100644 cocoalib/HSGeometry.h create mode 100644 cocoalib/HSGeometry.m create mode 100644 cocoalib/HSPyUtil.h create mode 100644 cocoalib/HSPyUtil.m create mode 100644 cocoalib/HSQuicklook.h create mode 100644 cocoalib/HSQuicklook.m create mode 100644 cocoalib/HSRecentFiles.h create mode 100644 cocoalib/HSRecentFiles.m create mode 100644 cocoalib/LICENSE create mode 100644 cocoalib/NSEventAdditions.h create mode 100644 cocoalib/NSEventAdditions.m create mode 100644 cocoalib/NSImageAdditions.h create mode 100644 cocoalib/NSImageAdditions.m create mode 100644 cocoalib/NSNotificationAdditions.h create mode 100644 cocoalib/NSNotificationAdditions.m create mode 100644 cocoalib/ProgressController.h create mode 100644 cocoalib/ProgressController.m create mode 120000 cocoalib/Sparkle.framework/Headers create mode 120000 cocoalib/Sparkle.framework/Resources create mode 120000 cocoalib/Sparkle.framework/Sparkle create mode 100644 cocoalib/Sparkle.framework/Versions/A/Headers/SUAppcast.h create mode 100644 cocoalib/Sparkle.framework/Versions/A/Headers/SUAppcastItem.h create mode 100644 cocoalib/Sparkle.framework/Versions/A/Headers/SUUpdater.h create mode 100644 cocoalib/Sparkle.framework/Versions/A/Headers/SUVersionComparisonProtocol.h create mode 100644 cocoalib/Sparkle.framework/Versions/A/Headers/Sparkle.h create mode 100644 cocoalib/Sparkle.framework/Versions/A/Resources/Info.plist create mode 100644 cocoalib/Sparkle.framework/Versions/A/Resources/License.txt create mode 100644 cocoalib/Sparkle.framework/Versions/A/Resources/SUModelTranslation.plist create mode 100644 cocoalib/Sparkle.framework/Versions/A/Resources/SUStatus.nib/classes.nib create mode 100644 cocoalib/Sparkle.framework/Versions/A/Resources/SUStatus.nib/info.nib create mode 100644 cocoalib/Sparkle.framework/Versions/A/Resources/SUStatus.nib/keyedobjects.nib create mode 100644 cocoalib/Sparkle.framework/Versions/A/Resources/en.lproj/SUAutomaticUpdateAlert.nib/classes.nib create mode 100644 cocoalib/Sparkle.framework/Versions/A/Resources/en.lproj/SUAutomaticUpdateAlert.nib/info.nib create mode 100644 cocoalib/Sparkle.framework/Versions/A/Resources/en.lproj/SUAutomaticUpdateAlert.nib/keyedobjects.nib create mode 100644 cocoalib/Sparkle.framework/Versions/A/Resources/en.lproj/SUUpdateAlert.nib/classes.nib create mode 100644 cocoalib/Sparkle.framework/Versions/A/Resources/en.lproj/SUUpdateAlert.nib/info.nib create mode 100644 cocoalib/Sparkle.framework/Versions/A/Resources/en.lproj/SUUpdateAlert.nib/keyedobjects.nib create mode 100644 cocoalib/Sparkle.framework/Versions/A/Resources/en.lproj/SUUpdatePermissionPrompt.nib/classes.nib create mode 100644 cocoalib/Sparkle.framework/Versions/A/Resources/en.lproj/SUUpdatePermissionPrompt.nib/info.nib create mode 100644 cocoalib/Sparkle.framework/Versions/A/Resources/en.lproj/SUUpdatePermissionPrompt.nib/keyedobjects.nib create mode 100644 cocoalib/Sparkle.framework/Versions/A/Resources/en.lproj/Sparkle.strings create mode 100755 cocoalib/Sparkle.framework/Versions/A/Resources/relaunch create mode 100755 cocoalib/Sparkle.framework/Versions/A/Sparkle create mode 120000 cocoalib/Sparkle.framework/Versions/Current create mode 100644 cocoalib/Utils.h create mode 100644 cocoalib/Utils.m create mode 100644 cocoalib/ValueTransformers.h create mode 100644 cocoalib/ValueTransformers.m create mode 100644 cocoalib/Worker.h create mode 100644 cocoalib/cocoa/CocoaProxy.h create mode 100644 cocoalib/cocoa/CocoaProxy.m create mode 100644 cocoalib/cocoa/__init__.py create mode 100644 cocoalib/cocoa/inter.py create mode 100644 cocoalib/controllers/HSColumns.h create mode 100644 cocoalib/controllers/HSColumns.m create mode 100644 cocoalib/controllers/HSComboBox.h create mode 100644 cocoalib/controllers/HSComboBox.m create mode 100644 cocoalib/controllers/HSGUIController.h create mode 100644 cocoalib/controllers/HSGUIController.m create mode 100644 cocoalib/controllers/HSOutline.h create mode 100644 cocoalib/controllers/HSOutline.m create mode 100644 cocoalib/controllers/HSPopUpList.h create mode 100644 cocoalib/controllers/HSPopUpList.m create mode 100644 cocoalib/controllers/HSSelectableList.h create mode 100644 cocoalib/controllers/HSSelectableList.m create mode 100644 cocoalib/controllers/HSTable.h create mode 100644 cocoalib/controllers/HSTable.m create mode 100644 cocoalib/controllers/HSTextField.h create mode 100644 cocoalib/controllers/HSTextField.m create mode 100644 cocoalib/en.lproj/cocoalib.strings create mode 100644 cocoalib/locale/cocoalib.pot create mode 100644 cocoalib/locale/cs/LC_MESSAGES/cocoalib.po create mode 100644 cocoalib/locale/de/LC_MESSAGES/cocoalib.po create mode 100755 cocoalib/locale/es/LC_MESSAGES/cocoalib.po create mode 100644 cocoalib/locale/fr/LC_MESSAGES/cocoalib.po create mode 100755 cocoalib/locale/hy/LC_MESSAGES/cocoalib.po create mode 100644 cocoalib/locale/it/LC_MESSAGES/cocoalib.po create mode 100644 cocoalib/locale/nl/LC_MESSAGES/cocoalib.po create mode 100644 cocoalib/locale/pt_BR/LC_MESSAGES/cocoalib.po create mode 100755 cocoalib/locale/ru/LC_MESSAGES/cocoalib.po create mode 100755 cocoalib/locale/uk/LC_MESSAGES/cocoalib.po create mode 100644 cocoalib/locale/zh_CN/LC_MESSAGES/cocoalib.po create mode 100644 cocoalib/ui/about.py create mode 100644 cocoalib/ui/demo_reminder.py create mode 100644 cocoalib/ui/enter_code.py create mode 100644 cocoalib/ui/error_report.py create mode 100644 cocoalib/ui/fairware_about.py create mode 100644 cocoalib/ui/progress.py create mode 100644 cocoalib/views/HSOutlineView.h create mode 100644 cocoalib/views/HSOutlineView.m create mode 100644 cocoalib/views/HSTableView.h create mode 100644 cocoalib/views/HSTableView.m create mode 100644 cocoalib/views/NSIndexPathAdditions.h create mode 100644 cocoalib/views/NSIndexPathAdditions.m create mode 100644 cocoalib/views/NSTableViewAdditions.h create mode 100644 cocoalib/views/NSTableViewAdditions.m diff --git a/cocoalib/.gitignore b/cocoalib/.gitignore new file mode 100644 index 00000000..aef674d2 --- /dev/null +++ b/cocoalib/.gitignore @@ -0,0 +1,15 @@ +.DS_Store +__pycache__ +autogen +*.pyc +*.so +nl.lproj +cs.lproj +de.lproj +fr.lproj +it.lproj +hy.lproj +ru.lproj +uk.lproj +zh_CN.lproj +pt_BR.lproj diff --git a/cocoalib/.tx/config b/cocoalib/.tx/config new file mode 100644 index 00000000..8b0d7920 --- /dev/null +++ b/cocoalib/.tx/config @@ -0,0 +1,8 @@ +[main] +host = https://www.transifex.net + +[hscommon.cocoalib] +file_filter = locale//LC_MESSAGES/cocoalib.po +source_file = locale/cocoalib.pot +source_lang = en +type = PO diff --git a/cocoalib/Dialogs.h b/cocoalib/Dialogs.h new file mode 100644 index 00000000..ed75266d --- /dev/null +++ b/cocoalib/Dialogs.h @@ -0,0 +1,14 @@ +/* +Copyright 2013 Hardcoded Software (http://www.hardcoded.net) + +This software is licensed under the "BSD" License as described in the "LICENSE" file, +which should be included with this package. The terms are also available at +http://www.hardcoded.net/licenses/bsd_license +*/ + +#import + +@interface Dialogs : NSObject ++ (void)showMessage:(NSString *)message; ++ (NSInteger)askYesNo:(NSString *)message; +@end diff --git a/cocoalib/Dialogs.m b/cocoalib/Dialogs.m new file mode 100644 index 00000000..194d5549 --- /dev/null +++ b/cocoalib/Dialogs.m @@ -0,0 +1,31 @@ +/* +Copyright 2013 Hardcoded Software (http://www.hardcoded.net) + +This software is licensed under the "BSD" License as described in the "LICENSE" file, +which should be included with this package. The terms are also available at +http://www.hardcoded.net/licenses/bsd_license +*/ + +#import "Dialogs.h" + +@implementation Dialogs ++ (void)showMessage:(NSString *)message +{ + NSAlert *a = [[NSAlert alloc] init]; + [a addButtonWithTitle:NSLocalizedStringFromTable(@"OK", @"cocoalib", @"")]; + [a setMessageText:message]; + [a runModal]; + [a release]; +} + ++ (NSInteger)askYesNo:(NSString *)message +{ + NSAlert *a = [[NSAlert alloc] init]; + [a addButtonWithTitle:NSLocalizedStringFromTable(@"Yes", @"cocoalib", @"")]; + [[a addButtonWithTitle:NSLocalizedStringFromTable(@"No", @"cocoalib", @"")] setKeyEquivalent:@"\E"]; + [a setMessageText:message]; + NSInteger r = [a runModal]; + [a release]; + return r; +} +@end diff --git a/cocoalib/HSAboutBox.h b/cocoalib/HSAboutBox.h new file mode 100644 index 00000000..bdb02acf --- /dev/null +++ b/cocoalib/HSAboutBox.h @@ -0,0 +1,29 @@ +/* +Copyright 2013 Hardcoded Software (http://www.hardcoded.net) + +This software is licensed under the "BSD" License as described in the "LICENSE" file, +which should be included with this package. The terms are also available at +http://www.hardcoded.net/licenses/bsd_license +*/ + +#import +#import "PyBaseApp.h" + +@interface HSAboutBox : NSWindowController +{ + NSTextField *titleTextField; + NSTextField *versionTextField; + NSTextField *copyrightTextField; + NSTextField *registeredTextField; + NSButton *registerButton; + + PyBaseApp *app; +} + +@property (readwrite, retain) NSTextField *titleTextField; +@property (readwrite, retain) NSTextField *versionTextField; +@property (readwrite, retain) NSTextField *copyrightTextField; + +- (id)initWithApp:(PyBaseApp *)app; +- (void)updateFields; +@end \ No newline at end of file diff --git a/cocoalib/HSAboutBox.m b/cocoalib/HSAboutBox.m new file mode 100644 index 00000000..e050afcb --- /dev/null +++ b/cocoalib/HSAboutBox.m @@ -0,0 +1,42 @@ +/* +Copyright 2013 Hardcoded Software (http://www.hardcoded.net) + +This software is licensed under the "BSD" License as described in the "LICENSE" file, +which should be included with this package. The terms are also available at +http://www.hardcoded.net/licenses/bsd_license +*/ + +#import "HSAboutBox.h" +#import "HSAboutBox_UI.h" + +@implementation HSAboutBox + +@synthesize titleTextField; +@synthesize versionTextField; +@synthesize copyrightTextField; + +- (id)initWithApp:(PyBaseApp *)aApp +{ + self = [super initWithWindow:nil]; + [self setWindow:createHSAboutBox_UI(self)]; + app = [aApp retain]; + [self updateFields]; + return self; +} + +- (void)dealloc +{ + [app release]; + [super dealloc]; +} + +- (void)updateFields +{ + [titleTextField setStringValue:[app appLongName]]; + NSString *version = [[NSBundle mainBundle] objectForInfoDictionaryKey:@"CFBundleVersion"]; + [versionTextField setStringValue:[NSString stringWithFormat:@"Version: %@",version]]; + NSString *copyright = [[NSBundle mainBundle] objectForInfoDictionaryKey:@"NSHumanReadableCopyright"]; + [copyrightTextField setStringValue:copyright]; +} + +@end diff --git a/cocoalib/HSErrorReportWindow.h b/cocoalib/HSErrorReportWindow.h new file mode 100644 index 00000000..0aa59fde --- /dev/null +++ b/cocoalib/HSErrorReportWindow.h @@ -0,0 +1,23 @@ +/* +Copyright 2013 Hardcoded Software (http://www.hardcoded.net) + +This software is licensed under the "BSD" License as described in the "LICENSE" file, +which should be included with this package. The terms are also available at +http://www.hardcoded.net/licenses/bsd_license +*/ + +#import + +@interface HSErrorReportWindow : NSWindowController +{ + NSTextView *contentTextView; +} + +@property (readwrite, retain) NSTextView *contentTextView; + ++ (void)showErrorReportWithContent:(NSString *)content; +- (id)initWithContent:(NSString *)content; + +- (void)send; +- (void)dontSend; +@end \ No newline at end of file diff --git a/cocoalib/HSErrorReportWindow.m b/cocoalib/HSErrorReportWindow.m new file mode 100644 index 00000000..fadc4455 --- /dev/null +++ b/cocoalib/HSErrorReportWindow.m @@ -0,0 +1,48 @@ +/* +Copyright 2013 Hardcoded Software (http://www.hardcoded.net) + +This software is licensed under the "BSD" License as described in the "LICENSE" file, +which should be included with this package. The terms are also available at +http://www.hardcoded.net/licenses/bsd_license +*/ + +#import "HSErrorReportWindow.h" +#import "HSErrorReportWindow_UI.h" + +@implementation HSErrorReportWindow + +@synthesize contentTextView; + ++ (void)showErrorReportWithContent:(NSString *)content +{ + HSErrorReportWindow *report = [[HSErrorReportWindow alloc] initWithContent:content]; + [NSApp runModalForWindow:[report window]]; + [report release]; +} + +- (id)initWithContent:(NSString *)content +{ + self = [super initWithWindow:nil]; + [self setWindow:createHSErrorReportWindow_UI(self)]; + [contentTextView alignLeft:nil]; + [[[contentTextView textStorage] mutableString] setString:content]; + return self; +} + +- (void)send +{ + NSString *text = [[contentTextView textStorage] string]; + NSString *URL = [NSString stringWithFormat:@"mailto:support@hardcoded.net?SUBJECT=Error Report&BODY=%@",text]; + NSString *encodedURL = [URL stringByAddingPercentEscapesUsingEncoding:NSUTF8StringEncoding]; + [[NSWorkspace sharedWorkspace] openURL:[NSURL URLWithString:encodedURL]]; + + [[self window] orderOut:self]; + [NSApp stopModalWithCode:NSOKButton]; +} + +- (void)dontSend +{ + [[self window] orderOut:self]; + [NSApp stopModalWithCode:NSCancelButton]; +} +@end \ No newline at end of file diff --git a/cocoalib/HSFairware.h b/cocoalib/HSFairware.h new file mode 100644 index 00000000..bb09475f --- /dev/null +++ b/cocoalib/HSFairware.h @@ -0,0 +1,19 @@ +/* +Copyright 2013 Hardcoded Software (http://www.hardcoded.net) + +This software is licensed under the "BSD" License as described in the "LICENSE" file, +which should be included with this package. The terms are also available at +http://www.hardcoded.net/licenses/bsd_license +*/ + +#import +#import "HSFairwareProtocol.h" + +@interface HSFairware : NSObject +{ + NSInteger appId; + NSString *name; + BOOL registered; +} +- (id)initWithAppId:(NSInteger)aAppId name:(NSString *)aName; +@end \ No newline at end of file diff --git a/cocoalib/HSFairware.m b/cocoalib/HSFairware.m new file mode 100644 index 00000000..60bcde2b --- /dev/null +++ b/cocoalib/HSFairware.m @@ -0,0 +1,150 @@ +/* +Copyright 2013 Hardcoded Software (http://www.hardcoded.net) + +This software is licensed under the "BSD" License as described in the "LICENSE" file, +which should be included with this package. The terms are also available at +http://www.hardcoded.net/licenses/bsd_license +*/ + +#import "HSFairware.h" +#import +#import "HSFairwareReminder.h" +#import "Dialogs.h" +#import "Utils.h" + +NSString* md5str(NSString *source) +{ + const char *cSource = [source UTF8String]; + unsigned char result[16]; + CC_MD5(cSource, strlen(cSource), result); + return fmt(@"%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x", + result[0], result[1], result[2], result[3], result[4], result[5], result[6], result[7], + result[8], result[9], result[10], result[11], result[12], result[13], result[14], result[15] + ); +} + +BOOL validateCode(NSString *code, NSString *email, NSInteger appId) +{ + if ([code length] != 32) { + return NO; + } + NSInteger i; + for (i=0; i<=100; i++) { + NSString *blob = fmt(@"%i%@%iaybabtu", appId, email, i); + if ([md5str(blob) isEqualTo:code]) { + return YES; + } + } + return NO; +} + +NSString* normalizeString(NSString *str) +{ + return [[str stringByTrimmingCharactersInSet:[NSCharacterSet whitespaceAndNewlineCharacterSet]] lowercaseString]; +} + +@implementation HSFairware +- (id)initWithAppId:(NSInteger)aAppId name:(NSString *)aName; +{ + self = [super init]; + appId = aAppId; + name = [aName retain]; + registered = NO; + return self; +} + +- (void)dealloc +{ + [name release]; + [super dealloc]; +} + +/* Private */ +- (void)setRegistrationCode:(NSString *)aCode email:(NSString *)aEmail +{ + registered = validateCode(aCode, aEmail, appId); +} + +/* Public */ +- (void)initialRegistrationSetup +{ + NSUserDefaults *ud = [NSUserDefaults standardUserDefaults]; + NSString *code = [ud stringForKey:@"RegistrationCode"]; + NSString *email = [ud stringForKey:@"RegistrationEmail"]; + if (code && email) { + [self setRegistrationCode:code email:email]; + } + if (!registered) { + BOOL fairwareMode = [ud boolForKey:@"FairwareMode"]; + if (!fairwareMode) { + NSString *prompt = @"%@ is fairware, which means \"open source software developed " + "with expectation of fair contributions from users\". It's a very interesting " + "concept, but one year of fairware has shown that most people just want to know " + "how much it costs and not be bothered with theories about intellectual property." + "\n\n" + "So I won't bother you and will be very straightforward: You can try %@ for " + "free but you have to buy it in order to use it without limitations. In demo mode, " + "%@ will show this dialog on startup." + "\n\n" + "So it's as simple as this. If you're curious about fairware, however, I encourage " + "you to read more about it by clicking on the \"Fairware?\" button."; + [HSFairwareReminder showDemoNagWithApp:self prompt:fmt(prompt, name, name, name)]; + } + } +} + +- (NSString *)appName +{ + return name; +} + +- (NSString *)appLongName +{ + return name; +} + +- (BOOL)isRegistered +{ + return registered; +} + +- (BOOL)setRegisteredCode:(NSString *)code andEmail:(NSString *)email +{ + code = normalizeString(code); + email = normalizeString(email); + NSUserDefaults *ud = [NSUserDefaults standardUserDefaults]; + if (([code isEqualTo:@"fairware"]) || ([email isEqualTo:@"fairware"])) { + [ud setBool:YES forKey:@"FairwareMode"]; + [Dialogs showMessage:@"Fairware mode enabled."]; + return YES; + } + [self setRegistrationCode:code email:email]; + if (registered) { + [ud setObject:code forKey:@"RegistrationCode"]; + [ud setObject:email forKey:@"RegistrationEmail"]; + [Dialogs showMessage:@"Your code is valid, thanks!"]; + return YES; + } + else { + [Dialogs showMessage:@"Your code is invalid. Make sure that you wrote the good code. Also " + "make sure that the e-mail you gave is the same as the e-mail you used for your purchase."]; + return NO; + } +} + +- (void)contribute +{ + [[NSWorkspace sharedWorkspace] openURL:[NSURL URLWithString:@"http://open.hardcoded.net/contribute/"]]; +} + +- (void)buy +{ + [[NSWorkspace sharedWorkspace] openURL:[NSURL URLWithString:@"http://www.hardcoded.net/purchase.htm"]]; +} + +- (void)aboutFairware +{ + [[NSWorkspace sharedWorkspace] openURL:[NSURL URLWithString:@"http://open.hardcoded.net/about/"]]; +} + +@end \ No newline at end of file diff --git a/cocoalib/HSFairwareAboutBox.h b/cocoalib/HSFairwareAboutBox.h new file mode 100644 index 00000000..ed22cb09 --- /dev/null +++ b/cocoalib/HSFairwareAboutBox.h @@ -0,0 +1,33 @@ +/* +Copyright 2013 Hardcoded Software (http://www.hardcoded.net) + +This software is licensed under the "BSD" License as described in the "LICENSE" file, +which should be included with this package. The terms are also available at +http://www.hardcoded.net/licenses/bsd_license +*/ + +#import +#import "PyFairware.h" + +@interface HSFairwareAboutBox : NSWindowController +{ + NSTextField *titleTextField; + NSTextField *versionTextField; + NSTextField *copyrightTextField; + NSTextField *registeredTextField; + NSButton *registerButton; + + PyFairware *app; +} + +@property (readwrite, retain) NSTextField *titleTextField; +@property (readwrite, retain) NSTextField *versionTextField; +@property (readwrite, retain) NSTextField *copyrightTextField; +@property (readwrite, retain) NSTextField *registeredTextField; +@property (readwrite, retain) NSButton *registerButton; + +- (id)initWithApp:(PyFairware *)app; +- (void)updateFields; + +- (void)showRegisterDialog; +@end \ No newline at end of file diff --git a/cocoalib/HSFairwareAboutBox.m b/cocoalib/HSFairwareAboutBox.m new file mode 100644 index 00000000..20302721 --- /dev/null +++ b/cocoalib/HSFairwareAboutBox.m @@ -0,0 +1,60 @@ +/* +Copyright 2013 Hardcoded Software (http://www.hardcoded.net) + +This software is licensed under the "BSD" License as described in the "LICENSE" file, +which should be included with this package. The terms are also available at +http://www.hardcoded.net/licenses/bsd_license +*/ + +#import "HSFairwareAboutBox.h" +#import "HSFairwareAboutBox_UI.h" +#import "HSFairwareReminder.h" + +@implementation HSFairwareAboutBox + +@synthesize titleTextField; +@synthesize versionTextField; +@synthesize copyrightTextField; +@synthesize registeredTextField; +@synthesize registerButton; + +- (id)initWithApp:(PyFairware *)aApp +{ + self = [super initWithWindow:nil]; + [self setWindow:createHSFairwareAboutBox_UI(self)]; + app = [aApp retain]; + [self updateFields]; + return self; +} + +- (void)dealloc +{ + [app release]; + [super dealloc]; +} + +- (void)updateFields +{ + [titleTextField setStringValue:[app appLongName]]; + NSString *version = [[NSBundle mainBundle] objectForInfoDictionaryKey:@"CFBundleVersion"]; + [versionTextField setStringValue:[NSString stringWithFormat:@"Version: %@",version]]; + NSString *copyright = [[NSBundle mainBundle] objectForInfoDictionaryKey:@"NSHumanReadableCopyright"]; + [copyrightTextField setStringValue:copyright]; + if ([app isRegistered]) { + [registeredTextField setHidden:NO]; + [registerButton setHidden:YES]; + } + else { + [registeredTextField setHidden:YES]; + [registerButton setHidden:NO]; + } +} + +- (void)showRegisterDialog +{ + HSFairwareReminder *fr = [[HSFairwareReminder alloc] initWithApp:app]; + [fr enterCode]; + [fr release]; + [self updateFields]; +} +@end diff --git a/cocoalib/HSFairwareProtocol.h b/cocoalib/HSFairwareProtocol.h new file mode 100644 index 00000000..e78767ea --- /dev/null +++ b/cocoalib/HSFairwareProtocol.h @@ -0,0 +1,20 @@ +/* +Copyright 2013 Hardcoded Software (http://www.hardcoded.net) + +This software is licensed under the "BSD" License as described in the "LICENSE" file, +which should be included with this package. The terms are also available at +http://www.hardcoded.net/licenses/bsd_license +*/ + +#import + +@protocol HSFairwareProtocol +- (void)initialRegistrationSetup; +- (NSString *)appName; +- (NSString *)appLongName; +- (BOOL)isRegistered; +- (BOOL)setRegisteredCode:(NSString *)code andEmail:(NSString *)email; +- (void)contribute; +- (void)buy; +- (void)aboutFairware; +@end \ No newline at end of file diff --git a/cocoalib/HSFairwareReminder.h b/cocoalib/HSFairwareReminder.h new file mode 100644 index 00000000..947945c3 --- /dev/null +++ b/cocoalib/HSFairwareReminder.h @@ -0,0 +1,46 @@ +/* +Copyright 2013 Hardcoded Software (http://www.hardcoded.net) + +This software is licensed under the "BSD" License as described in the "LICENSE" file, +which should be included with this package. The terms are also available at +http://www.hardcoded.net/licenses/bsd_license +*/ + +#import +#import "HSFairwareProtocol.h" + +@interface HSFairwareReminder : NSObject +{ + NSWindow *codePanel; + NSTextField *codePromptTextField; + NSTextField *codeTextField; + NSTextField *emailTextField; + NSWindow *demoNagPanel; + NSTextField *demoPromptTextField; + + id app; +} + +@property (readwrite, retain) NSWindow *codePanel; +@property (readwrite, retain) NSTextField *codePromptTextField; +@property (readwrite, retain) NSTextField *codeTextField; +@property (readwrite, retain) NSTextField *emailTextField; +@property (readwrite, retain) NSWindow *demoNagPanel; +@property (readwrite, retain) NSTextField *demoPromptTextField; + +//Show nag only if needed ++ (BOOL)showDemoNagWithApp:(id )app prompt:(NSString *)prompt; +- (id)initWithApp:(id )app; + +- (void)contribute; +- (void)buy; +- (void)moreInfo; +- (void)cancelCode; +- (void)showEnterCode; +- (void)submitCode; +- (void)closeDialog; + +- (BOOL)showNagPanel:(NSWindow *)panel; //YES: The code has been sucessfully submitted NO: The use wan't to try the demo. +- (BOOL)showDemoNagPanelWithPrompt:(NSString *)prompt; +- (NSInteger)enterCode; //returns the modal code. +@end diff --git a/cocoalib/HSFairwareReminder.m b/cocoalib/HSFairwareReminder.m new file mode 100644 index 00000000..3d61541a --- /dev/null +++ b/cocoalib/HSFairwareReminder.m @@ -0,0 +1,115 @@ +/* +Copyright 2013 Hardcoded Software (http://www.hardcoded.net) + +This software is licensed under the "BSD" License as described in the "LICENSE" file, +which should be included with this package. The terms are also available at +http://www.hardcoded.net/licenses/bsd_license +*/ + +#import "HSFairwareReminder.h" +#import "HSDemoReminder_UI.h" +#import "HSEnterCode_UI.h" +#import "Dialogs.h" +#import "Utils.h" + +@implementation HSFairwareReminder + +@synthesize codePanel; +@synthesize codePromptTextField; +@synthesize codeTextField; +@synthesize emailTextField; +@synthesize demoNagPanel; +@synthesize demoPromptTextField; + ++ (BOOL)showDemoNagWithApp:(id )app prompt:(NSString *)prompt +{ + HSFairwareReminder *fr = [[HSFairwareReminder alloc] initWithApp:app]; + BOOL r = [fr showDemoNagPanelWithPrompt:prompt]; + [fr release]; + return r; +} + +- (id)initWithApp:(id )aApp +{ + self = [super init]; + app = aApp; + [self setDemoNagPanel:createHSDemoReminder_UI(self)]; + [self setCodePanel:createHSEnterCode_UI(self)]; + [codePanel update]; + [codePromptTextField setStringValue:fmt([codePromptTextField stringValue],[app appName])]; + return self; +} + +- (void)contribute +{ + [app contribute]; +} + +- (void)buy +{ + [app buy]; +} + +- (void)moreInfo +{ + [app aboutFairware]; +} + +- (void)cancelCode +{ + [codePanel close]; + [NSApp stopModalWithCode:NSCancelButton]; +} + +- (void)showEnterCode +{ + [demoNagPanel close]; + [NSApp stopModalWithCode:NSOKButton]; +} + +- (void)submitCode +{ + NSString *code = [codeTextField stringValue]; + NSString *email = [emailTextField stringValue]; + if ([app setRegisteredCode:code andEmail:email]) { + [codePanel close]; + [NSApp stopModalWithCode:NSOKButton]; + } +} + +- (void)closeDialog +{ + [demoNagPanel close]; + [NSApp stopModalWithCode:NSCancelButton]; +} + +- (BOOL)showNagPanel:(NSWindow *)panel; +{ + NSInteger r; + while (YES) { + r = [NSApp runModalForWindow:panel]; + if (r == NSOKButton) { + r = [self enterCode]; + if (r == NSOKButton) { + return YES; + } + } + else { + return NO; + } + } +} + +- (BOOL)showDemoNagPanelWithPrompt:(NSString *)prompt +{ + [demoNagPanel setTitle:fmt([demoNagPanel title],[app appName])]; + [demoPromptTextField setStringValue:prompt]; + return [self showNagPanel:demoNagPanel]; +} + +- (NSInteger)enterCode +{ + return [NSApp runModalForWindow:codePanel]; +} + +@end diff --git a/cocoalib/HSGeometry.h b/cocoalib/HSGeometry.h new file mode 100644 index 00000000..e8779e2e --- /dev/null +++ b/cocoalib/HSGeometry.h @@ -0,0 +1,15 @@ +/* +Copyright 2013 Hardcoded Software (http://www.hardcoded.net) + +This software is licensed under the "BSD" License as described in the "LICENSE" file, +which should be included with this package. The terms are also available at +http://www.hardcoded.net/licenses/bsd_license +*/ + +#import +#import + +CGFloat deg2rad(CGFloat deg); +CGFloat distance(NSPoint p1, NSPoint p2); +NSPoint pointInCircle(NSPoint center, CGFloat radius, CGFloat angle); +CGFloat angleFromPoints(NSPoint pt1, NSPoint pt2); \ No newline at end of file diff --git a/cocoalib/HSGeometry.m b/cocoalib/HSGeometry.m new file mode 100644 index 00000000..128c65ef --- /dev/null +++ b/cocoalib/HSGeometry.m @@ -0,0 +1,71 @@ +/* +Copyright 2013 Hardcoded Software (http://www.hardcoded.net) + +This software is licensed under the "BSD" License as described in the "LICENSE" file, +which should be included with this package. The terms are also available at +http://www.hardcoded.net/licenses/bsd_license +*/ + +#import "HSGeometry.h" + +CGFloat deg2rad(CGFloat deg) +{ + return deg * M_PI / 180; +} + +CGFloat distance(NSPoint p1, NSPoint p2) +{ + CGFloat dX = p1.x - p2.x; + CGFloat dY = p1.y - p2.y; + return sqrt(dX * dX + dY * dY); +} + +NSPoint pointInCircle(NSPoint center, CGFloat radius, CGFloat angle) +{ + // a/sin(A) = b/sin(B) = c/sin(C) = 2R + // the start point it (center.x + radius, center.y) and goes counterclockwise + angle = fmod(angle, M_PI*2); + CGFloat C = M_PI/2; + CGFloat A = fmod(angle, M_PI/2); + CGFloat B = C - A; + CGFloat c = radius; + CGFloat ratio = c / sin(C); + CGFloat b = ratio * sin(B); + CGFloat a = ratio * sin(A); + if (angle >= M_PI * 1.5) + return NSMakePoint(center.x + a, center.y - b); + else if (angle >= M_PI) + return NSMakePoint(center.x - b, center.y - a); + else if (angle >= M_PI/2) + return NSMakePoint(center.x - a, center.y + b); + else + return NSMakePoint(center.x + b, center.y + a); +} + +CGFloat angleFromPoints(NSPoint pt1, NSPoint pt2) +{ + // Returns the angle (radian) formed by the line pt1-pt2. The angle follows the same logic + // as in pointInCircle. + // What we do here is that we take the line and reduce it to fit a "unit circle" (circle with + // a radius of 1). Then, either asin(adjusted_dy) or acos(adjusted_dx) will give us our angle. + // We'll use asin(adjusted_dy). + CGFloat length = distance(pt1, pt2); + CGFloat dx = pt2.x - pt1.x; + CGFloat dy = pt2.y - pt1.y; + CGFloat ajdusted_dy = ABS(dy) / length; + CGFloat angle = asin(ajdusted_dy); + + if ((dx < 0) && (dy >= 0)) { + // top-left quadrant + angle = M_PI - angle; + } + else if ((dx < 0) && (dy < 0)) { + // bottom-left quadrant + angle = M_PI + angle; + } + else if ((dx >= 0) && (dy < 0)) { + // bottom-right quadrant + angle = (2 * M_PI) - angle; + } + return angle; +} \ No newline at end of file diff --git a/cocoalib/HSPyUtil.h b/cocoalib/HSPyUtil.h new file mode 100644 index 00000000..2eda0b7b --- /dev/null +++ b/cocoalib/HSPyUtil.h @@ -0,0 +1,13 @@ +/* +Copyright 2013 Hardcoded Software (http://www.hardcoded.net) + +This software is licensed under the "BSD" License as described in the "LICENSE" file, +which should be included with this package. The terms are also available at +http://www.hardcoded.net/licenses/bsd_license +*/ + +#import +#import + +void setCocoaViewsModuleName(NSString *moduleName); +PyObject* createCallback(NSString *aViewClassName, id aViewRef); diff --git a/cocoalib/HSPyUtil.m b/cocoalib/HSPyUtil.m new file mode 100644 index 00000000..aff588c3 --- /dev/null +++ b/cocoalib/HSPyUtil.m @@ -0,0 +1,34 @@ +/* +Copyright 2013 Hardcoded Software (http://www.hardcoded.net) + +This software is licensed under the "BSD" License as described in the "LICENSE" file, +which should be included with this package. The terms are also available at +http://www.hardcoded.net/licenses/bsd_license +*/ + +#import "HSPyUtil.h" +#import "ObjP.h" + +static NSString *gCocoaViewsModuleName; +void setCocoaViewsModuleName(NSString *moduleName) +{ + if (gCocoaViewsModuleName != nil) { + [gCocoaViewsModuleName release]; + } + gCocoaViewsModuleName = [moduleName retain]; +} + +PyObject* createCallback(NSString *aViewClassName, id aViewRef) +{ + NSString *moduleName; + if (gCocoaViewsModuleName != nil) { + moduleName = gCocoaViewsModuleName; + } + else { + moduleName = @"inter.CocoaViews"; + } + PyGILState_STATE gilState = PyGILState_Ensure(); + PyObject *pCallback = ObjP_classInstanceWithRef(aViewClassName, moduleName, aViewRef); + PyGILState_Release(gilState); + return pCallback; +} diff --git a/cocoalib/HSQuicklook.h b/cocoalib/HSQuicklook.h new file mode 100644 index 00000000..2d220f92 --- /dev/null +++ b/cocoalib/HSQuicklook.h @@ -0,0 +1,18 @@ +/* +Copyright 2013 Hardcoded Software (http://www.hardcoded.net) + +This software is licensed under the "BSD" License as described in the "LICENSE" file, +which should be included with this package. The terms are also available at +http://www.hardcoded.net/licenses/bsd_license +*/ + +#import +#import + +@interface HSQLPreviewItem : NSObject +{ + NSURL *url; + NSString *title; +} +- (id)initWithUrl:(NSURL *)aUrl title:(NSString *)aTitle; +@end \ No newline at end of file diff --git a/cocoalib/HSQuicklook.m b/cocoalib/HSQuicklook.m new file mode 100644 index 00000000..b003adf5 --- /dev/null +++ b/cocoalib/HSQuicklook.m @@ -0,0 +1,36 @@ +/* +Copyright 2013 Hardcoded Software (http://www.hardcoded.net) + +This software is licensed under the "BSD" License as described in the "LICENSE" file, +which should be included with this package. The terms are also available at +http://www.hardcoded.net/licenses/bsd_license +*/ + +#import "HSQuicklook.h" + +@implementation HSQLPreviewItem +- (id)initWithUrl:(NSURL *)aUrl title:(NSString *)aTitle +{ + self = [super init]; + url = [aUrl retain]; + title = [aTitle retain]; + return self; +} + +- (void)dealloc +{ + [url release]; + [title release]; + [super dealloc]; +} + +- (NSURL *)previewItemURL +{ + return url; +} + +- (NSString *)previewItemTitle +{ + return title; +} +@end \ No newline at end of file diff --git a/cocoalib/HSRecentFiles.h b/cocoalib/HSRecentFiles.h new file mode 100644 index 00000000..987da851 --- /dev/null +++ b/cocoalib/HSRecentFiles.h @@ -0,0 +1,35 @@ +/* +Copyright 2013 Hardcoded Software (http://www.hardcoded.net) + +This software is licensed under the "BSD" License as described in the "LICENSE" file, +which should be included with this package. The terms are also available at +http://www.hardcoded.net/licenses/bsd_license +*/ + +#import + +@interface HSRecentFiles : NSObject +{ + id delegate; + NSMenu *menu; + NSString *name; + NSMutableArray *filepaths; + NSInteger numberOfMenuItemsToPreserve; +} +- (id)initWithName:(NSString *)aName menu:(NSMenu *)aMenu; + +- (void)addFile:(NSString *)path; +- (void)rebuildMenu; +- (void)fillMenu:(NSMenu *)menu; +- (void)clearMenu:(id)sender; +- (void)menuClick:(id)sender; + +- (NSMenu *)menu; +- (id)delegate; +- (void)setDelegate:(id)aDelegate; +- (NSArray *)filepaths; +@end + +@protocol HSRecentFilesDelegate +- (void)recentFileClicked:(NSString *)path; +@end diff --git a/cocoalib/HSRecentFiles.m b/cocoalib/HSRecentFiles.m new file mode 100644 index 00000000..8acc88e1 --- /dev/null +++ b/cocoalib/HSRecentFiles.m @@ -0,0 +1,89 @@ +/* +Copyright 2013 Hardcoded Software (http://www.hardcoded.net) + +This software is licensed under the "BSD" License as described in the "LICENSE" file, +which should be included with this package. The terms are also available at +http://www.hardcoded.net/licenses/bsd_license +*/ + +#import "HSRecentFiles.h" + +@implementation HSRecentFiles +- (id)initWithName:(NSString *)aName menu:(NSMenu *)aMenu +{ + self = [super init]; + name = aName; + menu = [aMenu retain]; + numberOfMenuItemsToPreserve = [menu numberOfItems]; + NSUserDefaults *ud = [NSUserDefaults standardUserDefaults]; + filepaths = [[NSMutableArray alloc] initWithArray:[ud arrayForKey:name]]; + NSFileManager *fm = [NSFileManager defaultManager]; + for (NSInteger i=[filepaths count]-1;i>=0;i--) { + NSString *path = [filepaths objectAtIndex:i]; + // We check for path class because we might be fed with garbage from the prefs. + if ((![path isKindOfClass:[NSString class]]) || (![fm fileExistsAtPath:path])) { + [filepaths removeObjectAtIndex:i]; + } + } + [self rebuildMenu]; + return self; +} + +- (void)dealloc +{ + NSUserDefaults *ud = [NSUserDefaults standardUserDefaults]; + [ud setObject:filepaths forKey:name]; + [ud synchronize]; + [filepaths release]; + [menu release]; + [super dealloc]; +} + +- (void)addFile:(NSString *)path +{ + [filepaths removeObject:path]; + [filepaths insertObject:path atIndex:0]; + [self rebuildMenu]; +} + +- (void)rebuildMenu +{ + while ([menu numberOfItems] > numberOfMenuItemsToPreserve) + [menu removeItemAtIndex:[menu numberOfItems]-1]; + [self fillMenu:menu]; + if ([filepaths count] > 0) { + [menu addItem:[NSMenuItem separatorItem]]; + NSMenuItem *mi = [menu addItemWithTitle:NSLocalizedStringFromTable(@"Clear List", @"cocoalib", @"") action:@selector(clearMenu:) keyEquivalent:@""]; + [mi setTarget:self]; + } +} + +- (void)fillMenu:(NSMenu *)menuToFill +{ + for (int i=0;i<[filepaths count];i++) { + NSMenuItem *mi = [menuToFill addItemWithTitle:[filepaths objectAtIndex:i] action:@selector(menuClick:) keyEquivalent:@""]; + [mi setTag:i]; + [mi setTarget:self]; + } +} + +- (void)clearMenu:(id)sender +{ + [filepaths removeAllObjects]; + [self rebuildMenu]; +} + +- (void)menuClick:(id)sender +{ + if (delegate == nil) + return; + if ([delegate respondsToSelector:@selector(recentFileClicked:)]) + [delegate recentFileClicked:[filepaths objectAtIndex:[sender tag]]]; +} + +/* Properties */ +- (NSMenu *)menu {return menu;} +- (id)delegate { return delegate; } +- (void)setDelegate:(id)aDelegate { delegate = aDelegate; } +- (NSArray *)filepaths {return filepaths;} +@end diff --git a/cocoalib/LICENSE b/cocoalib/LICENSE new file mode 100644 index 00000000..791cf728 --- /dev/null +++ b/cocoalib/LICENSE @@ -0,0 +1,10 @@ +Copyright 2013, Hardcoded Software Inc., http://www.hardcoded.net +All rights reserved. + +Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: + + * Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. + * Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution. + * Neither the name of Hardcoded Software Inc. nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. \ No newline at end of file diff --git a/cocoalib/NSEventAdditions.h b/cocoalib/NSEventAdditions.h new file mode 100644 index 00000000..ba9b4de9 --- /dev/null +++ b/cocoalib/NSEventAdditions.h @@ -0,0 +1,24 @@ +/* +Copyright 2013 Hardcoded Software (http://www.hardcoded.net) + +This software is licensed under the "BSD" License as described in the "LICENSE" file, +which should be included with this package. The terms are also available at +http://www.hardcoded.net/licenses/bsd_license +*/ + +#import + +@interface NSEvent(NSEventAdditions) +- (unichar)firstCharacter; +- (NSUInteger)flags; +- (NSUInteger)modifierKeysFlags; +- (BOOL)isDeleteOrBackspace; +- (BOOL)isReturnOrEnter; +- (BOOL)isTab; +- (BOOL)isBackTab; +- (BOOL)isSpace; +- (BOOL)isUp; +- (BOOL)isDown; +- (BOOL)isLeft; +- (BOOL)isRight; +@end diff --git a/cocoalib/NSEventAdditions.m b/cocoalib/NSEventAdditions.m new file mode 100644 index 00000000..5a5e6de8 --- /dev/null +++ b/cocoalib/NSEventAdditions.m @@ -0,0 +1,85 @@ +/* +Copyright 2013 Hardcoded Software (http://www.hardcoded.net) + +This software is licensed under the "BSD" License as described in the "LICENSE" file, +which should be included with this package. The terms are also available at +http://www.hardcoded.net/licenses/bsd_license +*/ + +#import "NSEventAdditions.h" + +@implementation NSEvent(NSEventAdditions) + +- (unichar)firstCharacter +{ + NSString *characters = [self characters]; + if ([characters length] == 0) + { + return '\0'; + } + return [characters characterAtIndex:0]; +} + +- (NSUInteger)flags +{ + // get flags and strip the lower 16 (device dependant) bits + // See modifierFlags's doc for details + return [self modifierFlags] & NSDeviceIndependentModifierFlagsMask; +} + +- (NSUInteger)modifierKeysFlags +{ + // This is modifierFlags with only Command, Opt, Ctrl and Shift, without the rest of the flags + // to pollute. + return [self flags] & (NSShiftKeyMask | NSControlKeyMask | NSAlternateKeyMask | NSCommandKeyMask); +} + +- (BOOL)isDeleteOrBackspace +{ + unichar firstChar = [self firstCharacter]; + return firstChar == NSDeleteFunctionKey || firstChar == NSDeleteCharFunctionKey || + firstChar == NSDeleteCharacter || firstChar == NSBackspaceCharacter; +} + +- (BOOL)isReturnOrEnter +{ + unichar firstChar = [self firstCharacter]; + return firstChar == NSCarriageReturnCharacter || firstChar == NSEnterCharacter; +} + +- (BOOL)isTab +{ + return [self firstCharacter] == NSTabCharacter; +} + +- (BOOL)isBackTab +{ + return [self firstCharacter] == NSBackTabCharacter; +} + +- (BOOL)isSpace +{ + return ([self firstCharacter] == 0x20) && (![self flags]); +} + +- (BOOL)isUp +{ + return [self firstCharacter] == NSUpArrowFunctionKey; +} + +- (BOOL)isDown +{ + return [self firstCharacter] == NSDownArrowFunctionKey; +} + +- (BOOL)isLeft +{ + return [self firstCharacter] == NSLeftArrowFunctionKey; +} + +- (BOOL)isRight +{ + return [self firstCharacter] == NSRightArrowFunctionKey; +} + +@end diff --git a/cocoalib/NSImageAdditions.h b/cocoalib/NSImageAdditions.h new file mode 100644 index 00000000..410d62d4 --- /dev/null +++ b/cocoalib/NSImageAdditions.h @@ -0,0 +1,21 @@ +// Created by Scott Stevenson on 9/28/07. +// +// Personal site: http://theocacao.com/ +// Post for this sample: http://theocacao.com/document.page/497 +// +// The code in this project is intended to be used as a learning +// tool for Cocoa programmers. You may freely use the code in +// your own programs, but please do not use the code as-is in +// other tutorials. + +#import + + +@interface NSImage (Extras) + +// creates a copy of the current image while maintaining +// proportions. also centers image, if necessary + +- (NSImage*)imageByScalingProportionallyToSize:(NSSize)aSize; + +@end \ No newline at end of file diff --git a/cocoalib/NSImageAdditions.m b/cocoalib/NSImageAdditions.m new file mode 100644 index 00000000..ad5fedd8 --- /dev/null +++ b/cocoalib/NSImageAdditions.m @@ -0,0 +1,114 @@ +// Created by Scott Stevenson on 9/28/07. +// +// Personal site: http://theocacao.com/ +// Post for this sample: http://theocacao.com/document.page/497 +// +// The code in this project is intended to be used as a learning +// tool for Cocoa programmers. You may freely use the code in +// your own programs, but please do not use the code as-is in +// other tutorials. + +#import "NSImageAdditions.h" + + +@implementation NSImage (Extras) + +- (NSImage*)imageByScalingProportionallyToSize:(NSSize)targetSize +{ + NSImage* sourceImage = self; + NSImage* newImage = nil; + + if ([sourceImage isValid]) + { + NSSize imageSize = [sourceImage size]; + CGFloat width = imageSize.width; + CGFloat height = imageSize.height; + + CGFloat targetWidth = targetSize.width; + CGFloat targetHeight = targetSize.height; + + // scaleFactor will be the fraction that we'll + // use to adjust the size. For example, if we shrink + // an image by half, scaleFactor will be 0.5. the + // scaledWidth and scaledHeight will be the original, + // multiplied by the scaleFactor. + // + // IMPORTANT: the "targetHeight" is the size of the space + // we're drawing into. The "scaledHeight" is the height that + // the image actually is drawn at, once we take into + // account the ideal of maintaining proportions + + CGFloat scaleFactor = 0.0; + CGFloat scaledWidth = targetWidth; + CGFloat scaledHeight = targetHeight; + + NSPoint thumbnailPoint = NSMakePoint(0,0); + + // since not all images are square, we want to scale + // proportionately. To do this, we find the longest + // edge and use that as a guide. + + if ( NSEqualSizes( imageSize, targetSize ) == NO ) + { + // use the longeset edge as a guide. if the + // image is wider than tall, we'll figure out + // the scale factor by dividing it by the + // intended width. Otherwise, we'll use the + // height. + + CGFloat widthFactor = targetWidth / width; + CGFloat heightFactor = targetHeight / height; + + if ( widthFactor < heightFactor ) + scaleFactor = widthFactor; + else + scaleFactor = heightFactor; + + // ex: 500 * 0.5 = 250 (newWidth) + + scaledWidth = width * scaleFactor; + scaledHeight = height * scaleFactor; + + // center the thumbnail in the frame. if + // wider than tall, we need to adjust the + // vertical drawing point (y axis) + + if ( widthFactor < heightFactor ) + thumbnailPoint.y = (targetHeight - scaledHeight) * 0.5; + + else if ( widthFactor > heightFactor ) + thumbnailPoint.x = (targetWidth - scaledWidth) * 0.5; + } + + + // create a new image to draw into + newImage = [[NSImage alloc] initWithSize:targetSize]; + + // once focus is locked, all drawing goes into this NSImage instance + // directly, not to the screen. It also receives its own graphics + // context. + // + // Also, keep in mind that we're doing this in a background thread. + // You only want to draw to the screen in the main thread, but + // drawing to an offscreen image is (apparently) okay. + + [newImage lockFocus]; + + NSRect thumbnailRect; + thumbnailRect.origin = thumbnailPoint; + thumbnailRect.size.width = scaledWidth; + thumbnailRect.size.height = scaledHeight; + + [sourceImage drawInRect: thumbnailRect + fromRect: NSZeroRect + operation: NSCompositeSourceOver + fraction: 1.0]; + + [newImage unlockFocus]; + + } + + return [newImage autorelease]; +} + +@end \ No newline at end of file diff --git a/cocoalib/NSNotificationAdditions.h b/cocoalib/NSNotificationAdditions.h new file mode 100644 index 00000000..0b8c2a0a --- /dev/null +++ b/cocoalib/NSNotificationAdditions.h @@ -0,0 +1,10 @@ +// from http://www.cocoadev.com/index.pl?NotificationsAcrossThreads +#import +@interface NSNotificationCenter (NSNotificationCenterAdditions) +- (void) postNotificationOnMainThread:(NSNotification *) notification; +- (void) postNotificationOnMainThread:(NSNotification *) notification waitUntilDone:(BOOL) wait; + +- (void) postNotificationOnMainThreadWithName:(NSString *) name object:(id) object; +- (void) postNotificationOnMainThreadWithName:(NSString *) name object:(id) object userInfo:(NSDictionary *) userInfo; +- (void) postNotificationOnMainThreadWithName:(NSString *) name object:(id) object userInfo:(NSDictionary *) userInfo waitUntilDone:(BOOL) wait; +@end diff --git a/cocoalib/NSNotificationAdditions.m b/cocoalib/NSNotificationAdditions.m new file mode 100644 index 00000000..c6081d06 --- /dev/null +++ b/cocoalib/NSNotificationAdditions.m @@ -0,0 +1,48 @@ +#import "NSNotificationAdditions.h" +#import + +@implementation NSNotificationCenter (NSNotificationCenterAdditions) +- (void) postNotificationOnMainThread:(NSNotification *) notification { + if( pthread_main_np() ) return [self postNotification:notification]; + [self postNotificationOnMainThread:notification waitUntilDone:NO]; +} + +- (void) postNotificationOnMainThread:(NSNotification *) notification waitUntilDone:(BOOL) wait { + if( pthread_main_np() ) return [self postNotification:notification]; + [[self class] performSelectorOnMainThread:@selector( _postNotification: ) withObject:notification waitUntilDone:wait]; +} + ++ (void) _postNotification:(NSNotification *) notification { + [[self defaultCenter] postNotification:notification]; +} + +- (void) postNotificationOnMainThreadWithName:(NSString *) name object:(id) object { + if( pthread_main_np() ) return [self postNotificationName:name object:object userInfo:nil]; + [self postNotificationOnMainThreadWithName:name object:object userInfo:nil waitUntilDone:NO]; +} + +- (void) postNotificationOnMainThreadWithName:(NSString *) name object:(id) object userInfo:(NSDictionary *) userInfo { + if( pthread_main_np() ) return [self postNotificationName:name object:object userInfo:userInfo]; + [self postNotificationOnMainThreadWithName:name object:object userInfo:nil waitUntilDone:NO]; +} + +- (void) postNotificationOnMainThreadWithName:(NSString *) name object:(id) object userInfo:(NSDictionary *) userInfo waitUntilDone:(BOOL) wait { + if( pthread_main_np() ) return [self postNotificationName:name object:object userInfo:userInfo]; + + NSMutableDictionary *info = [[NSMutableDictionary allocWithZone:nil] init]; + [info setObject:name forKey:@"name"]; + if( object ) [info setObject:object forKey:@"object"]; + if( userInfo ) [info setObject:userInfo forKey:@"userInfo"]; + + [[self class] performSelectorOnMainThread:@selector( _postNotificationName: ) withObject:info waitUntilDone:wait]; + [info release]; +} + ++ (void) _postNotificationName:(NSDictionary *) info { + NSString *name = [info objectForKey:@"name"]; + id object = [info objectForKey:@"object"]; + NSDictionary *userInfo = [info objectForKey:@"userInfo"]; + + [[self defaultCenter] postNotificationName:name object:object userInfo:userInfo]; +} +@end \ No newline at end of file diff --git a/cocoalib/ProgressController.h b/cocoalib/ProgressController.h new file mode 100644 index 00000000..59905192 --- /dev/null +++ b/cocoalib/ProgressController.h @@ -0,0 +1,50 @@ +/* +Copyright 2013 Hardcoded Software (http://www.hardcoded.net) + +This software is licensed under the "BSD" License as described in the "LICENSE" file, +which should be included with this package. The terms are also available at +http://www.hardcoded.net/licenses/bsd_license +*/ + +#import +#import "Worker.h" + +extern NSString *JobCompletedNotification; +extern NSString *JobCancelledNotification; + +@interface ProgressController : NSWindowController +{ + NSButton *cancelButton; + NSProgressIndicator *progressBar; + NSTextField *statusText; + NSTextField *descText; + + id _jobId; + BOOL _running; + NSObject *_worker; +} + +@property (readwrite, retain) NSButton *cancelButton; +@property (readwrite, retain) NSProgressIndicator *progressBar; +@property (readwrite, retain) NSTextField *statusText; +@property (readwrite, retain) NSTextField *descText; + ++ (ProgressController *)mainProgressController; + +- (id)init; + +- (void)cancel; + +- (void)hide; +- (void)show; +- (void)showWithCancelButton:(BOOL)cancelEnabled; +- (void)showSheetForParent:(NSWindow *) parentWindow; +- (void)showSheetForParent:(NSWindow *) parentWindow withCancelButton:(BOOL)cancelEnabled; + +/* Properties */ +- (BOOL)isShown; +- (id)jobId; +- (void)setJobId:(id)jobId; +- (void)setJobDesc:(NSString *)desc; +- (void)setWorker:(NSObject *)worker; +@end diff --git a/cocoalib/ProgressController.m b/cocoalib/ProgressController.m new file mode 100644 index 00000000..b4b361c9 --- /dev/null +++ b/cocoalib/ProgressController.m @@ -0,0 +1,160 @@ +/* +Copyright 2013 Hardcoded Software (http://www.hardcoded.net) + +This software is licensed under the "BSD" License as described in the "LICENSE" file, +which should be included with this package. The terms are also available at +http://www.hardcoded.net/licenses/bsd_license +*/ + +#import "ProgressController.h" +#import "Utils.h" +#import "ProgressController_UI.h" + +NSString *JobCompletedNotification = @"JobCompletedNotification"; +NSString *JobCancelledNotification = @"JobCancelledNotification"; +static ProgressController *_mainPC = nil; + +@implementation ProgressController + +@synthesize cancelButton; +@synthesize progressBar; +@synthesize statusText; +@synthesize descText; + ++ (ProgressController *)mainProgressController +{ + if (_mainPC == nil) + _mainPC = [[ProgressController alloc] init]; + return _mainPC; +} + +- (id)init +{ + self = [super initWithWindow:nil]; + [self setWindow:createProgressController_UI(self)]; + [progressBar setUsesThreadedAnimation:YES]; + _worker = nil; + _running = NO; + [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(applicationDidBecomeActive:) name:NSApplicationDidBecomeActiveNotification object:nil]; + return self; +} + +- (void)cancel +{ + [self hide]; +} + +- (void)hide +{ + if (_worker != nil) + [_worker cancelJob]; + [[NSNotificationCenter defaultCenter] postNotificationName:JobCancelledNotification object:self]; + _running = NO; + [NSApp endSheet:[self window] returnCode:NSRunAbortedResponse]; + /* There's this really strange thing where when the app is inactive at the point we want to hide + the progress dialog, it becomes impossible to close it. I guess it's due to some strange + thread-related crap. Anyway, *DO NOT HIDE THE SHEET WHILE THE APP IS INACTIVE*. Do it later, + when the app becomes active again. + */ + if ([NSApp isActive]) { + [[self window] orderOut:nil]; + } +} + +- (void)show +{ + [self showWithCancelButton:YES]; +} + +- (void)showWithCancelButton:(BOOL)cancelEnabled +{ + [progressBar setIndeterminate:YES]; + [[self window] makeKeyAndOrderFront:nil]; + [progressBar setUsesThreadedAnimation:YES]; + [progressBar startAnimation:nil]; + [cancelButton setEnabled:cancelEnabled]; + _running = YES; + [NSThread detachNewThreadSelector:@selector(threadedWorkerProbe) toTarget:self withObject:nil]; +} + +- (void)showSheetForParent:(NSWindow *) parentWindow +{ + [self showSheetForParent:parentWindow withCancelButton:YES]; +} + +- (void)showSheetForParent:(NSWindow *) parentWindow withCancelButton:(BOOL)cancelEnabled +{ + [progressBar setIndeterminate:YES]; + [progressBar startAnimation:nil]; + [cancelButton setEnabled:cancelEnabled]; + _running = YES; + [NSThread detachNewThreadSelector:@selector(threadedWorkerProbe) toTarget:self withObject:nil]; + [NSApp beginSheet:[self window] modalForWindow:parentWindow modalDelegate:nil didEndSelector:nil contextInfo:nil]; +} + +- (void)updateProgress +{ + if (!_running) + return; + NSNumber *progress = [_worker getJobProgress]; + NSString *status = [_worker getJobDesc]; + if ((status != nil) && ([status length] > 0)) + { + [statusText setStringValue:status]; + } + if (progress != nil) + { + [progressBar setDoubleValue:n2i(progress)]; + [progressBar setIndeterminate: n2i(progress) < 0]; + } + else + { + [self hide]; + [_worker jobCompleted:_jobId]; + [[NSNotificationCenter defaultCenter] postNotificationName:JobCompletedNotification object:self]; + } +} + +- (void)threadedWorkerProbe +{ + while (_running && (_worker != nil)) + { + NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init]; + [NSThread sleepUntilDate:[NSDate dateWithTimeIntervalSinceNow:1]]; + [self performSelectorOnMainThread:@selector(updateProgress) withObject:nil waitUntilDone:YES]; + [pool release]; + } +} + +/* Properties */ +- (BOOL)isShown +{ + return _running; +} + +- (id)jobId {return _jobId;} +- (void)setJobId:(id)jobId +{ + [_jobId autorelease]; + _jobId = [jobId retain]; +} + +- (void)setJobDesc:(NSString *)desc +{ + [descText setStringValue:desc]; + [statusText setStringValue:NSLocalizedStringFromTable(@"Please wait...", @"cocoalib", @"")]; +} + +- (void)setWorker:(NSObject *)worker +{ + _worker = worker; +} + +/* Delegate and Notifs */ +- (void)applicationDidBecomeActive:(NSNotification *)notification +{ + if (!_running) { + [[self window] orderOut:nil]; + } +} +@end diff --git a/cocoalib/Sparkle.framework/Headers b/cocoalib/Sparkle.framework/Headers new file mode 120000 index 00000000..a177d2a6 --- /dev/null +++ b/cocoalib/Sparkle.framework/Headers @@ -0,0 +1 @@ +Versions/Current/Headers \ No newline at end of file diff --git a/cocoalib/Sparkle.framework/Resources b/cocoalib/Sparkle.framework/Resources new file mode 120000 index 00000000..953ee36f --- /dev/null +++ b/cocoalib/Sparkle.framework/Resources @@ -0,0 +1 @@ +Versions/Current/Resources \ No newline at end of file diff --git a/cocoalib/Sparkle.framework/Sparkle b/cocoalib/Sparkle.framework/Sparkle new file mode 120000 index 00000000..b2c52731 --- /dev/null +++ b/cocoalib/Sparkle.framework/Sparkle @@ -0,0 +1 @@ +Versions/Current/Sparkle \ No newline at end of file diff --git a/cocoalib/Sparkle.framework/Versions/A/Headers/SUAppcast.h b/cocoalib/Sparkle.framework/Versions/A/Headers/SUAppcast.h new file mode 100644 index 00000000..171148a4 --- /dev/null +++ b/cocoalib/Sparkle.framework/Versions/A/Headers/SUAppcast.h @@ -0,0 +1,33 @@ +// +// SUAppcast.h +// Sparkle +// +// Created by Andy Matuschak on 3/12/06. +// Copyright 2006 Andy Matuschak. All rights reserved. +// + +#ifndef SUAPPCAST_H +#define SUAPPCAST_H + +@class SUAppcastItem; +@interface SUAppcast : NSObject { + NSArray *items; + NSString *userAgentString; + id delegate; + NSMutableData *incrementalData; +} + +- (void)fetchAppcastFromURL:(NSURL *)url; +- (void)setDelegate:delegate; +- (void)setUserAgentString:(NSString *)userAgentString; + +- (NSArray *)items; + +@end + +@interface NSObject (SUAppcastDelegate) +- (void)appcastDidFinishLoading:(SUAppcast *)appcast; +- (void)appcast:(SUAppcast *)appcast failedToLoadWithError:(NSError *)error; +@end + +#endif diff --git a/cocoalib/Sparkle.framework/Versions/A/Headers/SUAppcastItem.h b/cocoalib/Sparkle.framework/Versions/A/Headers/SUAppcastItem.h new file mode 100644 index 00000000..7f1ca65c --- /dev/null +++ b/cocoalib/Sparkle.framework/Versions/A/Headers/SUAppcastItem.h @@ -0,0 +1,47 @@ +// +// SUAppcastItem.h +// Sparkle +// +// Created by Andy Matuschak on 3/12/06. +// Copyright 2006 Andy Matuschak. All rights reserved. +// + +#ifndef SUAPPCASTITEM_H +#define SUAPPCASTITEM_H + +@interface SUAppcastItem : NSObject { + NSString *title; + NSDate *date; + NSString *itemDescription; + + NSURL *releaseNotesURL; + + NSString *DSASignature; + NSString *minimumSystemVersion; + + NSURL *fileURL; + NSString *versionString; + NSString *displayVersionString; + + NSDictionary *propertiesDictionary; +} + +// Initializes with data from a dictionary provided by the RSS class. +- initWithDictionary:(NSDictionary *)dict; + +- (NSString *)title; +- (NSString *)versionString; +- (NSString *)displayVersionString; +- (NSDate *)date; +- (NSString *)itemDescription; +- (NSURL *)releaseNotesURL; +- (NSURL *)fileURL; +- (NSString *)DSASignature; +- (NSString *)minimumSystemVersion; + +// Returns the dictionary provided in initWithDictionary; this might be useful later for extensions. +- (NSDictionary *)propertiesDictionary; + +@end + +#endif diff --git a/cocoalib/Sparkle.framework/Versions/A/Headers/SUUpdater.h b/cocoalib/Sparkle.framework/Versions/A/Headers/SUUpdater.h new file mode 100644 index 00000000..e78c4d35 --- /dev/null +++ b/cocoalib/Sparkle.framework/Versions/A/Headers/SUUpdater.h @@ -0,0 +1,118 @@ +// +// SUUpdater.h +// Sparkle +// +// Created by Andy Matuschak on 1/4/06. +// Copyright 2006 Andy Matuschak. All rights reserved. +// + +#ifndef SUUPDATER_H +#define SUUPDATER_H + +#import + +@class SUUpdateDriver, SUAppcastItem, SUHost, SUAppcast; +@interface SUUpdater : NSObject { + NSTimer *checkTimer; + SUUpdateDriver *driver; + + SUHost *host; + IBOutlet id delegate; +} + ++ (SUUpdater *)sharedUpdater; ++ (SUUpdater *)updaterForBundle:(NSBundle *)bundle; +- (NSBundle *)hostBundle; + +- (void)setDelegate:(id)delegate; +- delegate; + +- (void)setAutomaticallyChecksForUpdates:(BOOL)automaticallyChecks; +- (BOOL)automaticallyChecksForUpdates; + +- (void)setUpdateCheckInterval:(NSTimeInterval)interval; +- (NSTimeInterval)updateCheckInterval; + +- (void)setFeedURL:(NSURL *)feedURL; +- (NSURL *)feedURL; + +- (void)setSendsSystemProfile:(BOOL)sendsSystemProfile; +- (BOOL)sendsSystemProfile; + +- (void)setAutomaticallyDownloadsUpdates:(BOOL)automaticallyDownloadsUpdates; +- (BOOL)automaticallyDownloadsUpdates; + +// This IBAction is meant for a main menu item. Hook up any menu item to this action, +// and Sparkle will check for updates and report back its findings verbosely. +- (IBAction)checkForUpdates:sender; + +// This kicks off an update meant to be programmatically initiated. That is, it will display no UI unless it actually finds an update, +// in which case it proceeds as usual. If the fully automated updating is turned on, however, this will invoke that behavior, and if an +// update is found, it will be downloaded and prepped for installation. +- (void)checkForUpdatesInBackground; + +// Date of last update check. Returns null if no check has been performed. +- (NSDate*)lastUpdateCheckDate; + +// This begins a "probing" check for updates which will not actually offer to update to that version. The delegate methods, though, +// (up to updater:didFindValidUpdate: and updaterDidNotFindUpdate:), are called, so you can use that information in your UI. +- (void)checkForUpdateInformation; + +// Call this to appropriately schedule or cancel the update checking timer according to the preferences for time interval and automatic checks. This call does not change the date of the next check, but only the internal NSTimer. +- (void)resetUpdateCycle; + +- (BOOL)updateInProgress; +@end + +@interface NSObject (SUUpdaterDelegateInformalProtocol) +// This method allows you to add extra parameters to the appcast URL, potentially based on whether or not Sparkle will also be sending along the system profile. This method should return an array of dictionaries with keys: "key", "value", "displayKey", "displayValue", the latter two being specifically for display to the user. +- (NSArray *)feedParametersForUpdater:(SUUpdater *)updater sendingSystemProfile:(BOOL)sendingProfile; + +// Use this to override the default behavior for Sparkle prompting the user about automatic update checks. +- (BOOL)updaterShouldPromptForPermissionToCheckForUpdates:(SUUpdater *)bundle; + +// Implement this if you want to do some special handling with the appcast once it finishes loading. +- (void)updater:(SUUpdater *)updater didFinishLoadingAppcast:(SUAppcast *)appcast; + +// If you're using special logic or extensions in your appcast, implement this to use your own logic for finding +// a valid update, if any, in the given appcast. +- (SUAppcastItem *)bestValidUpdateInAppcast:(SUAppcast *)appcast forUpdater:(SUUpdater *)bundle; + +// Sent when a valid update is found by the update driver. +- (void)updater:(SUUpdater *)updater didFindValidUpdate:(SUAppcastItem *)update; + +// Sent when a valid update is not found. +- (void)updaterDidNotFindUpdate:(SUUpdater *)update; + +// Sent immediately before installing the specified update. +- (void)updater:(SUUpdater *)updater willInstallUpdate:(SUAppcastItem *)update; + +// Return YES to delay the relaunch until you do some processing; invoke the given NSInvocation to continue. +- (BOOL)updater:(SUUpdater *)updater shouldPostponeRelaunchForUpdate:(SUAppcastItem *)update untilInvoking:(NSInvocation *)invocation; + +// Called immediately before relaunching. +- (void)updaterWillRelaunchApplication:(SUUpdater *)updater; + +// This method allows you to provide a custom version comparator. +// If you don't implement this method or return nil, the standard version comparator will be used. +- (id )versionComparatorForUpdater:(SUUpdater *)updater; + +// Returns the path which is used to relaunch the client after the update is installed. By default, the path of the host bundle. +- (NSString *)pathToRelaunchForUpdater:(SUUpdater *)updater; + +@end + +// Define some minimum intervals to avoid DOS-like checking attacks. These are in seconds. +#ifdef DEBUG +#define SU_MIN_CHECK_INTERVAL 60 +#else +#define SU_MIN_CHECK_INTERVAL 60*60 +#endif + +#ifdef DEBUG +#define SU_DEFAULT_CHECK_INTERVAL 60 +#else +#define SU_DEFAULT_CHECK_INTERVAL 60*60*24 +#endif + +#endif diff --git a/cocoalib/Sparkle.framework/Versions/A/Headers/SUVersionComparisonProtocol.h b/cocoalib/Sparkle.framework/Versions/A/Headers/SUVersionComparisonProtocol.h new file mode 100644 index 00000000..3d11ae87 --- /dev/null +++ b/cocoalib/Sparkle.framework/Versions/A/Headers/SUVersionComparisonProtocol.h @@ -0,0 +1,27 @@ +// +// SUVersionComparisonProtocol.h +// Sparkle +// +// Created by Andy Matuschak on 12/21/07. +// Copyright 2007 Andy Matuschak. All rights reserved. +// + +#ifndef SUVERSIONCOMPARISONPROTOCOL_H +#define SUVERSIONCOMPARISONPROTOCOL_H + +/*! + @protocol + @abstract Implement this protocol to provide version comparison facilities for Sparkle. +*/ +@protocol SUVersionComparison + +/*! + @method + @abstract An abstract method to compare two version strings. + @discussion Should return NSOrderedAscending if b > a, NSOrderedDescending if b < a, and NSOrderedSame if they are equivalent. +*/ +- (NSComparisonResult)compareVersion:(NSString *)versionA toVersion:(NSString *)versionB; + +@end + +#endif diff --git a/cocoalib/Sparkle.framework/Versions/A/Headers/Sparkle.h b/cocoalib/Sparkle.framework/Versions/A/Headers/Sparkle.h new file mode 100644 index 00000000..08dd5777 --- /dev/null +++ b/cocoalib/Sparkle.framework/Versions/A/Headers/Sparkle.h @@ -0,0 +1,21 @@ +// +// Sparkle.h +// Sparkle +// +// Created by Andy Matuschak on 3/16/06. (Modified by CDHW on 23/12/07) +// Copyright 2006 Andy Matuschak. All rights reserved. +// + +#ifndef SPARKLE_H +#define SPARKLE_H + +// This list should include the shared headers. It doesn't matter if some of them aren't shared (unless +// there are name-space collisions) so we can list all of them to start with: + +#import + +#import +#import +#import + +#endif diff --git a/cocoalib/Sparkle.framework/Versions/A/Resources/Info.plist b/cocoalib/Sparkle.framework/Versions/A/Resources/Info.plist new file mode 100644 index 00000000..c7f277d0 --- /dev/null +++ b/cocoalib/Sparkle.framework/Versions/A/Resources/Info.plist @@ -0,0 +1,24 @@ + + + + + CFBundleDevelopmentRegion + en + CFBundleExecutable + Sparkle + CFBundleIdentifier + org.andymatuschak.Sparkle + CFBundleInfoDictionaryVersion + 6.0 + CFBundleName + Sparkle + CFBundlePackageType + FMWK + CFBundleShortVersionString + 1.5 Beta 6 + CFBundleSignature + ???? + CFBundleVersion + 313 + + diff --git a/cocoalib/Sparkle.framework/Versions/A/Resources/License.txt b/cocoalib/Sparkle.framework/Versions/A/Resources/License.txt new file mode 100644 index 00000000..20466c41 --- /dev/null +++ b/cocoalib/Sparkle.framework/Versions/A/Resources/License.txt @@ -0,0 +1,7 @@ +Copyright (c) 2006 Andy Matuschak + +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. \ No newline at end of file diff --git a/cocoalib/Sparkle.framework/Versions/A/Resources/SUModelTranslation.plist b/cocoalib/Sparkle.framework/Versions/A/Resources/SUModelTranslation.plist new file mode 100644 index 00000000..92ef9471 --- /dev/null +++ b/cocoalib/Sparkle.framework/Versions/A/Resources/SUModelTranslation.plist @@ -0,0 +1,174 @@ + + + + + ADP2,1 + Developer Transition Kit + MacBook1,1 + MacBook (Core Duo) + MacBook2,1 + MacBook (Core 2 Duo) + MacBook4,1 + MacBook (Core 2 Duo Feb 2008) + MacBookAir1,1 + MacBook Air (January 2008) + MacBookPro1,1 + MacBook Pro Core Duo (15-inch) + MacBookPro1,2 + MacBook Pro Core Duo (17-inch) + MacBookPro2,1 + MacBook Pro Core 2 Duo (17-inch) + MacBookPro2,2 + MacBook Pro Core 2 Duo (15-inch) + MacBookPro3,1 + MacBook Pro Core 2 Duo (15-inch LED, Core 2 Duo) + MacBookPro3,2 + MacBook Pro Core 2 Duo (17-inch HD, Core 2 Duo) + MacBookPro4,1 + MacBook Pro (Core 2 Duo Feb 2008) + MacPro1,1 + Mac Pro (four-core) + MacPro2,1 + Mac Pro (eight-core) + MacPro3,1 + Mac Pro (January 2008 4- or 8- core "Harpertown") + Macmini1,1 + Mac Mini (Core Solo/Duo) + PowerBook1,1 + PowerBook G3 + PowerBook2,1 + iBook G3 + PowerBook2,2 + iBook G3 (FireWire) + PowerBook2,3 + iBook G3 + PowerBook2,4 + iBook G3 + PowerBook3,1 + PowerBook G3 (FireWire) + PowerBook3,2 + PowerBook G4 + PowerBook3,3 + PowerBook G4 (Gigabit Ethernet) + PowerBook3,4 + PowerBook G4 (DVI) + PowerBook3,5 + PowerBook G4 (1GHz / 867MHz) + PowerBook4,1 + iBook G3 (Dual USB, Late 2001) + PowerBook4,2 + iBook G3 (16MB VRAM) + PowerBook4,3 + iBook G3 Opaque 16MB VRAM, 32MB VRAM, Early 2003) + PowerBook5,1 + PowerBook G4 (17 inch) + PowerBook5,2 + PowerBook G4 (15 inch FW 800) + PowerBook5,3 + PowerBook G4 (17-inch 1.33GHz) + PowerBook5,4 + PowerBook G4 (15 inch 1.5/1.33GHz) + PowerBook5,5 + PowerBook G4 (17-inch 1.5GHz) + PowerBook5,6 + PowerBook G4 (15 inch 1.67GHz/1.5GHz) + PowerBook5,7 + PowerBook G4 (17-inch 1.67GHz) + PowerBook5,8 + PowerBook G4 (Double layer SD, 15 inch) + PowerBook5,9 + PowerBook G4 (Double layer SD, 17 inch) + PowerBook6,1 + PowerBook G4 (12 inch) + PowerBook6,2 + PowerBook G4 (12 inch, DVI) + PowerBook6,3 + iBook G4 + PowerBook6,4 + PowerBook G4 (12 inch 1.33GHz) + PowerBook6,5 + iBook G4 (Early-Late 2004) + PowerBook6,7 + iBook G4 (Mid 2005) + PowerBook6,8 + PowerBook G4 (12 inch 1.5GHz) + PowerMac1,1 + Power Macintosh G3 (Blue & White) + PowerMac1,2 + Power Macintosh G4 (PCI Graphics) + PowerMac10,1 + Mac Mini G4 + PowerMac10,2 + Mac Mini (Late 2005) + PowerMac11,2 + Power Macintosh G5 (Late 2005) + PowerMac12,1 + iMac G5 (iSight) + PowerMac2,1 + iMac G3 (Slot-loading CD-ROM) + PowerMac2,2 + iMac G3 (Summer 2000) + PowerMac3,1 + Power Macintosh G4 (AGP Graphics) + PowerMac3,2 + Power Macintosh G4 (AGP Graphics) + PowerMac3,3 + Power Macintosh G4 (Gigabit Ethernet) + PowerMac3,4 + Power Macintosh G4 (Digital Audio) + PowerMac3,5 + Power Macintosh G4 (Quick Silver) + PowerMac3,6 + Power Macintosh G4 (Mirrored Drive Door) + PowerMac4,1 + iMac G3 (Early/Summer 2001) + PowerMac4,2 + iMac G4 (Flat Panel) + PowerMac4,4 + eMac + PowerMac4,5 + iMac G4 (17-inch Flat Panel) + PowerMac5,1 + Power Macintosh G4 Cube + PowerMac6,1 + iMac G4 (USB 2.0) + PowerMac6,3 + iMac G4 (20-inch Flat Panel) + PowerMac6,4 + eMac (USB 2.0, 2005) + PowerMac7,2 + Power Macintosh G5 + PowerMac7,3 + Power Macintosh G5 + PowerMac8,1 + iMac G5 + PowerMac8,2 + iMac G5 (Ambient Light Sensor) + PowerMac9,1 + Power Macintosh G5 (Late 2005) + RackMac1,1 + Xserve G4 + RackMac1,2 + Xserve G4 (slot-loading, cluster node) + RackMac3,1 + Xserve G5 + Xserve1,1 + Xserve (Intel Xeon) + Xserve2,1 + Xserve (January 2008 quad-core) + iMac1,1 + iMac G3 (Rev A-D) + iMac4,1 + iMac (Core Duo) + iMac4,2 + iMac for Education (17-inch, Core Duo) + iMac5,1 + iMac (Core 2 Duo, 17 or 20 inch, SuperDrive) + iMac5,2 + iMac (Core 2 Duo, 17 inch, Combo Drive) + iMac6,1 + iMac (Core 2 Duo, 24 inch, SuperDrive) + iMac8,1 + iMac (April 2008) + + diff --git a/cocoalib/Sparkle.framework/Versions/A/Resources/SUStatus.nib/classes.nib b/cocoalib/Sparkle.framework/Versions/A/Resources/SUStatus.nib/classes.nib new file mode 100644 index 00000000..22f13f8b --- /dev/null +++ b/cocoalib/Sparkle.framework/Versions/A/Resources/SUStatus.nib/classes.nib @@ -0,0 +1,56 @@ + + + + + IBClasses + + + CLASS + SUWindowController + LANGUAGE + ObjC + SUPERCLASS + NSWindowController + + + CLASS + NSApplication + LANGUAGE + ObjC + SUPERCLASS + NSResponder + + + CLASS + FirstResponder + LANGUAGE + ObjC + SUPERCLASS + NSObject + + + CLASS + NSObject + LANGUAGE + ObjC + + + CLASS + SUStatusController + LANGUAGE + ObjC + OUTLETS + + actionButton + NSButton + progressBar + NSProgressIndicator + + SUPERCLASS + SUWindowController + + + IBVersion + 1 + + diff --git a/cocoalib/Sparkle.framework/Versions/A/Resources/SUStatus.nib/info.nib b/cocoalib/Sparkle.framework/Versions/A/Resources/SUStatus.nib/info.nib new file mode 100644 index 00000000..a9ac8673 --- /dev/null +++ b/cocoalib/Sparkle.framework/Versions/A/Resources/SUStatus.nib/info.nib @@ -0,0 +1,20 @@ + + + + + IBFramework Version + 670 + IBLastKnownRelativeProjectPath + Sparkle.xcodeproj + IBOldestOS + 5 + IBOpenObjects + + 6 + + IBSystem Version + 10A96 + targetFramework + IBCocoaFramework + + diff --git a/cocoalib/Sparkle.framework/Versions/A/Resources/SUStatus.nib/keyedobjects.nib b/cocoalib/Sparkle.framework/Versions/A/Resources/SUStatus.nib/keyedobjects.nib new file mode 100644 index 0000000000000000000000000000000000000000..4f1d598179ccecb32c7a12eead96bb5fe3663eb0 GIT binary patch literal 7344 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 I{hK-Azn((800000 literal 0 HcmV?d00001 diff --git a/cocoalib/Sparkle.framework/Versions/A/Resources/en.lproj/SUAutomaticUpdateAlert.nib/classes.nib b/cocoalib/Sparkle.framework/Versions/A/Resources/en.lproj/SUAutomaticUpdateAlert.nib/classes.nib new file mode 100644 index 00000000..4b1ab30e --- /dev/null +++ b/cocoalib/Sparkle.framework/Versions/A/Resources/en.lproj/SUAutomaticUpdateAlert.nib/classes.nib @@ -0,0 +1,50 @@ + + + + + IBClasses + + + CLASS + SUWindowController + LANGUAGE + ObjC + SUPERCLASS + NSWindowController + + + ACTIONS + + doNotInstall + id + installLater + id + installNow + id + + CLASS + SUAutomaticUpdateAlert + LANGUAGE + ObjC + SUPERCLASS + SUWindowController + + + CLASS + FirstResponder + LANGUAGE + ObjC + SUPERCLASS + NSObject + + + CLASS + NSObject + LANGUAGE + ObjC + + + IBVersion + 1 + + diff --git a/cocoalib/Sparkle.framework/Versions/A/Resources/en.lproj/SUAutomaticUpdateAlert.nib/info.nib b/cocoalib/Sparkle.framework/Versions/A/Resources/en.lproj/SUAutomaticUpdateAlert.nib/info.nib new file mode 100644 index 00000000..ab36d310 --- /dev/null +++ b/cocoalib/Sparkle.framework/Versions/A/Resources/en.lproj/SUAutomaticUpdateAlert.nib/info.nib @@ -0,0 +1,20 @@ + + + + + IBFramework Version + 658 + IBLastKnownRelativeProjectPath + ../Sparkle.xcodeproj + IBOldestOS + 5 + IBOpenObjects + + 6 + + IBSystem Version + 9C7010 + targetFramework + IBCocoaFramework + + diff --git a/cocoalib/Sparkle.framework/Versions/A/Resources/en.lproj/SUAutomaticUpdateAlert.nib/keyedobjects.nib b/cocoalib/Sparkle.framework/Versions/A/Resources/en.lproj/SUAutomaticUpdateAlert.nib/keyedobjects.nib new file mode 100644 index 0000000000000000000000000000000000000000..7630390c89e63ae4aa0af3491cb03518c1321d8a GIT binary patch literal 7148 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 literal 0 HcmV?d00001 diff --git a/cocoalib/Sparkle.framework/Versions/A/Resources/en.lproj/SUUpdateAlert.nib/classes.nib b/cocoalib/Sparkle.framework/Versions/A/Resources/en.lproj/SUUpdateAlert.nib/classes.nib new file mode 100644 index 00000000..994d4c36 --- /dev/null +++ b/cocoalib/Sparkle.framework/Versions/A/Resources/en.lproj/SUUpdateAlert.nib/classes.nib @@ -0,0 +1,67 @@ + + + + + IBClasses + + + CLASS + SUWindowController + LANGUAGE + ObjC + SUPERCLASS + NSWindowController + + + CLASS + NSApplication + LANGUAGE + ObjC + SUPERCLASS + NSResponder + + + ACTIONS + + installUpdate + id + remindMeLater + id + skipThisVersion + id + + CLASS + SUUpdateAlert + LANGUAGE + ObjC + OUTLETS + + delegate + id + description + NSTextField + releaseNotesView + WebView + + SUPERCLASS + SUWindowController + + + CLASS + FirstResponder + LANGUAGE + ObjC + SUPERCLASS + NSObject + + + CLASS + NSObject + LANGUAGE + ObjC + + + IBVersion + 1 + + diff --git a/cocoalib/Sparkle.framework/Versions/A/Resources/en.lproj/SUUpdateAlert.nib/info.nib b/cocoalib/Sparkle.framework/Versions/A/Resources/en.lproj/SUUpdateAlert.nib/info.nib new file mode 100644 index 00000000..2fb8a837 --- /dev/null +++ b/cocoalib/Sparkle.framework/Versions/A/Resources/en.lproj/SUUpdateAlert.nib/info.nib @@ -0,0 +1,20 @@ + + + + + IBFramework Version + 670 + IBLastKnownRelativeProjectPath + ../Sparkle.xcodeproj + IBOldestOS + 5 + IBOpenObjects + + 18 + + IBSystem Version + 10A96 + targetFramework + IBCocoaFramework + + diff --git a/cocoalib/Sparkle.framework/Versions/A/Resources/en.lproj/SUUpdateAlert.nib/keyedobjects.nib b/cocoalib/Sparkle.framework/Versions/A/Resources/en.lproj/SUUpdateAlert.nib/keyedobjects.nib new file mode 100644 index 0000000000000000000000000000000000000000..e7e7497db4bbc8e89d15986ad7531f1b0a07c217 GIT binary patch literal 10623 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 literal 0 HcmV?d00001 diff --git a/cocoalib/Sparkle.framework/Versions/A/Resources/en.lproj/SUUpdatePermissionPrompt.nib/classes.nib b/cocoalib/Sparkle.framework/Versions/A/Resources/en.lproj/SUUpdatePermissionPrompt.nib/classes.nib new file mode 100644 index 00000000..5220a221 --- /dev/null +++ b/cocoalib/Sparkle.framework/Versions/A/Resources/en.lproj/SUUpdatePermissionPrompt.nib/classes.nib @@ -0,0 +1,59 @@ + + + + + IBClasses + + + CLASS + SUWindowController + LANGUAGE + ObjC + SUPERCLASS + NSWindowController + + + ACTIONS + + finishPrompt + id + toggleMoreInfo + id + + CLASS + SUUpdatePermissionPrompt + LANGUAGE + ObjC + OUTLETS + + delegate + id + descriptionTextField + NSTextField + moreInfoButton + NSButton + moreInfoView + NSView + + SUPERCLASS + SUWindowController + + + CLASS + FirstResponder + LANGUAGE + ObjC + SUPERCLASS + NSObject + + + CLASS + NSObject + LANGUAGE + ObjC + + + IBVersion + 1 + + diff --git a/cocoalib/Sparkle.framework/Versions/A/Resources/en.lproj/SUUpdatePermissionPrompt.nib/info.nib b/cocoalib/Sparkle.framework/Versions/A/Resources/en.lproj/SUUpdatePermissionPrompt.nib/info.nib new file mode 100644 index 00000000..b1cd28ed --- /dev/null +++ b/cocoalib/Sparkle.framework/Versions/A/Resources/en.lproj/SUUpdatePermissionPrompt.nib/info.nib @@ -0,0 +1,21 @@ + + + + + IBFramework Version + 670 + IBLastKnownRelativeProjectPath + ../Sparkle.xcodeproj + IBOldestOS + 5 + IBOpenObjects + + 6 + 41 + + IBSystem Version + 10A96 + targetFramework + IBCocoaFramework + + diff --git a/cocoalib/Sparkle.framework/Versions/A/Resources/en.lproj/SUUpdatePermissionPrompt.nib/keyedobjects.nib b/cocoalib/Sparkle.framework/Versions/A/Resources/en.lproj/SUUpdatePermissionPrompt.nib/keyedobjects.nib new file mode 100644 index 0000000000000000000000000000000000000000..e8dc5b88028a8bf491e46d29e25091c39735c921 GIT binary patch literal 13263 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 C5g()g literal 0 HcmV?d00001 diff --git a/cocoalib/Sparkle.framework/Versions/A/Resources/en.lproj/Sparkle.strings b/cocoalib/Sparkle.framework/Versions/A/Resources/en.lproj/Sparkle.strings new file mode 100644 index 0000000000000000000000000000000000000000..16e0787b46dd69d9a9d59133dfdfc683787f5293 GIT binary patch literal 8216 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

B-YH*!3RdDu#}q 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 literal 0 HcmV?d00001 diff --git a/cocoalib/Sparkle.framework/Versions/Current b/cocoalib/Sparkle.framework/Versions/Current new file mode 120000 index 00000000..8c7e5a66 --- /dev/null +++ b/cocoalib/Sparkle.framework/Versions/Current @@ -0,0 +1 @@ +A \ No newline at end of file diff --git a/cocoalib/Utils.h b/cocoalib/Utils.h new file mode 100644 index 00000000..8068827f --- /dev/null +++ b/cocoalib/Utils.h @@ -0,0 +1,36 @@ +/* +Copyright 2013 Hardcoded Software (http://www.hardcoded.net) + +This software is licensed under the "BSD" License as described in the "LICENSE" file, +which should be included with this package. The terms are also available at +http://www.hardcoded.net/licenses/bsd_license +*/ + +#import + +//Useful shortcuts +#define i2n(i) [NSNumber numberWithInteger:i] +#define n2i(n) [n integerValue] +#define b2n(b) [NSNumber numberWithBool:b] +#define n2b(n) [n boolValue] +#if __LP64__ + #define f2n(d) [NSNumber numberWithDouble:d] + #define n2f(n) [n doubleValue] +#else + #define f2n(f) [NSNumber numberWithFloat:f] + #define n2f(n) [n floatValue] +#endif +#define p2a(p) [Utils indexPath2Array:p] +#define a2p(a) [Utils array2IndexPath:a] +#define fmt(x,...) [NSString stringWithFormat:x,__VA_ARGS__] + +@interface Utils : NSObject ++ (NSArray *)indexSet2Array:(NSIndexSet *)aIndexSet; ++ (NSIndexSet *)array2IndexSet:(NSArray *)numberArray; ++ (NSArray *)indexPath2Array:(NSIndexPath *)aIndexPath; ++ (NSIndexPath *)array2IndexPath:(NSArray *)indexArray; ++ (NSString *)indexPath2String:(NSIndexPath *)aIndexPath; ++ (NSIndexPath *)string2IndexPath:(NSString *)aString; +@end + +void replacePlaceholderInView(NSView *placeholder, NSView *replaceWith); \ No newline at end of file diff --git a/cocoalib/Utils.m b/cocoalib/Utils.m new file mode 100644 index 00000000..6dbf4039 --- /dev/null +++ b/cocoalib/Utils.m @@ -0,0 +1,92 @@ +/* +Copyright 2013 Hardcoded Software (http://www.hardcoded.net) + +This software is licensed under the "BSD" License as described in the "LICENSE" file, +which should be included with this package. The terms are also available at +http://www.hardcoded.net/licenses/bsd_license +*/ + +#import "Utils.h" +#import + +@implementation Utils +//This is to pass index sets to python as arrays (so it can be converted to native lists) ++ (NSArray *)indexSet2Array:(NSIndexSet *)aIndexSet +{ + NSMutableArray *r = [NSMutableArray array]; + NSInteger i = [aIndexSet firstIndex]; + while (i != NSNotFound) + { + [r addObject:[NSNumber numberWithInteger:i]]; + i = [aIndexSet indexGreaterThanIndex:i]; + } + return r; +} + +// numberArray is an array of NSNumber ++ (NSIndexSet *)array2IndexSet:(NSArray *)numberArray +{ + NSMutableIndexSet *set = [NSMutableIndexSet indexSet]; + NSEnumerator *e = [numberArray objectEnumerator]; + NSNumber *n; + while (n = [e nextObject]) + [set addIndex:n2i(n)]; + return set; +} + +//Changes an NSIndexPath into an NSArray ++ (NSArray *)indexPath2Array:(NSIndexPath *)aIndexPath +{ + NSMutableArray *r = [NSMutableArray array]; + if (!aIndexPath) + return r; + for (int i=0;i<[aIndexPath length];i++) + [r addObject:i2n([aIndexPath indexAtPosition:i])]; + return r; +} + +// Changes a NSArray of numbers into a NSIndexPath +// indexArray must have at least one item ++ (NSIndexPath *)array2IndexPath:(NSArray *)indexArray +{ + if (![indexArray count]) + { + return nil; + } + NSEnumerator *e = [indexArray objectEnumerator]; + NSNumber *n = [e nextObject]; + NSIndexPath *ip = [NSIndexPath indexPathWithIndex:n2i(n)]; + while (n = [e nextObject]) + ip = [ip indexPathByAddingIndex:n2i(n)]; + return ip; +} + ++ (NSString *)indexPath2String:(NSIndexPath *)aIndexPath +{ + NSMutableArray *components = [NSMutableArray array]; + for (int i=0; i<[aIndexPath length]; i++) + [components addObject:i2n([aIndexPath indexAtPosition:i])]; + return [components componentsJoinedByString:@"_"]; +} + ++ (NSIndexPath *)string2IndexPath:(NSString *)aString +{ + if (aString == nil) + { + return nil; + } + NSArray *components = [aString componentsSeparatedByString:@"_"]; + NSMutableArray *indexes = [NSMutableArray array]; + for (int i=0; i<[components count]; i++) + [indexes addObject:i2n([[components objectAtIndex:i] intValue])]; + return [Utils array2IndexPath:indexes]; +} +@end + +void replacePlaceholderInView(NSView *placeholder, NSView *replaceWith) +{ + NSView *parent = [placeholder superview]; + [replaceWith setFrame:[placeholder frame]]; + [replaceWith setAutoresizingMask:[placeholder autoresizingMask]]; + [parent replaceSubview:placeholder with:replaceWith]; +} diff --git a/cocoalib/ValueTransformers.h b/cocoalib/ValueTransformers.h new file mode 100644 index 00000000..8d6858f0 --- /dev/null +++ b/cocoalib/ValueTransformers.h @@ -0,0 +1,26 @@ +/* +Copyright 2013 Hardcoded Software (http://www.hardcoded.net) + +This software is licensed under the "BSD" License as described in the "LICENSE" file, +which should be included with this package. The terms are also available at +http://www.hardcoded.net/licenses/bsd_license +*/ + +#import + + +@interface VTIsIntIn : NSValueTransformer +{ + NSIndexSet *ints; + BOOL reverse; +} +- (id)initWithValues:(NSIndexSet *)values; +- (id)initWithValues:(NSIndexSet *)values reverse:(BOOL)doReverse; +@end + +@interface HSVTAdd : NSValueTransformer +{ + int toAdd; +} +- (id)initWithValue:(int)value; +@end diff --git a/cocoalib/ValueTransformers.m b/cocoalib/ValueTransformers.m new file mode 100644 index 00000000..7dfb0ce7 --- /dev/null +++ b/cocoalib/ValueTransformers.m @@ -0,0 +1,79 @@ +/* +Copyright 2013 Hardcoded Software (http://www.hardcoded.net) + +This software is licensed under the "BSD" License as described in the "LICENSE" file, +which should be included with this package. The terms are also available at +http://www.hardcoded.net/licenses/bsd_license +*/ + +#import "ValueTransformers.h" +#import "Utils.h" + +@implementation VTIsIntIn +- (id)initWithValues:(NSIndexSet *)values +{ + return [self initWithValues:values reverse:NO]; +} + +- (id)initWithValues:(NSIndexSet *)values reverse:(BOOL)doReverse +{ + self = [super init]; + ints = values; + [ints retain]; + reverse = doReverse; + return self; +} + +- (void)dealloc +{ + [ints release]; + [super dealloc]; +} + ++ (Class)transformedValueClass +{ + return [NSNumber class]; //Boolean +} + ++ (BOOL)allowsReverseTransformation +{ + return NO; +} + +- (id)transformedValue:(id)value +{ + if (value == nil) + return nil; + NSNumber *i = value; + BOOL r = [ints containsIndex:[i intValue]]; + if (reverse) + r = !r; + return [NSNumber numberWithBool:r]; +} +@end + +@implementation HSVTAdd +- (id)initWithValue:(int)value +{ + self = [super init]; + toAdd = value; + return self; +} + ++ (Class)transformedValueClass +{ + return [NSNumber class]; +} + ++ (BOOL)allowsReverseTransformation +{ + return NO; +} + +- (id)transformedValue:(id)value +{ + if (value == nil) + return nil; + return i2n(n2i(value) + toAdd); +} +@end diff --git a/cocoalib/Worker.h b/cocoalib/Worker.h new file mode 100644 index 00000000..65130ff4 --- /dev/null +++ b/cocoalib/Worker.h @@ -0,0 +1,14 @@ +#import + +//The worker should work in a separate thread or have it's own mechanism to keep the GUI updated as ProgressController +//provides none. +@protocol Worker +// -1: Indeterminate. nil: Not working. 0-100: Progressing +- (NSNumber *)getJobProgress; +- (NSString *)getJobDesc; +- (void)cancelJob; +/* This might seem a little stupid, but it's the simplest way to get a **sync** call to the python +side after a job. Because the python-side app is not an NSObject subclass, it can't listen to +notifications. */ +- (void)jobCompleted:(NSString *)jobid; +@end \ No newline at end of file diff --git a/cocoalib/cocoa/CocoaProxy.h b/cocoalib/cocoa/CocoaProxy.h new file mode 100644 index 00000000..613cabb9 --- /dev/null +++ b/cocoalib/cocoa/CocoaProxy.h @@ -0,0 +1,32 @@ +#import + +@interface CocoaProxy : NSObject +{ + NSAutoreleasePool *currentPool; +} +- (void)openPath:(NSString *)path; +- (void)openURL:(NSString *)url; +- (void)revealPath:(NSString *)path; +- (NSString *)getUTI:(NSString *)path; +- (BOOL)type:(NSString *)type conformsToType:(NSString *)refType; +- (NSString *)getAppdataPath; +- (NSString *)getCachePath; +- (NSString *)getResourcePath; +- (NSString *)systemLang; +- (NSString *)systemShortDateFormat; +- (NSString *)systemNumberDecimalSeparator; +- (NSString *)systemNumberGroupingSeparator; +- (NSString *)systemCurrency; +- (NSString *)bundleIdentifier; +- (NSString *)appVersion; +- (NSString *)osxVersion; +- (void)postNotification:(NSString *)name userInfo:(NSDictionary *)userInfo; +- (id)prefValue:(NSString *)prefname; +- (void)setPrefValue:(NSString *)prefname value:(id)value; +- (id)prefValue:(NSString *)prefname inDomain:(NSString *)domain; +- (NSString *)url2path:(NSString *)url; +- (void)createPool; +- (void)destroyPool; +- (void)reportCrash:(NSString *)crashReport; +- (void)log:(NSString *)s; +@end \ No newline at end of file diff --git a/cocoalib/cocoa/CocoaProxy.m b/cocoalib/cocoa/CocoaProxy.m new file mode 100644 index 00000000..27948324 --- /dev/null +++ b/cocoalib/cocoa/CocoaProxy.m @@ -0,0 +1,155 @@ +#import "CocoaProxy.h" +#import +#import "HSErrorReportWindow.h" + +@implementation CocoaProxy +- (void)openPath:(NSString *)path +{ + [[NSWorkspace sharedWorkspace] openURL:[NSURL fileURLWithPath:path isDirectory:NO]]; +} + +- (void)openURL:(NSString *)url +{ + [[NSWorkspace sharedWorkspace] openURL:[NSURL URLWithString:url]]; +} + +- (void)revealPath:(NSString *)path +{ + [[NSWorkspace sharedWorkspace] selectFile:path inFileViewerRootedAtPath:@""]; +} + +- (NSString *)getUTI:(NSString *)path +{ + NSError *error; + return [[NSWorkspace sharedWorkspace] typeOfFile:path error:&error]; +} + +- (BOOL)type:(NSString *)type conformsToType:(NSString *)refType +{ + return [[NSWorkspace sharedWorkspace] type:type conformsToType:refType]; +} + +- (NSString *)getAppdataPath +{ + return [NSSearchPathForDirectoriesInDomains(NSApplicationSupportDirectory, NSUserDomainMask, YES) objectAtIndex:0]; +} +- (NSString *)getCachePath +{ + return [NSSearchPathForDirectoriesInDomains(NSCachesDirectory, NSUserDomainMask, YES) objectAtIndex:0]; +} + +- (NSString *)getResourcePath +{ + return [[[NSBundle mainBundle] resourceURL] path]; +} + +- (NSString *)systemLang +{ + return [[NSBundle preferredLocalizationsFromArray:[[NSBundle mainBundle] localizations]] objectAtIndex:0]; +} + +- (NSString *)systemShortDateFormat +{ + [NSDateFormatter setDefaultFormatterBehavior:NSDateFormatterBehavior10_4]; + NSDateFormatter *f = [[NSDateFormatter alloc] init]; + [f setDateStyle:NSDateFormatterShortStyle]; + [f setTimeStyle:NSDateFormatterNoStyle]; + NSString *result = [[f dateFormat] retain]; + [f release]; + return [result autorelease]; +} + +- (NSString *)systemNumberDecimalSeparator +{ + [NSNumberFormatter setDefaultFormatterBehavior:NSNumberFormatterBehavior10_4]; + NSNumberFormatter *f = [[NSNumberFormatter alloc] init]; + NSString *result = [[f decimalSeparator] retain]; + [f release]; + return [result autorelease]; +} + +- (NSString *)systemNumberGroupingSeparator +{ + [NSNumberFormatter setDefaultFormatterBehavior:NSNumberFormatterBehavior10_4]; + NSNumberFormatter *f = [[NSNumberFormatter alloc] init]; + NSString *result = [[f groupingSeparator] retain]; + [f release]; + return [result autorelease]; +} + +- (NSString *)systemCurrency +{ + return [[NSLocale currentLocale] objectForKey:NSLocaleCurrencyCode]; +} + +- (NSString *)bundleIdentifier +{ + return [[NSBundle mainBundle] bundleIdentifier]; +} + +- (NSString *)appVersion +{ + return [[NSBundle mainBundle] objectForInfoDictionaryKey:@"CFBundleVersion"]; +} + +- (NSString *)osxVersion +{ + SInt32 major, minor, bugfix; + Gestalt(gestaltSystemVersionMajor, &major); + Gestalt(gestaltSystemVersionMinor, &minor); + Gestalt(gestaltSystemVersionBugFix, &bugfix); + return [NSString stringWithFormat:@"%d.%d.%d", major, minor, bugfix]; +} + +- (void)postNotification:(NSString *)name userInfo:(NSDictionary *)userInfo +{ + [[NSNotificationCenter defaultCenter] postNotificationName:name object:nil userInfo:userInfo]; +} + +- (id)prefValue:(NSString *)prefname +{ + return [[NSUserDefaults standardUserDefaults] objectForKey:prefname]; +} + +- (void)setPrefValue:(NSString *)prefname value:(id)value +{ + [[NSUserDefaults standardUserDefaults] setObject:value forKey:prefname]; +} + +- (id)prefValue:(NSString *)prefname inDomain:(NSString *)domain +{ + NSDictionary *dict = [[NSUserDefaults standardUserDefaults] persistentDomainForName:domain]; + return [dict objectForKey:prefname]; +} + +// Changes a file:/// path into a normal path +- (NSString *)url2path:(NSString *)url +{ + NSURL *u = [NSURL URLWithString:url]; + return [u path]; +} + +// Create a pool for use into a separate thread. +- (void)createPool +{ + [self destroyPool]; + currentPool = [[NSAutoreleasePool alloc] init]; +} +- (void)destroyPool +{ + if (currentPool != nil) { + [currentPool release]; + currentPool = nil; + } +} + +- (void)reportCrash:(NSString *)crashReport +{ + [HSErrorReportWindow showErrorReportWithContent:crashReport]; +} + +- (void)log:(NSString *)s +{ + NSLog(@"%@", s); +} +@end \ No newline at end of file diff --git a/cocoalib/cocoa/__init__.py b/cocoalib/cocoa/__init__.py new file mode 100644 index 00000000..bdbd725e --- /dev/null +++ b/cocoalib/cocoa/__init__.py @@ -0,0 +1,115 @@ +# Created By: Virgil Dupras +# Created On: 2007-10-06 +# Copyright 2013 Hardcoded Software (http://www.hardcoded.net) + +# This software is licensed under the "BSD" License as described in the "LICENSE" file, +# which should be included with this package. The terms are also available at +# http://www.hardcoded.net/licenses/bsd_license + +import logging +import time +import traceback +import subprocess +import sys + +from .CocoaProxy import CocoaProxy + +proxy = CocoaProxy() + +try: + from jobprogress.performer import ThreadedJobPerformer as ThreadedJobPerformerBase + class ThreadedJobPerformer(ThreadedJobPerformerBase): + def _async_run(self, *args): + proxy.createPool() + try: + ThreadedJobPerformerBase._async_run(self, *args) + finally: + proxy.destroyPool() +except ImportError: + # jobprogress isn't used in all HS apps + pass + + +def as_fetch(as_list, as_type, step_size=1000): + """When fetching items from a very big list through applescript, the connection with the app + will timeout. This function is to circumvent that. 'as_type' is the type of the items in the + list (found in appscript.k). If we don't pass it to the 'each' arg of 'count()', it doesn't work. + applescript is rather stupid...""" + result = [] + # no timeout. default timeout is 60 secs, and it is reached for libs > 30k songs + item_count = as_list.count(each=as_type, timeout=0) + steps = item_count // step_size + if item_count % step_size: + steps += 1 + logging.info('Fetching %d items in %d steps' % (item_count, steps)) + # Don't forget that the indexes are 1-based and that the upper limit is included + for step in range(steps): + begin = step * step_size + 1 + end = min(item_count, begin + step_size - 1) + if end > begin: + result += as_list[begin:end](timeout=0) + else: # When there is only one item, the stupid fuck gives it directly instead of putting it in a list. + result.append(as_list[begin:end](timeout=0)) + time.sleep(.1) + logging.info('%d items fetched' % len(result)) + return result + +def extract_tb_noline(tb): + # Same as traceback.extract_tb(), but without line fetching + limit = 100 + list = [] + n = 0 + while tb is not None and (limit is None or n < limit): + f = tb.tb_frame + lineno = tb.tb_lineno + co = f.f_code + filename = co.co_filename + name = co.co_name + list.append((filename, lineno, name, None)) + tb = tb.tb_next + n = n+1 + return list + +def safe_format_exception(type, value, tb): + """Format exception from type, value and tb and fallback if there's a problem. + + In some cases in threaded exceptions under Cocoa, I get tracebacks targeting pyc files instead + of py files, which results in traceback.format_exception() trying to print lines from pyc files + and then crashing when trying to interpret that binary data as utf-8. We want a fallback in + these cases. + """ + try: + return traceback.format_exception(type, value, tb) + except Exception: + result = ['Traceback (most recent call last):\n'] + result.extend(traceback.format_list(extract_tb_noline(tb))) + result.extend(traceback.format_exception_only(type, value)) + return result + +def report_crash(type, value, tb): + app_identifier = proxy.bundleIdentifier() + app_version = proxy.appVersion() + osx_version = proxy.osxVersion() + s = "Application Identifier: {}\n".format(app_identifier) + s += "Application Version: {}\n".format(app_version) + s += "Mac OS X Version: {}\n\n".format(osx_version) + s += ''.join(safe_format_exception(type, value, tb)) + if app_identifier: + s += '\nRelevant Console logs:\n\n' + p = subprocess.Popen(['grep', app_identifier, '/var/log/system.log'], stdout=subprocess.PIPE) + try: + s += str(p.communicate()[0], encoding='utf-8') + except IndexError: + # This can happen if something went wrong with the grep (permission errors?) + pass + proxy.reportCrash_(s) + +def install_exception_hook(): + sys.excepthook = report_crash + +class CocoaHandler(logging.Handler): + def emit(self, record): + proxy.log_(record.getMessage()) + +def install_cocoa_logger(): + logging.getLogger().addHandler(CocoaHandler()) diff --git a/cocoalib/cocoa/inter.py b/cocoalib/cocoa/inter.py new file mode 100644 index 00000000..beb29298 --- /dev/null +++ b/cocoalib/cocoa/inter.py @@ -0,0 +1,306 @@ +import logging +from objp.util import pyref, dontwrap +from . import proxy + +class GUIObjectView: + def refresh(self): pass + +class PyGUIObject: + def __init__(self, model: pyref): + self.model = model + self.callback = None + + # This *has* to be called right after initialization. + def bindCallback_(self, callback: pyref): + self.callback = callback + self.model.view = self + + # Call this before the ObjC callback is deallocated to avoid calls to that deallocated instance. + def free(self): + self.model.view = None + self.callback = None + + def modelRef(self) -> pyref: + return self.model + + #--- Python -> Cocoa + @dontwrap + def refresh(self): + self.callback.refresh() + +class PyTextField(PyGUIObject): + def text(self) -> str: + return self.model.text + + def setText_(self, newtext: str): + self.model.text = newtext + + +class SelectableListView(GUIObjectView): + def updateSelection(self): pass + +class PySelectableList(PyGUIObject): + def items(self) -> list: + # Should normally always return strings + return self.model[:] + + def selectIndex_(self, index: int): + self.model.select(index) + + def selectedIndex(self) -> int: + result = self.model.selected_index + if result is None: + result = -1 + return result + + def selectedIndexes(self) -> list: + return self.model.selected_indexes + + def selectIndexes_(self, indexes: list): + self.model.select(indexes) + + def searchByPrefix_(self, prefix: str) -> int: + return self.model.search_by_prefix(prefix) + + #--- model --> view + @dontwrap + def update_selection(self): + self.callback.updateSelection() + +class ColumnsView: + def restoreColumns(self): pass + def setColumn_visible_(self, colname: str, visible: bool): pass + +class PyColumns(PyGUIObject): + def columnNamesInOrder(self) -> list: + return self.model.colnames + + def columnDisplay_(self, colname: str) -> str: + return self.model.column_display(colname) + + def columnIsVisible_(self, colname: str) -> bool: + return self.model.column_is_visible(colname) + + def columnWidth_(self, colname: str) -> int: + return self.model.column_width(colname) + + def moveColumn_toIndex_(self, colname: str, index: int): + self.model.move_column(colname, index) + + def resizeColumn_toWidth_(self, colname: str, newwidth: int): + self.model.resize_column(colname, newwidth) + + def setColumn_defaultWidth_(self, colname: str, width: int): + self.model.set_default_width(colname, width) + + def menuItems(self) -> list: + return self.model.menu_items() + + def toggleMenuItem_(self, index: int) -> bool: + return self.model.toggle_menu_item(index) + + def resetToDefaults(self): + self.model.reset_to_defaults() + + #--- Python --> Cocoa + @dontwrap + def restore_columns(self): + self.callback.restoreColumns() + + @dontwrap + def set_column_visible(self, colname: str, visible): + self.callback.setColumn_visible_(colname, visible) + +class OutlineView(GUIObjectView): + def startEditing(self): pass + def stopEditing(self): pass + def updateSelection(self): pass + +class PyOutline(PyGUIObject): + def cancelEdits(self): + self.model.cancel_edits() + + def canEditProperty_atPath_(self, property: str, path: list) -> bool: + node = self.model.get_node(path) + assert node is self.model.selected_node + return getattr(node, 'can_edit_' + property, False) + + def saveEdits(self): + self.model.save_edits() + + def selectedPath(self) -> list: + return self.model.selected_path + + def setSelectedPath_(self, path: list): + self.model.selected_path = path + + def selectedPaths(self) -> list: + return self.model.selected_paths + + def setSelectedPaths_(self, paths: list): + self.model.selected_paths = paths + + def property_valueAtPath_(self, property: str, path: list) -> object: + try: + return getattr(self.model.get_node(path), property) + except IndexError: + logging.warning("%r doesn't have a node at path %r", self.model, path) + return '' + + def setProperty_value_atPath_(self, property: str, value: object, path: list): + setattr(self.model.get_node(path), property, value) + + #--- Python -> Cocoa + @dontwrap + def start_editing(self): + self.callback.startEditing() + + @dontwrap + def stop_editing(self): + self.callback.stopEditing() + + @dontwrap + def update_selection(self): + self.callback.updateSelection() + +class TableView(GUIObjectView): + def showSelectedRow(self): pass + def startEditing(self): pass + def stopEditing(self): pass + def updateSelection(self): pass + +class PyTable(PyGUIObject): + #--- Helpers + @dontwrap + def _getrow(self, row): + try: + return self.model[row] + except IndexError: + msg = "Trying to get an out of bounds row ({} / {}) on table {}" + logging.warning(msg.format(row, len(self.model), self.model.__class__.__name__)) + + #--- Cocoa --> Python + def columns(self) -> pyref: + return self.model.columns + + def add(self): + self.model.add() + + def cancelEdits(self): + self.model.cancel_edits() + + def canEditColumn_atRow_(self, column: str, row: int) -> object: + return self.model.can_edit_cell(column, row) + + def deleteSelectedRows(self): + self.model.delete() + + def numberOfRows(self) -> int: + return len(self.model) + + def saveEdits(self): + self.model.save_edits() + + def selectRows_(self, rows: list): + self.model.select(list(rows)) + + def selectedRows(self) -> list: + return self.model.selected_indexes + + def selectionAsCSV(self) -> str: + return self.model.selection_as_csv() + + def setValue_forColumn_row_(self, value: object, column: str, row: int): + # this try except is important for the case while a row is in edition mode and the delete + # button is clicked. + try: + self._getrow(row).set_cell_value(column, value) + except AttributeError: + msg = "Trying to set an attribute that can't: {} with value {} at row {} on table {}" + logging.warning(msg.format(column, value, row, self.model.__class__.__name__)) + raise + + def sortByColumn_desc_(self, column: str, desc: bool): + self.model.sort_by(column, desc=desc) + + def valueForColumn_row_(self, column: str, row: int) -> object: + return self._getrow(row).get_cell_value(column) + + #--- Python -> Cocoa + @dontwrap + def show_selected_row(self): + self.callback.showSelectedRow() + + @dontwrap + def start_editing(self): + self.callback.startEditing() + + @dontwrap + def stop_editing(self): + self.callback.stopEditing() + + @dontwrap + def update_selection(self): + self.callback.updateSelection() + +class BaseAppView: + def showMessage_(self, msg: str): pass + +class PyBaseApp(PyGUIObject): + def appName(self) -> str: + return self.model.PROMPT_NAME + + def appLongName(self) -> str: + return self.model.NAME + + #--- Python --> Cocoa + @dontwrap + def get_default(self, key_name): + return proxy.prefValue_(key_name) + + @dontwrap + def set_default(self, key_name, value): + proxy.setPrefValue_value_(key_name, value) + + @dontwrap + def open_url(self, url): + proxy.openURL_(url) + + @dontwrap + def show_message(self, msg): + self.callback.showMessage_(msg) + +class FairwareView(BaseAppView): + def setupAsRegistered(self): pass + def showDemoNagWithPrompt_(self, prompt: str): pass + +class PyFairware(PyBaseApp): + FOLLOW_PROTOCOLS = ['HSFairwareProtocol'] + + def initialRegistrationSetup(self): + self.model.initial_registration_setup() + + def isRegistered(self) -> bool: + return self.model.registered + + def setRegisteredCode_andEmail_(self, code: str, email: str) -> bool: + return self.model.set_registration(code, email, False) + + def contribute(self): + self.model.contribute() + + def buy(self): + self.model.buy() + + def aboutFairware(self): + self.model.about_fairware() + + #--- Python --> Cocoa + @dontwrap + def setup_as_registered(self): + self.callback.setupAsRegistered() + + @dontwrap + def show_demo_nag(self, prompt): + self.callback.showDemoNagWithPrompt_(prompt) + diff --git a/cocoalib/controllers/HSColumns.h b/cocoalib/controllers/HSColumns.h new file mode 100644 index 00000000..fbb1cbd9 --- /dev/null +++ b/cocoalib/controllers/HSColumns.h @@ -0,0 +1,38 @@ +/* +Copyright 2013 Hardcoded Software (http://www.hardcoded.net) + +This software is licensed under the "BSD" License as described in the "LICENSE" file, +which should be included with this package. The terms are also available at +http://www.hardcoded.net/licenses/bsd_license +*/ + +#import +#import +#import "HSGUIController.h" +#import "PyColumns.h" + +/* + This structure is to define constants describing table columns (it's easier to maintain in code + than in XIB files). +*/ +typedef struct { + NSString *attrname; + NSUInteger defaultWidth; + NSUInteger minWidth; + NSUInteger maxWidth; + BOOL sortable; + Class cellClass; +} HSColumnDef; + +@interface HSColumns : HSGUIController {} +- (id)initWithPyRef:(PyObject *)aPyRef tableView:(NSTableView *)aTableView; +- (PyColumns *)model; +- (NSTableView *)view; +- (void)connectNotifications; +- (void)disconnectNotifications; +- (void)initializeColumns:(HSColumnDef *)columns; +- (void)initializeColumnsFromModel:(HSColumnDef)columnModel; +- (void)setColumnsAsReadOnly; +- (void)restoreColumns; +- (void)setColumn:(NSString *)colname visible:(BOOL)visible; +@end \ No newline at end of file diff --git a/cocoalib/controllers/HSColumns.m b/cocoalib/controllers/HSColumns.m new file mode 100644 index 00000000..4c35082d --- /dev/null +++ b/cocoalib/controllers/HSColumns.m @@ -0,0 +1,198 @@ +/* +Copyright 2013 Hardcoded Software (http://www.hardcoded.net) + +This software is licensed under the "BSD" License as described in the "LICENSE" file, +which should be included with this package. The terms are also available at +http://www.hardcoded.net/licenses/bsd_license +*/ + +#import "HSColumns.h" +#import "Utils.h" +#import "HSTableView.h" // To prevent warning on stopEditing + +@implementation HSColumns +- (id)initWithPyRef:(PyObject *)aPyRef tableView:(NSTableView *)aTableView +{ + self = [super initWithPyRef:aPyRef wrapperClass:[PyColumns class] + callbackClassName:@"ColumnsView" view:aTableView]; + [self connectNotifications]; + return self; +} + +- (void)dealloc +{ + [self disconnectNotifications]; + [super dealloc]; +} + +- (PyColumns *)model +{ + return (PyColumns *)model; +} + +- (NSTableView *)view +{ + return (NSTableView *)view; +} + +- (void)connectNotifications +{ + if ([self view] == nil) { + /* This can happen if there something broken somewhere, and even though when that happens, + it means that something serious is going on, the fact that we connect to all columnMoved: + events messes thigs up even MORE. Don't connect when tableView is nil! + */ + return; + } + [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(columnMoved:) + name:NSTableViewColumnDidMoveNotification object:[self view]]; + [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(columnMoved:) + name:NSOutlineViewColumnDidMoveNotification object:[self view]]; + [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(columnResized:) + name:NSTableViewColumnDidResizeNotification object:[self view]]; + [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(columnResized:) + name:NSOutlineViewColumnDidResizeNotification object:[self view]]; +} + +- (void)disconnectNotifications +{ + [[NSNotificationCenter defaultCenter] removeObserver:self]; +} + +/* + It is assumed, when this method is used, that the table/outline is empty *OR* that it is not + defined in the column list. + + Special note about NSOutlineView. You can use HSColumns on outline views, but you be aware that + the "main" column (the one having the tree disclosure buttons) cannot be removed. Therefore, + it has to be defined in the XIB and it must *not* be in column defs. +*/ +- (void)initializeColumns:(HSColumnDef *)columns +{ + /* We don't want default widths to overwrite stored with in the core code */ + [self disconnectNotifications]; + /* Translate the title of columns (needed for outlines) present already */ + for (NSTableColumn *c in [[self view] tableColumns]) { + NSString *title = NSLocalizedStringFromTable([[c headerCell] stringValue], @"columns", @""); + [[c headerCell] setStringValue:title]; + } + NSUserDefaults *udc = [NSUserDefaultsController sharedUserDefaultsController]; + HSColumnDef *cdef = columns; + while (cdef->attrname != nil) { + if ([[self view] tableColumnWithIdentifier:cdef->attrname] != nil) { + cdef++; + continue; + } + NSTableColumn *c = [[[NSTableColumn alloc] initWithIdentifier:cdef->attrname] autorelease]; + [c setResizingMask:NSTableColumnUserResizingMask]; + /* If the column is not added right away, it causes glitches under 10.5 (minwidths instead of default widths) */ + [[self view] addTableColumn:c]; + NSString *title = [[self model] columnDisplay:cdef->attrname]; + [[c headerCell] setStringValue:title]; + if (cdef->sortable) { + NSSortDescriptor *d = [[[NSSortDescriptor alloc] initWithKey:cdef->attrname ascending:YES] autorelease]; + [c setSortDescriptorPrototype:d]; + } + [c setWidth:cdef->defaultWidth]; + [[self model] setColumn:cdef->attrname defaultWidth:cdef->defaultWidth]; + [c setMinWidth:cdef->minWidth]; + NSUInteger maxWidth = cdef->maxWidth; + if (maxWidth == 0) { + maxWidth = 0xffffff; + } + [c setMaxWidth:maxWidth]; + if (cdef->cellClass != nil) { + id cell = [[[cdef->cellClass alloc] initTextCell:@""] autorelease]; + [cell setEditable:YES]; + [c setDataCell:cell]; + } + [c bind:@"fontSize" toObject:udc withKeyPath:@"values.TableFontSize" options:nil]; + cdef++; + } + [self connectNotifications]; +} + +/* + Here, instead of having all our column defs, we have one column model, which we use to create + our column defs using column names in [[self model] columnNamesInOrder]. +*/ +- (void)initializeColumnsFromModel:(HSColumnDef)columnModel +{ + NSArray *colnames = [[self model] columnNamesInOrder]; + HSColumnDef *defs = (HSColumnDef *)malloc(([colnames count]+1)*sizeof(HSColumnDef)); + HSColumnDef *def = defs; + for (NSString *colname in colnames) { + def->attrname = colname; + def->defaultWidth = columnModel.defaultWidth; + def->minWidth = columnModel.minWidth; + def->maxWidth = columnModel.maxWidth; + def->sortable = columnModel.sortable; + def->cellClass = columnModel.cellClass; + def++; + } + def->attrname = nil; // Sentinel + [self initializeColumns:defs]; + free(defs); +} + +- (void)setColumnsAsReadOnly +{ + for (NSTableColumn *col in [[self view] tableColumns]) { + [col setEditable:NO]; + } +} + +/* Notifications */ +- (void)columnMoved:(NSNotification *)notification +{ + /* We only get this call after the move. Although there's "NSOldColumn" and "NSNewColumn", + the old index is irrelevant since we have to find the moved column's name. + */ + NSInteger index = n2i([[notification userInfo] objectForKey:@"NSNewColumn"]); + NSTableColumn *c = [[[self view] tableColumns] objectAtIndex:index]; + NSString *colName = [c identifier]; + [[self model] moveColumn:colName toIndex:index]; +} + +- (void)columnResized:(NSNotification *)notification +{ + NSTableColumn *c = [[notification userInfo] objectForKey:@"NSTableColumn"]; + [[self model] resizeColumn:[c identifier] toWidth:[c width]]; +} + +/* Python --> Cocoa */ +- (void)restoreColumns +{ + [self disconnectNotifications]; + NSArray *columnOrder = [[self model] columnNamesInOrder]; + for (NSInteger i=0; i<[columnOrder count]; i++) { + NSString *colName = [columnOrder objectAtIndex:i]; + NSInteger index = [[self view] columnWithIdentifier:colName]; + if ((index != -1) && (index != i)) { + [[self view] moveColumn:index toColumn:i]; + } + } + for (NSTableColumn *c in [[self view] tableColumns]) { + NSInteger width = [[self model] columnWidth:[c identifier]]; + if (width > 0) { + [c setWidth:width]; + } + BOOL isVisible = [[self model] columnIsVisible:[c identifier]]; + [c setHidden:!isVisible]; + } + [self connectNotifications]; +} + +- (void)setColumn:(NSString *)colname visible:(BOOL)visible +{ + NSTableColumn *col = [[self view] tableColumnWithIdentifier:colname]; + if (col == nil) + return; + if ([col isHidden] == !visible) + return; + if ([[self view] respondsToSelector:@selector(stopEditing)]) { + [(id)[self view] stopEditing]; + } + [col setHidden:!visible]; +} +@end diff --git a/cocoalib/controllers/HSComboBox.h b/cocoalib/controllers/HSComboBox.h new file mode 100644 index 00000000..20c729e7 --- /dev/null +++ b/cocoalib/controllers/HSComboBox.h @@ -0,0 +1,25 @@ +/* +Copyright 2013 Hardcoded Software (http://www.hardcoded.net) + +This software is licensed under the "BSD" License as described in the "LICENSE" file, +which should be included with this package. The terms are also available at +http://www.hardcoded.net/licenses/bsd_license +*/ + +#import +#import "HSGUIController.h" +#import "PySelectableList.h" + +@interface HSComboBox : HSGUIController +{ + NSArray *items; +} +- (id)initWithPyRef:(PyObject *)aPyRef view:(NSComboBox *)aView; +- (NSComboBox *)view; +- (void)setView:(NSComboBox *)aComboboxView; +- (PySelectableList *)model; + +- (void)comboboxViewSelectionChanged; +- (void)refresh; +- (void)updateSelection; +@end \ No newline at end of file diff --git a/cocoalib/controllers/HSComboBox.m b/cocoalib/controllers/HSComboBox.m new file mode 100644 index 00000000..1f268e4e --- /dev/null +++ b/cocoalib/controllers/HSComboBox.m @@ -0,0 +1,119 @@ +/* +Copyright 2013 Hardcoded Software (http://www.hardcoded.net) + +This software is licensed under the "BSD" License as described in the "LICENSE" file, +which should be included with this package. The terms are also available at +http://www.hardcoded.net/licenses/bsd_license +*/ + +#import "HSComboBox.h" +#import "HSPyUtil.h" + +@implementation HSComboBox +- (id)initWithPyRef:(PyObject *)aPyRef view:(NSComboBox *)aView +{ + PySelectableList *m = [[PySelectableList alloc] initWithModel:aPyRef]; + self = [super initWithModel:m]; + [m bindCallback:createCallback(@"SelectableListView", self)]; + [m release]; + [self setView:aView]; + return self; +} + +- (void)dealloc +{ + [[self view] setTarget:nil]; + [[self view] setDataSource:nil]; + [items release]; + [super dealloc]; +} + +- (NSComboBox *)view +{ + return (NSComboBox *)view; +} + +- (void)setView:(NSComboBox *)aComboboxView +{ + if ([self view] != nil) { + [[self view] setDataSource:nil]; + [[self view] setTarget:nil]; + } + [super setView:aComboboxView]; + if (aComboboxView != nil) { + [aComboboxView setUsesDataSource:YES]; + [aComboboxView setDataSource:self]; + [aComboboxView setAction:@selector(comboboxViewSelectionChanged)]; + [aComboboxView setTarget:self]; + /* This is required for the combobox to send its action whenever it's changed. Normally, it's + already set, but then the combobox is created programmatically (xibless), it's not. We + make sure it is here. + */ + [[aComboboxView cell] setSendsActionOnEndEditing:YES]; + [self refresh]; + } +} + +- (PySelectableList *)model +{ + return (PySelectableList *)model; +} + +- (void)comboboxViewSelectionChanged +{ + NSInteger index = [[self view] indexOfSelectedItem]; + if (index >= 0) { + [[self model] selectIndex:index]; + } +} + +/* data source */ +- (id)comboBox:(NSComboBox *)aComboBox objectValueForItemAtIndex:(NSInteger)index +{ + if (index < 0) { + return nil; + } + return [items objectAtIndex:index]; +} + +- (NSInteger)numberOfItemsInComboBox:(NSComboBox *)aComboBox +{ + return [items count]; +} + +- (NSUInteger)comboBox:(NSComboBox *)aComboBox indexOfItemWithStringValue:(NSString *)aString +{ + NSInteger index = [[self model] searchByPrefix:aString]; + if (index >= 0) { + return index; + } + else { + return NSNotFound; + } +} + +- (NSString *)comboBox:(NSComboBox *)aComboBox completedString:(NSString *)uncompletedString +{ + NSInteger index = [[self model] searchByPrefix:uncompletedString]; + if (index >= 0) { + return [items objectAtIndex:index]; + } + else { + return nil; + } +} + +/* model --> view */ +- (void)refresh +{ + [items release]; + items = [[[self model] items] retain]; + [[self view] reloadData]; + [self updateSelection]; +} + +- (void)updateSelection +{ + [[self view] selectItemAtIndex:[[self model] selectedIndex]]; +} +@end \ No newline at end of file diff --git a/cocoalib/controllers/HSGUIController.h b/cocoalib/controllers/HSGUIController.h new file mode 100644 index 00000000..596db7ff --- /dev/null +++ b/cocoalib/controllers/HSGUIController.h @@ -0,0 +1,23 @@ +/* +Copyright 2013 Hardcoded Software (http://www.hardcoded.net) + +This software is licensed under the "BSD" License as described in the "LICENSE" file, +which should be included with this package. The terms are also available at +http://www.hardcoded.net/licenses/bsd_license +*/ + +#import +#import "PyGUIObject.h" + +@interface HSGUIController : NSObject +{ + PyGUIObject *model; + NSView *view; +} +- (id)initWithModel:(PyGUIObject *)aPy; +- (id)initWithModel:(PyGUIObject *)aPy view:(NSView *)aView; +- (id)initWithPyRef:(PyObject *)aPyRef wrapperClass:(Class)aWrapperClass callbackClassName:(NSString *)aCallbackClassName view:(NSView *)aView; +- (PyGUIObject *)model; +- (NSView *)view; +- (void)setView:(NSView *)aView; +@end diff --git a/cocoalib/controllers/HSGUIController.m b/cocoalib/controllers/HSGUIController.m new file mode 100644 index 00000000..bc62369b --- /dev/null +++ b/cocoalib/controllers/HSGUIController.m @@ -0,0 +1,62 @@ +/* +Copyright 2013 Hardcoded Software (http://www.hardcoded.net) + +This software is licensed under the "BSD" License as described in the "LICENSE" file, +which should be included with this package. The terms are also available at +http://www.hardcoded.net/licenses/bsd_license +*/ + +#import "HSGUIController.h" +#import "HSPyUtil.h" + +@implementation HSGUIController +- (id)initWithModel:(PyGUIObject *)aModel +{ + self = [super init]; + model = [aModel retain]; + view = nil; + return self; +} + +- (id)initWithModel:(PyGUIObject *)aModel view:(NSView *)aView +{ + self = [super init]; + model = [aModel retain]; + [self setView:aView]; + return self; +} + +- (id)initWithPyRef:(PyObject *)aPyRef wrapperClass:(Class)aWrapperClass callbackClassName:(NSString *)aCallbackClassName view:(NSView *)aView +{ + PyGUIObject *m = [[aWrapperClass alloc] initWithModel:aPyRef]; + self = [self initWithModel:m view:aView]; + [m bindCallback:createCallback(aCallbackClassName, self)]; + [m release]; + return self; +} + +- (void)dealloc +{ + // NSLog([NSString stringWithFormat:@"%@ dealloc",[[self class] description]]); + [self setView:nil]; + [model free]; + [model release]; + [super dealloc]; +} + +- (PyGUIObject *)model +{ + return model; +} + +- (NSView *)view +{ + return view; +} + +- (void)setView:(NSView *)aView +{ + [view release]; + view = [aView retain]; +} +@end diff --git a/cocoalib/controllers/HSOutline.h b/cocoalib/controllers/HSOutline.h new file mode 100644 index 00000000..7b9ce93f --- /dev/null +++ b/cocoalib/controllers/HSOutline.h @@ -0,0 +1,44 @@ +/* +Copyright 2013 Hardcoded Software (http://www.hardcoded.net) + +This software is licensed under the "BSD" License as described in the "LICENSE" file, +which should be included with this package. The terms are also available at +http://www.hardcoded.net/licenses/bsd_license +*/ + +#import +#import "HSGUIController.h" +#import "HSOutlineView.h" +#import "PyOutline.h" +#import "NSIndexPathAdditions.h" + +@interface HSOutline : HSGUIController { + NSMutableDictionary *itemData; + NSMutableSet *itemRetainer; +} +- (id)initWithPyRef:(PyObject *)aPyRef wrapperClass:(Class)aWrapperClass callbackClassName:(NSString *)aCallbackClassName view:(HSOutlineView *)aView; +- (PyOutline *)model; +- (HSOutlineView *)view; + +/* Public */ +- (void)refresh; +- (NSIndexPath *)selectedIndexPath; +- (NSArray *)selectedIndexPaths; +- (NSString *)dataForCopyToPasteboard; +- (void)startEditing; +- (void)stopEditing; +- (void)updateSelection; +- (void)expandItem:(NSIndexPath *)item; +- (NSIndexPath *)internalizedPath:(NSIndexPath *)path; + +/* Caching */ +- (id)property:(NSString *)property valueAtPath:(NSIndexPath *)path; +- (void)setProperty:(NSString *)property value:(id)value atPath:(NSIndexPath *)path; +- (NSString *)stringProperty:(NSString *)property valueAtPath:(NSIndexPath *)path; +- (void)setStringProperty:(NSString *)property value:(NSString *)value atPath:(NSIndexPath *)path; +- (BOOL)boolProperty:(NSString *)property valueAtPath:(NSIndexPath *)path; +- (void)setBoolProperty:(NSString *)property value:(BOOL)value atPath:(NSIndexPath *)path; +- (NSInteger)intProperty:(NSString *)property valueAtPath:(NSIndexPath *)path; +- (void)setIntProperty:(NSString *)property value:(int)value atPath:(NSIndexPath *)path; +- (void)refreshItemAtPath:(NSIndexPath *)path; +@end \ No newline at end of file diff --git a/cocoalib/controllers/HSOutline.m b/cocoalib/controllers/HSOutline.m new file mode 100644 index 00000000..41c52ed8 --- /dev/null +++ b/cocoalib/controllers/HSOutline.m @@ -0,0 +1,280 @@ +/* +Copyright 2013 Hardcoded Software (http://www.hardcoded.net) + +This software is licensed under the "BSD" License as described in the "LICENSE" file, +which should be included with this package. The terms are also available at +http://www.hardcoded.net/licenses/bsd_license +*/ + +#import "HSOutline.h" +#import "Utils.h" + +#define CHILDREN_COUNT_PROPERTY @"children_count" + +@implementation HSOutline +- (id)initWithPyRef:(PyObject *)aPyRef wrapperClass:(Class)aWrapperClass callbackClassName:(NSString *)aCallbackClassName view:(HSOutlineView *)aView +{ + self = [super initWithPyRef:aPyRef wrapperClass:aWrapperClass callbackClassName:aCallbackClassName view:aView]; + itemData = [[NSMutableDictionary dictionary] retain]; + /* Dictionaries don't retain its keys because it copies them. Our items are NSIndexPath and when + an index path has the same value, it's the same instance. Before OS X 10.7, all these instances + stayed in memory, so we didn't need to worry about retaining them. Hoever, it seems now that + index path instances are sometimes released. Oops. So, we now need to retain our index path + instances and that's why we use itemRetainer. + + In fact, it seems that unlike what the doc says, it's not true that two index paths with the + same value will always be the same instance. + */ + itemRetainer = [[NSMutableSet set] retain]; + if (([[self view] outlineTableColumn] == nil) && ([[[self view] tableColumns] count] > 0)) { + [[self view] setOutlineTableColumn:[[[self view] tableColumns] objectAtIndex:0]]; + } + return self; +} + +- (void)dealloc +{ + [itemData release]; + [itemRetainer release]; + [super dealloc]; +} + +- (HSOutlineView *)view +{ + return (HSOutlineView *)view; +} + +- (void)setView:(HSOutlineView *)aOutlineView +{ + if ([self view] != nil) { + [[self view] setDataSource:nil]; + [[self view] setDelegate:nil]; + } + [super setView:aOutlineView]; + if (aOutlineView != nil) { + [aOutlineView setDataSource:self]; + [aOutlineView setDelegate:self]; + } +} + +- (PyOutline *)model +{ + return (PyOutline *)model; +} + +/* Private */ +- (void)setPySelection +{ + NSMutableArray *paths = [NSMutableArray array]; + NSIndexSet *indexes = [[self view] selectedRowIndexes]; + NSInteger i = [indexes firstIndex]; + while (i != NSNotFound) { + NSIndexPath *path = [[self view] itemAtRow:i]; + [paths addObject:p2a(path)]; + i = [indexes indexGreaterThanIndex:i]; + } + [[self model] setSelectedPaths:paths]; +} + +- (NSIndexPath *)internalizedPath:(NSIndexPath *)path +{ + /* Because NSIndexPath stopped guaranteeing that the same paths always were represented by the + same instances, we have to make sure, when we manipulate paths, that we manipulate the same + instances as those that were given by outlineView:child:ofItem: + */ + NSIndexPath *result = [itemRetainer member:path]; + if (result == nil) { + result = path; + [itemData setObject:[NSMutableDictionary dictionary] forKey:result]; + [itemRetainer addObject:result]; + } + return result; +} + +/* Public */ +- (void)refresh +{ + [itemData removeAllObjects]; + // We can't get rid of our instances just yet, we have to wait until after reloadData + NSSet *oldRetainer = itemRetainer; + itemRetainer = [[NSMutableSet set] retain]; + [[self view] setDelegate:nil]; + [[self view] reloadData]; + [[self view] setDelegate:self]; + [oldRetainer release]; + [self updateSelection]; +} + +- (NSArray *)selectedIndexPaths +{ + NSArray *arrayPaths = [[self model] selectedPaths]; + NSMutableArray *result = [NSMutableArray array]; + for (NSArray *arrayPath in arrayPaths) { + [result addObject:[self internalizedPath:a2p(arrayPath)]]; + } + return result; +} + +- (void)startEditing +{ + [[self view] startEditing]; +} + +- (void)stopEditing +{ + [[self view] stopEditing]; +} + +- (void)updateSelection +{ + [[self view] updateSelection]; +} + +- (void)expandItem:(NSIndexPath *)item +{ + [[self view] ensureExpanded:item]; +} + +/* Caching */ +- (id)property:(NSString *)property valueAtPath:(NSIndexPath *)path +{ + NSMutableDictionary *props = [itemData objectForKey:path]; + id value = [props objectForKey:property]; + if (value == nil) { + value = [[self model] property:property valueAtPath:p2a(path)]; + if (value == nil) { + value = [NSNull null]; + } + [props setObject:value forKey:property]; + } + if (value == [NSNull null]) { + value = nil; + } + return value; +} + +- (void)setProperty:(NSString *)property value:(id)value atPath:(NSIndexPath *)path +{ + NSMutableDictionary *props = [itemData objectForKey:path]; + [props removeObjectForKey:property]; + [[self model] setProperty:property value:value atPath:p2a(path)]; +} + +- (NSString *)stringProperty:(NSString *)property valueAtPath:(NSIndexPath *)path +{ + return [self property:property valueAtPath:path]; +} + +- (void)setStringProperty:(NSString *)property value:(NSString *)value atPath:(NSIndexPath *)path +{ + [self setProperty:property value:value atPath:path]; +} + +- (BOOL)boolProperty:(NSString *)property valueAtPath:(NSIndexPath *)path +{ + NSNumber *value = [self property:property valueAtPath:path]; + return [value boolValue]; +} + +- (void)setBoolProperty:(NSString *)property value:(BOOL)value atPath:(NSIndexPath *)path +{ + [self setProperty:property value:[NSNumber numberWithBool:value] atPath:path]; +} + +- (NSInteger)intProperty:(NSString *)property valueAtPath:(NSIndexPath *)path +{ + NSNumber *value = [self property:property valueAtPath:path]; + return [value intValue]; +} + +- (void)setIntProperty:(NSString *)property value:(int)value atPath:(NSIndexPath *)path +{ + [self setProperty:property value:[NSNumber numberWithInt:value] atPath:path]; +} + +- (void)refreshItemAtPath:(NSIndexPath *)path +{ + NSMutableDictionary *props = [itemData objectForKey:path]; + [props removeAllObjects]; +} + +/* NSOutlineView data source */ + +- (NSInteger)outlineView:(NSOutlineView *)outlineView numberOfChildrenOfItem:(id)item +{ + return [self intProperty:CHILDREN_COUNT_PROPERTY valueAtPath:(NSIndexPath *)item]; +} + +- (id)outlineView:(NSOutlineView *)outlineView child:(NSInteger)index ofItem:(id)item +{ + NSIndexPath *parent = item; + NSIndexPath *path = parent == nil ? [NSIndexPath indexPathWithIndex:index] : [parent indexPathByAddingIndex:index]; + return [self internalizedPath:path]; +} + +- (BOOL)outlineView:(NSOutlineView *)theOutlineView isItemExpandable:(id)item +{ + return [self outlineView:[self view] numberOfChildrenOfItem:item] > 0; +} + +- (BOOL)outlineView:(NSOutlineView *)outlineView shouldEditTableColumn:(NSTableColumn *)column item:(id)item +{ + return [[self model] canEditProperty:[column identifier] atPath:p2a((NSIndexPath *)item)]; +} + +- (id)outlineView:(NSOutlineView *)outlineView objectValueForTableColumn:(NSTableColumn *)column byItem:(id)item +{ + return [self property:[column identifier] valueAtPath:(NSIndexPath *)item]; +} + +- (void)outlineView:(NSOutlineView *)outlineView setObjectValue:(id)value forTableColumn:(NSTableColumn *)column byItem:(id)item +{ + [self setProperty:[column identifier] value:value atPath:(NSIndexPath *)item]; +} + +/* We need to change the model selection at both IsChanging and DidChange. We need to set the +model selection at IsChanging before of the arrow clicking. The action launched by this little arrow +is performed before DidChange. However, when using the arrow to change the selection, IsChanging is +never called +*/ +- (void)outlineViewSelectionIsChanging:(NSNotification *)notification +{ + [self setPySelection]; +} + +- (void)outlineViewSelectionDidChange:(NSNotification *)notification +{ + [self setPySelection]; +} + +/* HSOutlineView delegate */ +- (NSIndexPath *)selectedIndexPath +{ + NSArray *paths = [self selectedIndexPaths]; + if ([paths count] > 0) { + return [paths objectAtIndex:0]; + } + else { + return nil; + } +} + +- (NSString *)dataForCopyToPasteboard +{ + return nil; +} + +- (void)outlineViewDidEndEditing:(HSOutlineView *)outlineView +{ + [[self model] saveEdits]; +} + +- (void)outlineViewWasDoubleClicked:(HSOutlineView *)outlineView +{ +} + +- (void)outlineViewCancelsEdition:(HSOutlineView *)outlineView +{ + [[self model] cancelEdits]; +} +@end \ No newline at end of file diff --git a/cocoalib/controllers/HSPopUpList.h b/cocoalib/controllers/HSPopUpList.h new file mode 100644 index 00000000..6797c771 --- /dev/null +++ b/cocoalib/controllers/HSPopUpList.h @@ -0,0 +1,23 @@ +/* +Copyright 2013 Hardcoded Software (http://www.hardcoded.net) + +This software is licensed under the "BSD" License as described in the "LICENSE" file, +which should be included with this package. The terms are also available at +http://www.hardcoded.net/licenses/bsd_license +*/ + +#import +#import +#import "HSGUIController.h" +#import "PySelectableList.h" + +@interface HSPopUpList : HSGUIController {} +- (id)initWithPyRef:(PyObject *)aPyRef popupView:(NSPopUpButton *)aPopupView; +- (NSPopUpButton *)view; +- (void)setView:(NSPopUpButton *)aPopupView; +- (PySelectableList *)model; + +- (void)popupViewSelectionChanged; +- (void)refresh; +- (void)updateSelection; +@end \ No newline at end of file diff --git a/cocoalib/controllers/HSPopUpList.m b/cocoalib/controllers/HSPopUpList.m new file mode 100644 index 00000000..a0b23c16 --- /dev/null +++ b/cocoalib/controllers/HSPopUpList.m @@ -0,0 +1,60 @@ +/* +Copyright 2013 Hardcoded Software (http://www.hardcoded.net) + +This software is licensed under the "BSD" License as described in the "LICENSE" file, +which should be included with this package. The terms are also available at +http://www.hardcoded.net/licenses/bsd_license +*/ + +#import "HSPopUpList.h" +#import "Utils.h" + +@implementation HSPopUpList +- (id)initWithPyRef:(PyObject *)aPyRef popupView:(NSPopUpButton *)aPopupView +{ + self = [super initWithPyRef:aPyRef wrapperClass:[PySelectableList class] + callbackClassName:@"SelectableListView" view:aPopupView]; + return self; +} + +- (NSPopUpButton *)view +{ + return (NSPopUpButton *)view; +} + +- (void)setView:(NSPopUpButton *)aPopupView +{ + if ([self view] != nil) { + [[self view] setTarget:nil]; + } + [super setView:aPopupView]; + if (aPopupView != nil) { + [aPopupView setAction:@selector(popupViewSelectionChanged)]; + [aPopupView setTarget:self]; + [self refresh]; + } +} + +- (PySelectableList *)model +{ + return (PySelectableList *)model; +} + +- (void)popupViewSelectionChanged +{ + [[self model] selectIndex:[[self view] indexOfSelectedItem]]; +} + +/* model --> view */ +- (void)refresh +{ + [[self view] removeAllItems]; + [[self view] addItemsWithTitles:[[self model] items]]; + [self updateSelection]; +} + +- (void)updateSelection +{ + [[self view] selectItemAtIndex:[[self model] selectedIndex]]; +} +@end \ No newline at end of file diff --git a/cocoalib/controllers/HSSelectableList.h b/cocoalib/controllers/HSSelectableList.h new file mode 100644 index 00000000..a8e3127f --- /dev/null +++ b/cocoalib/controllers/HSSelectableList.h @@ -0,0 +1,24 @@ +/* +Copyright 2013 Hardcoded Software (http://www.hardcoded.net) + +This software is licensed under the "BSD" License as described in the "LICENSE" file, +which should be included with this package. The terms are also available at +http://www.hardcoded.net/licenses/bsd_license +*/ + +#import +#import "HSGUIController.h" +#import "PySelectableList.h" + +@interface HSSelectableList : HSGUIController +{ + NSArray *items; +} +- (id)initWithPyRef:(PyObject *)aPyRef wrapperClass:(Class)aWrapperClass callbackClassName:(NSString *)aCallbackClassName view:(NSTableView *)aTableView; +- (id)initWithPyRef:(PyObject *)aPyRef tableView:(NSTableView *)aTableView; +- (NSTableView *)view; +- (void)setView:(NSTableView *)aTableView; +- (PySelectableList *)model; + +- (void)refresh; +@end diff --git a/cocoalib/controllers/HSSelectableList.m b/cocoalib/controllers/HSSelectableList.m new file mode 100644 index 00000000..77b981d5 --- /dev/null +++ b/cocoalib/controllers/HSSelectableList.m @@ -0,0 +1,107 @@ +/* +Copyright 2013 Hardcoded Software (http://www.hardcoded.net) + +This software is licensed under the "BSD" License as described in the "LICENSE" file, +which should be included with this package. The terms are also available at +http://www.hardcoded.net/licenses/bsd_license +*/ + +#import "HSSelectableList.h" +#import "Utils.h" + +@implementation HSSelectableList +- (id)initWithPyRef:(PyObject *)aPyRef wrapperClass:(Class)aWrapperClass callbackClassName:(NSString *)aCallbackClassName view:(NSTableView *)aTableView; +{ + self = [super initWithPyRef:aPyRef wrapperClass:aWrapperClass callbackClassName:aCallbackClassName view:aTableView]; + return self; +} + +- (id)initWithPyRef:(PyObject *)aPyRef tableView:(NSTableView *)aTableView +{ + self = [self initWithPyRef:aPyRef wrapperClass:[PySelectableList class] callbackClassName:@"SelectableListView" view:aTableView]; + return self; +} + +- (void)dealloc +{ + [items release]; + [super dealloc]; +} + +- (PySelectableList *)model +{ + return (PySelectableList *)model; +} + +- (NSTableView *)view +{ + return (NSTableView *)view; +} + +- (void)setView:(NSTableView *)aTableView +{ + if ([self view] != nil) { + [[self view] setDataSource:nil]; + [[self view] setDelegate:nil]; + } + [super setView:aTableView]; + if (aTableView != nil) { + [aTableView setDataSource:self]; + [aTableView setDelegate:self]; + [self refresh]; + } +} + +/* Private */ +- (void)setPySelection +{ + NSArray *selection = [Utils indexSet2Array:[[self view] selectedRowIndexes]]; + NSArray *pyselection = [[self model] selectedIndexes]; + if (![selection isEqualTo:pyselection]) { + [[self model] selectIndexes:selection]; + } +} + +- (void)setViewSelection +{ + NSIndexSet *selection = [Utils array2IndexSet:[[self model] selectedIndexes]]; + [[self view] selectRowIndexes:selection byExtendingSelection:NO]; +} + +/* Data source */ +- (NSInteger)numberOfRowsInTableView:(NSTableView *)tableView +{ + return [items count]; +} + +- (id)tableView:(NSTableView *)tableView objectValueForTableColumn:(NSTableColumn *)column row:(NSInteger)row +{ + // Cocoa's typeselect mechanism can call us with an out-of-range row + if (row >= [items count]) { + return @""; + } + return [items objectAtIndex:row]; +} + +- (void)tableViewSelectionDidChange:(NSNotification *)notification +{ + [self setPySelection]; +} + +/* Public */ + +- (void)refresh +{ + // If we just deleted the last item, we want to update the selection before we reload + [items release]; + items = [[[self model] items] retain]; + [[self view] reloadData]; + [self setViewSelection]; +} + +- (void)updateSelection +{ + NSIndexSet *selection = [NSIndexSet indexSetWithIndex:[[self model] selectedIndex]]; + [[self view] selectRowIndexes:selection byExtendingSelection:NO]; +} +@end diff --git a/cocoalib/controllers/HSTable.h b/cocoalib/controllers/HSTable.h new file mode 100644 index 00000000..9454b30f --- /dev/null +++ b/cocoalib/controllers/HSTable.h @@ -0,0 +1,32 @@ +/* +Copyright 2013 Hardcoded Software (http://www.hardcoded.net) + +This software is licensed under the "BSD" License as described in the "LICENSE" file, +which should be included with this package. The terms are also available at +http://www.hardcoded.net/licenses/bsd_license +*/ + +#import +#import "HSGUIController.h" +#import "HSColumns.h" +#import "PyTable.h" + +@interface HSTable : HSGUIController +{ + HSColumns *columns; +} +- (id)initWithModel:(PyTable *)aModel tableView:(NSTableView *)aTableView; +- (id)initWithPyRef:(PyObject *)aPyRef wrapperClass:(Class)aWrapperClass callbackClassName:(NSString *)aCallbackClassName view:(NSTableView *)aTableView; +- (id)initWithPyRef:(PyObject *)aPyRef tableView:(NSTableView *)aTableView; + +/* Virtual */ +- (PyTable *)model; +- (NSTableView *)view; +- (void)setView:(NSTableView *)aTableView; + +/* Public */ +- (HSColumns *)columns; +- (void)refresh; +- (void)showSelectedRow; +- (void)updateSelection; +@end diff --git a/cocoalib/controllers/HSTable.m b/cocoalib/controllers/HSTable.m new file mode 100644 index 00000000..694dd183 --- /dev/null +++ b/cocoalib/controllers/HSTable.m @@ -0,0 +1,136 @@ +/* +Copyright 2013 Hardcoded Software (http://www.hardcoded.net) + +This software is licensed under the "BSD" License as described in the "LICENSE" file, +which should be included with this package. The terms are also available at +http://www.hardcoded.net/licenses/bsd_license +*/ + +#import "HSTable.h" +#import "Utils.h" + +@implementation HSTable +- (id)initWithModel:(PyTable *)aModel tableView:(NSTableView *)aTableView +{ + self = [super initWithModel:aModel view:aTableView]; + columns = [[HSColumns alloc] initWithPyRef:[[self model] columns] tableView:aTableView]; + return self; +} + +- (id)initWithPyRef:(PyObject *)aPyRef wrapperClass:(Class)aWrapperClass callbackClassName:(NSString *)aCallbackClassName view:(NSTableView *)aTableView +{ + self = [super initWithPyRef:aPyRef wrapperClass:aWrapperClass callbackClassName:aCallbackClassName view:aTableView]; + columns = [[HSColumns alloc] initWithPyRef:[[self model] columns] tableView:aTableView]; + return self; +} + +- (id)initWithPyRef:(PyObject *)aPyRef tableView:(NSTableView *)aTableView +{ + return [self initWithPyRef:aPyRef wrapperClass:[PyTable class] callbackClassName:@"TableView" view:aTableView]; +} + +- (void)dealloc +{ + [columns release]; + [super dealloc]; +} + +/* Private */ +- (void)setPySelection +{ + NSArray *selection = [Utils indexSet2Array:[[self view] selectedRowIndexes]]; + NSArray *pyselection = [[self model] selectedRows]; + if (![selection isEqualTo:pyselection]) + [[self model] selectRows:selection]; +} + +- (void)setViewSelection +{ + NSIndexSet *selection = [Utils array2IndexSet:[[self model] selectedRows]]; + [[self view] selectRowIndexes:selection byExtendingSelection:NO]; +} + +/* HSGUIController */ +- (PyTable *)model +{ + return (PyTable *)model; +} + +- (NSTableView *)view +{ + return (NSTableView *)view; +} + +- (void)setView:(NSTableView *)aTableView +{ + if ([self view] != nil) { + [[self view] setDataSource:nil]; + [[self view] setDelegate:nil]; + } + [super setView:aTableView]; + if (aTableView != nil) { + [aTableView setDataSource:self]; + [aTableView setDelegate:self]; + } +} + +/* Data source */ +- (NSInteger)numberOfRowsInTableView:(NSTableView *)tableView +{ + return [[self model] numberOfRows]; +} + +- (id)tableView:(NSTableView *)tableView objectValueForTableColumn:(NSTableColumn *)column row:(NSInteger)row +{ + // Cocoa's typeselect mechanism can call us with an out-of-range row + if (row >= [[self model] numberOfRows]) { + return @""; + } + return [[self model] valueForColumn:[column identifier] row:row]; +} + +/* NSTableView Delegate */ +- (void)tableView:(NSTableView *)aTableView didClickTableColumn:(NSTableColumn *)column +{ + if ([[aTableView sortDescriptors] count] == 0) { + return; + } + NSSortDescriptor *sd = [[aTableView sortDescriptors] objectAtIndex:0]; + [[self model] sortByColumn:[sd key] desc:![sd ascending]]; +} + +// See HSOutline.outlineViewSelectionIsChanging: to know why we update selection in both notifs +- (void)tableViewSelectionIsChanging:(NSNotification *)notification +{ + [self setPySelection]; +} + +- (void)tableViewSelectionDidChange:(NSNotification *)notification +{ + [self setPySelection]; +} + +/* Public */ +- (HSColumns *)columns +{ + return columns; +} + +- (void)refresh +{ + // If we just deleted the last item, we want to update the selection before we reload + [self setViewSelection]; + [[self view] reloadData]; + [self setViewSelection]; +} + +- (void)showSelectedRow +{ + [[self view] scrollRowToVisible:[[self view] selectedRow]]; +} + +- (void)updateSelection +{ + [self setViewSelection]; +} +@end diff --git a/cocoalib/controllers/HSTextField.h b/cocoalib/controllers/HSTextField.h new file mode 100644 index 00000000..b78daa8c --- /dev/null +++ b/cocoalib/controllers/HSTextField.h @@ -0,0 +1,21 @@ +/* +Copyright 2013 Hardcoded Software (http://www.hardcoded.net) + +This software is licensed under the "BSD" License as described in the "LICENSE" file, +which should be included with this package. The terms are also available at +http://www.hardcoded.net/licenses/bsd_license +*/ + +#import +#import +#import "HSGUIController.h" +#import "PyTextField.h" + +@interface HSTextField : HSGUIController {} +- (id)initWithPyRef:(PyObject *)aPyRef view:(NSTextField *)aView; +- (NSTextField *)view; +- (void)setView:(NSTextField *)aView; +- (PyTextField *)model; + +- (void)refresh; +@end \ No newline at end of file diff --git a/cocoalib/controllers/HSTextField.m b/cocoalib/controllers/HSTextField.m new file mode 100644 index 00000000..4bea9a7b --- /dev/null +++ b/cocoalib/controllers/HSTextField.m @@ -0,0 +1,53 @@ +/* +Copyright 2013 Hardcoded Software (http://www.hardcoded.net) + +This software is licensed under the "BSD" License as described in the "LICENSE" file, +which should be included with this package. The terms are also available at +http://www.hardcoded.net/licenses/bsd_license +*/ + +#import "HSTextField.h" +#import "Utils.h" + +@implementation HSTextField +- (id)initWithPyRef:(PyObject *)aPyRef view:(NSTextField *)aView +{ + self = [super initWithPyRef:aPyRef wrapperClass:[PyTextField class] + callbackClassName:@"GUIObjectView" view:aView]; + return self; +} + +- (NSTextField *)view +{ + return (NSTextField *)view; +} + +- (void)setView:(NSTextField *)aView +{ + if ([self view] != nil) { + [[self view] setDelegate:nil]; + } + [super setView:aView]; + if (aView != nil) { + [aView setDelegate:self]; + [self refresh]; + } +} + +- (PyTextField *)model +{ + return (PyTextField *)model; +} + +/* Delegate */ +- (void)controlTextDidEndEditing:(NSNotification *)aNotification +{ + [[self model] setText:[[self view] stringValue]]; +} + +/* model --> view */ +- (void)refresh +{ + [[self view] setStringValue:[[self model] text]]; +} +@end \ No newline at end of file diff --git a/cocoalib/en.lproj/cocoalib.strings b/cocoalib/en.lproj/cocoalib.strings new file mode 100644 index 00000000..7ce758c1 --- /dev/null +++ b/cocoalib/en.lproj/cocoalib.strings @@ -0,0 +1,28 @@ + +"%@ is Fairware" = "%@ is Fairware"; +"Although the application should continue to run after this error, it may be in an instable state, so it is recommended that you restart the application." = "Although the application should continue to run after this error, it may be in an instable state, so it is recommended that you restart the application."; +"Buy" = "Buy"; +"Cancel" = "Cancel"; +"Clear List" = "Clear List"; +"Contribute" = "Contribute"; +"Don't Send" = "Don't Send"; +"Enter Key" = "Enter Key"; +"Enter your key" = "Enter your key"; +"Error Report" = "Error Report"; +"Fairware?" = "Fairware?"; +"No" = "No"; +"OK" = "OK"; +"Please wait..." = "Please wait..."; +"Register" = "Register"; +"Registration e-mail:" = "Registration e-mail:"; +"Registration key:" = "Registration key:"; +"Send" = "Send"; +"Something went wrong. Would you like to send the error report to Hardcoded Software?" = "Something went wrong. Would you like to send the error report to Hardcoded Software?"; +"Status: Working..." = "Status: Working..."; +"Submit" = "Submit"; +"This app is registered, thanks!" = "This app is registered, thanks!"; +"Try" = "Try"; +"Type the key you received when you contributed to %@, as well as the e-mail used as a reference for the purchase." = "Type the key you received when you contributed to %@, as well as the e-mail used as a reference for the purchase."; +"Work in progress, please wait." = "Work in progress, please wait."; +"Work in progress..." = "Work in progress..."; +"Yes" = "Yes"; diff --git a/cocoalib/locale/cocoalib.pot b/cocoalib/locale/cocoalib.pot new file mode 100644 index 00000000..6490ccdd --- /dev/null +++ b/cocoalib/locale/cocoalib.pot @@ -0,0 +1,119 @@ +# +msgid "" +msgstr "" +"Content-Type: text/plain; charset=utf-8\n" +"Content-Transfer-Encoding: utf-8\n" + +#: cocoalib/en.lproj/cocoalib.strings:0 +msgid "%@ is Fairware" +msgstr "" + +#: cocoalib/en.lproj/cocoalib.strings:0 +msgid "" +"Although the application should continue to run after this error, it may be " +"in an instable state, so it is recommended that you restart the application." +msgstr "" + +#: cocoalib/en.lproj/cocoalib.strings:0 +msgid "Buy" +msgstr "" + +#: cocoalib/en.lproj/cocoalib.strings:0 +msgid "Cancel" +msgstr "" + +#: cocoalib/en.lproj/cocoalib.strings:0 +msgid "Clear List" +msgstr "" + +#: cocoalib/en.lproj/cocoalib.strings:0 +msgid "Contribute" +msgstr "" + +#: cocoalib/en.lproj/cocoalib.strings:0 +msgid "Don't Send" +msgstr "" + +#: cocoalib/en.lproj/cocoalib.strings:0 +msgid "Enter Key" +msgstr "" + +#: cocoalib/en.lproj/cocoalib.strings:0 +msgid "Enter your key" +msgstr "" + +#: cocoalib/en.lproj/cocoalib.strings:0 +msgid "Error Report" +msgstr "" + +#: cocoalib/en.lproj/cocoalib.strings:0 +msgid "Fairware?" +msgstr "" + +#: cocoalib/en.lproj/cocoalib.strings:0 +msgid "No" +msgstr "" + +#: cocoalib/en.lproj/cocoalib.strings:0 +msgid "OK" +msgstr "" + +#: cocoalib/en.lproj/cocoalib.strings:0 +msgid "Please wait..." +msgstr "" + +#: cocoalib/en.lproj/cocoalib.strings:0 +msgid "Register" +msgstr "" + +#: cocoalib/en.lproj/cocoalib.strings:0 +msgid "Registration e-mail:" +msgstr "" + +#: cocoalib/en.lproj/cocoalib.strings:0 +msgid "Registration key:" +msgstr "" + +#: cocoalib/en.lproj/cocoalib.strings:0 +msgid "Send" +msgstr "" + +#: cocoalib/en.lproj/cocoalib.strings:0 +msgid "" +"Something went wrong. Would you like to send the error report to Hardcoded " +"Software?" +msgstr "" + +#: cocoalib/en.lproj/cocoalib.strings:0 +msgid "Status: Working..." +msgstr "" + +#: cocoalib/en.lproj/cocoalib.strings:0 +msgid "Submit" +msgstr "" + +#: cocoalib/en.lproj/cocoalib.strings:0 +msgid "This app is registered, thanks!" +msgstr "" + +#: cocoalib/en.lproj/cocoalib.strings:0 +msgid "Try" +msgstr "" + +#: cocoalib/en.lproj/cocoalib.strings:0 +msgid "" +"Type the key you received when you contributed to %@, as well as the e-mail " +"used as a reference for the purchase." +msgstr "" + +#: cocoalib/en.lproj/cocoalib.strings:0 +msgid "Work in progress, please wait." +msgstr "" + +#: cocoalib/en.lproj/cocoalib.strings:0 +msgid "Work in progress..." +msgstr "" + +#: cocoalib/en.lproj/cocoalib.strings:0 +msgid "Yes" +msgstr "" diff --git a/cocoalib/locale/cs/LC_MESSAGES/cocoalib.po b/cocoalib/locale/cs/LC_MESSAGES/cocoalib.po new file mode 100644 index 00000000..810451cb --- /dev/null +++ b/cocoalib/locale/cs/LC_MESSAGES/cocoalib.po @@ -0,0 +1,125 @@ +# +# Translators: +msgid "" +msgstr "" +"Project-Id-Version: hscommon\n" +"PO-Revision-Date: 2013-04-28 18:26+0000\n" +"Last-Translator: hsoft \n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: utf-8\n" +"Language: cs\n" +"Plural-Forms: nplurals=3; plural=(n==1) ? 0 : (n>=2 && n<=4) ? 1 : 2;\n" + +#: cocoalib/en.lproj/cocoalib.strings:0 +msgid "%@ is Fairware" +msgstr "%@ is Fairware" + +#: cocoalib/en.lproj/cocoalib.strings:0 +msgid "" +"Although the application should continue to run after this error, it may be " +"in an instable state, so it is recommended that you restart the application." +msgstr "" + +#: cocoalib/en.lproj/cocoalib.strings:0 +msgid "Buy" +msgstr "Buy" + +#: cocoalib/en.lproj/cocoalib.strings:0 +msgid "Cancel" +msgstr "Cancel" + +#: cocoalib/en.lproj/cocoalib.strings:0 +msgid "Clear List" +msgstr "" + +#: cocoalib/en.lproj/cocoalib.strings:0 +msgid "Contribute" +msgstr "Contribute" + +#: cocoalib/en.lproj/cocoalib.strings:0 +msgid "Don't Send" +msgstr "Don't Send" + +#: cocoalib/en.lproj/cocoalib.strings:0 +msgid "Enter Key" +msgstr "Enter Key" + +#: cocoalib/en.lproj/cocoalib.strings:0 +msgid "Enter your key" +msgstr "Enter your key" + +#: cocoalib/en.lproj/cocoalib.strings:0 +msgid "Error Report" +msgstr "" + +#: cocoalib/en.lproj/cocoalib.strings:0 +msgid "Fairware?" +msgstr "Fairware?" + +#: cocoalib/en.lproj/cocoalib.strings:0 +msgid "No" +msgstr "" + +#: cocoalib/en.lproj/cocoalib.strings:0 +msgid "OK" +msgstr "" + +#: cocoalib/en.lproj/cocoalib.strings:0 +msgid "Please wait..." +msgstr "" + +#: cocoalib/en.lproj/cocoalib.strings:0 +msgid "Register" +msgstr "Register" + +#: cocoalib/en.lproj/cocoalib.strings:0 +msgid "Registration e-mail:" +msgstr "" + +#: cocoalib/en.lproj/cocoalib.strings:0 +msgid "Registration key:" +msgstr "Registration key:" + +#: cocoalib/en.lproj/cocoalib.strings:0 +msgid "Send" +msgstr "Send" + +#: cocoalib/en.lproj/cocoalib.strings:0 +msgid "" +"Something went wrong. Would you like to send the error report to Hardcoded " +"Software?" +msgstr "Something went wrong. Would you like to send the error report to Hardcoded Software?" + +#: cocoalib/en.lproj/cocoalib.strings:0 +msgid "Status: Working..." +msgstr "" + +#: cocoalib/en.lproj/cocoalib.strings:0 +msgid "Submit" +msgstr "Submit" + +#: cocoalib/en.lproj/cocoalib.strings:0 +msgid "This app is registered, thanks!" +msgstr "This app is registered, thanks!" + +#: cocoalib/en.lproj/cocoalib.strings:0 +msgid "Try" +msgstr "Try" + +#: cocoalib/en.lproj/cocoalib.strings:0 +msgid "" +"Type the key you received when you contributed to %@, as well as the e-mail " +"used as a reference for the purchase." +msgstr "Type the key you received when you contributed to %@, as well as the e-mail used as a reference for the purchase." + +#: cocoalib/en.lproj/cocoalib.strings:0 +msgid "Work in progress, please wait." +msgstr "" + +#: cocoalib/en.lproj/cocoalib.strings:0 +msgid "Work in progress..." +msgstr "" + +#: cocoalib/en.lproj/cocoalib.strings:0 +msgid "Yes" +msgstr "" diff --git a/cocoalib/locale/de/LC_MESSAGES/cocoalib.po b/cocoalib/locale/de/LC_MESSAGES/cocoalib.po new file mode 100644 index 00000000..816ad6c8 --- /dev/null +++ b/cocoalib/locale/de/LC_MESSAGES/cocoalib.po @@ -0,0 +1,125 @@ +# +# Translators: +msgid "" +msgstr "" +"Project-Id-Version: hscommon\n" +"PO-Revision-Date: 2013-04-28 18:26+0000\n" +"Last-Translator: hsoft \n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: utf-8\n" +"Language: de\n" +"Plural-Forms: nplurals=2; plural=(n != 1);\n" + +#: cocoalib/en.lproj/cocoalib.strings:0 +msgid "%@ is Fairware" +msgstr "%@ is Fairware" + +#: cocoalib/en.lproj/cocoalib.strings:0 +msgid "" +"Although the application should continue to run after this error, it may be " +"in an instable state, so it is recommended that you restart the application." +msgstr "" + +#: cocoalib/en.lproj/cocoalib.strings:0 +msgid "Buy" +msgstr "Buy" + +#: cocoalib/en.lproj/cocoalib.strings:0 +msgid "Cancel" +msgstr "Abbrechen" + +#: cocoalib/en.lproj/cocoalib.strings:0 +msgid "Clear List" +msgstr "" + +#: cocoalib/en.lproj/cocoalib.strings:0 +msgid "Contribute" +msgstr "Spenden" + +#: cocoalib/en.lproj/cocoalib.strings:0 +msgid "Don't Send" +msgstr "Don't Send" + +#: cocoalib/en.lproj/cocoalib.strings:0 +msgid "Enter Key" +msgstr "Registrieren" + +#: cocoalib/en.lproj/cocoalib.strings:0 +msgid "Enter your key" +msgstr "Schlüssel eingeben" + +#: cocoalib/en.lproj/cocoalib.strings:0 +msgid "Error Report" +msgstr "" + +#: cocoalib/en.lproj/cocoalib.strings:0 +msgid "Fairware?" +msgstr "Fairware?" + +#: cocoalib/en.lproj/cocoalib.strings:0 +msgid "No" +msgstr "" + +#: cocoalib/en.lproj/cocoalib.strings:0 +msgid "OK" +msgstr "" + +#: cocoalib/en.lproj/cocoalib.strings:0 +msgid "Please wait..." +msgstr "" + +#: cocoalib/en.lproj/cocoalib.strings:0 +msgid "Register" +msgstr "Register" + +#: cocoalib/en.lproj/cocoalib.strings:0 +msgid "Registration e-mail:" +msgstr "" + +#: cocoalib/en.lproj/cocoalib.strings:0 +msgid "Registration key:" +msgstr "Registrierungsschlüssel:" + +#: cocoalib/en.lproj/cocoalib.strings:0 +msgid "Send" +msgstr "Send" + +#: cocoalib/en.lproj/cocoalib.strings:0 +msgid "" +"Something went wrong. Would you like to send the error report to Hardcoded " +"Software?" +msgstr "Something went wrong. Would you like to send the error report to Hardcoded Software?" + +#: cocoalib/en.lproj/cocoalib.strings:0 +msgid "Status: Working..." +msgstr "" + +#: cocoalib/en.lproj/cocoalib.strings:0 +msgid "Submit" +msgstr "Abschicken" + +#: cocoalib/en.lproj/cocoalib.strings:0 +msgid "This app is registered, thanks!" +msgstr "This app is registered, thanks!" + +#: cocoalib/en.lproj/cocoalib.strings:0 +msgid "Try" +msgstr "Try" + +#: cocoalib/en.lproj/cocoalib.strings:0 +msgid "" +"Type the key you received when you contributed to %@, as well as the e-mail " +"used as a reference for the purchase." +msgstr "Geben Sie den empfangenen Schlüssel und die E-Mail-Adresse als Referenz für den Kauf an, wenn Sie für %@ gespendet haben." + +#: cocoalib/en.lproj/cocoalib.strings:0 +msgid "Work in progress, please wait." +msgstr "" + +#: cocoalib/en.lproj/cocoalib.strings:0 +msgid "Work in progress..." +msgstr "" + +#: cocoalib/en.lproj/cocoalib.strings:0 +msgid "Yes" +msgstr "" diff --git a/cocoalib/locale/es/LC_MESSAGES/cocoalib.po b/cocoalib/locale/es/LC_MESSAGES/cocoalib.po new file mode 100755 index 00000000..ef0767d7 --- /dev/null +++ b/cocoalib/locale/es/LC_MESSAGES/cocoalib.po @@ -0,0 +1,125 @@ +# +# Translators: +msgid "" +msgstr "" +"Project-Id-Version: hscommon\n" +"PO-Revision-Date: 2013-04-28 18:26+0000\n" +"Last-Translator: hsoft \n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: utf-8\n" +"Language: es\n" +"Plural-Forms: nplurals=2; plural=(n != 1);\n" + +#: cocoalib/en.lproj/cocoalib.strings:0 +msgid "%@ is Fairware" +msgstr "%@ es Fairware" + +#: cocoalib/en.lproj/cocoalib.strings:0 +msgid "" +"Although the application should continue to run after this error, it may be " +"in an instable state, so it is recommended that you restart the application." +msgstr "Aunque la aplicación debería continuar funcionado tras el fallo, sin embargo podría volverse inestable. Se recomienda reiniciar la aplicación." + +#: cocoalib/en.lproj/cocoalib.strings:0 +msgid "Buy" +msgstr "Comprar" + +#: cocoalib/en.lproj/cocoalib.strings:0 +msgid "Cancel" +msgstr "Cancelar" + +#: cocoalib/en.lproj/cocoalib.strings:0 +msgid "Clear List" +msgstr "Limpiar lista" + +#: cocoalib/en.lproj/cocoalib.strings:0 +msgid "Contribute" +msgstr "Donar" + +#: cocoalib/en.lproj/cocoalib.strings:0 +msgid "Don't Send" +msgstr "No envíar" + +#: cocoalib/en.lproj/cocoalib.strings:0 +msgid "Enter Key" +msgstr "Introducir clave" + +#: cocoalib/en.lproj/cocoalib.strings:0 +msgid "Enter your key" +msgstr "Introduzca su clave" + +#: cocoalib/en.lproj/cocoalib.strings:0 +msgid "Error Report" +msgstr "Informe de error" + +#: cocoalib/en.lproj/cocoalib.strings:0 +msgid "Fairware?" +msgstr "¿Fairware?" + +#: cocoalib/en.lproj/cocoalib.strings:0 +msgid "No" +msgstr "No" + +#: cocoalib/en.lproj/cocoalib.strings:0 +msgid "OK" +msgstr "Aceptar" + +#: cocoalib/en.lproj/cocoalib.strings:0 +msgid "Please wait..." +msgstr "Por favor, espere..." + +#: cocoalib/en.lproj/cocoalib.strings:0 +msgid "Register" +msgstr "Registrar" + +#: cocoalib/en.lproj/cocoalib.strings:0 +msgid "Registration e-mail:" +msgstr "Correo electrónico de registro:" + +#: cocoalib/en.lproj/cocoalib.strings:0 +msgid "Registration key:" +msgstr "Clave de registro" + +#: cocoalib/en.lproj/cocoalib.strings:0 +msgid "Send" +msgstr "Enviar" + +#: cocoalib/en.lproj/cocoalib.strings:0 +msgid "" +"Something went wrong. Would you like to send the error report to Hardcoded " +"Software?" +msgstr "Se ha producido un error. ¿Desea enviar un informe de error a Harcoded Software?" + +#: cocoalib/en.lproj/cocoalib.strings:0 +msgid "Status: Working..." +msgstr "Estado: procesando..." + +#: cocoalib/en.lproj/cocoalib.strings:0 +msgid "Submit" +msgstr "Enviar" + +#: cocoalib/en.lproj/cocoalib.strings:0 +msgid "This app is registered, thanks!" +msgstr "La aplicación está registrada. ¡Gracias!" + +#: cocoalib/en.lproj/cocoalib.strings:0 +msgid "Try" +msgstr "Probar" + +#: cocoalib/en.lproj/cocoalib.strings:0 +msgid "" +"Type the key you received when you contributed to %@, as well as the e-mail " +"used as a reference for the purchase." +msgstr "Escriba la clave que recibió al donar a %@, así como el correo electrónico que usó en el proceso." + +#: cocoalib/en.lproj/cocoalib.strings:0 +msgid "Work in progress, please wait." +msgstr "En proceso, por favor, espere." + +#: cocoalib/en.lproj/cocoalib.strings:0 +msgid "Work in progress..." +msgstr "En proceso..." + +#: cocoalib/en.lproj/cocoalib.strings:0 +msgid "Yes" +msgstr "Sí" diff --git a/cocoalib/locale/fr/LC_MESSAGES/cocoalib.po b/cocoalib/locale/fr/LC_MESSAGES/cocoalib.po new file mode 100644 index 00000000..33820567 --- /dev/null +++ b/cocoalib/locale/fr/LC_MESSAGES/cocoalib.po @@ -0,0 +1,125 @@ +# +# Translators: +msgid "" +msgstr "" +"Project-Id-Version: hscommon\n" +"PO-Revision-Date: 2013-04-28 18:26+0000\n" +"Last-Translator: hsoft \n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: utf-8\n" +"Language: fr\n" +"Plural-Forms: nplurals=2; plural=(n > 1);\n" + +#: cocoalib/en.lproj/cocoalib.strings:0 +msgid "%@ is Fairware" +msgstr "%@ est Fairware" + +#: cocoalib/en.lproj/cocoalib.strings:0 +msgid "" +"Although the application should continue to run after this error, it may be " +"in an instable state, so it is recommended that you restart the application." +msgstr "" + +#: cocoalib/en.lproj/cocoalib.strings:0 +msgid "Buy" +msgstr "Acheter" + +#: cocoalib/en.lproj/cocoalib.strings:0 +msgid "Cancel" +msgstr "Annuler" + +#: cocoalib/en.lproj/cocoalib.strings:0 +msgid "Clear List" +msgstr "" + +#: cocoalib/en.lproj/cocoalib.strings:0 +msgid "Contribute" +msgstr "Contribuer" + +#: cocoalib/en.lproj/cocoalib.strings:0 +msgid "Don't Send" +msgstr "Ignorer" + +#: cocoalib/en.lproj/cocoalib.strings:0 +msgid "Enter Key" +msgstr "Enregistrer" + +#: cocoalib/en.lproj/cocoalib.strings:0 +msgid "Enter your key" +msgstr "Entrez votre clé" + +#: cocoalib/en.lproj/cocoalib.strings:0 +msgid "Error Report" +msgstr "" + +#: cocoalib/en.lproj/cocoalib.strings:0 +msgid "Fairware?" +msgstr "Fairware?" + +#: cocoalib/en.lproj/cocoalib.strings:0 +msgid "No" +msgstr "" + +#: cocoalib/en.lproj/cocoalib.strings:0 +msgid "OK" +msgstr "" + +#: cocoalib/en.lproj/cocoalib.strings:0 +msgid "Please wait..." +msgstr "" + +#: cocoalib/en.lproj/cocoalib.strings:0 +msgid "Register" +msgstr "Enregistrer" + +#: cocoalib/en.lproj/cocoalib.strings:0 +msgid "Registration e-mail:" +msgstr "" + +#: cocoalib/en.lproj/cocoalib.strings:0 +msgid "Registration key:" +msgstr "Clé d'enregistrement:" + +#: cocoalib/en.lproj/cocoalib.strings:0 +msgid "Send" +msgstr "Envoyer" + +#: cocoalib/en.lproj/cocoalib.strings:0 +msgid "" +"Something went wrong. Would you like to send the error report to Hardcoded " +"Software?" +msgstr "Il y a eu une erreur, voulez vous envoyer le rapport à Hardcoded Software?" + +#: cocoalib/en.lproj/cocoalib.strings:0 +msgid "Status: Working..." +msgstr "" + +#: cocoalib/en.lproj/cocoalib.strings:0 +msgid "Submit" +msgstr "Soumettre" + +#: cocoalib/en.lproj/cocoalib.strings:0 +msgid "This app is registered, thanks!" +msgstr "L'application est enregistrée, merci!" + +#: cocoalib/en.lproj/cocoalib.strings:0 +msgid "Try" +msgstr "Essayer" + +#: cocoalib/en.lproj/cocoalib.strings:0 +msgid "" +"Type the key you received when you contributed to %@, as well as the e-mail " +"used as a reference for the purchase." +msgstr "Entrez la clé que vous avez reçue en contribuant à %@, ainsi que le courriel utilisé pour la contribution." + +#: cocoalib/en.lproj/cocoalib.strings:0 +msgid "Work in progress, please wait." +msgstr "" + +#: cocoalib/en.lproj/cocoalib.strings:0 +msgid "Work in progress..." +msgstr "" + +#: cocoalib/en.lproj/cocoalib.strings:0 +msgid "Yes" +msgstr "" diff --git a/cocoalib/locale/hy/LC_MESSAGES/cocoalib.po b/cocoalib/locale/hy/LC_MESSAGES/cocoalib.po new file mode 100755 index 00000000..8a7c77f1 --- /dev/null +++ b/cocoalib/locale/hy/LC_MESSAGES/cocoalib.po @@ -0,0 +1,125 @@ +# +# Translators: +msgid "" +msgstr "" +"Project-Id-Version: hscommon\n" +"PO-Revision-Date: 2013-04-28 18:26+0000\n" +"Last-Translator: hsoft \n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: utf-8\n" +"Language: hy\n" +"Plural-Forms: nplurals=2; plural=(n != 1);\n" + +#: cocoalib/en.lproj/cocoalib.strings:0 +msgid "%@ is Fairware" +msgstr "$appname-ը Fairware է" + +#: cocoalib/en.lproj/cocoalib.strings:0 +msgid "" +"Although the application should continue to run after this error, it may be " +"in an instable state, so it is recommended that you restart the application." +msgstr "" + +#: cocoalib/en.lproj/cocoalib.strings:0 +msgid "Buy" +msgstr "Գնել" + +#: cocoalib/en.lproj/cocoalib.strings:0 +msgid "Cancel" +msgstr "Չեղարկել" + +#: cocoalib/en.lproj/cocoalib.strings:0 +msgid "Clear List" +msgstr "" + +#: cocoalib/en.lproj/cocoalib.strings:0 +msgid "Contribute" +msgstr "Մասնակցել" + +#: cocoalib/en.lproj/cocoalib.strings:0 +msgid "Don't Send" +msgstr "Չուղարկել" + +#: cocoalib/en.lproj/cocoalib.strings:0 +msgid "Enter Key" +msgstr "Գրել բանալին" + +#: cocoalib/en.lproj/cocoalib.strings:0 +msgid "Enter your key" +msgstr "Շարունակել" + +#: cocoalib/en.lproj/cocoalib.strings:0 +msgid "Error Report" +msgstr "" + +#: cocoalib/en.lproj/cocoalib.strings:0 +msgid "Fairware?" +msgstr "Fairware է՞" + +#: cocoalib/en.lproj/cocoalib.strings:0 +msgid "No" +msgstr "" + +#: cocoalib/en.lproj/cocoalib.strings:0 +msgid "OK" +msgstr "" + +#: cocoalib/en.lproj/cocoalib.strings:0 +msgid "Please wait..." +msgstr "" + +#: cocoalib/en.lproj/cocoalib.strings:0 +msgid "Register" +msgstr "Գրանցել" + +#: cocoalib/en.lproj/cocoalib.strings:0 +msgid "Registration e-mail:" +msgstr "" + +#: cocoalib/en.lproj/cocoalib.strings:0 +msgid "Registration key:" +msgstr "Գրանցման բանալին." + +#: cocoalib/en.lproj/cocoalib.strings:0 +msgid "Send" +msgstr "Ուղարկել" + +#: cocoalib/en.lproj/cocoalib.strings:0 +msgid "" +"Something went wrong. Would you like to send the error report to Hardcoded " +"Software?" +msgstr "Ինչ-որ բան սխալ էր: Ուղարկե՞լ սխալի մասին զեկույց Hardcoded Software-ին:" + +#: cocoalib/en.lproj/cocoalib.strings:0 +msgid "Status: Working..." +msgstr "" + +#: cocoalib/en.lproj/cocoalib.strings:0 +msgid "Submit" +msgstr "Հաստատել" + +#: cocoalib/en.lproj/cocoalib.strings:0 +msgid "This app is registered, thanks!" +msgstr "Այս ծրագիրը գրանցված է, շնորհակալություն!" + +#: cocoalib/en.lproj/cocoalib.strings:0 +msgid "Try" +msgstr "Փորձել" + +#: cocoalib/en.lproj/cocoalib.strings:0 +msgid "" +"Type the key you received when you contributed to %@, as well as the e-mail " +"used as a reference for the purchase." +msgstr "Մուտքագրեք այն բանալին, որը ստացել եք %@-ին աջակցելիս, քանզի Ձեր էլ. հասցեն օգտագործվել է գնման ժամանակ:" + +#: cocoalib/en.lproj/cocoalib.strings:0 +msgid "Work in progress, please wait." +msgstr "" + +#: cocoalib/en.lproj/cocoalib.strings:0 +msgid "Work in progress..." +msgstr "" + +#: cocoalib/en.lproj/cocoalib.strings:0 +msgid "Yes" +msgstr "" diff --git a/cocoalib/locale/it/LC_MESSAGES/cocoalib.po b/cocoalib/locale/it/LC_MESSAGES/cocoalib.po new file mode 100644 index 00000000..88312c6c --- /dev/null +++ b/cocoalib/locale/it/LC_MESSAGES/cocoalib.po @@ -0,0 +1,125 @@ +# +# Translators: +msgid "" +msgstr "" +"Project-Id-Version: hscommon\n" +"PO-Revision-Date: 2013-04-28 18:26+0000\n" +"Last-Translator: hsoft \n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: utf-8\n" +"Language: it\n" +"Plural-Forms: nplurals=2; plural=(n != 1);\n" + +#: cocoalib/en.lproj/cocoalib.strings:0 +msgid "%@ is Fairware" +msgstr "%@ è Fairware" + +#: cocoalib/en.lproj/cocoalib.strings:0 +msgid "" +"Although the application should continue to run after this error, it may be " +"in an instable state, so it is recommended that you restart the application." +msgstr "" + +#: cocoalib/en.lproj/cocoalib.strings:0 +msgid "Buy" +msgstr "Acquista" + +#: cocoalib/en.lproj/cocoalib.strings:0 +msgid "Cancel" +msgstr "Annulla" + +#: cocoalib/en.lproj/cocoalib.strings:0 +msgid "Clear List" +msgstr "" + +#: cocoalib/en.lproj/cocoalib.strings:0 +msgid "Contribute" +msgstr "Contribuisci" + +#: cocoalib/en.lproj/cocoalib.strings:0 +msgid "Don't Send" +msgstr "Non inviare" + +#: cocoalib/en.lproj/cocoalib.strings:0 +msgid "Enter Key" +msgstr "Inserisci Codice" + +#: cocoalib/en.lproj/cocoalib.strings:0 +msgid "Enter your key" +msgstr "Inserisci il tuo codice" + +#: cocoalib/en.lproj/cocoalib.strings:0 +msgid "Error Report" +msgstr "" + +#: cocoalib/en.lproj/cocoalib.strings:0 +msgid "Fairware?" +msgstr "Fairware?" + +#: cocoalib/en.lproj/cocoalib.strings:0 +msgid "No" +msgstr "" + +#: cocoalib/en.lproj/cocoalib.strings:0 +msgid "OK" +msgstr "" + +#: cocoalib/en.lproj/cocoalib.strings:0 +msgid "Please wait..." +msgstr "" + +#: cocoalib/en.lproj/cocoalib.strings:0 +msgid "Register" +msgstr "Registra" + +#: cocoalib/en.lproj/cocoalib.strings:0 +msgid "Registration e-mail:" +msgstr "" + +#: cocoalib/en.lproj/cocoalib.strings:0 +msgid "Registration key:" +msgstr "Codice di registrazione:" + +#: cocoalib/en.lproj/cocoalib.strings:0 +msgid "Send" +msgstr "Invia" + +#: cocoalib/en.lproj/cocoalib.strings:0 +msgid "" +"Something went wrong. Would you like to send the error report to Hardcoded " +"Software?" +msgstr "Qualcosa è andato storto. Desideri inviare la segnalazione di errore a Hardcoded Software?" + +#: cocoalib/en.lproj/cocoalib.strings:0 +msgid "Status: Working..." +msgstr "" + +#: cocoalib/en.lproj/cocoalib.strings:0 +msgid "Submit" +msgstr "Invia" + +#: cocoalib/en.lproj/cocoalib.strings:0 +msgid "This app is registered, thanks!" +msgstr "Questa applicazione è registrata, grazie!" + +#: cocoalib/en.lproj/cocoalib.strings:0 +msgid "Try" +msgstr "Prova" + +#: cocoalib/en.lproj/cocoalib.strings:0 +msgid "" +"Type the key you received when you contributed to %@, as well as the e-mail " +"used as a reference for the purchase." +msgstr "Inserisci il codice che hai ricevuto quando hai contribuito a %@, così come l'email di riferimento utilizzata per l'acquisto." + +#: cocoalib/en.lproj/cocoalib.strings:0 +msgid "Work in progress, please wait." +msgstr "" + +#: cocoalib/en.lproj/cocoalib.strings:0 +msgid "Work in progress..." +msgstr "" + +#: cocoalib/en.lproj/cocoalib.strings:0 +msgid "Yes" +msgstr "" diff --git a/cocoalib/locale/nl/LC_MESSAGES/cocoalib.po b/cocoalib/locale/nl/LC_MESSAGES/cocoalib.po new file mode 100644 index 00000000..ffbb3c66 --- /dev/null +++ b/cocoalib/locale/nl/LC_MESSAGES/cocoalib.po @@ -0,0 +1,125 @@ +# +# Translators: +msgid "" +msgstr "" +"Project-Id-Version: hscommon\n" +"PO-Revision-Date: 2013-04-28 18:26+0000\n" +"Last-Translator: hsoft \n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: utf-8\n" +"Language: nl\n" +"Plural-Forms: nplurals=2; plural=(n != 1);\n" + +#: cocoalib/en.lproj/cocoalib.strings:0 +msgid "%@ is Fairware" +msgstr "" + +#: cocoalib/en.lproj/cocoalib.strings:0 +msgid "" +"Although the application should continue to run after this error, it may be " +"in an instable state, so it is recommended that you restart the application." +msgstr "" + +#: cocoalib/en.lproj/cocoalib.strings:0 +msgid "Buy" +msgstr "" + +#: cocoalib/en.lproj/cocoalib.strings:0 +msgid "Cancel" +msgstr "" + +#: cocoalib/en.lproj/cocoalib.strings:0 +msgid "Clear List" +msgstr "" + +#: cocoalib/en.lproj/cocoalib.strings:0 +msgid "Contribute" +msgstr "" + +#: cocoalib/en.lproj/cocoalib.strings:0 +msgid "Don't Send" +msgstr "" + +#: cocoalib/en.lproj/cocoalib.strings:0 +msgid "Enter Key" +msgstr "" + +#: cocoalib/en.lproj/cocoalib.strings:0 +msgid "Enter your key" +msgstr "" + +#: cocoalib/en.lproj/cocoalib.strings:0 +msgid "Error Report" +msgstr "" + +#: cocoalib/en.lproj/cocoalib.strings:0 +msgid "Fairware?" +msgstr "" + +#: cocoalib/en.lproj/cocoalib.strings:0 +msgid "No" +msgstr "" + +#: cocoalib/en.lproj/cocoalib.strings:0 +msgid "OK" +msgstr "" + +#: cocoalib/en.lproj/cocoalib.strings:0 +msgid "Please wait..." +msgstr "" + +#: cocoalib/en.lproj/cocoalib.strings:0 +msgid "Register" +msgstr "" + +#: cocoalib/en.lproj/cocoalib.strings:0 +msgid "Registration e-mail:" +msgstr "" + +#: cocoalib/en.lproj/cocoalib.strings:0 +msgid "Registration key:" +msgstr "" + +#: cocoalib/en.lproj/cocoalib.strings:0 +msgid "Send" +msgstr "" + +#: cocoalib/en.lproj/cocoalib.strings:0 +msgid "" +"Something went wrong. Would you like to send the error report to Hardcoded " +"Software?" +msgstr "" + +#: cocoalib/en.lproj/cocoalib.strings:0 +msgid "Status: Working..." +msgstr "" + +#: cocoalib/en.lproj/cocoalib.strings:0 +msgid "Submit" +msgstr "" + +#: cocoalib/en.lproj/cocoalib.strings:0 +msgid "This app is registered, thanks!" +msgstr "This app is registered, thanks!" + +#: cocoalib/en.lproj/cocoalib.strings:0 +msgid "Try" +msgstr "" + +#: cocoalib/en.lproj/cocoalib.strings:0 +msgid "" +"Type the key you received when you contributed to %@, as well as the e-mail " +"used as a reference for the purchase." +msgstr "" + +#: cocoalib/en.lproj/cocoalib.strings:0 +msgid "Work in progress, please wait." +msgstr "" + +#: cocoalib/en.lproj/cocoalib.strings:0 +msgid "Work in progress..." +msgstr "" + +#: cocoalib/en.lproj/cocoalib.strings:0 +msgid "Yes" +msgstr "" diff --git a/cocoalib/locale/pt_BR/LC_MESSAGES/cocoalib.po b/cocoalib/locale/pt_BR/LC_MESSAGES/cocoalib.po new file mode 100644 index 00000000..7304d26b --- /dev/null +++ b/cocoalib/locale/pt_BR/LC_MESSAGES/cocoalib.po @@ -0,0 +1,125 @@ +# +# Translators: +msgid "" +msgstr "" +"Project-Id-Version: hscommon\n" +"PO-Revision-Date: 2013-04-28 18:26+0000\n" +"Last-Translator: hsoft \n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: utf-8\n" +"Language: pt_BR\n" +"Plural-Forms: nplurals=2; plural=(n > 1);\n" + +#: cocoalib/en.lproj/cocoalib.strings:0 +msgid "%@ is Fairware" +msgstr "%@ é Fairware" + +#: cocoalib/en.lproj/cocoalib.strings:0 +msgid "" +"Although the application should continue to run after this error, it may be " +"in an instable state, so it is recommended that you restart the application." +msgstr "Embora o aplicativo continue a funcionar após este erro, ele pode estar instável. É recomendável reiniciá-lo." + +#: cocoalib/en.lproj/cocoalib.strings:0 +msgid "Buy" +msgstr "Comprar" + +#: cocoalib/en.lproj/cocoalib.strings:0 +msgid "Cancel" +msgstr "Cancelar" + +#: cocoalib/en.lproj/cocoalib.strings:0 +msgid "Clear List" +msgstr "Limpar Lista" + +#: cocoalib/en.lproj/cocoalib.strings:0 +msgid "Contribute" +msgstr "Contribuir" + +#: cocoalib/en.lproj/cocoalib.strings:0 +msgid "Don't Send" +msgstr "Não Enviar" + +#: cocoalib/en.lproj/cocoalib.strings:0 +msgid "Enter Key" +msgstr "Entrar Chave" + +#: cocoalib/en.lproj/cocoalib.strings:0 +msgid "Enter your key" +msgstr "Entre sua chave" + +#: cocoalib/en.lproj/cocoalib.strings:0 +msgid "Error Report" +msgstr "" + +#: cocoalib/en.lproj/cocoalib.strings:0 +msgid "Fairware?" +msgstr "Fairware?" + +#: cocoalib/en.lproj/cocoalib.strings:0 +msgid "No" +msgstr "Não" + +#: cocoalib/en.lproj/cocoalib.strings:0 +msgid "OK" +msgstr "" + +#: cocoalib/en.lproj/cocoalib.strings:0 +msgid "Please wait..." +msgstr "Aguarde..." + +#: cocoalib/en.lproj/cocoalib.strings:0 +msgid "Register" +msgstr "Registrar" + +#: cocoalib/en.lproj/cocoalib.strings:0 +msgid "Registration e-mail:" +msgstr "" + +#: cocoalib/en.lproj/cocoalib.strings:0 +msgid "Registration key:" +msgstr "Chave de registro:" + +#: cocoalib/en.lproj/cocoalib.strings:0 +msgid "Send" +msgstr "Enviar" + +#: cocoalib/en.lproj/cocoalib.strings:0 +msgid "" +"Something went wrong. Would you like to send the error report to Hardcoded " +"Software?" +msgstr "Algo deu errado. Deseja enviar o relatório de erro à Hardcoded Software?" + +#: cocoalib/en.lproj/cocoalib.strings:0 +msgid "Status: Working..." +msgstr "" + +#: cocoalib/en.lproj/cocoalib.strings:0 +msgid "Submit" +msgstr "Enviar" + +#: cocoalib/en.lproj/cocoalib.strings:0 +msgid "This app is registered, thanks!" +msgstr "O app está registrado, obrigado!" + +#: cocoalib/en.lproj/cocoalib.strings:0 +msgid "Try" +msgstr "Testar" + +#: cocoalib/en.lproj/cocoalib.strings:0 +msgid "" +"Type the key you received when you contributed to %@, as well as the e-mail " +"used as a reference for the purchase." +msgstr "Digite a chave que você recebeu ao contribuir com o %@, assim como o e-mail usado para a compra." + +#: cocoalib/en.lproj/cocoalib.strings:0 +msgid "Work in progress, please wait." +msgstr "" + +#: cocoalib/en.lproj/cocoalib.strings:0 +msgid "Work in progress..." +msgstr "" + +#: cocoalib/en.lproj/cocoalib.strings:0 +msgid "Yes" +msgstr "Sim" diff --git a/cocoalib/locale/ru/LC_MESSAGES/cocoalib.po b/cocoalib/locale/ru/LC_MESSAGES/cocoalib.po new file mode 100755 index 00000000..a0876f43 --- /dev/null +++ b/cocoalib/locale/ru/LC_MESSAGES/cocoalib.po @@ -0,0 +1,125 @@ +# +# Translators: +msgid "" +msgstr "" +"Project-Id-Version: hscommon\n" +"PO-Revision-Date: 2013-04-28 18:26+0000\n" +"Last-Translator: hsoft \n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: utf-8\n" +"Language: ru\n" +"Plural-Forms: nplurals=3; plural=(n%10==1 && n%100!=11 ? 0 : n%10>=2 && n%10<=4 && (n%100<10 || n%100>=20) ? 1 : 2);\n" + +#: cocoalib/en.lproj/cocoalib.strings:0 +msgid "%@ is Fairware" +msgstr "%@ является Fairware" + +#: cocoalib/en.lproj/cocoalib.strings:0 +msgid "" +"Although the application should continue to run after this error, it may be " +"in an instable state, so it is recommended that you restart the application." +msgstr "" + +#: cocoalib/en.lproj/cocoalib.strings:0 +msgid "Buy" +msgstr "Купить" + +#: cocoalib/en.lproj/cocoalib.strings:0 +msgid "Cancel" +msgstr "Отменить" + +#: cocoalib/en.lproj/cocoalib.strings:0 +msgid "Clear List" +msgstr "" + +#: cocoalib/en.lproj/cocoalib.strings:0 +msgid "Contribute" +msgstr "Способствовайте" + +#: cocoalib/en.lproj/cocoalib.strings:0 +msgid "Don't Send" +msgstr "Не отправлять" + +#: cocoalib/en.lproj/cocoalib.strings:0 +msgid "Enter Key" +msgstr "Видите ключ" + +#: cocoalib/en.lproj/cocoalib.strings:0 +msgid "Enter your key" +msgstr "Видите Ваш ключ" + +#: cocoalib/en.lproj/cocoalib.strings:0 +msgid "Error Report" +msgstr "" + +#: cocoalib/en.lproj/cocoalib.strings:0 +msgid "Fairware?" +msgstr "Fairware?" + +#: cocoalib/en.lproj/cocoalib.strings:0 +msgid "No" +msgstr "" + +#: cocoalib/en.lproj/cocoalib.strings:0 +msgid "OK" +msgstr "" + +#: cocoalib/en.lproj/cocoalib.strings:0 +msgid "Please wait..." +msgstr "" + +#: cocoalib/en.lproj/cocoalib.strings:0 +msgid "Register" +msgstr "Регистрация" + +#: cocoalib/en.lproj/cocoalib.strings:0 +msgid "Registration e-mail:" +msgstr "" + +#: cocoalib/en.lproj/cocoalib.strings:0 +msgid "Registration key:" +msgstr "Регистрационный ключ:" + +#: cocoalib/en.lproj/cocoalib.strings:0 +msgid "Send" +msgstr "Отправить" + +#: cocoalib/en.lproj/cocoalib.strings:0 +msgid "" +"Something went wrong. Would you like to send the error report to Hardcoded " +"Software?" +msgstr "Что-то пошло не так. Хотите отправить отчет об ошибке в Hardcoded Software?" + +#: cocoalib/en.lproj/cocoalib.strings:0 +msgid "Status: Working..." +msgstr "" + +#: cocoalib/en.lproj/cocoalib.strings:0 +msgid "Submit" +msgstr "Передать" + +#: cocoalib/en.lproj/cocoalib.strings:0 +msgid "This app is registered, thanks!" +msgstr "Это приложение зарегистрировано, спасибо!" + +#: cocoalib/en.lproj/cocoalib.strings:0 +msgid "Try" +msgstr "Пробовать" + +#: cocoalib/en.lproj/cocoalib.strings:0 +msgid "" +"Type the key you received when you contributed to %@, as well as the e-mail " +"used as a reference for the purchase." +msgstr "Тип ключа, который вы получили при способствовала %@, а также электронной почты используется в качестве ссылки для покупки." + +#: cocoalib/en.lproj/cocoalib.strings:0 +msgid "Work in progress, please wait." +msgstr "" + +#: cocoalib/en.lproj/cocoalib.strings:0 +msgid "Work in progress..." +msgstr "" + +#: cocoalib/en.lproj/cocoalib.strings:0 +msgid "Yes" +msgstr "" diff --git a/cocoalib/locale/uk/LC_MESSAGES/cocoalib.po b/cocoalib/locale/uk/LC_MESSAGES/cocoalib.po new file mode 100755 index 00000000..1180f9e3 --- /dev/null +++ b/cocoalib/locale/uk/LC_MESSAGES/cocoalib.po @@ -0,0 +1,125 @@ +# +# Translators: +msgid "" +msgstr "" +"Project-Id-Version: hscommon\n" +"PO-Revision-Date: 2013-04-28 18:26+0000\n" +"Last-Translator: hsoft \n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: utf-8\n" +"Language: uk\n" +"Plural-Forms: nplurals=3; plural=(n%10==1 && n%100!=11 ? 0 : n%10>=2 && n%10<=4 && (n%100<10 || n%100>=20) ? 1 : 2);\n" + +#: cocoalib/en.lproj/cocoalib.strings:0 +msgid "%@ is Fairware" +msgstr "%@ це Fairware" + +#: cocoalib/en.lproj/cocoalib.strings:0 +msgid "" +"Although the application should continue to run after this error, it may be " +"in an instable state, so it is recommended that you restart the application." +msgstr "Хоча програма має продовжувати роботу після цієї помилки, вона може перебувати у нестабільному стані, тож рекомендується перезапустити програму." + +#: cocoalib/en.lproj/cocoalib.strings:0 +msgid "Buy" +msgstr "Купити" + +#: cocoalib/en.lproj/cocoalib.strings:0 +msgid "Cancel" +msgstr "Відмінити" + +#: cocoalib/en.lproj/cocoalib.strings:0 +msgid "Clear List" +msgstr "" + +#: cocoalib/en.lproj/cocoalib.strings:0 +msgid "Contribute" +msgstr "Зробити внесок" + +#: cocoalib/en.lproj/cocoalib.strings:0 +msgid "Don't Send" +msgstr "Не надсилати" + +#: cocoalib/en.lproj/cocoalib.strings:0 +msgid "Enter Key" +msgstr "Введіть ключ" + +#: cocoalib/en.lproj/cocoalib.strings:0 +msgid "Enter your key" +msgstr "Введіть Ваш ключ" + +#: cocoalib/en.lproj/cocoalib.strings:0 +msgid "Error Report" +msgstr "" + +#: cocoalib/en.lproj/cocoalib.strings:0 +msgid "Fairware?" +msgstr "Fairware?" + +#: cocoalib/en.lproj/cocoalib.strings:0 +msgid "No" +msgstr "" + +#: cocoalib/en.lproj/cocoalib.strings:0 +msgid "OK" +msgstr "" + +#: cocoalib/en.lproj/cocoalib.strings:0 +msgid "Please wait..." +msgstr "" + +#: cocoalib/en.lproj/cocoalib.strings:0 +msgid "Register" +msgstr "Зареєструвати" + +#: cocoalib/en.lproj/cocoalib.strings:0 +msgid "Registration e-mail:" +msgstr "" + +#: cocoalib/en.lproj/cocoalib.strings:0 +msgid "Registration key:" +msgstr "Реєстраційний ключ:" + +#: cocoalib/en.lproj/cocoalib.strings:0 +msgid "Send" +msgstr "Надіслати" + +#: cocoalib/en.lproj/cocoalib.strings:0 +msgid "" +"Something went wrong. Would you like to send the error report to Hardcoded " +"Software?" +msgstr "Щось пішло не так. Хочете відправити звіт про помилку до Hardcoded Software?" + +#: cocoalib/en.lproj/cocoalib.strings:0 +msgid "Status: Working..." +msgstr "" + +#: cocoalib/en.lproj/cocoalib.strings:0 +msgid "Submit" +msgstr "Надіслати" + +#: cocoalib/en.lproj/cocoalib.strings:0 +msgid "This app is registered, thanks!" +msgstr "Програму зареєстровано, дякуємо!" + +#: cocoalib/en.lproj/cocoalib.strings:0 +msgid "Try" +msgstr "Спробувати" + +#: cocoalib/en.lproj/cocoalib.strings:0 +msgid "" +"Type the key you received when you contributed to %@, as well as the e-mail " +"used as a reference for the purchase." +msgstr "Введіть ключ, який Ви отримали зробивши внесок за %@, а також адресу електронної пошти, яка була вказана під час покупки." + +#: cocoalib/en.lproj/cocoalib.strings:0 +msgid "Work in progress, please wait." +msgstr "" + +#: cocoalib/en.lproj/cocoalib.strings:0 +msgid "Work in progress..." +msgstr "" + +#: cocoalib/en.lproj/cocoalib.strings:0 +msgid "Yes" +msgstr "" diff --git a/cocoalib/locale/zh_CN/LC_MESSAGES/cocoalib.po b/cocoalib/locale/zh_CN/LC_MESSAGES/cocoalib.po new file mode 100644 index 00000000..12477712 --- /dev/null +++ b/cocoalib/locale/zh_CN/LC_MESSAGES/cocoalib.po @@ -0,0 +1,125 @@ +# +# Translators: +msgid "" +msgstr "" +"Project-Id-Version: hscommon\n" +"PO-Revision-Date: 2013-04-28 18:26+0000\n" +"Last-Translator: hsoft \n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: utf-8\n" +"Language: zh_CN\n" +"Plural-Forms: nplurals=1; plural=0;\n" + +#: cocoalib/en.lproj/cocoalib.strings:0 +msgid "%@ is Fairware" +msgstr "%@ is Fairware" + +#: cocoalib/en.lproj/cocoalib.strings:0 +msgid "" +"Although the application should continue to run after this error, it may be " +"in an instable state, so it is recommended that you restart the application." +msgstr "" + +#: cocoalib/en.lproj/cocoalib.strings:0 +msgid "Buy" +msgstr "Buy" + +#: cocoalib/en.lproj/cocoalib.strings:0 +msgid "Cancel" +msgstr "取消" + +#: cocoalib/en.lproj/cocoalib.strings:0 +msgid "Clear List" +msgstr "" + +#: cocoalib/en.lproj/cocoalib.strings:0 +msgid "Contribute" +msgstr "捐助" + +#: cocoalib/en.lproj/cocoalib.strings:0 +msgid "Don't Send" +msgstr "Don't Send" + +#: cocoalib/en.lproj/cocoalib.strings:0 +msgid "Enter Key" +msgstr "输入密钥" + +#: cocoalib/en.lproj/cocoalib.strings:0 +msgid "Enter your key" +msgstr "Enter your key" + +#: cocoalib/en.lproj/cocoalib.strings:0 +msgid "Error Report" +msgstr "" + +#: cocoalib/en.lproj/cocoalib.strings:0 +msgid "Fairware?" +msgstr "Fairware?" + +#: cocoalib/en.lproj/cocoalib.strings:0 +msgid "No" +msgstr "" + +#: cocoalib/en.lproj/cocoalib.strings:0 +msgid "OK" +msgstr "" + +#: cocoalib/en.lproj/cocoalib.strings:0 +msgid "Please wait..." +msgstr "" + +#: cocoalib/en.lproj/cocoalib.strings:0 +msgid "Register" +msgstr "Register" + +#: cocoalib/en.lproj/cocoalib.strings:0 +msgid "Registration e-mail:" +msgstr "" + +#: cocoalib/en.lproj/cocoalib.strings:0 +msgid "Registration key:" +msgstr "密钥:" + +#: cocoalib/en.lproj/cocoalib.strings:0 +msgid "Send" +msgstr "Send" + +#: cocoalib/en.lproj/cocoalib.strings:0 +msgid "" +"Something went wrong. Would you like to send the error report to Hardcoded " +"Software?" +msgstr "Something went wrong. Would you like to send the error report to Hardcoded Software?" + +#: cocoalib/en.lproj/cocoalib.strings:0 +msgid "Status: Working..." +msgstr "" + +#: cocoalib/en.lproj/cocoalib.strings:0 +msgid "Submit" +msgstr "提交" + +#: cocoalib/en.lproj/cocoalib.strings:0 +msgid "This app is registered, thanks!" +msgstr "This app is registered, thanks!" + +#: cocoalib/en.lproj/cocoalib.strings:0 +msgid "Try" +msgstr "Try" + +#: cocoalib/en.lproj/cocoalib.strings:0 +msgid "" +"Type the key you received when you contributed to %@, as well as the e-mail " +"used as a reference for the purchase." +msgstr "当您捐助 %@ 后,请输入收到的注册密钥以及电子邮件,这将作为购买凭证。" + +#: cocoalib/en.lproj/cocoalib.strings:0 +msgid "Work in progress, please wait." +msgstr "" + +#: cocoalib/en.lproj/cocoalib.strings:0 +msgid "Work in progress..." +msgstr "" + +#: cocoalib/en.lproj/cocoalib.strings:0 +msgid "Yes" +msgstr "" diff --git a/cocoalib/ui/about.py b/cocoalib/ui/about.py new file mode 100644 index 00000000..37fbe63b --- /dev/null +++ b/cocoalib/ui/about.py @@ -0,0 +1,36 @@ +ownerclass = 'HSAboutBox' +ownerimport = 'HSAboutBox.h' + +result = Window(259, 217, "") +result.canResize = False +result.canMinimize = False +image = ImageView(result, "NSApplicationIcon") +titleLabel = Label(result, NLSTR("AppTitle")) +versionLabel = Label(result, NLSTR("AppVersion")) +copyrightLabel = Label(result, NLSTR("AppCopyright")) + +owner.window = result +owner.titleTextField = titleLabel +owner.versionTextField = versionLabel +owner.copyrightTextField = copyrightLabel +for label in (titleLabel, versionLabel, copyrightLabel): + label.alignment = const.NSCenterTextAlignment +titleLabel.font = Font(FontFamily.Label, FontSize.RegularControl, traits=[FontTrait.Bold]) +for label in (versionLabel, copyrightLabel): + label.font = Font(FontFamily.Label, FontSize.SmallControl) + label.height = 14 + +image.height = 96 +image.packToCorner(Pack.UpperLeft) +image.y = result.height - 10 - image.height +image.fill(Pack.Right) +image.setAnchor(Pack.UpperLeft, growX=True) +titleLabel.packRelativeTo(image, Pack.Below, Pack.Left) +titleLabel.fill(Pack.Right) +titleLabel.setAnchor(Pack.UpperLeft, growX=True) +versionLabel.packRelativeTo(titleLabel, Pack.Below, Pack.Left) +versionLabel.fill(Pack.Right) +versionLabel.setAnchor(Pack.UpperLeft, growX=True) +copyrightLabel.packRelativeTo(versionLabel, Pack.Below, Pack.Left) +copyrightLabel.fill(Pack.Right) +copyrightLabel.setAnchor(Pack.UpperLeft, growX=True) diff --git a/cocoalib/ui/demo_reminder.py b/cocoalib/ui/demo_reminder.py new file mode 100644 index 00000000..d4f36502 --- /dev/null +++ b/cocoalib/ui/demo_reminder.py @@ -0,0 +1,32 @@ +ownerclass = 'HSFairwareReminder' +ownerimport = 'HSFairwareReminder.h' + +result = Window(528, 253, "%@ is Fairware") +result.canClose = False +result.canResize = False +result.canMinimize = False +demoPromptLabel = Label(result, NLSTR("")) +tryButton = Button(result, "Try") +enterKeyButton = Button(result, "Enter Key") +buyButton = Button(result, "Buy") +fairwareButton = Button(result, "Fairware?") + +owner.demoPromptTextField = demoPromptLabel +result.initialFirstResponder = tryButton +demoPromptLabel.font = Font(FontFamily.Label, FontSize.SmallControl) +tryButton.action = Action(owner, 'closeDialog') +tryButton.keyEquivalent = "\\r" +enterKeyButton.action = Action(owner, 'showEnterCode') +buyButton.action = Action(owner, 'buy') +fairwareButton.action = Action(owner, 'moreInfo') + +for button in (tryButton, enterKeyButton, buyButton, fairwareButton): + button.width = 113 +demoPromptLabel.height = 185 + +demoPromptLabel.packToCorner(Pack.UpperLeft) +demoPromptLabel.fill(Pack.Right) +tryButton.packRelativeTo(demoPromptLabel, Pack.Below, Pack.Left) +enterKeyButton.packRelativeTo(tryButton, Pack.Right, Pack.Middle) +buyButton.packRelativeTo(enterKeyButton, Pack.Right, Pack.Middle) +fairwareButton.packRelativeTo(buyButton, Pack.Right, Pack.Middle) diff --git a/cocoalib/ui/enter_code.py b/cocoalib/ui/enter_code.py new file mode 100644 index 00000000..70988713 --- /dev/null +++ b/cocoalib/ui/enter_code.py @@ -0,0 +1,52 @@ +ownerclass = 'HSFairwareReminder' +ownerimport = 'HSFairwareReminder.h' + +result = Window(450, 185, "Enter Key") +result.canClose = False +result.canResize = False +result.canMinimize = False +titleLabel = Label(result, "Enter your key") +promptLabel = Label(result, "Type the key you received when you contributed to %@, as well as the e-mail used as a reference for the purchase.") +regkeyLabel = Label(result, "Registration key:") +regkeyField = TextField(result, "") +regemailLabel = Label(result, "Registration e-mail:") +regemailField = TextField(result, "") +contributeButton = Button(result, "Contribute") +cancelButton = Button(result, "Cancel") +submitButton = Button(result, "Submit") + +owner.codePromptTextField = promptLabel +owner.codeTextField = regkeyField +owner.emailTextField = regemailField +result.initialFirstResponder = regkeyField + +titleLabel.font = Font(FontFamily.Label, FontSize.RegularControl, traits=[FontTrait.Bold]) +smallerFont = Font(FontFamily.Label, FontSize.SmallControl) +for control in (promptLabel, regkeyLabel, regemailLabel): + control.font = smallerFont +regkeyField.usesSingleLineMode = regemailField.usesSingleLineMode = True +contributeButton.action = Action(owner, 'contribute') +cancelButton.action = Action(owner, 'cancelCode') +cancelButton.keyEquivalent = "\\E" +submitButton.action = Action(owner, 'submitCode') +submitButton.keyEquivalent = "\\r" + +for button in (contributeButton, cancelButton, submitButton): + button.width = 100 +regkeyLabel.width = 128 +regemailLabel.width = 128 +promptLabel.height = 32 + +titleLabel.packToCorner(Pack.UpperLeft) +titleLabel.fill(Pack.Right) +promptLabel.packRelativeTo(titleLabel, Pack.Below, Pack.Left) +promptLabel.fill(Pack.Right) +regkeyField.packRelativeTo(promptLabel, Pack.Below, Pack.Right) +regkeyLabel.packRelativeTo(regkeyField, Pack.Left, Pack.Middle) +regkeyField.fill(Pack.Left) +regemailField.packRelativeTo(regkeyField, Pack.Below, Pack.Right) +regemailLabel.packRelativeTo(regemailField, Pack.Left, Pack.Middle) +regemailField.fill(Pack.Left) +contributeButton.packRelativeTo(regemailLabel, Pack.Below, Pack.Left) +submitButton.packRelativeTo(regemailField, Pack.Below, Pack.Right) +cancelButton.packRelativeTo(submitButton, Pack.Left, Pack.Middle) diff --git a/cocoalib/ui/error_report.py b/cocoalib/ui/error_report.py new file mode 100644 index 00000000..30f86d34 --- /dev/null +++ b/cocoalib/ui/error_report.py @@ -0,0 +1,33 @@ +ownerclass = 'HSErrorReportWindow' +ownerimport = 'HSErrorReportWindow.h' + +result = Window(524, 390, "Error Report") +result.canClose = False +result.canResize = False +result.canMinimize = False +label1 = Label(result, "Something went wrong. Would you like to send the error report to Hardcoded Software?") +errorTextView = TextView(result) +label2 = Label(result, "Although the application should continue to run after this error, it may be in an instable state, so it is recommended that you restart the application.") +sendButton = Button(result, "Send") +dontSendButton = Button(result, "Don't Send") + +owner.contentTextView = errorTextView +sendButton.action = Action(owner, 'send') +sendButton.keyEquivalent = "\\r" +dontSendButton.action = Action(owner, 'dontSend') +dontSendButton.keyEquivalent = "\\E" + +label1.height = 34 +errorTextView.height = 221 +label2.height = 51 +sendButton.width = 100 +dontSendButton.width = 100 + +label1.packToCorner(Pack.UpperLeft) +label1.fill(Pack.Right) +errorTextView.packRelativeTo(label1, Pack.Below, Pack.Left) +errorTextView.fill(Pack.Right) +label2.packRelativeTo(errorTextView, Pack.Below, Pack.Left) +label2.fill(Pack.Right) +sendButton.packRelativeTo(label2, Pack.Below, Pack.Right) +dontSendButton.packRelativeTo(sendButton, Pack.Left, Pack.Middle) diff --git a/cocoalib/ui/fairware_about.py b/cocoalib/ui/fairware_about.py new file mode 100644 index 00000000..9168bb72 --- /dev/null +++ b/cocoalib/ui/fairware_about.py @@ -0,0 +1,46 @@ +ownerclass = 'HSFairwareAboutBox' +ownerimport = 'HSFairwareAboutBox.h' + +result = Window(259, 217, "") +result.canResize = False +result.canMinimize = False +image = ImageView(result, "NSApplicationIcon") +titleLabel = Label(result, NLSTR("AppTitle")) +versionLabel = Label(result, NLSTR("AppVersion")) +copyrightLabel = Label(result, NLSTR("AppCopyright")) +registeredLabel = Label(result, "This app is registered, thanks!") +registerButton = Button(result, "Register") + +owner.window = result +owner.titleTextField = titleLabel +owner.versionTextField = versionLabel +owner.copyrightTextField = copyrightLabel +owner.registeredTextField = registeredLabel +owner.registerButton = registerButton +for label in (titleLabel, versionLabel, copyrightLabel, registeredLabel): + label.alignment = const.NSCenterTextAlignment +titleLabel.font = Font(FontFamily.Label, FontSize.RegularControl, traits=[FontTrait.Bold]) +for label in (versionLabel, copyrightLabel, registeredLabel): + label.font = Font(FontFamily.Label, FontSize.SmallControl) + label.height = 14 +registerButton.bezelStyle = const.NSRoundRectBezelStyle +registerButton.action = Action(owner, 'showRegisterDialog') + +image.height = 96 +image.packToCorner(Pack.UpperLeft) +image.y = result.height - 10 - image.height +image.fill(Pack.Right) +image.setAnchor(Pack.UpperLeft, growX=True) +titleLabel.packRelativeTo(image, Pack.Below, Pack.Left) +titleLabel.fill(Pack.Right) +titleLabel.setAnchor(Pack.UpperLeft, growX=True) +versionLabel.packRelativeTo(titleLabel, Pack.Below, Pack.Left) +versionLabel.fill(Pack.Right) +versionLabel.setAnchor(Pack.UpperLeft, growX=True) +copyrightLabel.packRelativeTo(versionLabel, Pack.Below, Pack.Left) +copyrightLabel.fill(Pack.Right) +copyrightLabel.setAnchor(Pack.UpperLeft, growX=True) +registeredLabel.packRelativeTo(copyrightLabel, Pack.Below, Pack.Left) +registeredLabel.fill(Pack.Right) +registeredLabel.setAnchor(Pack.UpperLeft, growX=True) +registerButton.packRelativeTo(copyrightLabel, Pack.Below, Pack.Middle) diff --git a/cocoalib/ui/progress.py b/cocoalib/ui/progress.py new file mode 100644 index 00000000..99dcbe7b --- /dev/null +++ b/cocoalib/ui/progress.py @@ -0,0 +1,31 @@ +ownerclass = 'ProgressController' +ownerimport = 'ProgressController.h' + +result = Window(323, 143, "Work in progress...") +result.canClose = result.canResize = result.canMinimize = False +descLabel = Label(result, "Work in progress, please wait.") +progress = ProgressIndicator(result) +statusLabel = Label(result, "Status: Working...") +cancelButton = Button(result, "Cancel") + +owner.window = result +owner.cancelButton = cancelButton +owner.descText = descLabel +owner.statusText = statusLabel +owner.progressBar = progress +result.properties['delegate'] = owner +statusLabel.font = Font(FontFamily.Label, FontSize.SmallControl) +cancelButton.keyEquivalent = '\\E' +cancelButton.action = Action(owner, 'cancel') + +descLabel.packToCorner(Pack.UpperLeft) +descLabel.fill(Pack.Right) +descLabel.setAnchor(Pack.UpperLeft, growX=True) +progress.packRelativeTo(descLabel, Pack.Below, Pack.Left) +progress.fill(Pack.Right) +progress.setAnchor(Pack.UpperLeft, growX=True) +statusLabel.packRelativeTo(progress, Pack.Below, Pack.Left) +statusLabel.fill(Pack.Right) +statusLabel.setAnchor(Pack.UpperLeft, growX=True) +cancelButton.packToCorner(Pack.LowerRight) +cancelButton.setAnchor(Pack.LowerRight) diff --git a/cocoalib/views/HSOutlineView.h b/cocoalib/views/HSOutlineView.h new file mode 100644 index 00000000..5770acca --- /dev/null +++ b/cocoalib/views/HSOutlineView.h @@ -0,0 +1,41 @@ +/* +Copyright 2013 Hardcoded Software (http://www.hardcoded.net) + +This software is licensed under the "BSD" License as described in the "LICENSE" file, +which should be included with this package. The terms are also available at +http://www.hardcoded.net/licenses/bsd_license +*/ + +#import +#import "NSTableViewAdditions.h" +#import "NSIndexPathAdditions.h" + +@class HSOutlineView; + +@protocol HSOutlineViewDelegate +- (NSArray *)selectedIndexPaths; /* array of NSIndexPath* */ +- (NSString *)dataForCopyToPasteboard; +- (NSIndexPath *)internalizedPath:(NSIndexPath *)path; +- (void)outlineViewDidEndEditing:(HSOutlineView *)outlineView; +- (void)outlineViewCancelsEdition:(HSOutlineView *)outlineView; +- (void)outlineViewWasDoubleClicked:(HSOutlineView *)outlineView; +@end + +@interface HSOutlineView : NSOutlineView +{ + BOOL manualEditionStop; + NSEvent *eventToIgnore; +} +- (id )delegate; +- (void)setDelegate:(id )aDelegate; +- (NSIndexPath *)selectedPath; +- (void)selectPath:(NSIndexPath *)aPath; +- (NSArray *)selectedNodePaths; +- (void)selectNodePaths:(NSArray *)nodePaths; +- (void)stopEditing; +- (void)updateSelection; +- (void)ignoreEventForEdition:(NSEvent *)aEvent; +- (void)ensureExpanded:(NSIndexPath *)aPath; + +- (IBAction)copy:(id)sender; +@end diff --git a/cocoalib/views/HSOutlineView.m b/cocoalib/views/HSOutlineView.m new file mode 100644 index 00000000..28779cf9 --- /dev/null +++ b/cocoalib/views/HSOutlineView.m @@ -0,0 +1,189 @@ +/* +Copyright 2013 Hardcoded Software (http://www.hardcoded.net) + +This software is licensed under the "BSD" License as described in the "LICENSE" file, +which should be included with this package. The terms are also available at +http://www.hardcoded.net/licenses/bsd_license +*/ + +#import "HSOutlineView.h" + +@implementation HSOutlineView +- (id )delegate +{ + return (id )[super delegate]; +} + +- (void)setDelegate:(id )aDelegate +{ + [super setDelegate:aDelegate]; + id delegate = [self delegate]; + if ([delegate respondsToSelector:@selector(outlineViewWasDoubleClicked:)]) { + [self setTarget:[self delegate]]; + [self setDoubleAction:@selector(outlineViewWasDoubleClicked:)]; + } +} +/* NSOutlineView overrides */ +- (void)keyDown:(NSEvent *)event +{ + if (![self dispatchSpecialKeys:event]) + { + [super keyDown:event]; + } +} + +- (BOOL)shouldEditTableColumn:(NSTableColumn *)column row:(NSInteger)row +{ + BOOL result = [super shouldEditTableColumn:column row:row]; + if (!result) + return result; + id delegate = [self delegate]; + if ([delegate respondsToSelector:@selector(outlineView:shouldEditTableColumn:item:)]) + return [delegate outlineView:self shouldEditTableColumn:column item:[self itemAtRow:row]]; + return YES; +} + +/* Notifications & Delegate */ +- (void)textDidEndEditing:(NSNotification *)notification +{ + notification = [self processTextDidEndEditing:notification]; + NSView *nextKeyView = [self nextKeyView]; + [self setNextKeyView:nil]; + [super textDidEndEditing:notification]; + [self setNextKeyView:nextKeyView]; + + if ([self editedColumn] == -1) + { + if (!manualEditionStop) + { + id delegate = [self delegate]; + if ([delegate respondsToSelector:@selector(outlineViewDidEndEditing:)]) + { + [delegate outlineViewDidEndEditing:self]; + } + } + // We may have lost the focus + [[self window] makeFirstResponder:self]; + } +} + +- (BOOL)textView:(NSTextView *)textView doCommandBySelector:(SEL)command +{ + if (command == @selector(cancelOperation:)) + { + [self stopEditing]; // The stop editing has to happen before the cancelEdits + id delegate = [self delegate]; + if ([delegate respondsToSelector:@selector(outlineViewCancelsEdition:)]) + { + [delegate outlineViewCancelsEdition:self]; + } + return YES; + } + return NO; +} + +/* Public */ +- (NSIndexPath *)selectedPath +{ + NSInteger row = [self selectedRow]; + return [self itemAtRow:row]; +} + +- (void)selectPath:(NSIndexPath *)aPath +{ + [self selectNodePaths:[NSArray arrayWithObject:aPath]]; +} + +- (NSArray *)selectedNodePaths +{ + NSMutableArray *r = [NSMutableArray array]; + NSIndexSet *indexes = [self selectedRowIndexes]; + NSInteger i = [indexes firstIndex]; + while (i != NSNotFound) { + NSIndexPath *path = [self itemAtRow:i]; + [r addObject:path]; + i = [indexes indexGreaterThanIndex:i]; + } + return r; +} + +- (void)selectNodePaths:(NSArray *)aPaths +{ + NSMutableIndexSet *toSelect = [NSMutableIndexSet indexSet]; + /* To ensure that we have correct row indexes, we must first expand all paths, and *then* select + * row indexes. + **/ + for (NSIndexPath *path in aPaths) { + [self ensureExpanded:path]; + } + for (NSIndexPath *path in aPaths) { + [toSelect addIndex:[self rowForItem:path]]; + } + [self selectRowIndexes:toSelect byExtendingSelection:NO]; + if ([toSelect count] > 0) { + [self scrollRowToVisible:[toSelect firstIndex]]; + } +} + +- (void)ensureExpanded:(NSIndexPath *)aPath +{ + /* Expands aPath and make sure that its parent items are expanded as well. + */ + id delegate = [self delegate]; + NSIndexPath *tmppath = [NSIndexPath indexPathWithIndex:[aPath indexAtPosition:0]]; + for (NSInteger i=1; i<[aPath length]; i++) { + [self expandItem:[delegate internalizedPath:tmppath]]; + tmppath = [tmppath indexPathByAddingIndex:[aPath indexAtPosition:i]]; + } +} + +- (void)stopEditing +{ + // If we're not editing, don't do anything because we don't want to steal focus from another view + if ([self editedColumn] >= 0) + { + manualEditionStop = YES; + [[self window] makeFirstResponder:self]; // This will abort edition + manualEditionStop = NO; + } +} + +- (void)updateSelection +{ + id delegate = [self delegate]; + if ([delegate respondsToSelector:@selector(selectedIndexPaths)]) { + [self selectNodePaths:[delegate selectedIndexPaths]]; + } +} + +/* Actions */ + +- (IBAction)copy:(id)sender +{ + NSString *data = [[self delegate] dataForCopyToPasteboard]; + if (data != nil) { + NSPasteboard *p = [NSPasteboard generalPasteboard]; + [p declareTypes:[NSArray arrayWithObjects:NSStringPboardType, nil] owner:nil]; + [p setString:data forType:NSStringPboardType]; + } +} + +/* BIG HACK ZONE +When tracking clicks in the NSTextField, the NSTableView goes in edition mode even if we click on the +arrow or the button. The only way I found to avoid this is this scheme: let the HSOutlineView know +of the event that caused the click, and don't go in edit mode if it happens. +*/ + +- (void)ignoreEventForEdition:(NSEvent *)aEvent +{ + eventToIgnore = aEvent; +} + +- (void)editColumn:(NSInteger)columnIndex row:(NSInteger)rowIndex withEvent:(NSEvent *)theEvent select:(BOOL)flag +{ + if ((theEvent != nil) && (theEvent == eventToIgnore)) + return; + [super editColumn:columnIndex row:rowIndex withEvent:theEvent select:flag]; +} + +@end diff --git a/cocoalib/views/HSTableView.h b/cocoalib/views/HSTableView.h new file mode 100644 index 00000000..79df8b42 --- /dev/null +++ b/cocoalib/views/HSTableView.h @@ -0,0 +1,31 @@ +/* +Copyright 2013 Hardcoded Software (http://www.hardcoded.net) + +This software is licensed under the "BSD" License as described in the "LICENSE" file, +which should be included with this package. The terms are also available at +http://www.hardcoded.net/licenses/bsd_license +*/ + +#import +#import "NSTableViewAdditions.h" + +@class HSTableView; + +@protocol HSTableViewDelegate +- (NSIndexSet *)selectedIndexes; +- (void)tableViewDidEndEditing:(HSTableView *)tableView; +- (void)tableViewCancelsEdition:(HSTableView *)tableView; +- (void)tableViewWasDoubleClicked:(HSTableView *)tableView; +@end + +@interface HSTableView : NSTableView +{ + BOOL manualEditionStop; +} +- (void)updateSelection; +- (void)stopEditing; +- (id )delegate; +- (void)setDelegate:(id )aDelegate; +- (NSScrollView *)wrapInScrollView; +@end + diff --git a/cocoalib/views/HSTableView.m b/cocoalib/views/HSTableView.m new file mode 100644 index 00000000..f153e540 --- /dev/null +++ b/cocoalib/views/HSTableView.m @@ -0,0 +1,102 @@ +/* +Copyright 2013 Hardcoded Software (http://www.hardcoded.net) + +This software is licensed under the "BSD" License as described in the "LICENSE" file, +which should be included with this package. The terms are also available at +http://www.hardcoded.net/licenses/bsd_license +*/ + +#import "HSTableView.h" +#import "NSEventAdditions.h" + +@implementation HSTableView +/* NSTableView */ +- (void)keyDown:(NSEvent *)event +{ + if (![self dispatchSpecialKeys:event]) { + [super keyDown:event]; + } +} + +- (id )delegate +{ + return (id )[super delegate]; +} + +- (void)setDelegate:(id )aDelegate +{ + [super setDelegate:aDelegate]; + id delegate = [self delegate]; + if ([delegate respondsToSelector:@selector(tableViewWasDoubleClicked:)]) { + [self setTarget:[self delegate]]; + [self setDoubleAction:@selector(tableViewWasDoubleClicked:)]; + } +} + +- (void)textDidEndEditing:(NSNotification *)notification +{ + notification = [self processTextDidEndEditing:notification]; + NSView *nextKeyView = [self nextKeyView]; + [self setNextKeyView:nil]; + [super textDidEndEditing:notification]; + [self setNextKeyView:nextKeyView]; + + if ([self editedColumn] == -1) { + if (!manualEditionStop) { + id delegate = [self delegate]; + if ([delegate respondsToSelector:@selector(tableViewDidEndEditing:)]) { + [delegate tableViewDidEndEditing:self]; + } + } + // We may have lost the focus + [[self window] makeFirstResponder:self]; + } +} + +/* NSTextView delegate */ +- (BOOL)textView:(NSTextView *)textView doCommandBySelector:(SEL)command +{ + if (command == @selector(cancelOperation:)) { + [self stopEditing]; // The stop editing has to happen before the cancelEdits + id delegate = [self delegate]; + if ([delegate respondsToSelector:@selector(tableViewCancelsEdition:)]) { + [delegate tableViewCancelsEdition:self]; + } + return YES; + } + return NO; +} + +/* Public methods */ + +- (void)updateSelection +{ + NSIndexSet *selection = [[self delegate] selectedIndexes]; + [self selectRowIndexes:selection byExtendingSelection:NO]; +} + +// Calling this does not result in a tableViewDidEndEditing: call +- (void)stopEditing +{ + // If we're not editing, don't do anything because we don't want to steal focus from another view + if ([self editedColumn] >= 0) { + manualEditionStop = YES; + [[self window] makeFirstResponder:self]; // This will abort edition + manualEditionStop = NO; + } +} + +- (NSScrollView *)wrapInScrollView; +{ + /* When programmatically creating an NSTableView, we have to wrap it in a scroll view for it to + behave properly. + */ + NSScrollView *container = [[NSScrollView alloc] initWithFrame:NSMakeRect(0, 0, 100, 100)]; + [container setDocumentView:self]; + [container setHasVerticalScroller:YES]; + [container setHasHorizontalScroller:YES]; + [container setAutohidesScrollers:YES]; + return [container autorelease]; +} + +@end diff --git a/cocoalib/views/NSIndexPathAdditions.h b/cocoalib/views/NSIndexPathAdditions.h new file mode 100644 index 00000000..25ba2369 --- /dev/null +++ b/cocoalib/views/NSIndexPathAdditions.h @@ -0,0 +1,20 @@ +/* +Copyright 2013 Hardcoded Software (http://www.hardcoded.net) + +This software is licensed under the "BSD" License as described in the "LICENSE" file, +which should be included with this package. The terms are also available at +http://www.hardcoded.net/licenses/bsd_license +*/ + +#import + +/* This is a hack to easily get around a cocoa limitation + +In some weird circumstances, NSOutlineView calls [item indexPath] to the item instances given to +it. I guess is expects eveyone to give it NSTreeNode instances. Anyway, because in MG, simple +NSIndexPath are used, it causes problems. Not anymore. +*/ + +@interface NSIndexPath(NSIndexPathAdditions) +- (NSIndexPath *)indexPath; +@end \ No newline at end of file diff --git a/cocoalib/views/NSIndexPathAdditions.m b/cocoalib/views/NSIndexPathAdditions.m new file mode 100644 index 00000000..956e2691 --- /dev/null +++ b/cocoalib/views/NSIndexPathAdditions.m @@ -0,0 +1,16 @@ +/* +Copyright 2013 Hardcoded Software (http://www.hardcoded.net) + +This software is licensed under the "BSD" License as described in the "LICENSE" file, +which should be included with this package. The terms are also available at +http://www.hardcoded.net/licenses/bsd_license +*/ + +#import "NSIndexPathAdditions.h" + +@implementation NSIndexPath(NSIndexPathAdditions) +- (NSIndexPath *)indexPath +{ + return self; +} +@end \ No newline at end of file diff --git a/cocoalib/views/NSTableViewAdditions.h b/cocoalib/views/NSTableViewAdditions.h new file mode 100644 index 00000000..6849cfac --- /dev/null +++ b/cocoalib/views/NSTableViewAdditions.h @@ -0,0 +1,24 @@ +/* +Copyright 2013 Hardcoded Software (http://www.hardcoded.net) + +This software is licensed under the "BSD" License as described in the "LICENSE" file, +which should be included with this package. The terms are also available at +http://www.hardcoded.net/licenses/bsd_license +*/ + +#import + + +@interface NSTableView(NSTableViewAdditions) +- (BOOL)dispatchSpecialKeys:(NSEvent *)event; +- (NSNotification *)processTextDidEndEditing:(NSNotification *)notification; +- (void)startEditing; +@end + +@interface NSObject(NSTableViewAdditionsDelegate) +- (BOOL)tableViewHadDeletePressed:(NSTableView *)tableView; +- (BOOL)tableViewHadReturnPressed:(NSTableView *)tableView; +- (BOOL)tableViewHadSpacePressed:(NSTableView *)tableView; +- (BOOL)tableView:(NSTableView *)tableView receivedKeyEvent:(NSEvent *)aEvent; +- (BOOL)shouldEditTableColumn:(NSTableColumn *)column row:(NSInteger)row; +@end \ No newline at end of file diff --git a/cocoalib/views/NSTableViewAdditions.m b/cocoalib/views/NSTableViewAdditions.m new file mode 100644 index 00000000..2c91fb96 --- /dev/null +++ b/cocoalib/views/NSTableViewAdditions.m @@ -0,0 +1,118 @@ +/* +Copyright 2013 Hardcoded Software (http://www.hardcoded.net) + +This software is licensed under the "BSD" License as described in the "LICENSE" file, +which should be included with this package. The terms are also available at +http://www.hardcoded.net/licenses/bsd_license +*/ + +#import "NSTableViewAdditions.h" +#import "NSEventAdditions.h" +#import "Utils.h" + +@implementation NSTableView(NSTableViewAdditions) + +/* Private methods */ + +// Alright, this is a hack. It has been added to put in common some table and outline code, but the +// thing is an outline view delegate doesn't use tableView:shouldEditTableColumn:row:. Anyway, for +// the outline, just using [column isEditable] works in moneyGuru for now, so we can keep it that way. +- (BOOL)shouldEditTableColumn:(NSTableColumn *)column row:(NSInteger)row +{ + if (![column isEditable]) + return NO; + id delegate = [self delegate]; + if ([delegate respondsToSelector:@selector(tableView:shouldEditTableColumn:row:)]) + { + return [delegate tableView:self shouldEditTableColumn:column row:row]; + } + else + { + return YES; + } +} + +/* Public Methods */ + +// Returns whether the responder chain should be stopeed or not +- (BOOL)dispatchSpecialKeys:(NSEvent *)event +{ + id delegate = [self delegate]; + if ([delegate respondsToSelector:@selector(tableView:receivedKeyEvent:)]) { + if ([delegate tableView:self receivedKeyEvent:event]) { + return YES; + } + } + BOOL stopChain = NO; + if ([event isDeleteOrBackspace] && [delegate respondsToSelector:@selector(tableViewHadDeletePressed:)]) + { + stopChain = [delegate tableViewHadDeletePressed:self]; + } + if ([event isReturnOrEnter] && [delegate respondsToSelector:@selector(tableViewHadReturnPressed:)]) + { + stopChain = [delegate tableViewHadReturnPressed:self]; + } + if ([event isSpace] && [delegate respondsToSelector:@selector(tableViewHadSpacePressed:)]) + { + stopChain = [delegate tableViewHadSpacePressed:self]; + } + if ([event isTab]) + { + stopChain = YES; + [[self window] makeFirstResponder:[self nextValidKeyView]]; + } + if ([event isBackTab]) + { + stopChain = YES; + // Ok, this is a big hack. the normal handling of NSTableView must handle this, but we must skip over + // a NSClipView and a NSScrollView before getting to the actual previousValidKeyView. + // However, when we are not in Full Keyboard Access mode, there's no problem. Thus, we assume that + // when previousValidKeyView's class is a NSClipView, it means we must perform the hack + NSView *previous = [self previousValidKeyView]; + if ([[previous className] isEqualTo:@"NSClipView"]) // Can't use isKindOfClass, we don't want to test for a subclass + previous = [[previous previousValidKeyView] previousValidKeyView]; + [[self window] makeFirstResponder:previous]; + } + return stopChain; +} + +- (NSNotification *)processTextDidEndEditing:(NSNotification *)notification; +{ + NSDictionary *userInfo = [notification userInfo]; + int textMovement = [[userInfo valueForKey:@"NSTextMovement"] intValue]; + if (textMovement == NSReturnTextMovement) + { + // Stop editing + NSMutableDictionary *newInfo; + newInfo = [NSMutableDictionary dictionaryWithDictionary:userInfo]; + [newInfo setObject:[NSNumber numberWithInt:NSIllegalTextMovement] forKey:@"NSTextMovement"]; + notification = [NSNotification notificationWithName:[notification name] object:[notification object] userInfo:newInfo]; + } + return notification; +} + +- (void)startEditing +{ + // Make sure one row is selected + if ([self selectedRow] == -1) + { + return; + } + + // We only want to edit columns that are editable. If there aren't any, don't edit. + for (NSInteger i=0;i<[[self tableColumns] count];i++) { + NSTableColumn *col = [[self tableColumns] objectAtIndex:i]; + if ([col isHidden]) { + continue; + } + if (![self shouldEditTableColumn:col row:[self selectedRow]]) { + continue; + } + // We only want one row to be selected. + NSIndexSet *selection = [NSIndexSet indexSetWithIndex:[self selectedRow]]; + [self selectRowIndexes:selection byExtendingSelection:NO]; + [self editColumn:i row:[self selectedRow] withEvent:nil select:YES]; + break; + } +} +@end