This is Controller.m in view mode; [Download] [Up]
/* Controller.m: * You may freely copy, distribute, and reuse the code in this example. * NeXT disclaims any warranty of any kind, expressed or implied, as to its * fitness for any particular use. * * Written by: Mai Nguyen, NeXT Developer Support * * */ #import <appkit/appkit.h> #import <dbkit/dbkit.h> #import <objc/List.h> #import <objc/NXBundle.h> #import <sys/param.h> #import <libc.h> #import "Controller.h" #import "AddressView.h" #import "Appender.h" #define FAILURE NXLocalizedString("Failure:", NULL, "Message given to user when connection to database can't be made") #define CANNOT_CONNECT NXLocalizedString("Couldn't connect to database", NULL, "Message given to user to explain what fails. ") #define CANNOT_ADD NXLocalizedString("Add operation failed", NULL, "Message given to user that add operation has failed") #define CANNOT_UPDATE NXLocalizedString("Update operation failed",NULL,"Message given to user that update operation has failed") #define CANNOT_DELETE NXLocalizedString("Delete operation failed",NULL,"Message given to user that delete operation has failed") @implementation Controller - appDidInit:sender { /* Try to connect to the database specified using the Sybase Adaptor * and the default login sa, NULL password, SYBASE server, and * pubs database. */ database = [[DBDatabase alloc]init]; [database connectUsingAdaptor:"SybaseAdaptor" andString:"sa@SYBASE/pubs"]; if ( ![database isConnected] ) { NXRunAlertPanel(FAILURE, CANNOT_CONNECT, "OK", NULL, NULL); return self; } /* Once successfully connected, build the data to be displayed in the * matrix */ [self initRecordList]; [addressView loadCellsFrom:self]; /* Assign the controller to become the database delegate */ [database setDelegate:self]; cellMatrix = [addressView cellMatrix]; /* Select a cell as a start */ [[cellMatrix selectCellAt:0 :0] sendAction]; /* Bring the main application window up front */ [theWindow makeKeyAndOrderFront:nil]; return self; } /* Set up the DBRecordList object. Create a list of properties which contains * all properties needed for display or updating. */ - initRecordList { id firstName, lastName, phone; id state, city, address, zipCode, contract; List *keyList; if (recordList) [recordList free]; if (propertyList) [propertyList free]; /* get the author table from the database */ authorEntity = [database entityNamed:"authors"]; /* get the properties */ lastName = [authorEntity propertyNamed:"au_lname"]; firstName = [authorEntity propertyNamed:"au_fname"]; authId = [authorEntity propertyNamed:"au_id"]; phone = [authorEntity propertyNamed:"phone"]; address = [authorEntity propertyNamed:"address"]; city = [authorEntity propertyNamed:"city"]; state = [authorEntity propertyNamed:"state"]; zipCode = [authorEntity propertyNamed:"zip"]; contract = [authorEntity propertyNamed:"contract"]; /* Set up the property list * Note that certain properties need to be defined in order * for an Insert or Update operation to work. This depends * on how your data dictionary has been defined. Here pubs * is being used as the model. */ propertyList = [[List alloc] init]; [propertyList addObject:authId]; [propertyList addObject:lastName]; [propertyList addObject:firstName]; [propertyList addObject:phone]; [propertyList addObject:address]; [propertyList addObject:city]; [propertyList addObject:state]; [propertyList addObject:zipCode]; [propertyList addObject:contract]; recordList = [[DBRecordList alloc] init]; /* A unique key is needed if you want to update or insert new * data via the record list into the database. If no key is defined, * the data retrieved via the record list is read-only. * This is needed here, since we do not use a dbmodel to define * the key. */ keyList = (List *)[[List alloc] init]; [keyList addObject:authId]; [recordList setKeyProperties:keyList]; [keyList free]; /* You must set the properties FIRST before setting the retrieve order */ [recordList setProperties:propertyList ofSource:authorEntity]; [recordList addRetrieveOrder:DB_AscendingOrder for:lastName]; [recordList addRetrieveOrder:DB_AscendingOrder for:firstName]; [recordList fetchUsingQualifier:nil]; recordCount = [recordList count]; return self; } /* This method is called when selecting "Insert" */ - addRecords:sender { int row; if (recordCount > 0) { if ( ![addressView addRecordFrom:sender at:(recordCount-1)]) { NXRunAlertPanel(NULL, CANNOT_ADD, NULL, NULL, NULL); return self; } [self initRecordList]; [addressView loadCellsFrom:self]; /* Find the row of the newly inserted record */ row = [addressView getNewRow]; [cellMatrix scrollCellToVisible:row :0]; [[cellMatrix selectCellAt:row:0] sendAction]; } else fprintf(stderr, "empty record list - NOP\n"); return self; } /* This method gets called when selecting "Update" */ - updateRecords:sender { int row; row = [cellMatrix selectedRow]; if ( ![addressView updateRecordFrom:sender at:row]) { NXRunAlertPanel(NULL, CANNOT_UPDATE, NULL, NULL, NULL); return self; } /* Redisplay the records */ [self initRecordList]; [addressView loadCellsFrom:self]; /* find the row of the updated record */ row = [addressView getNewRow]; [cellMatrix scrollCellToVisible:row :0]; [[cellMatrix selectCellAt:row:0] sendAction]; return self; } - deleteRecords:sender { int row; row = [cellMatrix selectedRow]; if (recordCount > 0) { if (![addressView deleteSelectedRecord:sender]) { NXRunAlertPanel(NULL, CANNOT_DELETE, NULL, NULL, NULL); return self; } [self initRecordList]; [addressView loadCellsFrom:self]; [cellMatrix scrollCellToVisible:row :0]; [[cellMatrix selectCellAt:row:0] sendAction]; } else fprintf(stderr, "empty record list - NOP\n"); return self; } - getRecordList { return recordList; } - getPropertyList { return propertyList; } - (int)getRecordCount { return recordCount; } - showSQLPanel:sender { [SQLPanel makeKeyAndOrderFront:nil]; return self; } /* The use of NXBundle here ensures that the proper panel is loaded in case * it's being localized. */ - showInfoPanel:sender { char path[MAXPATHLEN+1]; if (!infoPanel) { if ([[NXBundle mainBundle] getPath:path forResource:"InfoPanel" ofType:"nib"]) { infoPanel = [NXApp loadNibFile:path owner:NXApp withNames:NO fromZone:[NXApp zone]]; } } [infoPanel orderFront:nil]; return self; } - appWillTerminate:sender { /* deallocate what has been allocated */ if (recordList) [recordList free]; if (propertyList) [propertyList free]; return self; } /* DBDatabase delegate methods to log error messages and SQL queries */ - (BOOL)db:aDb willEvaluateString:(const char*)aString usingBinder:aBinder { [appender appendToText:"SQL Query:\n"]; [appender appendToText:aString]; [appender appendToText:"\n"]; return YES; } @end
These are the contents of the former NiCE NeXT User Group NeXTSTEP/OpenStep software archive, currently hosted by Netfuture.ch.