|
|
1.1 root 1: /* MainController.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: #import "MainController.h"
11: #import "Department.h"
12: #import "strings.h"
13:
14: @implementation MainController
15:
16: - init
17: {
18: [super init];
19: return self;
20: }
21:
22: - appDidInit:sender
23: {
24:
25: dbDataSource = [masterController dataSource];
26: dbChannel = [dbDataSource databaseChannel];
27: adaptorChannel = [dbChannel adaptorChannel];
28: eoAdaptor = [[adaptorChannel adaptorContext] adaptor];
29:
30:
31: // Bring up a login panel and get the valid connection dictionary
32:
33: if(![eoAdaptor runLoginPanelAndValidateConnectionDictionary])
34: [NXApp terminate:self];
35: [eoAdaptor setConnectionDictionary: [eoAdaptor connectionDictionary]];
36:
37: rootEntity = [dbDataSource entity];
38:
39: [self setDelegates];
40:
41: // set up the controller to not alter the selection after a fetch
42: [masterController setSelectsFirstObjectAfterFetch:NO];
43:
44: [self fetch:sender];
45: return self;
46: }
47:
48: // Perform a fetch based on the latest options specified by user.
49:
50: - fetch:sender
51: {
52: if (optionsPanel)
53: [optionsPanel orderOut:sender];
54:
55: [self setUpFetch:sender];
56:
57: [masterController fetch];
58: return self;
59: }
60:
61: - newRecord:sender
62: {
63: int i;
64:
65: // Clear all the current values in the form cells to prepare
66: // for the insertion of a new record.
67:
68: for (i = 0; i < 5; i++)
69: [formMatrix setStringValue:"" at:i];
70: return self;
71: }
72:
73: - insert:sender
74: {
75: // Disable the INSERT Button if the input is not valid
76: if ([self validateRecord] == NO) {
77: [insertButton setState:0];
78: NXRunAlertPanel(NULL, ERR_INSERT_FAIL, NULL, NULL, NULL);
79: }
80: else {
81: [insertButton setState:1];
82: [masterController insert:sender];
83: }
84: return self;
85: }
86:
87:
88: // Set up the fetch order and specify a qualifier
89: // for the master table "Department"
90:
91: - setUpFetch:sender
92: {
93: const char *inputString;
94: const char *attrName = NULL;
95: EOQualifier *aQualifier;
96: id fetchOrder;
97: id sortAttribute;
98: int orderType;
99:
100: // build the qualifier.
101: // If the input string is empty, fetch all records.
102:
103: inputString = [(TextField *)textField stringValue];
104:
105: if (inputString == NULL)
106: [dbDataSource setQualifier: [rootEntity qualifier]];
107: else {
108: aQualifier = [[[EOQualifier alloc] initWithEntity:rootEntity
109: qualifierFormat:@"%A >= %d", @"DeptId",
110: [textField intValue]] autorelease];
111: [dbDataSource setQualifier:aQualifier];
112: }
113:
114: // build the fetch order based on the first column of the master
115: // tableview
116:
117: orderType = [sortMatrix selectedTag];
118: attrName = [[masterTableview columnAt:0] title];
119: sortAttribute = [rootEntity attributeNamed:[ [[NSString alloc]
120: initWithCString:attrName] autorelease]];
121: fetchOrder = [NSArray arrayWithObject:[[[EOAttributeOrdering alloc]
122: initWithAttribute:sortAttribute ordering: orderType] autorelease]];
123:
124: [dbDataSource setFetchOrder:fetchOrder];
125: return self;
126: }
127:
128:
129: - (BOOL) validateRecord
130: {
131: int newId, newLocation;
132: BOOL result = YES;
133:
134: newId = [formMatrix intValueAt:0];
135: newLocation = [formMatrix intValueAt:2];
136:
137: // Do validation here
138: if ( newId < 100 || newId > 999) {
139: NXRunAlertPanel(NULL, ERR_INVALID_ID, NULL, NULL, NULL);
140: result = NO;
141: }
142: if ( newLocation != 1101 && newLocation != 1103
143: && newLocation != 1104 && newLocation != 1106
144: && newLocation != 1207) {
145: NXRunAlertPanel(NULL, ERR_INVALID_LOCATION, NULL, NULL, NULL);
146: result = NO;
147: }
148: return result;
149:
150: }
151: - setDelegates
152: {
153: #ifdef DEBUG
154: [adaptorChannel setDebugEnabled:YES];
155: #endif
156: [adaptorChannel setDelegate:self];
157: [(EOController *) masterController setDelegate:self];
158:
159: return self;
160: }
161:
162: @end
163:
164: @implementation MainController (EOAdaptorDelegation)
165:
166: //This method is useful to trace SQL queries
167: - (void)adaptorChannel:channel
168: didEvaluateExpression:(NSString *)expression
169: {
170: if (sqlPanel) {
171: [text appendToText:"SQL Query:\n"];
172: [text appendToText:[expression cString]];
173: [text appendToText:"\n"];
174: }
175: }
176: @end
177:
178:
179: @implementation MainController (EOControllerDelegation)
180:
181: // This method is called before each update. Since the controller has
182: // buffer edits turned ON, this method is called when the user explicitly
183: // presses the UPDATE button.
184:
185: - (NSDictionary *)controller:(EOController *)controller
186: willSaveEdits: (NSDictionary *)edits
187: toObject:object
188: {
189: if ([self validateRecord] == YES)
190: return edits;
191: else {
192: NXRunAlertPanel(NULL, ERR_UPDATE_FAIL, NULL, NULL, NULL);
193: return nil;
194: }
195: }
196:
197: // Take the input from the formcells and create a new record.
198: // This delegate method can be used to set up the default values of a newly
199: // created EO. By default, we use the current user input in the formcells
200: // to create a new record.
201:
202:
203: - (BOOL)controller:(EOController *)controller willInsertObject:object atIndex: (unsigned)newIndex
204: {
205: [object setDeptId: (int)[formMatrix intValueAt:0]];
206: [object setDepartmentName:[[[NSString alloc] initWithCString:
207: [formMatrix stringValueAt:1]] autorelease]];
208: [object setLocationId:(int)[formMatrix intValueAt:2]];
209: // The to-many relationship points to an empty autoreleased array
210: [object setToEmployee:[NSArray array]];
211: return YES;
212:
213: }
214:
215: // After insertion, refetch object so that the derived attributes are
216: // properly redisplayed.
217:
218: - (void)controller:(EOController *)controller didInsertObject:object
219: inDataSource:dataSource
220: {
221: [dbChannel refetchObject:object];
222: }
223:
224: // After an update, refetch object so that the derived attributes are
225: // properly redisplayed.
226:
227: - (void)controller:(EOController *)controller didUpdateObject:object
228: inDataSource:dataSource
229: {
230: [dbChannel refetchObject:object];
231: }
232:
233: // When the insert operation failed, remove the wrong record and rollback
234: // the data source. A failure usually happens when trying to insert a duplicate
235: // key. Since an insert operation adds a new record after the current
236: // selection, the index has to be computed accordingly.
237:
238:
239: - (EODataSourceFailureResponse)controller:(EOController *)controller
240: failedToInsertObject:object
241: inDataSource:dataSource;
242: {
243: NXRunAlertPanel(NULL, ERR_INSERT_FAIL, NULL, NULL, NULL);
244:
245: [controller deleteObjectAtIndex:([masterTableview selectedRow] + 1)];
246:
247: return EORollbackDataSourceFailureResponse;
248: }
249:
250: - (EODataSourceFailureResponse) controller:(EOController *)controller
251: failedToUpdateObject:object
252: inDataSource:dataSource
253: {
254: NXRunAlertPanel(NULL, ERR_UPDATE_FAIL, NULL, NULL, NULL);
255: // Restore object to its previous state
256: [dbChannel refetchObject:object];
257:
258: return EORollbackDataSourceFailureResponse;
259: }
260:
261:
262: // When deleting a department, we need to null all the references
263: // to that department. Therefore, the "toEmployee" relationship is
264: // used to find the employee records attached to a given department.
265: // All department ids will then be nulled out.
266:
267:
268: - (BOOL)controller:controller willDeleteObject:object
269: {
270:
271: NSArray *employeeArray = [object toEmployee];
272: NSEnumerator *enumerator = [employeeArray objectEnumerator];
273: EOGenericRecord *employee;
274:
275: while((employee = [enumerator nextObject]) != nil) {
276: [employee setObject:[EONull null] forKey:@"DeptId"];
277: [(id)[controller dataSource] updateObject:employee];
278: }
279:
280: return YES;
281: }
282:
283:
284: // Implementing this delegate method allows the controller to discard
285: // pending edits. In this example, pending edits are edits rejected by
286: // the validation mechanism, hence they can be discarded.
287:
288: - (BOOL) controllerWillDiscardEdits:(EOController *)controller
289: {
290: return YES;
291: }
292:
293: @end
294:
295: @implementation Text(printResults)
296:
297: - appendToText:(const char *)newText
298: {
299: int currentLength = [self textLength];
300:
301: [self setSel:currentLength :currentLength];
302: [self replaceSel:newText];
303: [self scrollSelToVisible];
304: return self;
305: }
306:
307: @end
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.