├── CIPAppleScriptHelper.h ├── CIPAppleScriptHelper.m ├── FirefoxPrefsParser.h ├── FirefoxPrefsParser.m ├── GCUndoManager.h ├── GCUndoManager.m ├── IFVerticallyExpandingTextField.h ├── IFVerticallyExpandingTextField.m ├── License.txt ├── MAKVONotificationCenter.h ├── MAKVONotificationCenter.m ├── NSFancyPanel.h ├── NSFancyPanel.m ├── NSPredicate+SSYPreflight.h ├── NSPredicate+SSYPreflight.m ├── NSSet+MoreComparisons.h ├── NSSet+MoreComparisons.m ├── NSString+PythonPickles.h ├── NSString+PythonPickles.m ├── README.md ├── SCEvents ├── SCEvent.h ├── SCEvent.m ├── SCEventListenerProtocol.h ├── SCEvents.h └── SCEvents.m ├── SSButton.h ├── SSButton.m ├── SSCheckboxTableColumn.h ├── SSCheckboxTableColumn.m ├── SSContactInfoReviewer.h ├── SSContactInfoReviewer.m ├── SSContactInfoWindow.nib ├── classes.nib ├── info.nib └── keyedobjects.nib ├── SSCronJob.h ├── SSCronJob.m ├── SSDocInPrefs.h ├── SSDocInPrefs.m ├── SSJunkA.h ├── SSJunkA.m ├── SSJunkB.h ├── SSJunkB.m ├── SSMatrixButtons.h ├── SSMatrixButtons.m ├── SSMenu.h ├── SSMenu.m ├── SSMonthMatrix.h ├── SSMonthMatrix.m ├── SSMoveableToolTip.h ├── SSMoveableToolTip.m ├── SSProgTextField.h ├── SSProgTextField.m ├── SSQueuedSpeechSynthesizer.h ├── SSQueuedSpeechSynthesizer.m ├── SSRadioButtonCell.h ├── SSRadioButtonCell.m ├── SSTableKit.h ├── SSTableKit.m ├── SSTableView.h ├── SSTableView.m ├── SSTruncatingTextField.h ├── SSTruncatingTextField.m ├── SSWebBrowsing.h ├── SSWebBrowsing.m ├── SSYAbbreviateMarker.h ├── SSYAbbreviateMarker.m ├── SSYAboutPanelController.h ├── SSYAboutPanelController.m ├── SSYAlert.h ├── SSYAlert.m ├── SSYAlertSounder (original).h ├── SSYAlertSounder (original).m ├── SSYAppInfo.h ├── SSYAppInfo.m ├── SSYAppleScripter.h ├── SSYAppleScripter.m ├── SSYArrayController.h ├── SSYArrayController.m ├── SSYAutoHeightBox.h ├── SSYAutoHeightBox.m ├── SSYAutoHeightTableView.h ├── SSYAutoHeightTableView.m ├── SSYBackgroundAwareWindow.h ├── SSYBackgroundAwareWindow.m ├── SSYBinderView.h ├── SSYBinderView.m ├── SSYBlocker.h ├── SSYBlocker.m ├── SSYCachyAliasResolver.h ├── SSYCachyAliasResolver.m ├── SSYCarbonSearcher.h ├── SSYCarbonSearcher.m ├── SSYChromePaths.h ├── SSYChromePaths.m ├── SSYClickActionTextField.h ├── SSYClickActionTextField.m ├── SSYDeallocDetector.h ├── SSYDeallocDetector.m ├── SSYDebug.h ├── SSYDebug.m ├── SSYDictionaryDebugger.h ├── SSYDictionaryDebugger.m ├── SSYDictionaryEntry.h ├── SSYDictionaryEntry.m ├── SSYDigester.h ├── SSYDigester.m ├── SSYDisplayAlotPopUpButtonCell.h ├── SSYDisplayAlotPopUpButtonCell.m ├── SSYDocChildObject.h ├── SSYDocChildObject.m ├── SSYDocTabViewController.h ├── SSYDocTabViewController.m ├── SSYDooDoo+GCUndoManager.zip ├── SSYDooDooUndoManager.h ├── SSYDooDooUndoManager.m ├── SSYDragDestinationTextView.h ├── SSYDragDestinationTextView.m ├── SSYDragTableView.h ├── SSYDragTableView.m ├── SSYDropboxGuy.h ├── SSYDropboxGuy.m ├── SSYDropboxIdler.h ├── SSYDropboxIdler.m ├── SSYDynamicMenu.h ├── SSYDynamicMenu.m ├── SSYEventInfo.h ├── SSYEventInfo.m ├── SSYExtrospectiveViewController.h ├── SSYExtrospectiveViewController.m ├── SSYFileDropView.h ├── SSYFileDropView.m ├── SSYFileFinder.h ├── SSYFileFinder.m ├── SSYFileThumbnailView.h ├── SSYFileThumbnailView.m ├── SSYFirefoxProfiler.h ├── SSYFirefoxProfiler.m ├── SSYFolderMenu.h ├── SSYFolderMenu.m ├── SSYFoo.h ├── SSYFoo.m ├── SSYHintArrow.h ├── SSYHintArrow.m ├── SSYHintArrow.zip ├── SSYHintableWindow.h ├── SSYHintableWindow.m ├── SSYIOKit.h ├── SSYIOKit.m ├── SSYInterappClient.h ├── SSYInterappClient.m ├── SSYInterappServer.h ├── SSYInterappServer.m ├── SSYKeychain.h ├── SSYKeychain.m ├── SSYKeychainQuery.h ├── SSYKeychainQuery.m ├── SSYLabelledList.h ├── SSYLabelledList.m ├── SSYLabelledPopUp.h ├── SSYLabelledPopUp.m ├── SSYLabelledRadioButtons.h ├── SSYLabelledRadioButtons.m ├── SSYLabelledTextField.h ├── SSYLabelledTextField.m ├── SSYLaunchdBasics.h ├── SSYLaunchdBasics.m ├── SSYLaunchdGuy.h ├── SSYLaunchdGuy.m ├── SSYLazyNotificationCenter.h ├── SSYLazyNotificationCenter.m ├── SSYLineBox.h ├── SSYLineBox.m ├── SSYLinearFileWriter.h ├── SSYLinearFileWriter.m ├── SSYListPicker.h ├── SSYListPicker.m ├── SSYMOCManager.h ├── SSYMOCManager.m ├── SSYMailto.h ├── SSYMailto.m ├── SSYManagedObject.h ├── SSYManagedObject.m ├── SSYManagedTreeObject.h ├── SSYManagedTreeObject.m ├── SSYMenuButton.h ├── SSYMenuButton.m ├── SSYMiniProgressWindow.h ├── SSYMiniProgressWindow.m ├── SSYModelChangeTypes.h ├── SSYModelChangeTypes.m ├── SSYMojo.h ├── SSYMojo.m ├── SSYMoreObserveableArrayController.h ├── SSYMoreObserveableArrayController.m ├── SSYMultiTextFieldCell.h ├── SSYMultiTextFieldCell.m ├── SSYNetServiceResolver.h ├── SSYNetServiceResolver.m ├── SSYNetServicesSearcher.h ├── SSYNetServicesSearcher.m ├── SSYNoVoiceOverControls.h ├── SSYNoVoiceOverControls.m ├── SSYNull.h ├── SSYNull.m ├── SSYOAuthTalker.h ├── SSYOAuthTalker.m ├── SSYOperation.h ├── SSYOperation.m ├── SSYOperationQueue.h ├── SSYOperationQueue.m ├── SSYOtherApper.h ├── SSYOtherApper.m ├── SSYPathObserver.h ├── SSYPathObserver.m ├── SSYPathWaiter.h ├── SSYPathWaiter.m ├── SSYPersistentDocumentMultiMigrator.h ├── SSYPersistentDocumentMultiMigrator.m ├── SSYPieProgressView.h ├── SSYPieProgressView.m ├── SSYPoller.h ├── SSYPoller.m ├── SSYPopUpTableHeaderCell.h ├── SSYPopUpTableHeaderCell.m ├── SSYPrefsWindowController.h ├── SSYPrefsWindowController.m ├── SSYProcessTyper.h ├── SSYProcessTyper.m ├── SSYProgressView.h ├── SSYProgressView.m ├── SSYQueuedSpeechSynthesizer.h ├── SSYQueuedSpeechSynthesizer.m ├── SSYRSSParser.h ├── SSYRSSParser.m ├── SSYRecurringDate.h ├── SSYRecurringDate.m ├── SSYReplacePredicateEditorRowTemplate.h ├── SSYReplacePredicateEditorRowTemplate.m ├── SSYRunLoopTickler.h ├── SSYRunLoopTickler.m ├── SSYRuntimeUtilities.h ├── SSYRuntimeUtilities.m ├── SSYSearchField.h ├── SSYSearchField.m ├── SSYSemaphore.h ├── SSYSemaphore.m ├── SSYSheetEnder.h ├── SSYSheetEnder.m ├── SSYShellTasker.h ├── SSYShellTasker.m ├── SSYShortcutActuator.h ├── SSYShortcutActuator.m ├── SSYShortcutBackEnd.h ├── SSYShortcutBackEnd.m ├── SSYSidebarController.h ├── SSYSidebarController.m ├── SSYSizeFixxerSubview.h ├── SSYSizeFixxerSubview.m ├── SSYSmartHiliTableView.h ├── SSYSmartHiliTableView.m ├── SSYSpotlighter.h ├── SSYSpotlighter.m ├── SSYSqliter.h ├── SSYSqliter.m ├── SSYStarRatingView.h ├── SSYStarRatingView.m ├── SSYSuffixedMenuItem.h ├── SSYSuffixedMenuItem.m ├── SSYSuperFileManager.h ├── SSYSuperFileManager.m ├── SSYSynchronousHttp.h ├── SSYSynchronousHttp.m ├── SSYSystemDescriber.h ├── SSYSystemDescriber.m ├── SSYSystemSemaphore.h ├── SSYSystemSemaphore.m ├── SSYSystemUptimer.h ├── SSYSystemUptimer.m ├── SSYTabView.h ├── SSYTabView.m ├── SSYTabViewController.h ├── SSYTabViewController.m ├── SSYTableHeaderView.h ├── SSYTableHeaderView.m ├── SSYTasker.h ├── SSYTasker.m ├── SSYTempWindowController.h ├── SSYTempWindowController.m ├── SSYTextCodec.h ├── SSYTextCodec.m ├── SSYThreadConfinedCoreDataStack.h ├── SSYThreadConfinedCoreDataStack.m ├── SSYThreadPauser.h ├── SSYThreadPauser.m ├── SSYTokenField.h ├── SSYTokenField.m ├── SSYTokenFieldCell.h ├── SSYTokenFieldCell.m ├── SSYToolbarButton.h ├── SSYToolbarButton.m ├── SSYTransformBoolToTextColor.h ├── SSYTransformBoolToTextColor.m ├── SSYTransformDicToString.h ├── SSYTransformDicToString.m ├── SSYTransformIndexBase0To1.h ├── SSYTransformIndexBase0To1.m ├── SSYTransformNumberToString.h ├── SSYTransformNumberToString.m ├── SSYTransformSetToArray.h ├── SSYTransformSetToArray.m ├── SSYTreeTransformer.h ├── SSYTreeTransformer.m ├── SSYTroubleZipper.h ├── SSYTroubleZipper.m ├── SSYUserInfo.h ├── SSYUserInfo.m ├── SSYUuid.h ├── SSYUuid.m ├── SSYVectorImages.h ├── SSYVectorImages.m ├── SSYVersionTriplet.h ├── SSYVersionTriplet.m ├── SSYVerticalCenteredTextField.h ├── SSYVerticalCenteredTextField.m ├── SSYVolumeMountie.h ├── SSYVolumeMountie.m ├── SSYVolumeServerGuy.h ├── SSYVolumeServerGuy.m ├── SSYWeblocGuy.h ├── SSYWeblocGuy.m ├── SSYWindowHangout.h ├── SSYWindowHangout.m ├── SSYWrappingCheckbox.h ├── SSYWrappingCheckbox.m ├── SSYXMLPeeker.h ├── SSYXMLPeeker.m ├── Swift_Companions ├── SSYMethodSignatureDumper.h └── SSYMethodSignatureDumper.m ├── UKKQueue.zip ├── UKKQueue ├── .DS_Store ├── UKFNSubscribeFileWatcher.h ├── UKFNSubscribeFileWatcher.m ├── UKFileWatcher.h ├── UKFileWatcher.m ├── UKKQueue Readme.txt ├── UKKQueue.h ├── UKKQueue.m ├── UKMainThreadProxy.h └── UKMainThreadProxy.m ├── WBTimeControl.h └── WBTimeControl.m /CIPAppleScriptHelper.h: -------------------------------------------------------------------------------- 1 | // 2 | // CIPAppleScriptHelper.h 3 | // BirthdayWuff 4 | // 5 | // Created by Stefan Landvogt on 29.08.04. 6 | // Copyright 2004 Cipresso GmbH. All rights reserved. 7 | // 8 | 9 | #import 10 | 11 | 12 | @interface CIPAppleScriptHelper : NSObject { 13 | } 14 | 15 | + (id)sharedHelper; 16 | 17 | - (NSAppleEventDescriptor *)callInResource: (NSString *)resourcePath script: (NSString *)scriptName; 18 | - (NSAppleEventDescriptor *)callInResource: (NSString *)resourcePath script: (NSString *)scriptName withArg:(NSString *)argument; 19 | - (NSAppleEventDescriptor *)callInResource: (NSString *)resourcePath script: (NSString *)scriptName withArgs:(NSString *)args, ...; 20 | 21 | @end 22 | -------------------------------------------------------------------------------- /FirefoxPrefsParser.h: -------------------------------------------------------------------------------- 1 | #import 2 | 3 | @interface FirefoxPrefsParser : NSObject 4 | 5 | /*! 6 | @details The prefs.js file apparently contains a deep JavaScript object, 7 | expressed in JavaScript code, with everything quoted with escaped quotes. I 8 | don't know of any parser to handle that, so I wrote my own. I suppose I could 9 | have gotten something out of Firefox' open-source code, but would that have 10 | been any faster?? 11 | */ 12 | + (NSInteger)integerValueFromFirefoxPrefs:(NSString*)prefs 13 | identifier:(NSString*)targetIdentifier 14 | key:(NSString*)targetKey ; 15 | 16 | @end 17 | -------------------------------------------------------------------------------- /License.txt: -------------------------------------------------------------------------------- 1 | Copyright 2012 Jerome Krinock 2 | 3 | Licensed under the Apache License, Version 2.0 (the "License"); you may not use the files in this repository except in compliance with the License. You may obtain a copy of the License at 4 | 5 | http://www.apache.org/licenses/LICENSE-2.0 6 | 7 | Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License. 8 | 9 | If you need a different license, let me know. -------------------------------------------------------------------------------- /NSFancyPanel.h: -------------------------------------------------------------------------------- 1 | #import 2 | 3 | @interface NSFancyPanel : NSPanel 4 | 5 | @end 6 | -------------------------------------------------------------------------------- /NSFancyPanel.m: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jerrykrinock/ClassesObjC/9f8edc5f804e8d8e1d6183fe9cb91a94b2b83cf2/NSFancyPanel.m -------------------------------------------------------------------------------- /NSPredicate+SSYPreflight.h: -------------------------------------------------------------------------------- 1 | #import 2 | 3 | /*! 4 | @brief Returns whether or not the receiver can be used without raising 5 | an exception 6 | 7 | @details If the user sets a row in NSPredicateEditor to the "matches" 8 | predicate type and fills in an invalid regular expression pattern such as this 9 | one: 10 | (*( 11 | the predicate returned by -[NSPredicateRuleEditor objectValue] be an invalid 12 | and an exception will be raised if such a predicate is passed to, for example, 13 | -[NSArrayController setFilterPredicate:], an exception will be raised :( 14 | 15 | This method preflights such a predicate so you can avoid such an exception. */ 16 | @interface NSPredicate (SSYValidate) 17 | 18 | - (BOOL)preflightValidate ; 19 | 20 | @end 21 | -------------------------------------------------------------------------------- /NSPredicate+SSYPreflight.m: -------------------------------------------------------------------------------- 1 | #import "NSPredicate+SSYPreflight.h" 2 | 3 | @implementation NSPredicate (SSYValidate) 4 | 5 | - (BOOL)preflightValidate { 6 | BOOL answer = YES ; 7 | if ([self isKindOfClass:[NSComparisonPredicate class]]) { 8 | if ([(NSComparisonPredicate*)self predicateOperatorType] == NSMatchesPredicateOperatorType) { 9 | NSExpression* expression = [(NSComparisonPredicate*)self rightExpression] ; 10 | if ([expression expressionType] == NSConstantValueExpressionType) { 11 | id constantValue = [expression constantValue] ; 12 | if ([constantValue isKindOfClass:[NSString class]]) { 13 | NSError* error = nil ; 14 | NSRegularExpression* regex = [[NSRegularExpression alloc] initWithPattern:constantValue 15 | options:0 16 | error:&error] ; 17 | /* The error returned does not usually give much 18 | additional information. Here is an example: 19 | Error Domain=NSCocoaErrorDomain Code=2048 "The value “(*(” is invalid." UserInfo={NSInvalidValue=(*(} 20 | So, we don't bother passing it up. */ 21 | if (!regex || (error != nil)) { 22 | answer = NO ; 23 | } 24 | [regex release] ; 25 | } 26 | } 27 | } 28 | } 29 | else if ([self respondsToSelector:@selector(subpredicates)]) { 30 | for (NSPredicate* predicate in [(NSCompoundPredicate*)self subpredicates]) { 31 | if (![predicate preflightValidate]) { 32 | answer = NO ; 33 | break ; 34 | } 35 | } 36 | } 37 | else { 38 | /* Could be something like NSTruePredicate */ 39 | } 40 | 41 | return answer ; 42 | } 43 | 44 | @end 45 | -------------------------------------------------------------------------------- /NSSet+MoreComparisons.h: -------------------------------------------------------------------------------- 1 | #import 2 | 3 | 4 | @interface NSSet (MoreComparisons) 5 | 6 | /*! 7 | @brief Compares two set values for equality 8 | 9 | @details Use this instead of -isEqualToSet: 10 | if it is possible that both sets are nil, because, 11 | unlike -isEqualToSet:, it will give the correct answer 12 | of YES. 13 | @param set1 One of two sets to be compared. May be nil. 14 | @param set2 One of two sets to be compared. May be nil. 15 | @result If neither argument is nil, the value returned by sending 16 | -isEqualToSet: to either of them. If one argument is nil and the other 17 | is not nil, NO. If both arguments are nil, YES. 18 | Otherwise, NO 19 | */ 20 | + (BOOL)isEqualHandlesNilSet1:(NSSet*)set1 21 | set2:(NSSet*)set2 ; 22 | 23 | @end 24 | -------------------------------------------------------------------------------- /NSSet+MoreComparisons.m: -------------------------------------------------------------------------------- 1 | #import "NSSet+MoreComparisons.h" 2 | 3 | 4 | @implementation NSSet (MoreComparisons) 5 | 6 | + (BOOL)isEqualHandlesNilSet1:(NSSet*)set1 7 | set2:(NSSet*)set2 { 8 | BOOL isEqual = YES ; 9 | if (set1) { 10 | if (!set2) { 11 | // Documentation for -isEqualToSet does not state if 12 | // the argument can be nil, so for safety I handle that 13 | // here, without invoking it. 14 | isEqual = NO ; 15 | } 16 | else { 17 | isEqual = [set1 isEqualToSet:set2] ; 18 | } 19 | } 20 | else if (set2) { 21 | // oldValue is nil but newValue is not 22 | isEqual = NO ; 23 | } 24 | 25 | return isEqual ; 26 | } 27 | 28 | @end 29 | 30 | -------------------------------------------------------------------------------- /NSString+PythonPickles.h: -------------------------------------------------------------------------------- 1 | #import 2 | 3 | extern NSString* const SSYPythonPicklesErrorDomain ; 4 | extern NSString* const SSYPythonPicklesUnderErrorDomain ; 5 | 6 | @interface NSString (PythonPickles) 7 | 8 | - (NSString*)pythonUnpickledError_p:(NSError**)error_p ; 9 | 10 | @end 11 | 12 | 13 | #if 0 14 | TEST CODE 15 | 16 | int main(int argc, char *argv[]) { 17 | NSAutoreleasePool* pool = [[NSAutoreleasePool alloc] init] ; 18 | 19 | // The following string is an actual Python pickle. 20 | // Of course, one would never hard code such a thing in a real program. 21 | // This is just a test :) 22 | NSString* s = @"V/Users/jk/Dropbox2/Dropbox\np1\n.\n" ; 23 | NSError* error = nil ; 24 | 25 | // Do it three times to test for Python initialization issues. 26 | NSLog(@"Unpickled result: %@\n", 27 | [s pythonUnpickledError_p:&error]) ; 28 | 29 | NSLog(@"Unpickled result: %@\n", 30 | [s pythonUnpickledError_p:&error]) ; 31 | 32 | NSLog(@"Unpickled result: %@\n", 33 | [s pythonUnpickledError_p:&error]) ; 34 | 35 | // The correct answer for Unpickled result is: 36 | // "/Users/jk/Dropbox2/Dropbox" 37 | NSLog(@"error:\n%@", error) ; 38 | 39 | 40 | [pool release] ; 41 | return 0 ; 42 | } 43 | 44 | #endif -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | ClassesObjC 2 | =========== 3 | 4 | My general-purpose Objective-C classes which I use in various projects. Now requires macOS 10.12 or later. For older projects, use branch FrozenForMacOS10.10. 5 | -------------------------------------------------------------------------------- /SCEvents/SCEvent.h: -------------------------------------------------------------------------------- 1 | /* 2 | * $Id: SCEvent.h 36 2009-09-08 21:36:02Z stuart $ 3 | * 4 | * SCEvents 5 | * 6 | * Copyright (c) 2009 Stuart Connolly 7 | * http://stuconnolly.com/projects/source-code/ 8 | * 9 | * Permission is hereby granted, free of charge, to any person 10 | * obtaining a copy of this software and associated documentation 11 | * files (the "Software"), to deal in the Software without 12 | * restriction, including without limitation the rights to use, 13 | * copy, modify, merge, publish, distribute, sublicense, and/or sell 14 | * copies of the Software, and to permit persons to whom the 15 | * Software is furnished to do so, subject to the following 16 | * conditions: 17 | * 18 | * The above copyright notice and this permission notice shall be 19 | * included in all copies or substantial portions of the Software. 20 | * 21 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, 22 | * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES 23 | * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND 24 | * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT 25 | * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, 26 | * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING 27 | * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR 28 | * OTHER DEALINGS IN THE SOFTWARE. 29 | */ 30 | 31 | #import 32 | #import 33 | 34 | @interface SCEvent : NSObject 35 | { 36 | NSUInteger eventId; 37 | NSDate *eventDate; 38 | NSString *eventPath; 39 | FSEventStreamEventFlags eventFlag; 40 | } 41 | 42 | @property (readwrite, assign) NSUInteger eventId; 43 | @property (readwrite, retain) NSDate *eventDate; 44 | @property (readwrite, retain) NSString *eventPath; 45 | @property (readwrite, assign) FSEventStreamEventFlags eventFlag; 46 | 47 | + (SCEvent *)eventWithEventId:(NSUInteger)identifier eventDate:(NSDate *)date eventPath:(NSString *)path eventFlag:(FSEventStreamEventFlags)flag; 48 | 49 | - (id)initWithEventId:(NSUInteger)identifier eventDate:(NSDate *)date eventPath:(NSString *)path eventFlag:(FSEventStreamEventFlags)flag; 50 | 51 | @end -------------------------------------------------------------------------------- /SCEvents/SCEventListenerProtocol.h: -------------------------------------------------------------------------------- 1 | /* 2 | * $Id: SCEventListenerProtocol.h 34 2009-09-01 00:42:14Z stuart $ 3 | * 4 | * SCEvents 5 | * 6 | * Copyright (c) 2009 Stuart Connolly 7 | * http://stuconnolly.com/projects/source-code/ 8 | * 9 | * Permission is hereby granted, free of charge, to any person 10 | * obtaining a copy of this software and associated documentation 11 | * files (the "Software"), to deal in the Software without 12 | * restriction, including without limitation the rights to use, 13 | * copy, modify, merge, publish, distribute, sublicense, and/or sell 14 | * copies of the Software, and to permit persons to whom the 15 | * Software is furnished to do so, subject to the following 16 | * conditions: 17 | * 18 | * The above copyright notice and this permission notice shall be 19 | * included in all copies or substantial portions of the Software. 20 | * 21 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, 22 | * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES 23 | * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND 24 | * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT 25 | * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, 26 | * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING 27 | * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR 28 | * OTHER DEALINGS IN THE SOFTWARE. 29 | */ 30 | 31 | @class SCEvents, SCEvent; 32 | 33 | @protocol SCEventListenerProtocol 34 | 35 | /** 36 | * Conforming objects' implementation of this method will be called whenever an 37 | * event occurs. The instance of SCEvents which received the event and the event 38 | * itself are passed as parameters. 39 | */ 40 | - (void)pathWatcher:(SCEvents *)pathWatcher eventOccurred:(SCEvent *)event; 41 | 42 | @end 43 | -------------------------------------------------------------------------------- /SSButton.h: -------------------------------------------------------------------------------- 1 | #import 2 | 3 | 4 | @interface SSButtonCell : NSButtonCell { 5 | 6 | NSColor* _color ; 7 | } 8 | 9 | - (id)initWithTitleFont:(NSFont*)font ; 10 | - (void)setColor:(NSColor*)color ; 11 | 12 | @end 13 | 14 | @interface SSButton : NSButton { 15 | NSString* _titleText ; 16 | NSString* _keyEquivalentSuffix ; 17 | BOOL keyEquivalentShowing ; 18 | CGFloat widthMargin ; 19 | BOOL keyEquivalentWithOrWithoutAltKey ; 20 | } 21 | 22 | - (BOOL)keyEquivalentWithOrWithoutAltKey; 23 | - (void)setKeyEquivalentWithOrWithoutAltKey:(BOOL)value; 24 | 25 | - (void)setColor:(NSColor*)color ; 26 | - (void)setTitleText:(NSString*)titleText ; 27 | - (void)setKeyEquivalentSuffix:(NSString*)suffix ; 28 | - (void)setWidthMargin:(CGFloat)wm ; 29 | - (void)showKeyEquivalent ; 30 | - (void)hideKeyEquivalent ; 31 | 32 | 33 | @end 34 | -------------------------------------------------------------------------------- /SSCheckboxTableColumn.h: -------------------------------------------------------------------------------- 1 | @interface SSCheckboxTableColumn : NSTableColumn 2 | { 3 | } 4 | 5 | @end 6 | 7 | -------------------------------------------------------------------------------- /SSCheckboxTableColumn.m: -------------------------------------------------------------------------------- 1 | #import "SSCheckboxTableColumn.h" 2 | 3 | 4 | @implementation SSCheckboxTableColumn 5 | 6 | // This is a callback from the OS 7 | - (id)dataCellForRow:(NSInteger)iRow 8 | { 9 | NSButtonCell * cell =[[NSButtonCell alloc] init]; 10 | [cell setControlSize:NSSmallControlSize] ; 11 | [cell setButtonType:NSSwitchButton] ; 12 | [cell setTitle:@""] ; 13 | [cell setImagePosition:NSImageOnly] ; 14 | return [cell autorelease] ; 15 | } 16 | 17 | @end 18 | 19 | -------------------------------------------------------------------------------- /SSContactInfoReviewer.h: -------------------------------------------------------------------------------- 1 | #import 2 | 3 | @interface SSContactInfoReviewer : NSWindowController 4 | { 5 | IBOutlet NSButton *buttonOK; 6 | IBOutlet NSButton *buttonCancel; 7 | 8 | IBOutlet NSTextField *labelEmail; 9 | IBOutlet NSTextField *labelIntro; 10 | IBOutlet NSTextField *labelName; 11 | IBOutlet NSTextField *labelAnythingElse; 12 | 13 | IBOutlet NSTextField *textEmail; 14 | IBOutlet NSTextField *textFirstName; 15 | IBOutlet NSTextField *textLastName; 16 | IBOutlet NSTextField *textUneditable; 17 | IBOutlet NSTextView *textAnythingElse; 18 | 19 | IBOutlet NSWindow *window; 20 | 21 | NSString* _displayText ; 22 | NSArray* _apps ; 23 | NSArray* _appVersions ; 24 | NSString* _runningVersion ; 25 | NSDictionary* _miscellaneousInfo ; 26 | BOOL sendIt ; 27 | } 28 | 29 | // This factory method: 30 | // initializes a SSContactInfoReviewer, 31 | // shows user the info in a modal window to allow some changes, 32 | // retrieves edited info from window and places into NSDictionary* info 33 | // destroys the SSContactInfoReviewer 34 | // returns the info 35 | 36 | + (NSDictionary*)infoWithDisplayText:(NSString*)displayText 37 | appsToReportVersion:(NSArray*)apps 38 | miscellaneousInfo:(NSDictionary*)miscellaneousInfo ; 39 | 40 | // display text is intro text to be shown to user. Will not be further localized. 41 | // apps is a list of (string) app names whose version number will be included in info 42 | // miscellaneousInfo are strings of info to be shown to user and included in info. 43 | // keys in miscellaneousInfo will be NSLocalized for showing to user 44 | // keys in miscellaneousInfo will be translated accouring to TransmittedKeyForKey for transmitting 45 | 46 | 47 | @end 48 | -------------------------------------------------------------------------------- /SSContactInfoWindow.nib/info.nib: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | IBFramework Version 6 | 629 7 | IBLastKnownRelativeProjectPath 8 | ../../SSApp.xcodeproj 9 | IBOldestOS 10 | 5 11 | IBOpenObjects 12 | 13 | 2 14 | 15 | IBSystem Version 16 | 9C31 17 | targetFramework 18 | IBCocoaFramework 19 | 20 | 21 | -------------------------------------------------------------------------------- /SSContactInfoWindow.nib/keyedobjects.nib: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jerrykrinock/ClassesObjC/9f8edc5f804e8d8e1d6183fe9cb91a94b2b83cf2/SSContactInfoWindow.nib/keyedobjects.nib -------------------------------------------------------------------------------- /SSCronJob.h: -------------------------------------------------------------------------------- 1 | #import 2 | #import "SSAppGlobals.h" 3 | 4 | enum SSWhichCrontab { 5 | SSSystemCrontab, 6 | SSUserCrontab 7 | } ; 8 | 9 | //enum SSCronHoursMask { 10 | // SSMaskNoHour = 0 , 11 | // SSMaskEveryHour = 0x00ffffff 12 | // // To indicate any hour, shift the number 1 left by the hour. 13 | // // Example, for hour 0, so the SSDateOfMonth would be 1 << 0 = 0x1 14 | //} ; 15 | // 16 | //// Named day of week 17 | //enum SSCronDaysMask { 18 | // SSMaskNoDay = 0 , 19 | // SSMaskSunday = 1 , 20 | // SSMaskMonday = 2 , 21 | // SSMaskTuesday = 4 , 22 | // SSMaskWednesday = 8 , 23 | // SSMaskThursday = 16 , 24 | // SSMaskFriday = 32 , 25 | // SSMaskSaturday = 64 , 26 | // SSMaskWeekdays = 0x3E , 27 | // SSMaskEveryDay = 0x7F 28 | //} ; 29 | // 30 | //// Numbered date of month 31 | //enum SSCronDatesMask { 32 | // SSMaskNoDate = 0 , 33 | // SSMaskEveryDate = 0xfffffffe 34 | // // To indicate any day, shift the number 1 left by the date. 35 | // // Example, for September 4, date = 4, so the SSDateOfMonth would be 1 << 4 36 | // // Note that the least significant bit is never used. 37 | //} ; 38 | // 39 | //enum SSCronMonthsMask { 40 | // SSMaskNoMonth = 0 , 41 | // SSMaskEveryMonth = 0x00001ffe 42 | // // To indicate any month, shift the number 1 left by the date. 43 | // // Example, for September 4, date = 4, so the SSDateOfMonth would be 1 << 4 44 | // // Note that the least significant bit is never used. 45 | //} ; 46 | // 47 | //typedef int unsigned SSCronMask ; 48 | 49 | NSString* SSLocalizedDayOfWeekFromCronNumber(NSInteger n) ; 50 | NSArray* SSLocalizedDaysOfWeekFromCronNumbers(NSArray* numbers) ; 51 | 52 | @interface SSCronJob : NSObject 53 | { 54 | NSString* _commentOut ; 55 | // if _commentOut is nil, job will be enabled 56 | // else, job will be disabled by commenting out with the prefix field "#_commentOut\t" 57 | // When reading crontab files, whitespace will be trimmed from ends of _commentOut 58 | NSArray* _minutes ; 59 | NSArray* _hours ; 60 | NSArray* _days ; 61 | NSArray* _dates ; 62 | NSArray* _months ; 63 | NSString* _user ; 64 | NSString* _directory ; 65 | NSString* _filename ; 66 | } ; 67 | 68 | SSAOh(NSString*,commentOut, setCommentOut) 69 | SSAOh(NSArray*, minutes, setMinutes) 70 | SSAOh(NSArray*, hours, setHours) 71 | SSAOh(NSArray*, days, setDays) 72 | SSAOh(NSArray*, dates, setDates) 73 | SSAOh(NSArray*, months, setMonths) 74 | SSAOh(NSString*, user, setUser) 75 | SSAOh(NSString*, directory, setDirectory) 76 | SSAOh(NSString*, filename, setFilename) 77 | 78 | + (NSArray*)readCronJobsFromWhichCrontab:(enum SSWhichCrontab)which user:(NSString*)user ; 79 | - (void)appendToFileWhichCrontab:(enum SSWhichCrontab)which ; 80 | 81 | @end -------------------------------------------------------------------------------- /SSDocInPrefs.h: -------------------------------------------------------------------------------- 1 | #import 2 | 3 | //////////////////////////////////////////////// 4 | // ACCESSOR MACROS 5 | // 6 | // These macros may be used in the document .m file 7 | // to generate accessors 8 | // 9 | // Note: SSBIDA = Sheep Systems Built-In Document Accessor 10 | //////////////////////////////////////////////// 11 | 12 | // for objects (O) 13 | #define SSBIDAO(NAME,SETNAME,KEY) - (void)SETNAME:(id)in { \ 14 | [self setObject:in forKey:KEY] ; \ 15 | } \ 16 | \ 17 | - (id)NAME { \ 18 | return [self objectForKey:KEY] ; \ 19 | } \ 20 | 21 | // for integer (I) 22 | #define SSBIDAI(NAME,SETNAME,KEY) - (void)SETNAME:(NSInteger)in { \ 23 | [self setInteger:in forKey:KEY] ; \ 24 | } \ 25 | \ 26 | - (NSInteger)NAME { \ 27 | return [self integerForKey:KEY] ; \ 28 | } \ 29 | 30 | // for BOOL (B) 31 | #define SSBIDAB(NAME,SETNAME,KEY) - (void)SETNAME:(BOOL)in { \ 32 | [self setBool:in forKey:KEY] ; \ 33 | } \ 34 | \ 35 | - (BOOL)NAME { \ 36 | return [self boolForKey:KEY] ; \ 37 | } \ 38 | 39 | @interface SSDocInPrefs : NSObject 40 | { 41 | NSString* _aggregateKey ; 42 | NSString* _documentKey ; 43 | NSDictionary* _defaultDefaults ; 44 | } 45 | 46 | - (id)initWithAggregateKey:(NSString*)aggregateName 47 | documentKey:(NSString*)documentKey 48 | defaultDefaults:(NSDictionary*)defaultDefaults ; 49 | 50 | + (id)SSBuiltInDocumentWithAggregateKey:(NSString*)aggregateKey 51 | documentKey:(NSString*)documentKey 52 | defaultDefaults:(NSDictionary*)defaultDefaults ; 53 | 54 | - (void)setObject:(id)object forKey:(NSString*)attributeKey ; 55 | - (id)objectForKey:(NSString*)attributeKey ; 56 | - (void)setBool:(BOOL)yn forKey:(NSString*)attributeKey ; 57 | - (BOOL)boolForKey:(NSString*)attributeKey ; 58 | - (void)setInteger:(NSInteger)n forKey:(NSString*)attributeKey ; 59 | - (NSInteger)integerForKey:(NSString*)attributeKey ; 60 | 61 | - (void)removeObjectForKey:(NSString*)attributeKey ; 62 | - (void)removeAllAttributes ; 63 | 64 | @end -------------------------------------------------------------------------------- /SSJunkA.h: -------------------------------------------------------------------------------- 1 | @interface SSJunkA : NSObject { 2 | } 3 | 4 | + (void)sayHello ; 5 | 6 | @end 7 | -------------------------------------------------------------------------------- /SSJunkA.m: -------------------------------------------------------------------------------- 1 | #import "SSJunkA.h" 2 | 3 | @implementation SSJunkA : NSObject 4 | 5 | + (void)sayHello { 6 | NSLog(@"Hello A") ; 7 | } 8 | 9 | @end 10 | -------------------------------------------------------------------------------- /SSJunkB.h: -------------------------------------------------------------------------------- 1 | @interface SSJunkB : NSObject { 2 | } 3 | 4 | + (void)sayHello ; 5 | 6 | @end 7 | 8 | -------------------------------------------------------------------------------- /SSJunkB.m: -------------------------------------------------------------------------------- 1 | #import "SSJunkB.h" 2 | 3 | @implementation SSJunkB : NSObject 4 | 5 | + (void)sayHello { 6 | NSLog(@"Hello B") ; 7 | } 8 | 9 | @end 10 | -------------------------------------------------------------------------------- /SSMatrixButtons.h: -------------------------------------------------------------------------------- 1 | #define KEY_CELL_KEY @"CellKey" 2 | #define KEY_CELL_VALUE @"CellValue" 3 | 4 | @interface SSMatrixButtons : NSMatrix { 5 | NSInteger _tagOffset ; 6 | } 7 | 8 | SSANh(NSInteger, tagOffset, setTagOffset) 9 | 10 | 11 | @end 12 | -------------------------------------------------------------------------------- /SSMatrixButtons.m: -------------------------------------------------------------------------------- 1 | #import "SSMatrixButtons.h" 2 | 3 | @implementation SSMatrixButtons 4 | 5 | SSANm(NSInteger, tagOffset, setTagOffset) 6 | 7 | // Over-rides of NSMatrix methods 8 | // The objectValue is an NSArray of NSNumbers of buttons which are pushed 9 | 10 | - (NSArray*)objectValue { 11 | NSMutableArray* pushedButtonIndexes = [[NSMutableArray alloc] init] ; 12 | NSEnumerator* e = [[self cells] objectEnumerator] ; 13 | NSCell* cell ; 14 | while ((cell = [e nextObject])) { 15 | if ([[cell objectValue] boolValue]) { 16 | NSNumber* value = [NSNumber numberWithInteger:([cell tag] + _tagOffset)] ; 17 | [pushedButtonIndexes addObject:value] ; 18 | } 19 | } 20 | 21 | NSArray* output = [pushedButtonIndexes copy] ; 22 | [pushedButtonIndexes release] ; 23 | return [output autorelease] ; 24 | } 25 | 26 | - (void)setObjectValue:(NSArray*)pushedButtonIndexes { 27 | NSEnumerator* e = [[self cells] objectEnumerator] ; 28 | NSCell* cell ; 29 | while ((cell = [e nextObject])) { 30 | NSNumber* cellKey = [NSNumber numberWithInteger:([cell tag] + _tagOffset)] ; 31 | BOOL active = ([pushedButtonIndexes indexOfObject:cellKey] != NSNotFound) ; 32 | NSNumber* value = [NSNumber numberWithBool:active] ; 33 | [cell setObjectValue:value] ; 34 | } 35 | } 36 | 37 | - (id)initWithCoder:(NSCoder*)coder { 38 | if ((self = [super initWithCoder:coder])) { 39 | _tagOffset = 0 ; 40 | } 41 | 42 | return self ; 43 | } 44 | 45 | @end 46 | -------------------------------------------------------------------------------- /SSMenu.h: -------------------------------------------------------------------------------- 1 | @interface SSMenu : NSMenu { 2 | 3 | NSMenuItem* owningMenuItem ; // the NSMenuItem which this object is the submenu of 4 | // weak reference, to avoid retain cycles 5 | } 6 | 7 | - (NSMenuItem *)owningMenuItem; 8 | - (void)setOwningMenuItem:(NSMenuItem *)value; 9 | 10 | 11 | - (id)initWithOwningMenuItem:(id)owningMenuItem ; 12 | // Note: Retains weak reference to owningMenuItem, to avoid retain cycle 13 | 14 | @end 15 | -------------------------------------------------------------------------------- /SSMonthMatrix.h: -------------------------------------------------------------------------------- 1 | #import "SSMatrixButtons.h" 2 | 3 | @interface SSMonthMatrix : SSMatrixButtons { 4 | 5 | } 6 | 7 | 8 | @end 9 | -------------------------------------------------------------------------------- /SSMonthMatrix.m: -------------------------------------------------------------------------------- 1 | #import "SSMonthMatrix.h" 2 | #import "SSUtilityCategories.h" 3 | #import "SSYLocalize/NSString+Localize.h" 4 | 5 | @implementation SSMonthMatrix 6 | 7 | // Over-rides of NSMatrix methods 8 | // The objectValue is an NSArray of NSNumbers of buttons which are pushed 9 | //- (NSArray*)objectValue { 10 | // NSMutableArray* pushedButtonIndexes = [[NSMutableArray alloc] init] ; 11 | // NSEnumerator* e = [[self cells] reverseObjectEnumerator] ; 12 | // // We go in reverse because we first want to see if lastDayOfTheMonth is active 13 | // // because if it is, we filter out days 29, 30 and 31. 14 | // BOOL lastDayOfMonthActive = NO ; 15 | // NSCell* cell ; 16 | // while ((cell = [e nextObject])) { 17 | // if ([[cell objectValue] boolValue]) { 18 | // int intValue = ([cell tag] + _tagOffset) ; 19 | // if (intValue == 32) { 20 | // lastDayOfMonthActive = YES ; 21 | // } 22 | // if (!lastDayOfMonthActive || (intValue <= 28) || (intValue >= 32)) { 23 | // NSNumber* value = [NSNumber numberWithInt:intValue] ; 24 | // [pushedButtonIndexes addObject:value] ; 25 | // } 26 | // } 27 | // } 28 | // 29 | // NSArray* output = [[NSArray arrayWithArray:pushedButtonIndexes] arrayByReversingOrder] ; 30 | // // Note that we also re-reverse the array to get it back in normal order 31 | // [pushedButtonIndexes release] ; 32 | // return output ; 33 | //} 34 | 35 | //- (void)setObjectValue:(NSArray*)pushedButtonIndexes { 36 | // [super setObjectValue:pushedButtonIndexes] ; 37 | // 38 | // int i ; 39 | // for (i=28; i<=31; i++) { 40 | // NSButtonCell* cell = [self cellWithTag:(i - _tagOffset)] ; 41 | // if (lastDayOfMonthActive) { 42 | // [cell setState:NSOffState] ; 43 | // [cell setEnabled:NO] ; 44 | // } 45 | // else { 46 | // [cell setEnabled:YES] ; 47 | // } 48 | // } 49 | //} 50 | 51 | - (id)initWithCoder:(NSCoder*)coder { 52 | if ((self = [super initWithCoder:coder])) { 53 | _tagOffset = 1 ; // Since cells start with 0 but months start with 1 54 | } 55 | 56 | return self ; 57 | } 58 | 59 | - (void)awakeFromNib { 60 | [self setToolTip:[NSString localize:@"lastDayOfTheMonth"] forCell:[self cellWithTag:(32 - _tagOffset)]] ; 61 | NSInteger i ; 62 | for (i=29; i<=31; i++) { 63 | NSButtonCell* cell = [self cellWithTag:(i - _tagOffset)] ; 64 | [self setToolTip:[NSString localize:@"warningWillRunOnLastDay"] forCell:cell] ; 65 | } 66 | } 67 | 68 | @end 69 | -------------------------------------------------------------------------------- /SSMoveableToolTip.h: -------------------------------------------------------------------------------- 1 | // Adapted from code by Eric Forget, http://www.cocoadev.com/index.pl?ToolTip 2 | 3 | @interface SSMoveableToolTip : NSObject { 4 | NSPoint _offset ; 5 | NSWindow* _window ; 6 | NSTextField* _textField ; 7 | } 8 | 9 | /* 10 | @brief Displays a moveable tool tip with given parameters 11 | 12 | @details Any tooltip displayed by a prior invocation of this method 13 | disappears, so that there isonly one simultaneous moveable tooltip per app. 14 | If you really want more than one, talk to the User Interface Police :)) 15 | @param font The font to be used in the tooltip. If you pass nil, defaults 16 | to [NSFont toolTipsFontOfSize:[NSFont systemFontSize]] which is what Cocoa 17 | uses. 18 | @param offset On 2013-12-04, removed hard-coded 19 | offset of (10.0, 28.0) in the implementation which was 20 | being added to the offset you pass here. 21 | */ 22 | + (void)setString:(NSString *)string 23 | font:(NSFont*)font 24 | origin:(NSPoint)origin 25 | inWindow:(NSWindow*)hostWindow ; 26 | 27 | + (void)goAway ; 28 | 29 | + (void)setOffset:(NSPoint)offset ; 30 | 31 | @end 32 | -------------------------------------------------------------------------------- /SSProgTextField.h: -------------------------------------------------------------------------------- 1 | @interface SSRolloverButton : NSButton { 2 | } 3 | @end 4 | 5 | @interface SSProgTextField : NSControl { 6 | NSProgressIndicator* _progBar ; 7 | NSTextField* _textField ; 8 | SSRolloverButton* _hyperButton ; 9 | SSRolloverButton* _cancelButton ; 10 | NSRect _wholeFrame ; 11 | NSInteger progBarLimit ; 12 | NSTimeInterval _nextProgressUpdate ; 13 | } 14 | 15 | - (void)setVerb:(NSString*)newVerb 16 | resize:(BOOL)resize ; 17 | - (void)setProgressBarWidth:(CGFloat)width ; 18 | - (void)setHasCancelButtonWithTarget:(id)target 19 | action:(SEL)action ; 20 | // To show determinate progress 21 | - (void)setMaxValue:(double)value ; 22 | // also sets it to determinate 23 | - (void)setIndeterminate:(BOOL)yn ; 24 | - (void)setDoubleValue:(double)value ; 25 | - (void)incrementDoubleValueBy:(double)value ; 26 | - (void)incrementDoubleValueByObject:(NSNumber*)value ; 27 | 28 | // The following methods configuration methods will invoke 29 | // -display to display immediately 30 | 31 | - (void)displayClearAll ; 32 | - (void)displayIndeterminate:(BOOL)indeterminate 33 | withLocalizableVerb:(NSString*)localizableVerb ; 34 | // localizableVerb will be localized and an ellipsis appended. 35 | // It will be displayed alongside the progress bar. 36 | - (void)displayIndeterminate:(BOOL)indeterminate 37 | withLocalizedVerb:(NSString*)localizableVerb ; 38 | // localizedVerb will have ellipsis appended. 39 | // It will be displayed alongside the progress bar. 40 | - (void)displayOnlyText:(NSString*)text 41 | hyperText:(NSString*)hyperText 42 | target:(id)target 43 | action:(SEL)action ; 44 | // text may be nil 45 | // hyperText may be nil 46 | // target and action may be nil if hyperText is nil. 47 | 48 | @end 49 | -------------------------------------------------------------------------------- /SSQueuedSpeechSynthesizer.h: -------------------------------------------------------------------------------- 1 | @interface SSQueuedSpeechSynthesizer : NSObject { 2 | 3 | NSSpeechSynthesizer* _synth ; 4 | NSMutableArray* _queue ; 5 | } 6 | 7 | + (SSQueuedSpeechSynthesizer*)createSharedSpeaker ; 8 | // must be invoked before any of the other methods work. 9 | 10 | + (SSQueuedSpeechSynthesizer*)sharedSpeaker ; 11 | // only returns the sharedSpeaker if +createSharedSpeaker has been called first. 12 | // Will return nil otherwise 13 | 14 | - (void)speak:(NSString*)s1 then:(NSString*)s2 then:(NSString*)s3 ; 15 | 16 | @end 17 | -------------------------------------------------------------------------------- /SSRadioButtonCell.h: -------------------------------------------------------------------------------- 1 | // Somewhat adapted from Buzz Andersen's Cocoalicious class, SFHFRatingCell 2 | 3 | #import 4 | 5 | @interface SSRadioButtonCell : NSActionCell { 6 | NSImage* _selectedImage ; 7 | NSImage* _deselectedImage ; 8 | NSMutableArray* _widths ; 9 | 10 | NSRect _currentFrameInControlView ; 11 | NSInteger _numberOfButtons ; 12 | } 13 | 14 | - (void)setSelectedImage:(NSImage*)newImage ; 15 | - (void)setDeselectedImage:(NSImage*)newImage ; 16 | - (NSImage*)selectedImage ; 17 | - (NSImage*)deselectedImage ; 18 | 19 | - (NSNumber *) calculateSelectionForPoint: (NSPoint) point inView: (NSView *) controlView; 20 | 21 | - (void)setNumberOfButtons:(NSInteger)x ; 22 | - (NSInteger)numberOfButtons ; 23 | - (NSMutableArray*)widths ; 24 | - (NSInteger)numberOfButtons ; 25 | - (void)triggerKVO ; 26 | 27 | - (void)setWidth:(CGFloat)width forSegment:(NSInteger)segment ; 28 | 29 | @end 30 | -------------------------------------------------------------------------------- /SSTableKit.h: -------------------------------------------------------------------------------- 1 | - (void)setArray:(NSArray*)array sender:(id)sender ; 2 | 3 | @end 4 | 5 | @interface SSTableKit : NSView { 6 | IBOutlet id textTop ; 7 | IBOutlet id table ; 8 | IBOutlet id buttonMinus ; 9 | IBOutlet id buttonPlus ; 10 | 11 | NSArrayController* _arrayController ; 12 | id _defaultNewObject ; 13 | id _dataStore ; // The data source behind the table's dataSource 14 | } 15 | 16 | - (void)setArray:(id)array ; 17 | 18 | - (void)setTopText:(NSString*)topText 19 | defaultNewItem:(id)defaultNewObject 20 | dataStore:(id )dataStore ; 21 | 22 | @end -------------------------------------------------------------------------------- /SSTableView.h: -------------------------------------------------------------------------------- 1 | /* SSTableView */ 2 | 3 | #import 4 | 5 | @interface SSTableView : NSTableView 6 | { 7 | } 8 | 9 | @end 10 | -------------------------------------------------------------------------------- /SSTableView.m: -------------------------------------------------------------------------------- 1 | #import "SSTableView.h" 2 | 3 | @interface NSObject ( ContextualMenuDelegate ) 4 | - (NSMenu*)menuForTableColumnIndex:(NSInteger)iCol rowIndex:(NSInteger)iRow ; 5 | @end 6 | 7 | @implementation SSTableView 8 | 9 | //- (id)initWithFrame:(NSRect)frameRect 10 | //{ 11 | // if ((self = [super initWithFrame:frameRect]) != nil) 12 | // { 13 | // // Add initialization code here 14 | // } 15 | // return self; 16 | //} 17 | // 18 | //- (void)drawRect:(NSRect)rect 19 | //{ 20 | // [super drawRect:rect] ; 21 | //} 22 | 23 | -(NSMenu*)menuForEvent:(NSEvent*)evt 24 | { 25 | NSMenu* output = nil ; 26 | 27 | NSPoint point = [self convertPoint:[evt locationInWindow] fromView:nil] ; 28 | NSInteger iCol = [self columnAtPoint:point]; 29 | NSInteger iRow = [self rowAtPoint:point]; 30 | 31 | if ( iCol >= 0 32 | && iRow >= 0 33 | && [[self delegate] respondsToSelector:@selector(menuForTableColumnIndex:rowIndex:)] ) { 34 | output = [[self delegate] menuForTableColumnIndex:iCol rowIndex:iRow]; 35 | } 36 | 37 | return output; 38 | } 39 | 40 | // ***** NSDraggingSource Methods (These must be here, in the subclass, not in its dataSource!) ***** // 41 | 42 | - (NSDragOperation)draggingSourceOperationMaskForLocal:(BOOL)isIntraApp; 43 | { 44 | return isIntraApp 45 | ? (NSDragOperationCopy | NSDragOperationMove) 46 | : NSDragOperationCopy ; 47 | } 48 | 49 | 50 | 51 | 52 | @end 53 | -------------------------------------------------------------------------------- /SSTruncatingTextField.h: -------------------------------------------------------------------------------- 1 | @interface SSTruncatingTextField : NSTextField { 2 | 3 | } 4 | 5 | - (void)setTruncationStyle:(NSInteger)truncationStyle ; 6 | 7 | @end 8 | -------------------------------------------------------------------------------- /SSTruncatingTextField.m: -------------------------------------------------------------------------------- 1 | #import "SSTruncatingTextField.h" 2 | #import "SSTextFieldCell.h" 3 | 4 | @implementation SSTruncatingTextField 5 | 6 | - (id)initWithFrame:(NSRect)frame { 7 | if ((self = [super initWithFrame:frame])) { 8 | SSTextFieldCell* cell = [[SSTextFieldCell alloc] init] ; 9 | [self setCell:cell] ; 10 | [cell release] ; 11 | } 12 | 13 | return self ; 14 | } 15 | 16 | - (void)setTruncationStyle:(NSInteger)truncationStyle { 17 | [[self cell] setTruncationStyle:truncationStyle] ; 18 | } 19 | 20 | @end -------------------------------------------------------------------------------- /SSWebBrowsing.h: -------------------------------------------------------------------------------- 1 | #import 2 | 3 | 4 | @interface NSString (FirefoxQuicksearch) 5 | 6 | /*! 7 | @brief To fix a stupid thing that happens when opening a Firefox 8 | "quicksearch" URL 9 | 10 | @details 11 | @result 12 | */ 13 | - (NSString*)stringByFixingFirefoxQuicksearch ; 14 | 15 | @end 16 | 17 | 18 | @interface SSWebBrowsing : NSObject { 19 | 20 | } 21 | 22 | + (NSString*)defaultBrowserDisplayName ; 23 | 24 | + (NSString*)defaultBrowserBundleIdentifier ; 25 | 26 | /*! 27 | @details In macOS 10.10, there is Apple Bug 19642555, which causes 28 | -[NSWorkspace openURLs:::::] to fail (and indeed return NO, if you rapid-fire 29 | it too quickly. Experimenting on my 2013 13 inch MacBook Air, opening 13 URLs 30 | in Safari, I find that a 50-100 millisecond delay is necessary between 31 | invocations of this method to avoid failures. To be safe, I recommend using 32 | 500 milliseconds; since web pages generally take way longer than that to load, 33 | user experience is not affected. Apple Bug 19642555 is detailed here: 34 | http://openradar.appspot.com/19642555 35 | 36 | @param browserBundleIdentifier bundle identifier of browser to 37 | be used. Pass nil to use the user's default browser. 38 | */ 39 | + (void)browseToURLString:(NSString*)url 40 | browserBundleIdentifier:(NSString*)browserBundleIdentifier 41 | activate:(BOOL)activate ; 42 | 43 | /*! 44 | @brief 45 | 46 | @details Downloads the favicon from the internet 47 | @param domain 48 | @result 49 | */ 50 | + (NSImage*)faviconForDomain:(NSString*)domain ; 51 | 52 | @end 53 | -------------------------------------------------------------------------------- /SSYAbbreviateMarker.h: -------------------------------------------------------------------------------- 1 | #import 2 | 3 | /*! 4 | @brief This transformer DOES NOT WORK when used in an IB binding 5 | because, possibly, the placeholder substitutions specified in Interface 6 | Builder get substituted in before the value transformer, or something 7 | like that. DO NOT USE THIS CLASS. 8 | 9 | A transformer which replaces Selection Marker constants: 10 | NSNoSelectionMarker or nil, NSMultipleValuesMarker, and NSNotApplicableMarker. 11 | Transformed values are: an em dash, three bullets, and a thick "X", respectively. 12 | 13 | @details Use this in text fields that are not wide enough fit the 14 | full text such as the localized strings of "Multiple Selection", 15 | "No Selection" or "Not Applicable". 16 | */ 17 | @interface SSYAbbreviateMarker : NSValueTransformer { 18 | } 19 | 20 | @end 21 | -------------------------------------------------------------------------------- /SSYAbbreviateMarker.m: -------------------------------------------------------------------------------- 1 | #import "SSYAbbreviateMarker.h" 2 | 3 | 4 | @implementation SSYAbbreviateMarker 5 | 6 | + (Class)transformedValueClass { 7 | return [NSString class] ; 8 | } 9 | 10 | + (BOOL)allowsReverseTransformation { 11 | return NO ; 12 | } 13 | 14 | - (id)transformedValue:(id)value { 15 | id answer = value ; 16 | 17 | if ((!value) || value == NSNoSelectionMarker) { 18 | answer = @"\xe2\x80\x94" ; // em dash 19 | } 20 | if (value == NSMultipleValuesMarker) { 21 | answer = @"\xe2\x80\xa2\xe2\x80\xa2\xe2\x80\xa2" ; // three bullets 22 | } 23 | else if (value == NSNotApplicableMarker) { 24 | answer = @"\xe2\x92\x96" ; // a thick "X" 25 | } 26 | 27 | return answer ; 28 | } 29 | 30 | @end 31 | -------------------------------------------------------------------------------- /SSYAboutPanelController.h: -------------------------------------------------------------------------------- 1 | #import 2 | 3 | extern NSString* const SSYAboutPanelHelpAnchorAcknowledgements ; 4 | 5 | @class ScrollingTextView; 6 | 7 | @interface SSYAboutPanelController : NSWindowController 8 | #if (MAC_OS_X_VERSION_MAX_ALLOWED >= 1060) 9 | 10 | #endif 11 | { 12 | // This panel exists in the nib file, but the user never sees it, because 13 | // we rip out its contents and place them in “panelToDisplay”. 14 | IBOutlet NSPanel *panelInNib; 15 | 16 | // This panel is not in the nib file; we create it programmatically. 17 | NSPanel *panelToDisplay; 18 | 19 | // Scrolling text: the scroll-view and the text-view itself 20 | IBOutlet NSScrollView *textScrollView; 21 | IBOutlet NSTextView *textView; 22 | 23 | // Outlet we fill in using information from the application’s bundle 24 | IBOutlet NSTextField *versionField; 25 | IBOutlet NSTextField *shortInfoField; 26 | 27 | // Buttons 28 | IBOutlet NSButton *buttonClose ; 29 | IBOutlet NSButton *buttonInfo ; 30 | IBOutlet NSButton *buttonHelp ; 31 | 32 | // Timer to fire scrolling animation 33 | NSTimer *scrollingTimer; 34 | 35 | /* 36 | In -awakeFromNib, we look in main bundle resources for an image 37 | with same name as CFBundleExecutable (name) and setImage of 38 | iconView to it. 39 | */ 40 | IBOutlet NSImageView *iconView ; 41 | } 42 | 43 | 44 | #pragma mark * PUBLIC CLASS METHODS 45 | 46 | + (SSYAboutPanelController *) sharedInstance; 47 | 48 | #pragma mark * PUBLIC INSTANCE METHODS 49 | 50 | // Show the panel, starting the text at the top with the animation going 51 | - (void) showPanel; 52 | 53 | // Stop scrolling and hide the panel. 54 | - (void) hidePanel; 55 | 56 | // Buttons 57 | - (IBAction)close:(id)sender ; 58 | - (IBAction)info:(id)sender ; 59 | - (IBAction)help:(id)sender ; 60 | 61 | @end 62 | 63 | -------------------------------------------------------------------------------- /SSYAlertSounder (original).h: -------------------------------------------------------------------------------- 1 | #import 2 | 3 | /* 4 | Use this if you need to keep a process running long enough for your 5 | sound to complete playing. This is an integer so that it can be 6 | used as a parameters to functions that require integers, like sleep(). 7 | */ 8 | #define SECONDS_NEEDED_FOR_ONE_ALERT_SOUND 1 9 | 10 | 11 | /*! 12 | @brief This is a quick hacky wrapper on Audio Services 13 | to play an alert sound cheaply and reliably (in contrast to NSSound) 14 | 15 | @details Requires System/Library/Frameworks/AudioToolbox.framework, 16 | which is Mac OS 10.5 or later. 17 | 18 | In the earlier System Sound API, for these sounds to play, it was required 19 | that, in System Preferences > Sound > Play User Interface Sound Effects 20 | be enabled. But this appears to work without it. 21 | */ 22 | __attribute__((visibility("default"))) @interface SSYAlertSounder : NSObject { 23 | NSMutableDictionary* m_soundIds ; 24 | } 25 | 26 | /*! 27 | @brief Plays a desired sound 28 | 29 | @details 30 | @param name The name of a sound file, not including the .aiff extension, 31 | or nil to no-op 32 | */ 33 | - (void)playAlertSoundNamed:(NSString*)name ; 34 | 35 | /*! 36 | @brief Returns an array, localizedly sorted, containing all of the names 37 | of the sounds which are available for use by -playAlertSoundNamed, provided 38 | that none of the underlying files disappear in the meantime 39 | */ 40 | - (NSArray*)availableSoundsSorted ; 41 | 42 | + (SSYAlertSounder*)sharedSounder ; 43 | 44 | @end 45 | 46 | -------------------------------------------------------------------------------- /SSYAutoHeightBox.h: -------------------------------------------------------------------------------- 1 | #import 2 | 3 | 4 | @interface SSYAutoHeightBox : NSBox { 5 | } 6 | 7 | @end 8 | -------------------------------------------------------------------------------- /SSYAutoHeightBox.m: -------------------------------------------------------------------------------- 1 | #import "SSYAutoHeightBox.h" 2 | 3 | @interface NSView (SortByOriginY) 4 | 5 | - (NSComparisonResult)compareOriginY:(NSView*)other ; 6 | 7 | @end 8 | 9 | @implementation NSView (SortByOriginY) 10 | 11 | - (NSComparisonResult)compareOriginY:(NSView*)other { 12 | CGFloat selfY = [self frame].origin.y ; 13 | CGFloat otherY = [other frame].origin.y ; 14 | if (selfY < otherY) { 15 | return NSOrderedAscending ; 16 | } 17 | else if (selfY > otherY) { 18 | return NSOrderedDescending ; 19 | } 20 | 21 | return NSOrderedSame ; 22 | } 23 | 24 | 25 | @end 26 | 27 | 28 | @implementation SSYAutoHeightBox 29 | 30 | - (void)awakeFromNib { 31 | // Since we are going to use "manual" control of the 32 | // y-axis margins, the "automatic" had better be off 33 | // in all of our subviews. 34 | // Since the animation in 35 | // Interface Builder is confusing, we (re)-do it here: 36 | NSArray* subviews = [[self contentView] subviews] ; 37 | for (NSView* subview in subviews) { 38 | NSUInteger autoresizingMask = [subview autoresizingMask] ; 39 | NSUInteger mask = ~(NSViewMinYMargin + NSViewMaxYMargin) ; 40 | autoresizingMask = autoresizingMask & mask ; 41 | [subview setAutoresizingMask:autoresizingMask] ; 42 | } 43 | 44 | } 45 | 46 | 47 | - (void)drawRect:(NSRect)rect { 48 | [super drawRect:rect] ; 49 | } 50 | 51 | - (void)doLayout { 52 | NSRect frame ; 53 | 54 | frame = [self frame] ; 55 | frame.origin.y = 2.0 ; 56 | [self setFrame:frame] ; 57 | 58 | NSArray* subviews = [[[self contentView] subviews] sortedArrayUsingSelector:@selector(compareOriginY:)] ; 59 | 60 | CGFloat y = 6.0 ; 61 | 62 | for (NSView* subview in subviews) { 63 | NSRect subframe = [subview frame] ; 64 | 65 | subframe.origin.y = y ; 66 | [subview setFrame:subframe] ; 67 | y += subframe.size.height ; 68 | y += 2.0 ; 69 | } 70 | 71 | y += 4.0 ; 72 | 73 | frame = [[self contentView] frame] ; 74 | frame.size.height = y ; 75 | [[self contentView] setFrame:frame] ; 76 | 77 | frame = [self frame] ; 78 | frame.size.height = y ; 79 | [self setFrame:frame] ; 80 | } 81 | 82 | - (void)viewWillDraw { 83 | // Now recurse to handle all our descendants. 84 | // Overrides must call up to super like this. 85 | [super viewWillDraw]; 86 | 87 | // Perform some operations that might depend on descendants 88 | // already having had a chance to update. 89 | [self doLayout] ; 90 | 91 | } 92 | 93 | 94 | 95 | @end -------------------------------------------------------------------------------- /SSYAutoHeightTableView.h: -------------------------------------------------------------------------------- 1 | #import 2 | 3 | 4 | @interface SSYAutoHeightTableView : NSTableView { 5 | 6 | } 7 | 8 | @end 9 | -------------------------------------------------------------------------------- /SSYAutoHeightTableView.m: -------------------------------------------------------------------------------- 1 | #import "SSYAutoHeightTableView.h" 2 | 3 | @class SSYAutoHeightBox ; 4 | 5 | 6 | @implementation SSYAutoHeightTableView 7 | 8 | #ifdef j 9 | - (NSRect)frame { 10 | CGFloat headerHeight = NSHeight([[self headerView] frame]) ; 11 | NSInteger nRows = [self numberOfRows] ; 12 | CGFloat rowsHeight = nRows * [self rowHeight] ; 13 | CGFloat gapsHeight = (nRows-1) * [self intercellSpacing].height ; 14 | CGFloat height = headerHeight + rowsHeight + gapsHeight ; 15 | 16 | NSRect frame_ = [super frame] ; 17 | frame_.size.height = height ; 18 | 19 | return frame_ ; 20 | } 21 | #endif 22 | 23 | - (void)noteHeightOfRowsWithIndexesChanged:(NSIndexSet *)indexSet { 24 | } 25 | 26 | - (void)viewWillDraw { 27 | // Perform some operations before recursing for descendants. 28 | 29 | // Now recurse to handle all our descendants. 30 | // Overrides must call up to super like this. 31 | [super viewWillDraw]; 32 | 33 | // Perform some operations that might depend on descendants 34 | // already having had a chance to update. 35 | NSTableHeaderView* headerView = [self headerView] ; 36 | CGFloat headerHeight ; 37 | if (headerView) { 38 | headerHeight = NSHeight([headerView frame]) ; 39 | } 40 | else { 41 | headerHeight = 0.0 ; 42 | } 43 | NSInteger nRows = [self numberOfRows] ; 44 | 45 | CGFloat rowsHeight = nRows * [self rowHeight] ; 46 | CGFloat gapsHeight = (nRows-1) * [self intercellSpacing].height ; 47 | CGFloat height = headerHeight + rowsHeight + gapsHeight ; 48 | 49 | NSRect frame = [self frame] ; 50 | frame.size.height = height ; 51 | [self setFrame:frame] ; 52 | CGFloat width = frame.size.width ; 53 | 54 | NSScrollView* enclosingScrollView = [self enclosingScrollView] ; 55 | 56 | frame = [enclosingScrollView frame] ; 57 | frame.size.width = width + 2.0 ; 58 | frame.size.height = height + 2.0 ; 59 | [enclosingScrollView setFrame:frame] ; 60 | } 61 | @end -------------------------------------------------------------------------------- /SSYBackgroundAwareWindow.h: -------------------------------------------------------------------------------- 1 | #import 2 | 3 | /* 4 | @brief A subclass of NSWindow instance methods which behave appropriately 5 | in case a process is launched as or is transformed to a background or 6 | UI element type (currentType != SSYProcessTyperTypeForeground), 7 | 8 | This class was added in BookMacster 1.16.1. 9 | */ 10 | @interface SSYBackgroundAwareWindow : NSWindow { 11 | } 12 | 13 | /* 14 | @brief Override which returns NO if the the current process is not a 15 | foreground process (currentType != SSYProcessTyperTypeForeground), otherwise 16 | invokes super 17 | */ 18 | - (BOOL)canBecomeMainWindow ; 19 | 20 | /* 21 | @brief Override which returns NO if the the current process is not a 22 | foreground process (currentType != SSYProcessTyperTypeForeground), otherwise 23 | invokes super 24 | */ 25 | - (BOOL)canBecomeKeyWindow ; 26 | 27 | 28 | 29 | 30 | @end 31 | -------------------------------------------------------------------------------- /SSYBackgroundAwareWindow.m: -------------------------------------------------------------------------------- 1 | #import "SSYBackgroundAwareWindow.h" 2 | #import "SSYProcessTyper.h" 3 | 4 | @implementation SSYBackgroundAwareWindow 5 | 6 | - (BOOL)keepHidden { 7 | return ([SSYProcessTyper currentType] != NSApplicationActivationPolicyRegular) ; 8 | } 9 | 10 | - (BOOL)canBecomeKeyWindow { 11 | if ([self keepHidden]) { 12 | return NO ; 13 | } 14 | return [super canBecomeKeyWindow] ; 15 | } 16 | 17 | - (BOOL)canBecomeMainWindow { 18 | if ([self keepHidden]) { 19 | return NO ; 20 | } 21 | return [super canBecomeMainWindow] ; 22 | } 23 | 24 | #if 0 25 | #warning Experimenting with More Windowlessness 26 | // I found it not necessary to override these methods, so I didn't. 27 | // But maybe I didn't find all the corner cases. Someday, I might? 28 | 29 | /* 30 | @brief Override which becomes a no-op if the the current process is not a 31 | foreground process (currentType != SSYProcessTyperTypeForeground), otherwise 32 | invokes super 33 | */ 34 | - (void)displayIfNeeded { 35 | if ([self keepHidden]) { 36 | return ; 37 | } 38 | [super displayIfNeeded] ; 39 | } 40 | 41 | - (void)display { 42 | if ([self keepHidden]) { 43 | return ; 44 | } 45 | [super display] ; 46 | } 47 | 48 | - (void)orderFrontRegardless { 49 | if ([self keepHidden]) { 50 | return ; 51 | } 52 | [super orderFrontRegardless] ; 53 | } 54 | 55 | - (void)orderFront:(id)sender { 56 | if ([self keepHidden]) { 57 | return ; 58 | } 59 | [super display] ; 60 | } 61 | 62 | - (void)orderBack:(id)sender { 63 | if ([self keepHidden]) { 64 | return ; 65 | } 66 | [super orderFront:sender] ; 67 | } 68 | 69 | - (void)makeMainWindow { 70 | if ([self keepHidden]) { 71 | return ; 72 | } 73 | [super makeMainWindow] ; 74 | } 75 | 76 | - (void)makeKeyWindow { 77 | if ([self keepHidden]) { 78 | return ; 79 | } 80 | [super makeKeyWindow] ; 81 | } 82 | 83 | - (void)makeKeyAndOrderFront:(id)sender { 84 | if ([self keepHidden]) { 85 | return ; 86 | } 87 | [super makeKeyAndOrderFront:sender] ; 88 | } 89 | 90 | - (void)orderWindow:(NSWindowOrderingMode)orderingMode relativeTo:(NSInteger)otherWindowNumber { 91 | if ([self keepHidden]) { 92 | return ; 93 | } 94 | [super orderWindow:orderingMode relativeTo:otherWindowNumber] ; 95 | } 96 | 97 | #endif 98 | 99 | @end 100 | -------------------------------------------------------------------------------- /SSYBinderView.h: -------------------------------------------------------------------------------- 1 | #import 2 | 3 | 4 | /*! 5 | @brief A view which manages the bindings of its subviews 6 | 7 | @details 8 | */ 9 | @interface SSYBinderView : NSView { 10 | BOOL m_isBound ; 11 | NSMutableSet* m_bindings ; 12 | } 13 | 14 | /*! 15 | @brief A friendly wrapper around bind:toObject:withKeyPath:options: 16 | which will remember the binding and unbind it whenever the given subview 17 | is either removed from its superview, or else added to a superview 18 | that does not itself have a window, and re-bind it whenever it is added 19 | to a superview that does have a window. 20 | 21 | @details No-op if any of the first four parameters are nil. 22 | @param subview The subview which will be bound; i.e. the receiver 23 | of bind:toObject:withKeyPath:options. 24 | @param bindingName The 'bind' parameter in bind:toObject:withKeyPath:options. 25 | @param object The 'object' parameter in bind:toObject:withKeyPath:options: 26 | @param keyPath The 'keyPath' parameter in bind:toObject:withKeyPath:options: 27 | @param options The 'options' parameter in bind:toObject:withKeyPath:options: 28 | */ 29 | - (void)bindSubview:(NSView*)subview 30 | bindingName:(NSString*)bindingName 31 | toObject:(id)object 32 | withKeyPath:(NSString*)keyPath 33 | options:(NSDictionary*)options ; 34 | 35 | /* todo 36 | - (void)unbindSubview:(NSView*)subview 37 | bindingName:(NSString*)bindingName ; 38 | */ 39 | 40 | @end 41 | -------------------------------------------------------------------------------- /SSYBlocker.h: -------------------------------------------------------------------------------- 1 | #import 2 | 3 | 4 | /*! 5 | @brief This class exposes three methods to block a "waiter" thread 6 | until a "worker" thread completes work. 7 | 8 | @details The typical usage of an SSYBlocker is: 9 | 10 | • Waiter or Worker sends +alloc -init. 11 | • Worker sends -lockLock. 12 | • Worker begins work. 13 | • Waiter sends -blockForLock, which blocks. 14 | • Worker completes work. 15 | • Worker sends -unlockLock 16 | • -blockForLock returns, and Waiter continues its execution 17 | 18 | Memory management of an SSYBlocker instance can be dangerous 19 | if you cannot guarantee the order in which the messages will 20 | be sent, or edge cases in which they might be re-sent. If you 21 | don't have too many of these things, you might want to be 22 | conservative and retain them as instance variables of some 23 | long-lived object. 24 | */ 25 | @interface SSYBlocker : NSObject { 26 | NSConditionLock* m_lock ; 27 | } 28 | 29 | /*! 30 | @brief Initializes the receiver and its condition lock. 31 | */ 32 | - (id)init ; 33 | 34 | /*! 35 | @brief Locks the receiver's condition lock. 36 | */ 37 | - (void)lockLock ; 38 | 39 | /*! 40 | @brief Blocks until the receiver's condition lock is unlocked 41 | by -unlockLock. 42 | */ 43 | - (void)blockForLock ; 44 | 45 | /*! 46 | @brief Unlocks the receiver's condition lock. 47 | 48 | @details Before unlocking the lock, this method checks to see that the 49 | receiver's lock is still locked, so it is OK if, during some edge case 50 | condition, you send this message more than once. 51 | */ 52 | - (void)unlockLock ; 53 | 54 | @end 55 | -------------------------------------------------------------------------------- /SSYBlocker.m: -------------------------------------------------------------------------------- 1 | #import "SSYBlocker.h" 2 | 3 | #define SSY_BLOCKER_BLOCKED 0 4 | #define SSY_BLOCKER_CLEARED 1 5 | 6 | @interface SSYBlocker () 7 | 8 | @property (retain) NSConditionLock* lock ; 9 | 10 | @end 11 | 12 | @implementation SSYBlocker 13 | 14 | @synthesize lock = m_lock ; 15 | 16 | - (void)dealloc { 17 | [m_lock release] ; 18 | 19 | [super dealloc] ; 20 | } 21 | 22 | - (id)init { 23 | self = [super init] ; 24 | if (self) { 25 | NSConditionLock* lock = [[NSConditionLock alloc] initWithCondition:SSY_BLOCKER_BLOCKED] ; 26 | [self setLock:lock] ; 27 | [lock release] ; 28 | } 29 | 30 | return self ; 31 | } 32 | 33 | - (void)lockLock { 34 | [[self lock] lock] ; 35 | } 36 | 37 | - (void)blockForLock { 38 | NSConditionLock* lock = [self lock] ; 39 | BOOL workFinishedInTime = [lock lockWhenCondition:SSY_BLOCKER_CLEARED 40 | beforeDate:[NSDate distantFuture]] ; 41 | if (workFinishedInTime) { 42 | [lock unlock] ; 43 | } 44 | } 45 | 46 | - (void)unlockLock { 47 | // If we send -unlockWithCondition to a condition lock which has already 48 | // been unlocked, Cocoa raises an exception. To avoid that, we check 49 | // that -unlockLock has not already been sent for this locking cycle. 50 | if ([[self lock] condition] == SSY_BLOCKER_BLOCKED) { 51 | [[self lock] unlockWithCondition:SSY_BLOCKER_CLEARED] ; 52 | } 53 | } 54 | 55 | @end -------------------------------------------------------------------------------- /SSYCachyAliasResolver.h: -------------------------------------------------------------------------------- 1 | #import 2 | 3 | 4 | /*! 5 | @brief Provides a singleton which caches aliases it resolves 6 | for re-use, up to a given lifetime. 7 | 8 | @details A wrapper around a wrapper around a tool which invokes 9 | the notoriously slow and blocking FSResolveAlias() function. 10 | */ 11 | @interface SSYCachyAliasResolver : NSObject { 12 | NSMutableDictionary* m_cache ; 13 | } 14 | 15 | + (SSYCachyAliasResolver*)sharedResolver ; 16 | 17 | /*! 18 | @brief Resolves an alias to a path, blocking only up to a given 19 | timeout, caching the path for future invocations up to a given 20 | lifetime if desired, and if desired for performance reasons, will 21 | cache the result for later and/or return a cached result if available. 22 | 23 | @details This method requires that an executable FileAliasWorker 24 | be available in the application's main bundle. 25 | @param alias The alias data to be resolved 26 | @param useCache YES if you will accept a cached result, which 27 | can be returned instantly. 28 | @param timeout In case useCache is NO, or if a cached result 29 | is not availble, the timeout for which this method will block 30 | @param lifetime The time interval for which the result, if 31 | resolved from scratch, will be cached for future invocations of 32 | this method 33 | @param error_p Pointer which will, upon return, if an error 34 | occurred and said pointer is not NULL, point to an NSError 35 | describing said error. 36 | @result The resolved path, or nil if the path could not be 37 | resolved. 38 | */ 39 | - (NSString*)pathFromAlias:(NSData*)alias 40 | useCache:(BOOL)useCache 41 | timeout:(NSTimeInterval)timeout 42 | lifetime:(NSTimeInterval)lifetime 43 | error_p:(NSError**)error_p ; 44 | 45 | @end -------------------------------------------------------------------------------- /SSYCachyAliasResolver.m: -------------------------------------------------------------------------------- 1 | #import "SSYCachyAliasResolver.h" 2 | #import "NSData+FileAlias.h" 3 | 4 | static SSYCachyAliasResolver* sharedResolver = nil ; 5 | 6 | 7 | @interface SSYCachyAliasResolver () 8 | 9 | @property (retain, readonly) NSMutableDictionary* cache ; 10 | 11 | @end 12 | 13 | 14 | @implementation SSYCachyAliasResolver 15 | 16 | - (void)dealloc { 17 | [m_cache release] ; 18 | 19 | [super dealloc] ; 20 | } 21 | 22 | - (NSMutableDictionary*)cache { 23 | NSMutableDictionary* cache ; 24 | @synchronized(self) { 25 | if (!m_cache) { 26 | m_cache = [[NSMutableDictionary alloc] init] ; 27 | } 28 | 29 | cache = [[m_cache retain] autorelease] ; 30 | } 31 | 32 | return cache ; 33 | } 34 | 35 | + (SSYCachyAliasResolver*)sharedResolver { 36 | @synchronized(self) { 37 | if (!sharedResolver) { 38 | sharedResolver = [[self alloc] init] ; 39 | } 40 | } 41 | 42 | // No autorelease. This sticks around forever. 43 | return sharedResolver ; 44 | } 45 | 46 | - (NSString*)pathFromAlias:(NSData*)alias 47 | useCache:(BOOL)useCache 48 | timeout:(NSTimeInterval)timeout 49 | lifetime:(NSTimeInterval)lifetime 50 | error_p:(NSError**)error_p { 51 | if (!alias) { 52 | return nil ; 53 | } 54 | 55 | id path = nil ; 56 | NSNumber* key = nil ; 57 | BOOL alreadyInCache = NO ; 58 | // First, try to get from cache if allowed 59 | if (useCache) { 60 | NSUInteger hash = [alias hash] ; 61 | key = [NSNumber numberWithInteger:hash] ; 62 | path = [[self cache] objectForKey:key] ; 63 | alreadyInCache = (path != nil) ; 64 | } 65 | 66 | // If not found in cache, try to resolve alias 67 | if (!path) { 68 | path = [alias pathFromAliasRecordWithTimeout:timeout 69 | error_p:error_p] ; 70 | } 71 | 72 | // If nothing in cache and could not resolve alias, set to a Null 73 | if (!path) { 74 | path = [NSNull null] ; 75 | } 76 | 77 | // Cache the result 78 | if (!alreadyInCache && (lifetime > 0.0)) { 79 | if (!key) { 80 | NSUInteger hash = [alias hash] ; 81 | key = [NSNumber numberWithInteger:hash] ; 82 | } 83 | 84 | [[self cache] setObject:path 85 | forKey:key] ; 86 | 87 | [NSTimer scheduledTimerWithTimeInterval:lifetime 88 | target:self 89 | selector:@selector(clearCachedPath:) 90 | userInfo:key 91 | repeats:NO] ; 92 | } 93 | 94 | if ([path isKindOfClass:[NSNull class]]) { 95 | path = nil ; 96 | } 97 | 98 | return path ; 99 | } 100 | 101 | - (void)clearCachedPath:(NSTimer*)timer { 102 | NSNumber* key = [timer userInfo] ; 103 | [[self cache] removeObjectForKey:key] ; 104 | } 105 | 106 | @end -------------------------------------------------------------------------------- /SSYChromePaths.h: -------------------------------------------------------------------------------- 1 | #import 2 | 3 | -------------------------------------------------------------------------------- /SSYChromePaths.m: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jerrykrinock/ClassesObjC/9f8edc5f804e8d8e1d6183fe9cb91a94b2b83cf2/SSYChromePaths.m -------------------------------------------------------------------------------- /SSYClickActionTextField.h: -------------------------------------------------------------------------------- 1 | #import 2 | 3 | /*! 4 | @brief A text field which will sends its target/action message 5 | when it is clicked. 6 | 7 | @details Useful if you are using this to display static text 8 | in a control and want the behavior to be like a checkbox 9 | implemented with NSButton; i.e., clicking the text toggles the 10 | checkbox the same as if you clicked the checkbox. 11 | */ 12 | @interface SSYClickActionTextField : NSTextField { 13 | 14 | } 15 | 16 | @end 17 | -------------------------------------------------------------------------------- /SSYClickActionTextField.m: -------------------------------------------------------------------------------- 1 | #import "SSYClickActionTextField.h" 2 | 3 | 4 | @implementation SSYClickActionTextField 5 | 6 | - (void)mouseDown:(NSEvent*)theEvent { 7 | [self performClick:self] ; 8 | } 9 | 10 | @end 11 | -------------------------------------------------------------------------------- /SSYDeallocDetector.h: -------------------------------------------------------------------------------- 1 | #import 2 | 3 | 4 | /*! 5 | @brief An instance of this class will send a given invocation 6 | during its deallocation. 7 | 8 | @details We leave the usage of this class to your imagination! 9 | */ 10 | @interface SSYDeallocDetector : NSObject { 11 | } 12 | 13 | @property (retain) NSInvocation* invocation ; 14 | @property (retain) NSString* logMsg ; 15 | 16 | + (SSYDeallocDetector*)detectorWithInvocation:(NSInvocation*)invocation 17 | logMsg:(NSString*)logMsg ; 18 | 19 | @end 20 | -------------------------------------------------------------------------------- /SSYDeallocDetector.m: -------------------------------------------------------------------------------- 1 | #import "SSYDeallocDetector.h" 2 | 3 | 4 | @implementation SSYDeallocDetector 5 | 6 | #if 0 7 | #warning Logging retains, releases and deallocs of Dealloc Detector 8 | #define LOG_RETAINS_RELEASES_AND_DEALLOCS 1 9 | #endif 10 | 11 | #if LOG_RETAINS_RELEASES_AND_DEALLOCS 12 | - (id)retain { 13 | NSLog(@"75133: Retained SSYDeallocDetector %p", (__bridge void*)self) ; 14 | return [super retain] ; 15 | } 16 | 17 | - (oneway void)release { 18 | NSLog(@"75143: Released SSYDeallocDetector %p", (__bridge void*)self) ; 19 | [super release] ; 20 | } 21 | #endif 22 | 23 | - (void)dealloc { 24 | [_invocation invoke] ; 25 | 26 | [_invocation release] ; 27 | #if LOG_RETAINS_RELEASES_AND_DEALLOCS 28 | NSLog(@"75153 Deallocced %p", (__bridge void*)self) ; 29 | #else 30 | if (_logMsg) { 31 | NSLog(@"Deallocced %p %@", (__bridge void*)self, _logMsg) ; 32 | } 33 | #endif 34 | 35 | [_logMsg release] ; 36 | 37 | [super dealloc] ; 38 | } 39 | 40 | - (id)initWithInvocation:(NSInvocation*)invocation 41 | logMsg:(NSString*)logMsg { 42 | self = [super init] ; 43 | if (self) { 44 | [self setInvocation:invocation] ; 45 | [self setLogMsg:logMsg] ; 46 | if (logMsg) { 47 | NSLog(@"Created %p %@", (__bridge void*)self, logMsg) ; 48 | } 49 | } 50 | 51 | return self ; 52 | } 53 | 54 | + (SSYDeallocDetector*)detectorWithInvocation:(NSInvocation*)invocation 55 | logMsg:(NSString*)logMsg { 56 | SSYDeallocDetector* instance = [[SSYDeallocDetector alloc] initWithInvocation:invocation 57 | logMsg:logMsg] ; 58 | return [instance autorelease] ; 59 | } 60 | 61 | @end 62 | -------------------------------------------------------------------------------- /SSYDictionaryDebugger.h: -------------------------------------------------------------------------------- 1 | #import 2 | 3 | #if 0 4 | #warning Compiling with SSYDebuggingMutableDictionary 5 | #define SSY_DEBUGGING_MUTABLE_DICTIONARY_INCLUDED 6 | 7 | // Set one or both of the following to 1 8 | #define SSY_DEBUGGING_MUTABLE_DICTIONARY_LOG_CONTENTS_CHANGED 0 9 | #define SSY_DEBUGGING_MUTABLE_DICTIONARY_LOG_MEMORY_MANAGEMENT 0 10 | 11 | 12 | 13 | /*! 14 | @brief A thin wrapper around NSMutableDictionary which may 15 | be used in place of NSMutableDictionary when you want to have 16 | logged whenever the dictionary's contents are changed, and/or 17 | to log memory management. 18 | 19 | @details When using this class in place of NSMutableDictionary, 20 | you may get compiler warnings that SSYDebuggingMutableDictionary 21 | may not implement methods such as -count.  Ignore those 22 | warnings.  SSYDebuggingMutableDictionary will forward those 23 | messages to the NSMutableDictionary that it wraps. 24 | 25 | This class requires Mac OS 10.5 or later due to the use of 26 | -forwardingTargetForSelector. 27 | */ 28 | @interface SSYDebuggingMutableDictionary : NSObject 29 | { 30 | NSMutableDictionary* dic ; 31 | } 32 | 33 | @end 34 | 35 | #endif -------------------------------------------------------------------------------- /SSYDictionaryDebugger.m: -------------------------------------------------------------------------------- 1 | #import "SSYDictionaryDebugger.h" 2 | 3 | #ifdef SSY_DEBUGGING_MUTABLE_DICTIONARY_INCLUDED 4 | 5 | @implementation SSYDebuggingMutableDictionary 6 | 7 | - (id) init 8 | { 9 | self = [super init]; 10 | if (self != nil) { 11 | dic = [[NSMutableDictionary alloc] init] ; 12 | 13 | } 14 | #if SSY_DEBUGGING_MUTABLE_DICTIONARY_LOG_MEMORY_MANAGEMENT 15 | NSLog(@"info %p has been initted", self) ; 16 | #endif 17 | return self; 18 | } 19 | 20 | - (NSString*)description { 21 | return [dic description] ; 22 | } 23 | 24 | - (id)forwardingTargetForSelector:(SEL)sel { 25 | return dic ; 26 | } 27 | 28 | - (void)setValue:(id)value 29 | forUndefinedKey:key { 30 | [dic setValue:value 31 | forKey:key] ;; 32 | } 33 | 34 | - (void)dealloc { 35 | #if SSY_DEBUGGING_MUTABLE_DICTIONARY_LOG_MEMORY_MANAGEMENT 36 | NSLog(@"info %p is being deallocced", self) ; 37 | #endif 38 | [dic release] ; 39 | 40 | [super dealloc] ; 41 | } 42 | 43 | #if SSY_DEBUGGING_MUTABLE_DICTIONARY_LOG_MEMORY_MANAGEMENT 44 | 45 | - (id)retain { 46 | id x = [super retain] ; 47 | NSLog(@"info %p retained to %ld by %@", self, (long)[self retainCount], SSYDebugCaller()) ; 48 | return x ; 49 | } 50 | 51 | - (id)autorelease { 52 | id x = [super autorelease] ; 53 | NSLog(@"info %p autoreleased by %@", self, SSYDebugCaller()) ; 54 | return x ; 55 | } 56 | 57 | - (oneway void)release { 58 | NSInteger rc = [self retainCount] ; 59 | [super release] ; 60 | NSLog(@"info %p released fr %ld by %@", self, (long)rc, SSYDebugCaller()) ; 61 | } 62 | 63 | #endif 64 | 65 | 66 | #if SSY_DEBUGGING_MUTABLE_DICTIONARY_LOG_CONTENTS_CHANGED 67 | 68 | - (void)setValue:(id)value forKey:(NSString *)key { 69 | NSLog(@"12686-01 %s", __PRETTY_FUNCTION__) ; 70 | 71 | NSLog(@" key=%@", key) ; 72 | NSLog(@" value=%@", value) ; 73 | if (!value) { 74 | NSLog(@"An object is being removed!") ; 75 | } 76 | [dic setValue:value forKey:key] ; 77 | } 78 | 79 | - (void)removeObjectForKey:(id)aKey{ 80 | NSLog(@"12686-02 %s", __PRETTY_FUNCTION__) ; 81 | NSLog(@"An object is being removed!") ; 82 | NSLog(@" key=%@", aKey) ; 83 | [dic removeObjectForKey:aKey] ; 84 | } 85 | 86 | - (void)removeAllObjects{ 87 | NSLog(@"12686-03 %s", __PRETTY_FUNCTION__) ; 88 | NSLog(@"An object is being removed!") ; 89 | [dic removeAllObjects] ; 90 | } 91 | - (void)setObject:(id)anObject forKey:(id)aKey{ 92 | NSLog(@"12686-04 %s", __PRETTY_FUNCTION__) ; 93 | NSLog(@" key=%@", aKey) ; 94 | NSLog(@" value=%@", anObject) ; 95 | [dic setObject:anObject forKey:aKey] ; 96 | } 97 | 98 | #endif 99 | 100 | 101 | @end 102 | 103 | #endif -------------------------------------------------------------------------------- /SSYDictionaryEntry.h: -------------------------------------------------------------------------------- 1 | #import 2 | 3 | 4 | @interface SSYDictionaryEntry : NSObject { 5 | NSMutableDictionary* _parent ; 6 | id _key ; 7 | id _value ; 8 | } 9 | 10 | @end 11 | 12 | // Transforms a dictionary into an array of SSDictionaryEntrys 13 | // Reverse transforms an array of SSDictionaryEntrys into a dictionary 14 | @interface DicToReadableValuesArray : NSValueTransformer 15 | @end 16 | 17 | -------------------------------------------------------------------------------- /SSYDisplayAlotPopUpButtonCell.h: -------------------------------------------------------------------------------- 1 | #import 2 | 3 | 4 | @interface SSYDisplayAlotPopUpButtonCell : NSPopUpButtonCell { 5 | 6 | } 7 | 8 | @end 9 | -------------------------------------------------------------------------------- /SSYDisplayAlotPopUpButtonCell.m: -------------------------------------------------------------------------------- 1 | #import "SSYDisplayAlotPopUpButtonCell.h" 2 | 3 | @implementation SSYDisplayAlotPopUpButtonCell 4 | 5 | #if 0 6 | #warning No kludge SSYPopUpButtonCell 7 | #else 8 | 9 | - (void)dismissPopUp { 10 | [super dismissPopUp] ; 11 | [[self controlView] display] ; 12 | } 13 | 14 | #if (MAC_OS_X_VERSION_MAX_ALLOWED < 101000) 15 | // macOS 10.9.x or earlier 16 | // This makes absolutely no sense. 17 | #define NSCellHitResult NSUInteger 18 | #endif 19 | 20 | - (NSCellHitResult)hitTestForEvent:(NSEvent *)event 21 | inRect:(NSRect)cellFrame 22 | ofView:(NSView *)controlView { 23 | NSUInteger result = [super hitTestForEvent:event 24 | inRect:cellFrame 25 | ofView:controlView] ; 26 | [controlView display] ; 27 | return result ; 28 | } 29 | 30 | #endif 31 | 32 | @end 33 | -------------------------------------------------------------------------------- /SSYDocChildObject.h: -------------------------------------------------------------------------------- 1 | #import 2 | 3 | @class BkmxDoc ; 4 | 5 | @interface SSYDocChildObject : NSObject { 6 | BkmxDoc* m_document ; 7 | } 8 | 9 | /* 10 | @details It is very important that someone counter this assignment by 11 | sending us a setDocument:nil sometime between the time we find out that the 12 | document is closing and the time that the document deallocs. 13 | */ 14 | - (id)initWithDocument:(BkmxDoc*)document ; 15 | 16 | // Weak reference, not retained, to avoid retain cycles 17 | @property (assign) BkmxDoc* document ; 18 | 19 | @end 20 | -------------------------------------------------------------------------------- /SSYDocChildObject.m: -------------------------------------------------------------------------------- 1 | #import "SSYDocChildObject.h" 2 | #import "BkmxGlobals.h" 3 | #import "SSYDooDooUndoManager.h" 4 | 5 | @implementation SSYDocChildObject 6 | 7 | - (BkmxDoc*)document { 8 | BkmxDoc* document ; 9 | @synchronized(self) { 10 | document = [[m_document retain] autorelease] ; 11 | } 12 | return document ; 13 | } 14 | 15 | - (void)setDocument:(BkmxDoc *)document { 16 | @synchronized(self) { 17 | m_document = document ; 18 | } 19 | } 20 | 21 | - (id)initWithDocument:(BkmxDoc*)document_ { 22 | self = [super init] ; 23 | 24 | if (self != 0) { 25 | [self setDocument:document_] ; 26 | } 27 | 28 | return self; 29 | } 30 | 31 | @end -------------------------------------------------------------------------------- /SSYDocTabViewController.h: -------------------------------------------------------------------------------- 1 | #import 2 | 3 | /* 4 | I was going to factor much of BkmxDocTabViewController into this, 5 | and also factor an BkmxLazyView out of SSYLazyView, but 6 | then decided not to, because it would just be for reuse vanity that 7 | no one would ever re-use. 8 | */ 9 | #if 0 10 | 11 | @interface SSYDocTabViewController : NSViewController { 12 | NSWindowController* m_windowController ; 13 | BOOL m_awakened ; 14 | } 15 | 16 | @property (assign) NSWindowController* windowController ; 17 | @property (assign) BOOL awakened ; 18 | 19 | - (id)initWithNibName:(NSString*)nibNameOrNil 20 | windowController:(NSWindowController*)windowController 21 | bundle:(NSBundle*)nibBundleOrNil ; 22 | 23 | - (NSDocument*)document ; 24 | 25 | - (void)tearDown ; 26 | 27 | @end 28 | 29 | #endif -------------------------------------------------------------------------------- /SSYDocTabViewController.m: -------------------------------------------------------------------------------- 1 | #import "SSYDocTabViewController.h" 2 | 3 | /* 4 | I was going to factor much of BkmxDocTabViewController into this, 5 | and also factor an SSYLazyView out of BkmxLazyView, but 6 | then decided not to, because it would just be for reuse vanity that 7 | no one would ever re-use. 8 | */ 9 | #if 0 10 | 11 | @interface SSYDocTabViewController () 12 | 13 | @end 14 | 15 | @implementation SSYDocTabViewController 16 | 17 | @synthesize windowController = m_windowController ; 18 | @synthesize awakened = m_awakened ; 19 | 20 | - (void)logIfBadInit { 21 | if (self) { 22 | if (![self conformsToProtocol:@protocol(BkmxDocTabViewControls)]) { 23 | NSLog(@"Internal Error 194-2390 %@ no conform", [self className]) ; 24 | } 25 | } 26 | } 27 | 28 | - (id)initWithNibName:(NSString*)nibNameOrNil 29 | windowController:(BkmxDocWinCon*)windowController 30 | bundle:(NSBundle*)nibBundleOrNil { 31 | [self setWindowController:windowController] ; 32 | self = [super initWithNibName:nibNameOrNil 33 | bundle:nibBundleOrNil] ; 34 | [self logIfBadInit] ; 35 | return self ; 36 | } 37 | 38 | - (id)initWithCoder:(NSCoder*)aDecoder { 39 | self = [super initWithCoder:aDecoder] ; 40 | [self logIfBadInit] ; 41 | return self ; 42 | } 43 | 44 | - (void)endEditing:(NSNotification*)note { 45 | [[self windowController] endEditing] ; 46 | } 47 | 48 | - (void)awakeFromNib { 49 | // Safely invoke super 50 | [self safelySendSuperSelector:_cmd 51 | prettyFunction:__PRETTY_FUNCTION__ 52 | arguments:nil] ; 53 | 54 | [self setNextResponder:[[self windowController] nextResponder]] ; 55 | [[self windowController] setNextResponder:self] ; 56 | } 57 | 58 | - (BOOL) tabView:(NSTabView*)tabView 59 | shouldSelectTabViewItem:(NSTabViewItem*)tabViewItem { 60 | return [[self windowController] tabView:tabView 61 | shouldSelectTabViewItem:tabViewItem] ; 62 | } 63 | 64 | - (void) tabView:(NSTabView*)tabView 65 | willSelectTabViewItem:(NSTabViewItem*)tabViewItem { 66 | [[self windowController] tabView:tabView 67 | willSelectTabViewItem:tabViewItem] ; 68 | } 69 | 70 | - (void) tabView:(NSTabView*)tabView 71 | didSelectTabViewItem:(NSTabViewItem*)tabViewItem { 72 | [[self windowController] tabView:tabView 73 | didSelectTabViewItem:tabViewItem] ; 74 | } 75 | 76 | - (void)tearDown { 77 | [self setWindowController:nil] ; 78 | } 79 | 80 | - (BkmxDoc*)document { 81 | return [[self windowController] document] ; 82 | } 83 | 84 | @end 85 | 86 | #endif 87 | -------------------------------------------------------------------------------- /SSYDooDoo+GCUndoManager.zip: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jerrykrinock/ClassesObjC/9f8edc5f804e8d8e1d6183fe9cb91a94b2b83cf2/SSYDooDoo+GCUndoManager.zip -------------------------------------------------------------------------------- /SSYDragDestinationTextView.h: -------------------------------------------------------------------------------- 1 | #import 2 | 3 | @interface SSYDragDestinationTextView : NSTextView { 4 | } 5 | 6 | @property BOOL activateUponDrop ; 7 | 8 | /*! 9 | @brief A wrapper around @property fieldEditor, which has a more meaningful 10 | name than fieldEditor 11 | 12 | @details You can get the same result in Interface Builder, by switching on the 13 | receiver's *Field Editor* checkbox. 14 | */ 15 | @property BOOL ignoreTabsAndReturns ; 16 | 17 | @end 18 | 19 | 20 | -------------------------------------------------------------------------------- /SSYDragDestinationTextView.m: -------------------------------------------------------------------------------- 1 | #import "SSYDragDestinationTextView.h" 2 | 3 | @implementation SSYDragDestinationTextView : NSTextView 4 | 5 | - (void)setIgnoreTabsAndReturns:(BOOL)ignoreTabsAndReturns { 6 | [self setFieldEditor:ignoreTabsAndReturns] ; 7 | } 8 | 9 | - (BOOL)ignoreTabsAndReturns { 10 | return [self isFieldEditor] ; 11 | } 12 | 13 | - (BOOL)performDragOperation:(id )sender { 14 | BOOL didDo = [super performDragOperation:sender] ; 15 | 16 | if (self.activateUponDrop) { 17 | [NSApp activateIgnoringOtherApps:YES] ; 18 | [[self window] makeKeyAndOrderFront:self] ; 19 | } 20 | 21 | return didDo ; 22 | } 23 | 24 | @end 25 | -------------------------------------------------------------------------------- /SSYDragTableView.h: -------------------------------------------------------------------------------- 1 | #import 2 | 3 | /*! 4 | @brief A table view which adds several features to a 5 | table when used in conjunction with SSYArrayController 6 | to which its columns are bound in the conventional way. 7 | 8 | @details The features added are: 9 |
    10 |
  • Drag and Drop reordering (Notes 1, 2, 3)
  • 11 |
  • cmd+upArrow or downArrow to move selection (Note 1)
  • 12 |
  • 'delete' key to delete selection (Note 1)
  • 13 |
14 | 15 | Note 1. Requires that the receiver's 'delegate' outlet be 16 | connected to the associated array controller. 17 | Note 2. Requires that the receiver's 'dataSource' outlet be 18 | connected to the associated array controller. 19 | Note 3. Requires that the associated SSYArrayController's 20 | 'tableView' outlet be connected to the receiver. 21 | */ 22 | @interface SSYDragTableView : NSTableView { 23 | } 24 | 25 | @end 26 | -------------------------------------------------------------------------------- /SSYDropboxIdler.h: -------------------------------------------------------------------------------- 1 | #import 2 | 3 | @protocol SSYDropboxIdlerDelegate 4 | 5 | - (void)appendProgress:(NSString*)progress ; 6 | 7 | @end 8 | 9 | @interface SSYDropboxIdler : NSObject { 10 | NSObject * m_delegate ; 11 | NSString* m_logPath ; 12 | } 13 | 14 | - (id)initWithDelegate:(NSObject *)delegate 15 | logPath:(NSString*)logPath ; 16 | 17 | /*! 18 | @brief Blocks until the Dropbox application appears to be not busy. 19 | 20 | @details The criteria used is that first the CPU usage of the Dropbox 21 | application, returned by /bin/ps, is measured once per 2 seconds for 10 22 | seconds. If the average of these five measurements is less than 1.0 percent, 23 | then three more measurements are taken at 1-second intervals. If all 24 | three of these are less than 0.25 percent, then isIdle_p is set to point 25 | to YES and the method returns. If either of these tests fail, then 26 | they are repeated, and this continues until the timeout. 27 | 28 | When Dropbox is idle, this method usually returns the affirmative result 29 | after 13-39 seconds. When Dropbox is receiving a file, it will not 30 | return an affirmative result until Dropbox is idle. Also when Time 31 | Machine is doing a backup, this usually keeps Dropbox active enough 32 | to not return an affirmative result for a minute or two. But you 33 | probably don't want to be messing with Dropbox while Time Machine 34 | is doing its thing anyhow. 35 | 36 | This method sleeps the thread between measurements, so it's not a 37 | CPU hog, just a thread hog. 38 | 39 | @param timeout time to wait for Dropbox to become idle. However, 40 | one measurement cycle, which takes about 15 seconds, will always 41 | execute. So this method will always block for at least about 15 42 | seconds no matter what value you pass here. 43 | @param isIdle_p Pointer which will, upon return, if not nil, 44 | point to YES if Dropbox is idle and no error occurred, NO otherwise. 45 | @param error_p Pointer which will, upon return, if the method 46 | was not able to determine isIdle_p and error_p is not 47 | NULL, point to an NSError describing said error. 48 | @result YES if the method was able to set isIdle_p, 49 | otherwise NO. 50 | */ 51 | - (BOOL)waitForIdleDropboxTimeout:(NSTimeInterval)samplePeriod 52 | isIdle:(BOOL*)isIdle_p 53 | narrative_p:(NSString**)narrative_p 54 | error_p:(NSError**)error_p ; 55 | 56 | @end 57 | -------------------------------------------------------------------------------- /SSYDynamicMenu.m: -------------------------------------------------------------------------------- 1 | #import "SSYDynamicMenu.h" 2 | #import "SSYRuntimeUtilities.h" 3 | 4 | 5 | @implementation SSYDynamicMenu 6 | 7 | @synthesize target = m_target ; 8 | @synthesize selector = m_selector ; 9 | @synthesize targetInfo = m_targetInfo ; 10 | @synthesize representedObjects = m_representedObjects ; 11 | @synthesize selectedRepresentedObject = m_selectedRepresentedObject ; 12 | 13 | @synthesize owningPopUpButton = m_owningPopUpButton ; 14 | 15 | - (id)initWithTitle:(NSString*)title { 16 | self = [super initWithTitle:title] ; 17 | [self setDelegate:self] ; 18 | return self ; 19 | } 20 | 21 | - (id)initWithCoder:(NSCoder *)coder { 22 | self = [super initWithCoder:coder] ; 23 | [self setDelegate:self] ; 24 | return self ; 25 | } 26 | 27 | - (void)dealloc { 28 | [m_target release] ; 29 | [m_targetInfo release] ; 30 | [m_representedObjects release] ; 31 | [m_selectedRepresentedObject release] ; 32 | 33 | [super dealloc] ; 34 | } 35 | 36 | - (id)initWithTarget:(id)target 37 | selector:(SEL)selector 38 | targetInfo:(id)targetInfo { 39 | self = [super init] ; 40 | 41 | if(self) { 42 | [self setTarget:target] ; 43 | [self setSelector:selector] ; 44 | [self setTargetInfo:targetInfo] ; 45 | } 46 | 47 | return self ; 48 | } 49 | 50 | - (IBAction)hierarchicalMenuAction:(id)sender { 51 | SEL selector = [self selector] ; 52 | NSInteger numberOfArguments = [SSYRuntimeUtilities numberOfArgumentsInSelector:selector] ; 53 | switch (numberOfArguments) { 54 | case 1: 55 | [[self target] performSelector:selector 56 | withObject:[sender representedObject]] ; 57 | break ; 58 | case 2: 59 | [[self target] performSelector:selector 60 | withObject:[self targetInfo] 61 | withObject:[sender representedObject]] ; 62 | break ; 63 | default: 64 | NSLog(@"Internal Error 657-0183") ; 65 | } 66 | } 67 | 68 | - (void)reload { 69 | [[self delegate] menuNeedsUpdate:self] ; 70 | } 71 | 72 | @end -------------------------------------------------------------------------------- /SSYEventInfo.h: -------------------------------------------------------------------------------- 1 | #import 2 | 3 | 4 | /*! 5 | @brief Returns the current state of the modifier keys on the 6 | keyboard. 7 | 8 | @details Uses a Quartz event function because [NSEvent currentEvent] 9 | may return nil during -applicationDidFinishLaunching. 10 | 11 | There are also Carbon functions which work, but they appear to 12 | be kind of depracated, returning a UInt32. 13 | #import "Carbon/Carbon.h" 14 | UInt32 carbonModifiers = GetCurrentEventKeyModifiers() ; 15 | UInt32 carbonModifiers = GetCurrentKeyModifiers() ; 16 | So I don't use them. 17 | */ 18 | @interface SSYEventInfo : NSObject { 19 | } 20 | 21 | + (BOOL)alternateKeyDown; 22 | + (BOOL)shiftKeyDown; 23 | + (BOOL)commandKeyDown; 24 | + (BOOL)controlKeyDown; 25 | 26 | @end 27 | -------------------------------------------------------------------------------- /SSYEventInfo.m: -------------------------------------------------------------------------------- 1 | #import "SSYEventInfo.h" 2 | 3 | 4 | @implementation SSYEventInfo 5 | 6 | + (BOOL)alternateKeyDown { 7 | CGEventFlags modifiers = (CGEventFlags)CGEventSourceFlagsState(kCGEventSourceStateCombinedSessionState) ; 8 | return (modifiers & kCGEventFlagMaskAlternate) != 0 ; 9 | } 10 | 11 | + (BOOL)shiftKeyDown { 12 | CGEventFlags modifiers = (CGEventFlags)CGEventSourceFlagsState(kCGEventSourceStateCombinedSessionState) ; 13 | return (modifiers & kCGEventFlagMaskShift) != 0 ; 14 | } 15 | 16 | + (BOOL)commandKeyDown { 17 | CGEventFlags modifiers = (CGEventFlags)CGEventSourceFlagsState(kCGEventSourceStateCombinedSessionState) ; 18 | return (modifiers & kCGEventFlagMaskCommand) != 0 ; 19 | } 20 | 21 | + (BOOL)controlKeyDown { 22 | CGEventFlags modifiers = (CGEventFlags)CGEventSourceFlagsState(kCGEventSourceStateCombinedSessionState) ; 23 | return (modifiers & kCGEventFlagMaskControl) != 0 ; 24 | } 25 | 26 | @end 27 | -------------------------------------------------------------------------------- /SSYExtrospectiveViewController.h: -------------------------------------------------------------------------------- 1 | #import 2 | #import "SSYSizability.h" 3 | 4 | @interface SSYExtrospectiveViewController : NSViewController { 5 | IBOutlet NSWindowController* windowController ; 6 | } 7 | 8 | - (NSWindowController*)windowController ; 9 | 10 | @end 11 | -------------------------------------------------------------------------------- /SSYExtrospectiveViewController.m: -------------------------------------------------------------------------------- 1 | #import "SSYExtrospectiveViewController.h" 2 | #import "NSObject+SuperUtils.h" 3 | 4 | @implementation SSYExtrospectiveViewController 5 | 6 | - (void)awakeFromNib { 7 | // Safely invoke super 8 | [self safelySendSuperSelector:_cmd 9 | prettyFunction:__PRETTY_FUNCTION__ 10 | arguments:nil] ; 11 | 12 | [self setNextResponder:[windowController nextResponder]] ; 13 | [windowController setNextResponder:self] ; 14 | } 15 | 16 | - (NSWindowController*)windowController { 17 | return windowController ; 18 | } 19 | 20 | @end 21 | -------------------------------------------------------------------------------- /SSYFileDropView.h: -------------------------------------------------------------------------------- 1 | #import 2 | 3 | // Based largely on FileDropView by Seth Willits, 2005 4 | // This still has some pretty kludgey code in it (probably mine - JK) 5 | 6 | @interface SSYFileDropView : NSControl { 7 | BOOL highlight ; 8 | NSString* m_filePath ; 9 | 10 | IBOutlet NSButton* image ; 11 | // In IB, the above is a borderless NSButton. I tried to use a NSView 12 | // here but then this sub-view was outside the drop zone for the 13 | // FIleDropView, and thus FileDropView had a "hole" where the file could 14 | // not be dropped. According to Glenn Andreas: 15 | // NSImageView already has support for drag & drop built in, which is 16 | // what you're seeing (since when dropping, AppKit finds the "deepest" 17 | // view under the mouse that deals with the drop) 18 | IBOutlet NSTextField* label ; 19 | } 20 | 21 | @property (copy) NSString* path ; 22 | 23 | - (NSString*)objectValue ; 24 | - (void)setObjectValue:(NSString*)objectValue ; 25 | 26 | @end -------------------------------------------------------------------------------- /SSYFileFinder.h: -------------------------------------------------------------------------------- 1 | /* This class is adapted from Apple's Sample Code project "Spotlighter", class "AppController" */ 2 | 3 | #import 4 | 5 | /*! 6 | @superclass NSObject { NSMetadataQuery *query ; id callbackTarget ; SEL callbackSelector ; } 7 | @brief A class for programmatically conducting a Spotlight search for a named file, 8 | returning an array of paths. 9 | 10 | @details Two class methods is exposed. findPathsWithPredicate:callbackTarget:callbackSelector: 11 | is the general, base method. findPathsWithFilename:callbackTarget:callbackSelector: is a wrapper 12 | around the base method which shows how to construct predicates for a the search you need. For a complete 13 | list of attributes, consult Apple's "MD Item Reference" documentation and scroll down to 14 | "File System Metadata Attribute Keys". 15 | 16 | The class method creates an instance which self-destructs after the search is complete. 17 | This class requires Mac OS 10.5 or later. 18 | */ 19 | @interface SSYFileFinder : NSObject { 20 | NSMetadataQuery *query ; 21 | id callbackTarget ; 22 | SEL callbackSelector ; 23 | } 24 | 25 | @property(retain) NSMetadataQuery *query ; 26 | @property(retain) id callbackTarget ; 27 | 28 | 29 | /*! 30 | @brief Finds paths of files with a given predicate, by doing a Spotlight search, i.e. using NSMetadaQuery 31 | 32 | @details Runs asynchronously and returns an NSArray of NSString objects to a specified callback 33 | target object, via a specified callback selector. 34 | @param predicate The predicate used to filter items, or qualify results, in the search. 35 | @param callbackTarget The object which will receive the callback. 36 | @param callbackSelector The selector in the callback target which will be invoked. This selector 37 | should take one argument, an NSArray, and should return void. 38 | */ 39 | + (void)findPathsWithPredicate:(NSPredicate*)predicate 40 | callbackTarget:(id)callbackTarget 41 | callbackSelector:(SEL)callbackSelector ; 42 | 43 | 44 | /*! 45 | @brief Invokes findPathsWithPredicate:callbackTarget:callbackSelector: 46 | after constructing a predicate requiring that a results' displayName equal 47 | the passed filename. 48 | @param filename The filename to be searched for. To search for an application, use the extension ".app". 49 | */ 50 | + (void)findPathsWithFilename:(NSString*)filename 51 | callbackTarget:(id)callbackTarget 52 | callbackSelector:(SEL)callbackSelector ; 53 | 54 | @end -------------------------------------------------------------------------------- /SSYFileThumbnailView.h: -------------------------------------------------------------------------------- 1 | #import 2 | 3 | @interface SSYFileThumbnailView : NSImageView 4 | 5 | @end 6 | -------------------------------------------------------------------------------- /SSYFirefoxProfiler.h: -------------------------------------------------------------------------------- 1 | #import 2 | 3 | 4 | @interface SSYFirefoxProfiler : NSObject { 5 | } 6 | 7 | + (NSArray*)profilePseudonymsForHomePath:(NSString*)homePath ; 8 | 9 | + (NSArray*)profileNames ; 10 | 11 | + (NSString*)displayedSuffixForProfileName:(NSString*)profileName 12 | homePath:(NSString*)homePath ; 13 | 14 | /*! 15 | @brief Gets path to the Firefox profile folder for a given Firefox profile 16 | name and home folder, or nil if a failure occurs 17 | 18 | @details Operates by finding the Firefox profiles.ini file in a given home 19 | folder, parsing its entries to find the one pertaining to the given profile 20 | name, and resolving the profile folder path indicated by this entry. 21 | 22 | This method performs the inverse of -profileNameForPath:error_p:. 23 | 24 | @param homePath If nil, defaults to the current user's home path 25 | */ 26 | + (NSString*)pathForProfileName:(NSString*)profileName 27 | homePath:(NSString*)homePath 28 | error_p:(NSError**)error_p ; 29 | 30 | /* 31 | @brief Returns the Firefox profile name given a Firefox profile path 32 | @details Although I did this for years by simply taking the last path 33 | component of the profile path and un-tweaking it, in January 2014 I have 34 | evidence from at least one user that this doesn't always work. Specifically, 35 | his profile name is "Default" but the path to his profile is 36 | ~/Library/Application Support/Firefox/Profiles 37 | That's correct, all of the 3-dozen-or-so files and folders containing his 38 | profile data are in the parent folder "Profiles" instead of in a subfolder. 39 | However, his profiles.ini file contains the correct information in the 40 | following entry… 41 | 42 | [Profile0] 43 | Name=Default 44 | IsRelative=1 45 | Path=Profiles 46 | Default=1 47 | 48 | Oh, well. So, after several hours, I have written this method which finds the 49 | Firefox profiles.ini file which is in the same Home folder that the given 50 | profile path is in, parses the entries in it until it finds the entry whose 51 | path description resolves to the given profile path, and finally extracts from 52 | that entry the profile name. 53 | 54 | The old code which is 99% simpler but only works for 99+% of users, is given 55 | as a comment in the implementation file. 56 | 57 | This method performs the inverse of -pathForProfileName:homePath:error_p: 58 | */ 59 | + (NSString*)profileNameForPath:(NSString*)path 60 | error_p:(NSError**)error_p ; 61 | @end 62 | -------------------------------------------------------------------------------- /SSYFolderMenu.h: -------------------------------------------------------------------------------- 1 | #import 2 | 3 | @protocol SSYFolderItemRepresentedObject 4 | 5 | - (NSInteger)lineageDepth ; 6 | 7 | @end 8 | 9 | 10 | /*! 11 | @brief A subclass of NSMenu which has overridden -insertItemWithTitle:::: 12 | to insert a subclass of NSMenuItem which has its icon a folder icon and 13 | which has as its indentation a multiple of the -lineageDepth of its 14 | represented objects. 15 | 16 | @details The represented objects of the items inserted into this menu 17 | must conform to the protocol SSYFolderItemRepresentedObject. 18 | 19 | A flattened-but-indented hierarchical menu is used in three 20 | places in BookMacster. In BkmxDoc.xib ▸ Settings ▸ New Bookmark Landing, 21 | I use a StarkContainersFlatMenu, which is populated dynamically. I tried 22 | to use that in TalderMapsController.xib, in the two "Folder" columns in the 23 | tables, but couldn't get it to work with bindings. So in those cases I 24 | subclassed NSMenu and NSMenuItem to SSYFolderMenu and SSYFolderMenuItem. 25 | */ 26 | @interface SSYFolderMenu : NSMenu 27 | 28 | @end 29 | -------------------------------------------------------------------------------- /SSYFolderMenu.m: -------------------------------------------------------------------------------- 1 | #import "SSYFolderMenu.h" 2 | 3 | @interface SSYFolderMenuItem : NSMenuItem 4 | 5 | @end 6 | 7 | @implementation SSYFolderMenuItem 8 | 9 | - (NSImage*)image { 10 | return [NSImage imageNamed:@"folder.tif"] ; 11 | } 12 | 13 | - (NSInteger)indentationLevel { 14 | return [[self representedObject] lineageDepth] ; 15 | } 16 | 17 | @end 18 | 19 | 20 | @implementation SSYFolderMenu 21 | 22 | - (NSMenuItem *)insertItemWithTitle:(NSString*)title 23 | action:(SEL)action 24 | keyEquivalent:(NSString*)keyEquiv 25 | atIndex:(NSInteger)index { 26 | NSMenuItem* item = [[SSYFolderMenuItem alloc] initWithTitle:title 27 | action:action 28 | keyEquivalent:keyEquiv] ; 29 | [self insertItem:item 30 | atIndex:index] ; 31 | [item release] ; 32 | 33 | return item ; 34 | } 35 | 36 | @end 37 | -------------------------------------------------------------------------------- /SSYFoo.h: -------------------------------------------------------------------------------- 1 | #import 2 | 3 | /*! 4 | @brief When you are using this class for debugging, 5 | #if the following directive to 1. 6 | */ 7 | #if 0 8 | #warning SSYFoo Debugging Utility class is included 9 | #define SSY_FOO_INCLUDED 1 10 | #endif 11 | 12 | #if SSY_FOO_INCLUDED 13 | 14 | /*! 15 | @brief Class which logs each instance when initialized and when 16 | deallocced; useful for checking retain cycles in, for example, 17 | dictionaries. 18 | 19 | @details This class is useful for finding retain cycles when objects 20 | are put in collections and invocations, for example, so you can see 21 | if and when these objects get deallocced. For collections, 22 | add/set a +fooWithIdentifier: into the collection. (For dictionaries, 23 | set for an arbitrary key like @"Test Key".) For invocations, 24 | add it as an extra, unused argument. For example, if creating with 25 | -invocationWithTarget:selector:retainArguments:argumentAddresses:, 26 | SSYFoo* foo = [SSYFoo fooWithIdentifer:@"Checkpoint 1234"] ; 27 | and then add ,&foo to the end of argumentAddresses varargs. The 28 | argument will, I *think*, be ignored, but it will be released when 29 | the invocation is released. 30 | 31 | In either case, the SSYFoo object will log when it is allocced 32 | and deallocced, showing the identifier you give and also a unique 33 | serial number. 34 | 35 | Serial numbers begin with 1 when the application launches and increment. 36 | */ 37 | @interface SSYFoo : NSObject { 38 | NSInteger m_serialNumber ; 39 | NSString* m_identifier ; 40 | } 41 | 42 | /*! 43 | @brief Object that logs when it is initialized and when it 44 | is deallocced. 45 | 46 | @param identifier Whatever you want. It will be logged. 47 | */ 48 | + (id)fooWithIdentifier:(NSString*)identifier ; 49 | 50 | /*! 51 | @brief A wrapper around NSLog which may be used when you need 52 | to send a message to an object, for example if you want to log 53 | as the result of an invocation 54 | 55 | @param msg The string to be logged. Does not support varargs 56 | format strings. 57 | */ 58 | + (void)log:(NSString*)msg ; 59 | 60 | @end 61 | 62 | #endif 63 | -------------------------------------------------------------------------------- /SSYFoo.m: -------------------------------------------------------------------------------- 1 | #import "SSYFoo.h" 2 | 3 | #if SSY_FOO_INCLUDED 4 | 5 | static NSInteger static_nextSerialNumber = 0 ; 6 | 7 | @interface SSYFoo () 8 | 9 | @property (assign) NSInteger serialNumber ; 10 | @property (retain) NSString* identifier ; 11 | 12 | @end 13 | 14 | 15 | @implementation SSYFoo 16 | 17 | @synthesize serialNumber = m_serialNumber ; 18 | @synthesize identifier = m_identifier ; 19 | 20 | - (id)initWithIdentifier:(NSString*)identifier { 21 | self = [super init] ; 22 | if (self) { 23 | [self setSerialNumber:++static_nextSerialNumber] ; 24 | [self setIdentifier:identifier] ; 25 | } 26 | NSLog(@"Initted Foo %ld %@ %p", (long)[self serialNumber], [self identifier], self) ; 27 | 28 | return self ; 29 | } 30 | 31 | + (SSYFoo*)fooWithIdentifier:(NSString*)identifier { 32 | return [[[SSYFoo alloc] initWithIdentifier:identifier] autorelease] ; 33 | } 34 | 35 | - (void)dealloc { 36 | NSLog(@"Dealloc: Foo %ld %@ %p", (long)[self serialNumber], [self identifier], self) ; 37 | [m_identifier release] ; 38 | 39 | [super dealloc] ; 40 | } 41 | 42 | + (void)log:(NSString*)msg { 43 | NSLog(@"%@", msg) ; 44 | } 45 | 46 | @end 47 | 48 | #endif 49 | -------------------------------------------------------------------------------- /SSYHintArrow.zip: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jerrykrinock/ClassesObjC/9f8edc5f804e8d8e1d6183fe9cb91a94b2b83cf2/SSYHintArrow.zip -------------------------------------------------------------------------------- /SSYHintableWindow.h: -------------------------------------------------------------------------------- 1 | #import 2 | 3 | @interface SSYHintableWindow : NSWindow { 4 | IBOutlet NSWindowController* windowController ; 5 | } 6 | 7 | 8 | @end 9 | -------------------------------------------------------------------------------- /SSYHintableWindow.m: -------------------------------------------------------------------------------- 1 | #import "SSYHintableWindow.h" 2 | #import "SSYHintArrow.h" 3 | 4 | 5 | @implementation SSYHintableWindow 6 | 7 | - (void)sendEvent:(NSEvent *)event { 8 | [SSYHintArrow removeIfEvent:event] ; 9 | [super sendEvent:event] ; 10 | } 11 | 12 | @end 13 | -------------------------------------------------------------------------------- /SSYIOKit.h: -------------------------------------------------------------------------------- 1 | #import 2 | 3 | 4 | @interface SSYIOKit : NSObject 5 | 6 | + (NSData*)primaryMACAddressOrMachineSerialNumberData; 7 | + (NSData*)hashedMACAddress; 8 | + (NSData*)hashedMACAddressAndShortUserName; 9 | 10 | //+ (NSData*)machineSerialNumberData ; 11 | 12 | @end 13 | -------------------------------------------------------------------------------- /SSYLabelledPopUp.h: -------------------------------------------------------------------------------- 1 | #import 2 | 3 | /*! 4 | @brief This class provides a control which consists of a non-editable NSTextField 5 | label and, below it, a popup button. 6 | 7 | @details May be used, for example for a user to select Favorite Color, 8 | etc. etc. 9 | */ 10 | @interface SSYLabelledPopUp : NSView { 11 | NSTextField* labelField ; 12 | NSPopUpButton* popUpButton ; 13 | } 14 | 15 | @property (retain) NSTextField* labelField ; 16 | @property (retain) NSPopUpButton* popUpButton ; 17 | 18 | /*! 19 | @brief Convenience method for getting an autoreleased instance of this class. 20 | 21 | @param label The text value of the label which will appear above 22 | the popup button in the returned instance. 23 | @result The instance, autoreleased 24 | */ 25 | + (SSYLabelledPopUp*)popUpControlWithLabel:(NSString*)label ; 26 | 27 | /*! 28 | @brief Sets the array of choices to appear in the receiver's popup button. 29 | 30 | @param choices An array of strings 31 | */ 32 | - (void)setChoices:(NSArray*)choices ; 33 | 34 | /*! 35 | @brief Returns the index selected in the menu of the receiver's popup 36 | button. 37 | */ 38 | - (NSInteger)selectedIndex ; 39 | 40 | /*! 41 | @brief Resizes the height of the receiver to accomodate the its current values, 42 | subject to allowsShrinking 43 | 44 | @param allowShrinking YES if the height is allowed to be reduced. If this parameter 45 | is NO, and less height than the current height is required, this invocation will not reduce 46 | the height but will instead leave empty space. 47 | */ 48 | - (void)sizeHeightToFitAllowShrinking:(BOOL)allowShrinking ; 49 | 50 | @end 51 | 52 | -------------------------------------------------------------------------------- /SSYLaunchdBasics.h: -------------------------------------------------------------------------------- 1 | #import 2 | 3 | 4 | /*! 5 | @brief Some basic methods for finding out about installed 6 | launchd agents 7 | 8 | @details I refactored these methods out of SSYLaunchdGuy so 9 | I could use them in the CTypes dylib in our Firefox extension 10 | without including a ton of other crap. 11 | */ 12 | @interface SSYLaunchdBasics : NSObject { 13 | } 14 | 15 | + (NSString*)homeLaunchAgentsPath ; 16 | 17 | /*! 18 | @brief Returns a set of all labels (that is, filenames without the 19 | .plist filename extension) in this user's Launch Agents 20 | directory that have a given prefix, possibly an empty set. 21 | 22 | @param The target prefix. May be nil; if so, method returns empty set. 23 | Assumes that the plist files are named using the convention stated in 24 | man launchd.plist(5) "for launchd property list files to be named