|
|
1.1 root 1: /* TableViewController.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 "TableViewController.h"
11:
12: #define INSTALL_MODEL NXLocalizedString("Please install SybaseDemo.dbmodela or OracleDemo.dbmodela in your project.", NULL, "Notify user that the ascii model files must be installed in his project directory.")
13:
14: /* Comment this line out if you want to run an Oracle version */
15: #define SYBASE_DEMO 1
16:
17: @implementation TableViewController
18: /*
19: * Miscellaneous initialization tasks: connect to database, initialize
20: * tableview, set up dbModule.
21: */
22: -appDidInit:sender
23: {
24: NXRect viewFrame;
25:
26: #ifdef SYBASE_DEMO
27: /* Notify the user if the database can't be found */
28: if (!(dbDatabase = [DBDatabase findDatabaseNamed:"SybaseDemo"
29: connect:YES])) {
30: NXRunAlertPanel(NULL,INSTALL_MODEL, "OK", NULL, NULL);
31: return self;
32: }
33: #else
34: /* Notify the user if the database can't be found */
35: if (!(dbDatabase = [DBDatabase findDatabaseNamed:"OracleDemo"
36: connect:YES])) {
37: NXRunAlertPanel(NULL,INSTALL_MODEL, "OK", NULL, NULL);
38: return self;
39: }
40: #endif
41:
42: [dbDatabase setDelegate:self];
43:
44: /* Install the tableview into the custom view */
45: [[dbTableView getFrame:&viewFrame] free];
46: dbTableView = [[DBTableView alloc] initFrame:&viewFrame];
47: [[window contentView] addSubview:dbTableView];
48: [dbTableView setHorizScrollerRequired:YES];
49: [dbTableView setVertScrollerRequired:YES];
50: [dbTableView setDelegate: self];
51:
52: #ifdef SYBASE_DEMO
53: rootEntity = [dbDatabase entityNamed:"Author"];
54: #else
55: rootEntity = [dbDatabase entityNamed:"Order"];
56: #endif
57: /* Must initialize your dbModule */
58: dbModule = [[DBModule alloc] initDatabase:dbDatabase
59: entity:rootEntity];
60: dbFetchGroup = [dbModule rootFetchGroup];
61: [dbFetchGroup setDelegate:self];
62: #ifdef SYBASE_DEMO
63: dbQualifier = [[DBQualifier alloc] initForEntity:[dbModule entity]
64: fromDescription:"state = %s", "CA"];
65: #else
66: dbQualifier = [[DBQualifier alloc] initForEntity:[dbModule entity]
67: fromDescription:"customer.state = %s", "CA"];
68: #endif
69: [window disableFlushWindow];
70: [self initTableView];
71: [[window reenableFlushWindow] flushWindow];
72:
73: return self;
74: }
75: - showAll:sender
76: {
77: [dbFetchGroup fetchContentsOf:[dbModule entity]
78: usingQualifier:dbQualifier];
79: [dbTableView display];
80:
81: return self;
82: }
83:
84: /* In order to replicate the Interface Builder functionality, one has to
85: * add an expression to the fetchgroup for each attribute and subattribute.
86: */
87:
88: - addTableColumn:(const char *)label
89: {
90: id newExpression;
91:
92: /* allocate a new expression, add it to the FetchGroup and add it */
93: /* to the TableView */
94: newExpression = [[DBExpression alloc] initForEntity:[dbModule entity]
95: fromDescription:label];
96: [dbFetchGroup addExpression:newExpression];
97: [dbTableView addColumn:newExpression withTitle:label];
98: return self;
99: }
100:
101:
102: /* Get all the attributes and subattributes from the defined table and
103: * initialize the tableview accordingly.
104: */
105: - initTableView
106: {
107: int i, j, propCount, subpropCount;
108: id prop, subprop, subpropList;
109: char buffer[100];
110: id <DBEntities, DBTypes> theEntity;
111:
112: propList = [[List alloc] init];
113: [rootEntity getProperties: propList];
114: propCount = [propList count];
115:
116: for (i = 0; i < propCount; i++) {
117: prop = [propList objectAt:i];
118: theEntity = (id<DBTypes>)[prop propertyType];
119: if(! [theEntity isEntity]) {
120:
121: /* add top-level attribute */
122: [self addTableColumn:[prop name]]; /* defined above */
123: } else if ([prop isSingular]) {
124:
125: /* add all sub-attributes but skip sub-relationships.
126: Note that getting sub-attributes only work for
127: to-one relationship
128: */
129: subpropList = [[List alloc] init];
130:
131: [theEntity getProperties:subpropList];
132: subpropCount = [subpropList count];
133: for (j = 0; j < subpropCount; j++) {
134: subprop = [subpropList objectAt:j];
135: if (![[subprop propertyType] isEntity]) {
136: sprintf(buffer, "%s.%s", [prop name], [subprop name]);
137: [self addTableColumn:buffer]; /* defined above */
138: }
139: }
140: [subpropList free]; /* to prevent a memory leak */
141: }
142: }
143:
144: /* Making this association will make the fetchgroup
145: * become the tableview data source.
146: */
147: [dbFetchGroup makeAssociationFrom:nil to:dbTableView];
148: /*
149: * free property list which is no longer needed
150: */
151: [propList free];
152: [window makeKeyAndOrderFront:self];
153: return self;
154: }
155:
156:
157: /* Set the sort order before the actual fetch */
158: - fetchGroupWillFetch: sender
159: {
160: if( sortProp == nil) {
161: sortProp = [[dbTableView columnAt: 0] identifier];
162: }
163: [[sender recordList]
164: addRetrieveOrder: DB_AscendingOrder
165: for: sortProp];
166: return self;
167: }
168:
169: /* Find the new sort property every time the tableView column gets moved */
170: - tableView:sender movedColumnFrom:(unsigned int) old to:(unsigned int) new
171: {
172: sortProp = [[sender columnAt: new] identifier];
173: return [dbModule fetchAllRecords: self];
174: }
175:
176:
177:
178:
179: - free
180: {
181: if (dbQualifier)
182: [dbQualifier free];
183: if (dbTableView)
184: [dbTableView free];
185: return [super free];
186: }
187:
188: /* DBDatabase delegate methods to log SQL queries - Useful for debugging */
189:
190: - (BOOL)db:aDb willEvaluateString:(const char*)aString usingBinder:aBinder
191: {
192: fprintf(stderr, "SQL query:%s\n", aString);
193: return YES;
194: }
195:
196: @end
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.