|
|
1.1 ! root 1: /* Controller.m: ! 2: * You may freely copy, distribute, and reuse the code in this example. ! 3: * NeXT disclaims any warranty of any kind, expressed or implied, as to its ! 4: * fitness for any particular use. ! 5: * ! 6: * Written by: Mai Nguyen, NeXT Developer Support ! 7: * ! 8: * ! 9: */ ! 10: ! 11: #import <appkit/appkit.h> ! 12: #import <dbkit/dbkit.h> ! 13: #import <objc/List.h> ! 14: #import <objc/NXBundle.h> ! 15: #import <sys/param.h> ! 16: #import <libc.h> ! 17: ! 18: #import "Controller.h" ! 19: #import "AddressView.h" ! 20: ! 21: ! 22: #define FAILURE NXLocalizedString("Failure:", NULL, "Message given to user when connection to database can't be made") ! 23: #define CANNOT_CONNECT NXLocalizedString("Couldn't connect to database", NULL, "Message given to user to explain what fails. ") ! 24: #define CANNOT_ADD NXLocalizedString("Add operation failed", NULL, "Message given to user that add operation has failed") ! 25: #define CANNOT_UPDATE NXLocalizedString("Update operation failed",NULL,"Message given to user that update operation has failed") ! 26: #define CANNOT_DELETE NXLocalizedString("Delete operation failed",NULL,"Message given to user that delete operation has failed") ! 27: ! 28: @implementation Controller ! 29: ! 30: - appDidInit:sender ! 31: { ! 32: /* Try to connect to the database specified using the Sybase Adaptor ! 33: * and the default login sa, NULL password, SYBASE server, and ! 34: * pubs database. ! 35: */ ! 36: database = [[DBDatabase alloc]init]; ! 37: [database connectUsingAdaptor:"SybaseAdaptor" ! 38: andString:"sa@SYBASE/pubs"]; ! 39: ! 40: if ( ![database isConnected] ) { ! 41: NXRunAlertPanel(FAILURE, CANNOT_CONNECT, "OK", NULL, NULL); ! 42: return self; ! 43: } ! 44: /* Once successfully connected, build the data to be displayed in the ! 45: * matrix ! 46: */ ! 47: [self initRecordList]; ! 48: [addressView loadCellsFrom:self]; ! 49: ! 50: /* Assign the controller to become the database delegate */ ! 51: [database setDelegate:self]; ! 52: ! 53: cellMatrix = [addressView cellMatrix]; ! 54: ! 55: /* Select a cell as a start */ ! 56: [[cellMatrix selectCellAt:0 :0] sendAction]; ! 57: /* Bring the main application window up front */ ! 58: [theWindow makeKeyAndOrderFront:nil]; ! 59: ! 60: return self; ! 61: } ! 62: ! 63: /* Set up the DBRecordList object. Create a list of properties which contains ! 64: * all properties needed for display or updating. ! 65: */ ! 66: - initRecordList ! 67: { ! 68: id firstName, lastName, phone; ! 69: id state, city, address, zipCode, contract; ! 70: List *keyList; ! 71: ! 72: if (recordList) ! 73: [recordList free]; ! 74: if (propertyList) ! 75: [propertyList free]; ! 76: ! 77: /* get the author table from the database */ ! 78: authorEntity = [database entityNamed:"authors"]; ! 79: ! 80: /* get the properties */ ! 81: lastName = [authorEntity propertyNamed:"au_lname"]; ! 82: firstName = [authorEntity propertyNamed:"au_fname"]; ! 83: authId = [authorEntity propertyNamed:"au_id"]; ! 84: ! 85: phone = [authorEntity propertyNamed:"phone"]; ! 86: address = [authorEntity propertyNamed:"address"]; ! 87: city = [authorEntity propertyNamed:"city"]; ! 88: state = [authorEntity propertyNamed:"state"]; ! 89: zipCode = [authorEntity propertyNamed:"zip"]; ! 90: contract = [authorEntity propertyNamed:"contract"]; ! 91: ! 92: /* Set up the property list ! 93: * Note that certain properties need to be defined in order ! 94: * for an Insert or Update operation to work. This depends ! 95: * on how your data dictionary has been defined. Here pubs ! 96: * is being used as the model. ! 97: */ ! 98: propertyList = [[List alloc] init]; ! 99: [propertyList addObject:authId]; ! 100: [propertyList addObject:lastName]; ! 101: [propertyList addObject:firstName]; ! 102: [propertyList addObject:phone]; ! 103: [propertyList addObject:address]; ! 104: [propertyList addObject:city]; ! 105: [propertyList addObject:state]; ! 106: [propertyList addObject:zipCode]; ! 107: [propertyList addObject:contract]; ! 108: ! 109: recordList = [[DBRecordList alloc] init]; ! 110: ! 111: ! 112: /* A unique key is needed if you want to update or insert new ! 113: * data via the record list into the database. If no key is defined, ! 114: * the data retrieved via the record list is read-only. ! 115: * This is needed here, since we do not use a dbmodel to define ! 116: * the key. ! 117: */ ! 118: keyList = (List *)[[List alloc] init]; ! 119: [keyList addObject:authId]; ! 120: [recordList setKeyProperties:keyList]; ! 121: [keyList free]; ! 122: ! 123: /* You must set the properties FIRST before setting the retrieve order */ ! 124: [recordList setProperties:propertyList ofSource:authorEntity]; ! 125: ! 126: [recordList addRetrieveOrder:DB_AscendingOrder for:lastName]; ! 127: [recordList addRetrieveOrder:DB_AscendingOrder for:firstName]; ! 128: [recordList fetchUsingQualifier:nil]; ! 129: recordCount = [recordList count]; ! 130: ! 131: return self; ! 132: } ! 133: ! 134: /* This method is called when selecting "Insert" ! 135: */ ! 136: - addRecords:sender ! 137: { ! 138: ! 139: int row; ! 140: ! 141: if (recordCount > 0) { ! 142: ! 143: if ( ![addressView addRecordFrom:sender at:(recordCount-1)]) { ! 144: NXRunAlertPanel(NULL, CANNOT_ADD, NULL, NULL, NULL); ! 145: return self; ! 146: } ! 147: ! 148: [self initRecordList]; ! 149: [addressView loadCellsFrom:self]; ! 150: /* Find the row of the newly inserted record */ ! 151: row = [addressView getNewRow]; ! 152: [cellMatrix scrollCellToVisible:row :0]; ! 153: [[cellMatrix selectCellAt:row:0] sendAction]; ! 154: } ! 155: else ! 156: fprintf(stderr, "empty record list - NOP\n"); ! 157: return self; ! 158: } ! 159: ! 160: /* This method gets called when selecting "Update" ! 161: */ ! 162: - updateRecords:sender ! 163: { ! 164: int row; ! 165: ! 166: row = [cellMatrix selectedRow]; ! 167: if ( ![addressView updateRecordFrom:sender at:row]) { ! 168: NXRunAlertPanel(NULL, CANNOT_UPDATE, NULL, NULL, NULL); ! 169: return self; ! 170: } ! 171: /* Redisplay the records */ ! 172: [self initRecordList]; ! 173: [addressView loadCellsFrom:self]; ! 174: /* find the row of the updated record */ ! 175: row = [addressView getNewRow]; ! 176: [cellMatrix scrollCellToVisible:row :0]; ! 177: [[cellMatrix selectCellAt:row:0] sendAction]; ! 178: ! 179: return self; ! 180: } ! 181: ! 182: ! 183: - deleteRecords:sender ! 184: { ! 185: ! 186: int row; ! 187: ! 188: row = [cellMatrix selectedRow]; ! 189: if (recordCount > 0) { ! 190: ! 191: if (![addressView deleteSelectedRecord:sender]) { ! 192: NXRunAlertPanel(NULL, CANNOT_DELETE, NULL, NULL, NULL); ! 193: return self; ! 194: } ! 195: ! 196: [self initRecordList]; ! 197: [addressView loadCellsFrom:self]; ! 198: [cellMatrix scrollCellToVisible:row :0]; ! 199: [[cellMatrix selectCellAt:row:0] sendAction]; ! 200: } ! 201: else ! 202: fprintf(stderr, "empty record list - NOP\n"); ! 203: ! 204: return self; ! 205: } ! 206: - getRecordList ! 207: { ! 208: return recordList; ! 209: } ! 210: ! 211: - getPropertyList ! 212: { ! 213: return propertyList; ! 214: } ! 215: ! 216: - (int)getRecordCount ! 217: { ! 218: return recordCount; ! 219: } ! 220: ! 221: - showSQLPanel:sender ! 222: { ! 223: [SQLPanel makeKeyAndOrderFront:nil]; ! 224: return self; ! 225: } ! 226: ! 227: - showInfoPanel:sender ! 228: { ! 229: if (!infoPanel) { ! 230: infoPanel = [NXApp loadNibSection:"InfoPanel.nib" owner:NXApp ! 231: withNames:NO]; ! 232: } ! 233: [infoPanel orderFront:nil]; ! 234: return self; ! 235: } ! 236: ! 237: - appWillTerminate:sender ! 238: { ! 239: /* deallocate what has been allocated */ ! 240: if (recordList) ! 241: [recordList free]; ! 242: if (propertyList) ! 243: [propertyList free]; ! 244: return self; ! 245: } ! 246: ! 247: /* DBDatabase delegate methods to log error messages and SQL queries */ ! 248: ! 249: - (BOOL)db:aDb willEvaluateString:(const unsigned char*)aString ! 250: usingBinder:aBinder ! 251: { ! 252: [textObj appendToText:"SQL Query:\n"]; ! 253: [textObj appendToText:aString]; ! 254: [textObj appendToText:"\n"]; ! 255: return YES; ! 256: } ! 257: ! 258: @end ! 259: ! 260: @implementation Text(printResults) ! 261: ! 262: - appendToText:(const char *)newText ! 263: { ! 264: int currentLength = [self textLength]; ! 265: ! 266: [self setSel:currentLength :currentLength]; ! 267: [self replaceSel:newText]; ! 268: [self scrollSelToVisible]; ! 269: return self; ! 270: } ! 271: ! 272: @end
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.