Annotation of Examples/DatabaseKit/AddressBook/AddressView.m, revision 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.