This is MiscPickList.m in view mode; [Download] [Up]
// // MiscPickList.m -- Pick List // Written by Don Yacktman Copyright (c) 1994 by Don Yacktman. // Version 0.1. All rights reserved. // // This notice may not be removed from this source code. // // This object is included in the MiscKit by permission from the author // and its use is governed by the MiscKit license, found in the file // "LICENSE.rtf" in the MiscKit distribution. Please refer to that file // for a list of all applicable permissions and restrictions. // #import "MiscPickList.h" #import <sys/param.h> #define MISC_PickListExtension "picklist" static MiscDictionary *availableLists = nil; @interface MiscPickList(private) - _enableButtons:(BOOL)flag; - _updateBrowser; @end @implementation MiscPickList(private) - _enableButtons:(BOOL)flag { [modifyButton setEnabled:flag]; [addButton setEnabled:flag]; return self; } - _updateBrowser { // adds/removes the items in the browser as necessary int i, cnt; [self loadNibIfNeeded]; cnt = [sortedKeys count]; [browser renewRows:cnt cols:1]; for (i=0; i<cnt; i++) { id newCell = [browser cellAt:i :0]; [newCell setTag:i]; [newCell setTitle:[[sortedKeys objectAt:i] stringValue]]; } [[browser sizeToCells] display]; return self; } @end @implementation MiscPickList + findPickListNamed:(MiscString *)aName { if (!availableLists) { availableLists = [[MiscDictionary alloc] init]; } if ([availableLists isKey:aName]) { return [availableLists valueForKey:aName]; } else { MiscPickList *theList = [[self alloc] initForListNamed:aName]; [availableLists insertKey:aName value:theList]; return theList; } return nil; } + (MiscString *)pickListExtension { static id theExtension = nil; if (!theExtension) theExtension = [MiscString newWithString:MISC_PickListExtension]; return theExtension; } + (MiscString *)fileNameForPickListNamed:(MiscString *)aName { char path[MAXPATHLEN+1]; char *file; MiscString *fileName; if ([[NXBundle mainBundle] getPath:path forResource:[aName stringValue] ofType:[[self pickListExtension] stringValue]]) return [MiscString newWithString:path]; // Couldn't find it in the app bundle, so we'll check the // various libraries and see what we can find... if (![MiscFileFinder findFileTypeNamed: "PickLists"]) { [[MiscFileFinder alloc] initName:"PickLists" defaultPath: "~/Library/PickLists:/Library/PickLists:/LocalLibrary/PickLists" pathVariable:"PICKLISTPATH" mode:R_OK]; } fileName = [[MiscString alloc] initFromFormat:"%s.%s", [aName stringValue], [[self pickListExtension] stringValue]]; file = [[MiscFileFinder findFileTypeNamed:"PickLists"] fullPathForFile:[fileName stringValue]]; [fileName free]; if (file) return [MiscString newWithString:file]; return nil; // couldn't find it. } - init { // return [self error:"Don't call MiscPickList's -init method!"]; return [self initForListNamed:[MiscString newWithString:"Default"]]; } - free { [itemList freeObjects]; [itemList free]; [sortedKeys freeObjects]; [sortedKeys free]; [listPath free]; [listName free]; return [super free]; } - initForListNamed:(MiscString *)aName { [super init]; autoSave = YES; sortedKeys = [[List alloc] init]; itemList = nil; [self loadItemList:nil name:aName]; return self; } - loadItemList:(MiscString *)aPath name:(MiscString *)aName { if (listName) [listName free]; listName = [aName copy]; if (listPath) [listPath free]; listPath = [aPath copy]; if (!listPath) { listPath = [[self class] fileNameForPickListNamed:aName]; } [self reloadItemList]; return self; } - reloadItemList; { if (itemList) { [itemList freeObjects]; [itemList free]; } itemList = MiscParseTableFile(listPath); [sortedKeys freeObjects]; [sortedKeys empty]; { void *k, *v; NXHashState hs = [itemList initState]; while ([itemList nextState:&hs key:&k value:&v]) { [sortedKeys addObject:[(id)k copy]]; } [sortedKeys miscStringSort]; } changed = NO; return self; } - saveList { return [self saveListToPath:listPath]; } - saveListToPath:(MiscString *)aPath { // ***** If we can't save to a global list, then we should try to // save to a list in the user's ~Library directory. MiscWriteTableFile(aPath, itemList); changed = NO; return self; } - popUp:sender { [self _updateBrowser]; [browser selectCellAt:0 :0]; [browser scrollCellToVisible:0 :0]; [entryText takeStringValueFrom:[self selectedKey]]; [[self window] setTitle:[listName stringValue]]; [[self window] makeKeyAndOrderFront:self]; // ***** probably want to position the window near the text field... return self; } - popUpForTextPal:aTextField { [self setTextPal:aTextField]; return [self popUp:nil]; } - doEntry:sender { [entryText takeStringValueFrom:[self selectedKey]]; [textPal takeStringValueFrom:[itemList valueForKey:[self selectedKey]]]; return self; } - finishEntry:sender { [self doEntry:sender]; [[self window] orderOut:self]; return self; } - addItem:sender { id theString = [MiscString new]; if (![entryText respondsTo:@selector(stringValue)]) return nil; [theString takeStringValueFrom:entryText]; [self addItemToList:theString value:theString]; [self _enableButtons:NO]; return self; } - modifyItem:sender { // Take the selected key, delete it, and then do an add. [[self window] disableDisplay]; [[self window] disableFlushWindow]; [self removeItemFromList:[self selectedKey]]; [self addItem:sender]; [self _enableButtons:NO]; [[self window] reenableDisplay]; [[self window] reenableFlushWindow]; [[self window] display]; return self; } - addItemToList:(MiscString *)anItem { [self addItemToList:anItem value:anItem]; return self; } - addItemToList:(MiscString *)anItem value:(MiscString *)aValue { BOOL haveIt = ([itemList isKey:anItem] ? YES : NO); // return if already have key _and_ it has identical value: if (haveIt) { id existingValue = [itemList valueForKey:anItem]; if ([existingValue isEqual:aValue]) return nil; // no changes... } [[self window] disableDisplay]; [[self window] disableFlushWindow]; // add the item to the list, update the browser [itemList insertKey:anItem value:aValue]; if (!haveIt) { [sortedKeys addObject:anItem]; [sortedKeys miscStringSort]; [self _updateBrowser]; // browser displays keys, we only update // if we didn't have the key before. [self selectKey:anItem]; } changed = YES; if (autoSave) [self saveList]; [[self window] reenableDisplay]; [[self window] reenableFlushWindow]; [[self window] display]; return self; } - removeItemFromList:(MiscString *)anItem { int i; if (![itemList isKey:anItem]) return nil; [itemList removeKey:anItem]; for (i=0; i<[sortedKeys count]; i++) { if ([[sortedKeys objectAt:i] isEqual:anItem]) { [sortedKeys removeObjectAt:i]; changed = YES; [self _updateBrowser]; if (autoSave) [self saveList]; return self; } } return nil; } - (MiscDictionary *)itemList { return itemList; } - (BOOL)isDirty { return changed; } - (MiscString *)listPath { return listPath; } - (MiscString *)listName { return listName; } - (BOOL)autoSave { return autoSave; } - setAutoSave:(BOOL)flag { autoSave = flag; return self; } - browser { return browser; } - entryText { return entryText; } - textPal { return textPal; } - setBrowser:anObject { browser = anObject; return self; } - setEntryText:anObject { entryText = anObject; return self; } - setTextPal:anObject { textPal = anObject; return self; } - nibDidLoad { [browser setDoubleAction:@selector(finishEntry:)]; return [super nibDidLoad]; } - (BOOL)textWillChange:textObject { [self _enableButtons:YES]; return NO; } - (MiscString *)selectedKey { static id aString = nil; if (!aString) aString = [MiscString new]; [aString setStringValue:[[browser selectedCell] title]]; return aString; } - selectKey:(MiscString *)aKey { int i; for (i=0; i<[sortedKeys count]; i++) { if ([aKey isEqual:[sortedKeys objectAt:i]]) { [browser selectCellAt:i :0]; [browser scrollCellToVisible:i :0]; [self doEntry:browser]; // as if they clicked here... return self; } } return nil; } @end
These are the contents of the former NiCE NeXT User Group NeXTSTEP/OpenStep software archive, currently hosted by Netfuture.ch.