Annotation of Examples/DatabaseKit/AddressBook/AddressView.m, revision 1.1.1.1

1.1       root        1: /* AddressView.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 <appkit/appkit.h>
                     11: #import <objc/List.h>
                     12: #import <dbkit/DBRecordList.h>
                     13: #import <dbkit/DBValue.h>
                     14: #import <libc.h>
                     15: 
                     16: #import "AddressView.h"
                     17: #import "Controller.h"
                     18: 
                     19: #define EMPTY_STRING NXLocalizedString("Cannot accept empty string", NULL, "Notify user that empty string input is not valid.")
                     20: 
                     21: static char cellName[100];
                     22: 
                     23: @implementation AddressView
                     24: 
                     25: - initFrame:(const NXRect *)frameRect
                     26: {
                     27:        NXSize interCellSpacing = {0.0, 0.0}, docSize;
                     28: 
                     29:   [    super initFrame:frameRect];
                     30:        cellMatrix = [[Matrix alloc] initFrame:frameRect
                     31:                mode:NX_LISTMODE
                     32:                cellClass:[TextFieldCell class]
                     33:                numRows:0
                     34:                numCols:1];
                     35: 
                     36:        /*
                     37:         * In the following lines,
                     38:         * remember that "cellMatrix" is the matrix that will be installed
                     39:         * in the scrollview, "self" is the scrollview.
                     40:         */
                     41: 
                     42:                /* we don't want any space between the matrix's cells  */
                     43:        [cellMatrix setIntercell:&interCellSpacing];
                     44:                /* resize the matrix to contain the cells */
                     45:        [cellMatrix sizeToCells];
                     46:        [cellMatrix setAutosizeCells:YES];
                     47:        
                     48:        /*
                     49:         * when the user clicks in the matrix and then drags the mouse out of
                     50:         * scrollView's contentView, we want the matrix to scroll
                     51:         */
                     52:        [cellMatrix setAutoscroll:YES];
                     53:                /* let the matrix stretch horizontally */
                     54:        [cellMatrix setAutosizing:NX_WIDTHSIZABLE];  
                     55:                /* Install the matrix as the docview of the scrollview */
                     56:        [[self setDocView:cellMatrix] free];
                     57:                /* set up the visible attributes of the scrollview */
                     58:        [self setVertScrollerRequired:YES];
                     59:        [self setBorderType:NX_BEZEL];
                     60:                /* tell the subviews to resize along with the scrollview */
                     61:        [self setAutoresizeSubviews:YES];
                     62:                /* This is the only way to get the clipview to resize too */
                     63:        [[cellMatrix superview] setAutoresizeSubviews:YES];
                     64:                /* Allow the scrollview to stretch both horizontally and vertically */
                     65:        [self setAutosizing:NX_WIDTHSIZABLE|NX_HEIGHTSIZABLE];
                     66:                /* Resize the matrix to fill the inside of the scrollview */
                     67:        [self getContentSize:&docSize];
                     68:        [cellMatrix sizeTo:docSize.width :docSize.height];
                     69: 
                     70:        /* Set the matrix single click action */
                     71:        [cellMatrix setTarget:self];
                     72:        [cellMatrix setAction:@selector(showInfo:)];
                     73:         
                     74:        /* Allocate DBValue instances for accessing record contents */
                     75:        aValue = [[DBValue alloc] init];
                     76:        aValue2 = [[DBValue alloc] init];
                     77:        return self;
                     78: }
                     79: 
                     80: - free
                     81: {
                     82:         [cellMatrix free];
                     83:         if (aValue)
                     84:                [aValue free];
                     85:        if (aValue2)
                     86:                [aValue2 free];
                     87:         return [super free];
                     88: }
                     89: 
                     90: - cellMatrix
                     91: {
                     92:         return cellMatrix;
                     93: }
                     94: 
                     95: /*
                     96:  * Since we recycle the cells (via renewRows:cols:), we also set the state
                     97:  * of each cell to 0 and unhighlight it.  If we don't do that, the recycled
                     98:  * cells will display their previous state.
                     99:  */
                    100: - loadCellsFrom:sender
                    101: 
                    102: {
                    103:     int i, cellCount;
                    104:        const char *firstName, *lastName;
                    105:        char buf[100];
                    106:        DBRecordList *  recordList;
                    107:        List *  propertyList;
                    108:                
                    109:        recordList = (DBRecordList *)[controller getRecordList];
                    110:        propertyList = (List *)[controller getPropertyList];
                    111:        cellCount = (int) [controller getRecordCount];
                    112:        
                    113:        if (cellCount == 0 )
                    114:                return self;
                    115:   
                    116:         
                    117:         /* tell the matrix there are 0 cells in it (but don't deallocate them) */
                    118:        [cellMatrix renewRows:0 cols:1];
                    119:        [cellMatrix lockFocus];         /* for highlightCellAt::lit: */
                    120:         for (i=0;i<cellCount;i++) {
                    121:        TextFieldCell *cell;
                    122:                 /*
                    123:         * add a row to the matrix.  (This doesn't necessarily allocate a new
                    124:         * cell, thanks to renewRows:cols:).
                    125:         */
                    126:        [cellMatrix addRow];
                    127:        cell = [cellMatrix cellAt:i:0];
                    128:                 /* make sure the cell is neither selected nor highlighted */
                    129:                 [cellMatrix highlightCellAt:i:0 lit:NO];
                    130:        [cell setState:0];
                    131:                
                    132:        /* install the string value in that cell */
                    133:                [recordList getValue:aValue 
                    134:                                        forProperty:[propertyList objectAt:1]at:i];                                                                                      
                    135:                lastName= (const char *)[aValue stringValue];
                    136: 
                    137:                [recordList getValue:aValue2 
                    138:                                        forProperty:[propertyList objectAt:2]at:i];                                                                                                              
                    139:                firstName = (const char *)[aValue2 stringValue];
                    140:                sprintf(buf, "%s %s", lastName, firstName);
                    141:        [cell setStringValue:buf];
                    142:                
                    143:        }
                    144:        [cellMatrix unlockFocus];
                    145:        [cellMatrix sizeToCells];
                    146:        [cellMatrix display];
                    147:        
                    148:         return self;
                    149: }
                    150: 
                    151: /* Get the newly added row */
                    152: - (int) getNewRow
                    153: {
                    154:        int i;
                    155:        int count, row;
                    156:        const char* name;
                    157:        
                    158:        count = [cellMatrix cellCount];
                    159:        row = count;    /* Initialize row to a meaningful number */
                    160:        for (i = 0; i < count; i++) {
                    161:                name = [[cellMatrix cellAt:i:0] stringValue];
                    162:                if (!strcmp(cellName, name) ) {
                    163:                        row = i;
                    164:                        break;
                    165:                }
                    166:        }
                    167:        return row;
                    168: }
                    169: 
                    170: 
                    171: /* Show the information contained in each selected record
                    172:  */
                    173:  
                    174: - showInfo:sender
                    175: {
                    176:        int index;
                    177:        DBRecordList * recordList;
                    178:        List *  propertyList;
                    179: 
                    180:        recordList = [controller getRecordList];
                    181:        propertyList = [controller getPropertyList];
                    182: 
                    183:        index = [cellMatrix selectedRow];
                    184: 
                    185:                /* Find the person's id */
                    186:        
                    187:        [recordList getValue:aValue forProperty:[propertyList objectAt:0]at:index];                                                                                                                                                                                                                                                                      
                    188:        [ssnField setStringValue:(const char *)[aValue stringValue]];
                    189: 
                    190: 
                    191:                /* Find the person's last name and first name */
                    192:        [recordList getValue:aValue forProperty:[propertyList objectAt:1]at:index];                                                                                                                                                                                                                                                                      
                    193:        [lnameField setStringValue: (const char *)[aValue stringValue]];
                    194: 
                    195:        [recordList getValue:aValue forProperty:[propertyList objectAt:2]at:index];                                                                                                                                      
                    196:     [fnameField setStringValue:(const char *)[aValue stringValue]];
                    197: 
                    198:                                /* Find the person's phone number */
                    199:        [recordList getValue:aValue forProperty:[propertyList objectAt:3]at:index];                                                                                                                                                                                                                                                              
                    200:        [phoneField setStringValue:(const char *)[aValue stringValue]];
                    201:        
                    202:                /* Find the person's address */
                    203:        [recordList getValue:aValue forProperty:[propertyList objectAt:4]at:index];                                                                                                                                                                                                                                                              
                    204:        [addressField setStringValue:(const char *)[aValue stringValue]];
                    205: 
                    206:                /* Find the person's city of residence */
                    207:        [recordList getValue:aValue forProperty:[propertyList objectAt:5]at:index];
                    208:        [cityField setStringValue:(const char *)[aValue stringValue]];
                    209: 
                    210: 
                    211:                /* Find the person's state of residence */
                    212:        [recordList getValue:aValue forProperty:[propertyList objectAt:6]at:index];                                                                                                                                                                                                                                                              
                    213:        [stateField setStringValue:(const char *)[aValue stringValue]];
                    214: 
                    215:                /* Find the person's zip code */
                    216:        [recordList getValue:aValue forProperty:[propertyList objectAt:7]at:index];                                                                                                                                                                                                                                                              
                    217:        [zipField setStringValue:(const char *)[aValue stringValue]];
                    218:        return self;
                    219: }
                    220: 
                    221: /* Add a new record at the specified index. 
                    222:  */
                    223: - addRecordFrom:sender at:(unsigned)index
                    224: {              
                    225:        DBRecordList *  recordList;
                    226:        List *  propertyList;
                    227:        
                    228:        recordList = (DBRecordList *)[controller getRecordList];
                    229:        propertyList = (List *)[controller getPropertyList];
                    230:        
                    231:                        /* In order to get records in and out, 
                    232:                         *      we must use a value object all the time
                    233:                         */
                    234:                                        
                    235:                /* add empty record */
                    236:        [recordList insertRecordAt:index];
                    237:        if ([self setNewRecordFrom:sender at:index] == nil) {
                    238:                return nil;
                    239:        }
                    240:                                                                                        
                    241:        if ([recordList saveModifications] == 0)
                    242:                return self;
                    243:                        
                    244:        return nil;     
                    245: }
                    246: 
                    247: /* Update the record specified at index.
                    248:  */
                    249:  
                    250: - updateRecordFrom:sender at:(unsigned) index
                    251: {
                    252:        DBRecordList *  recordList;
                    253:        List * propertyList;    
                    254:                
                    255:        recordList = (DBRecordList *)[controller getRecordList];
                    256:        propertyList = (List *) [controller getPropertyList];
                    257:                
                    258:        if ([self setNewRecordFrom:sender at:index] == nil) {
                    259:                return nil;
                    260:        }
                    261:        
                    262:        if ([recordList saveModifications] == 0)
                    263:                return self;
                    264:        return nil;     
                    265: }
                    266: 
                    267: /* Get the user input from the text fields. Note that if a field is empty,
                    268:  * the operation (either insert or update) would fail. Also, for simplicity,
                    269:  * an arbitrary contract number is assigned to new records.
                    270:  */
                    271: - setNewRecordFrom:sender at:(unsigned)index
                    272: {
                    273:        DBRecordList *aRecList;
                    274:        List *aPropList;
                    275:        const char *inputString;
                    276:        const char *lastName;
                    277: 
                    278:        aRecList = (DBRecordList *)[controller getRecordList];
                    279:        aPropList = (List *)[controller getPropertyList];
                    280:        
                    281:        /* get the ssn or author id */
                    282:  
                    283:        inputString = (const char *)[ssnField stringValue];
                    284:        
                    285:                /* If the string is empty, abort the operation */
                    286:        if  ( !strcmp(inputString,"")){
                    287:                NXRunAlertPanel (NULL,EMPTY_STRING,NULL, NULL, NULL);
                    288:                return nil;
                    289:        }
                    290:        else {  
                    291:                [aValue setStringValue:inputString];
                    292:                [aRecList setValue:aValue forProperty:[aPropList objectAt:0] at:index];
                    293:        }
                    294:                
                    295:                
                    296:                /* set last name */             
                    297:        lastName = (const char *)[lnameField stringValue];
                    298:        if  ( !strcmp(lastName,"")){
                    299:                NXRunAlertPanel (NULL,EMPTY_STRING,NULL, NULL, NULL);
                    300:                return nil;
                    301:        } 
                    302:        else {
                    303:                [aValue setStringValue:lastName];
                    304:                [aRecList setValue:aValue forProperty:[aPropList objectAt:1] at:index];                  
                    305:        }
                    306:                
                    307:                
                    308:                /* set first name */
                    309:        inputString = (const char *)[fnameField stringValue];
                    310:        if  ( !strcmp(inputString,"")){
                    311:                NXRunAlertPanel (NULL, EMPTY_STRING, NULL, NULL, NULL);
                    312:                return nil;
                    313:        }
                    314:        else {
                    315:                [aValue setStringValue:(const char *)inputString];
                    316:                [aRecList setValue:aValue forProperty:[aPropList objectAt:2] at:index];
                    317:                sprintf( cellName, "%s %s", lastName, inputString);
                    318:        }
                    319:                
                    320:                        /* set phone number */
                    321:        inputString = (const char *)[phoneField stringValue];
                    322:        if  ( !strcmp(inputString,"")){
                    323:                NXRunAlertPanel (NULL,EMPTY_STRING,NULL, NULL, NULL);
                    324:                return nil;
                    325:        }
                    326:        else {   
                    327:                [aValue setStringValue: inputString];
                    328:                [aRecList setValue:aValue forProperty:[aPropList objectAt:3] at:index];
                    329:        }
                    330:        
                    331:                        /* set address */
                    332:        inputString = (const char *)[addressField stringValue];
                    333:        if  ( !strcmp(inputString,"")){
                    334:                NXRunAlertPanel (NULL,EMPTY_STRING,NULL, NULL, NULL);
                    335:                return nil;
                    336:        }
                    337:        else {
                    338:                [aValue setStringValue: inputString];
                    339:                [aRecList setValue:aValue forProperty:[aPropList objectAt:4] at:index];
                    340:        }
                    341: 
                    342:                        /* set city name */
                    343:        inputString = (const char *)[cityField stringValue];
                    344:        if  ( !strcmp(inputString,"")){
                    345:                NXRunAlertPanel (NULL,EMPTY_STRING,NULL, NULL, NULL);
                    346:                return nil;
                    347:        } 
                    348:        else {
                    349:                [aValue setStringValue: inputString];
                    350:                [aRecList setValue:aValue forProperty:[aPropList objectAt:5] at:index];
                    351:        }
                    352: 
                    353:                        /* set state */
                    354:        inputString = (const char *)[stateField stringValue];
                    355:        if  ( !strcmp(inputString,"")){
                    356:                NXRunAlertPanel (NULL,EMPTY_STRING,NULL, NULL, NULL);
                    357:                return nil;
                    358:        }
                    359:        else {   
                    360:                [aValue setStringValue: inputString];
                    361:                [aRecList setValue:aValue forProperty:[aPropList objectAt:6] at:index];
                    362:        }
                    363: 
                    364:                        /* set zip code */
                    365:        inputString = (const char *)[zipField stringValue];
                    366:        if  ( !strcmp(inputString,"")){
                    367:                NXRunAlertPanel (NULL,EMPTY_STRING,NULL, NULL, NULL);
                    368:                return nil;
                    369:        } 
                    370:        else {
                    371:                [aValue setStringValue: inputString];
                    372:                [aRecList setValue:aValue forProperty:[aPropList objectAt:7] at:index]; 
                    373:        }
                    374: 
                    375: 
                    376:                /* assign an arbitrary contract number 1 to the new record */
                    377:        [aRecList getValue:aValue forProperty:[aPropList objectAt:8] at:index];
                    378:        
                    379:        if ( ![aValue intValue]) {
                    380:                [aValue setIntValue:1];
                    381:                [aRecList setValue:aValue forProperty:[aPropList objectAt:8] at:index];
                    382:        }
                    383: 
                    384:        return self;
                    385: }
                    386: 
                    387: 
                    388: 
                    389: - deleteSelectedRecord:sender
                    390: {
                    391:        int row;
                    392:        DBRecordList * recordList;
                    393: 
                    394:        row = [cellMatrix selectedRow];
                    395:        recordList = (DBRecordList *)[controller getRecordList];
                    396:        [recordList deleteRecordAt:row];
                    397:        if ([recordList saveModifications] == 0)
                    398:                return self;
                    399:        else
                    400:                return nil;
                    401: }
                    402: 
                    403: @end

unix.superglobalmegacorp.com

This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.