home *** CD-ROM | disk | FTP | other *** search
- /* AddressView.m:
- * You may freely copy, distribute, and reuse the code in this example.
- * NeXT disclaims any warranty of any kind, expressed or implied, as to its
- * fitness for any particular use.
- *
- * Written by Mai Nguyen, NeXT Developer Support
- *
- */
-
- #import <appkit/appkit.h>
- #import <objc/List.h>
- #import <dbkit/DBRecordList.h>
- #import <dbkit/DBValue.h>
- #import <libc.h>
-
- #import "AddressView.h"
- #import "Controller.h"
-
- #define EMPTY_STRING NXLocalizedString("Cannot accept empty string", NULL, "Notify user that empty string input is not valid.")
-
- static char cellName[100];
-
- @implementation AddressView
-
- - initFrame:(const NXRect *)frameRect
- {
- NXSize interCellSpacing = {0.0, 0.0}, docSize;
-
- [ super initFrame:frameRect];
- cellMatrix = [[Matrix alloc] initFrame:frameRect
- mode:NX_LISTMODE
- cellClass:[TextFieldCell class]
- numRows:0
- numCols:1];
-
- /*
- * In the following lines,
- * remember that "cellMatrix" is the matrix that will be installed
- * in the scrollview, "self" is the scrollview.
- */
-
- /* we don't want any space between the matrix's cells */
- [cellMatrix setIntercell:&interCellSpacing];
- /* resize the matrix to contain the cells */
- [cellMatrix sizeToCells];
- [cellMatrix setAutosizeCells:YES];
-
- /*
- * when the user clicks in the matrix and then drags the mouse out of
- * scrollView's contentView, we want the matrix to scroll
- */
- [cellMatrix setAutoscroll:YES];
- /* let the matrix stretch horizontally */
- [cellMatrix setAutosizing:NX_WIDTHSIZABLE];
- /* Install the matrix as the docview of the scrollview */
- [[self setDocView:cellMatrix] free];
- /* set up the visible attributes of the scrollview */
- [self setVertScrollerRequired:YES];
- [self setBorderType:NX_BEZEL];
- /* tell the subviews to resize along with the scrollview */
- [self setAutoresizeSubviews:YES];
- /* This is the only way to get the clipview to resize too */
- [[cellMatrix superview] setAutoresizeSubviews:YES];
- /* Allow the scrollview to stretch both horizontally and vertically */
- [self setAutosizing:NX_WIDTHSIZABLE|NX_HEIGHTSIZABLE];
- /* Resize the matrix to fill the inside of the scrollview */
- [self getContentSize:&docSize];
- [cellMatrix sizeTo:docSize.width :docSize.height];
-
- /* Set the matrix single click action */
- [cellMatrix setTarget:self];
- [cellMatrix setAction:@selector(showInfo:)];
-
- /* Allocate DBValue instances for accessing record contents */
- aValue = [[DBValue alloc] init];
- aValue2 = [[DBValue alloc] init];
- return self;
- }
-
- - free
- {
- [cellMatrix free];
- if (aValue)
- [aValue free];
- if (aValue2)
- [aValue2 free];
- return [super free];
- }
-
- - cellMatrix
- {
- return cellMatrix;
- }
-
- /*
- * Since we recycle the cells (via renewRows:cols:), we also set the state
- * of each cell to 0 and unhighlight it. If we don't do that, the recycled
- * cells will display their previous state.
- */
- - loadCellsFrom:sender
-
- {
- int i, cellCount;
- const char *firstName, *lastName;
- char buf[100];
- DBRecordList * recordList;
- List * propertyList;
-
- recordList = (DBRecordList *)[controller getRecordList];
- propertyList = (List *)[controller getPropertyList];
- cellCount = (int) [controller getRecordCount];
-
- if (cellCount == 0 )
- return self;
-
-
- /* tell the matrix there are 0 cells in it (but don't deallocate them) */
- [cellMatrix renewRows:0 cols:1];
- [cellMatrix lockFocus]; /* for highlightCellAt::lit: */
- for (i=0;i<cellCount;i++) {
- TextFieldCell *cell;
- /*
- * add a row to the matrix. (This doesn't necessarily allocate a new
- * cell, thanks to renewRows:cols:).
- */
- [cellMatrix addRow];
- cell = [cellMatrix cellAt:i:0];
- /* make sure the cell is neither selected nor highlighted */
- [cellMatrix highlightCellAt:i:0 lit:NO];
- [cell setState:0];
-
- /* install the string value in that cell */
- [recordList getValue:aValue
- forProperty:[propertyList objectAt:1]at:i];
- lastName= (const char *)[aValue stringValue];
-
- [recordList getValue:aValue2
- forProperty:[propertyList objectAt:2]at:i];
- firstName = (const char *)[aValue2 stringValue];
- sprintf(buf, "%s %s", lastName, firstName);
- [cell setStringValue:buf];
-
- }
- [cellMatrix unlockFocus];
- [cellMatrix sizeToCells];
- [cellMatrix display];
-
- return self;
- }
-
- /* Get the newly added row */
- - (int) getNewRow
- {
- int i;
- int count, row;
- const char* name;
-
- count = [cellMatrix cellCount];
- row = count; /* Initialize row to a meaningful number */
- for (i = 0; i < count; i++) {
- name = [[cellMatrix cellAt:i:0] stringValue];
- if (!strcmp(cellName, name) ) {
- row = i;
- break;
- }
- }
- return row;
- }
-
-
- /* Show the information contained in each selected record
- */
-
- - showInfo:sender
- {
- int index;
- DBRecordList * recordList;
- List * propertyList;
-
- recordList = [controller getRecordList];
- propertyList = [controller getPropertyList];
-
- index = [cellMatrix selectedRow];
-
- /* Find the person's id */
-
- [recordList getValue:aValue forProperty:[propertyList objectAt:0]at:index];
- [ssnField setStringValue:(const char *)[aValue stringValue]];
-
-
- /* Find the person's last name and first name */
- [recordList getValue:aValue forProperty:[propertyList objectAt:1]at:index];
- [lnameField setStringValue: (const char *)[aValue stringValue]];
-
- [recordList getValue:aValue forProperty:[propertyList objectAt:2]at:index];
- [fnameField setStringValue:(const char *)[aValue stringValue]];
-
- /* Find the person's phone number */
- [recordList getValue:aValue forProperty:[propertyList objectAt:3]at:index];
- [phoneField setStringValue:(const char *)[aValue stringValue]];
-
- /* Find the person's address */
- [recordList getValue:aValue forProperty:[propertyList objectAt:4]at:index];
- [addressField setStringValue:(const char *)[aValue stringValue]];
-
- /* Find the person's city of residence */
- [recordList getValue:aValue forProperty:[propertyList objectAt:5]at:index];
- [cityField setStringValue:(const char *)[aValue stringValue]];
-
-
- /* Find the person's state of residence */
- [recordList getValue:aValue forProperty:[propertyList objectAt:6]at:index];
- [stateField setStringValue:(const char *)[aValue stringValue]];
-
- /* Find the person's zip code */
- [recordList getValue:aValue forProperty:[propertyList objectAt:7]at:index];
- [zipField setStringValue:(const char *)[aValue stringValue]];
- return self;
- }
-
- /* Add a new record at the specified index.
- */
- - addRecordFrom:sender at:(unsigned)index
- {
- DBRecordList * recordList;
- List * propertyList;
-
- recordList = (DBRecordList *)[controller getRecordList];
- propertyList = (List *)[controller getPropertyList];
-
- /* In order to get records in and out,
- * we must use a value object all the time
- */
-
- /* add empty record */
- [recordList insertRecordAt:index];
- if ([self setNewRecordFrom:sender at:index] == nil) {
- return nil;
- }
-
- if ([recordList saveModifications] == 0)
- return self;
-
- return nil;
- }
-
- /* Update the record specified at index.
- */
-
- - updateRecordFrom:sender at:(unsigned) index
- {
- DBRecordList * recordList;
- List * propertyList;
-
- recordList = (DBRecordList *)[controller getRecordList];
- propertyList = (List *) [controller getPropertyList];
-
- if ([self setNewRecordFrom:sender at:index] == nil) {
- return nil;
- }
-
- if ([recordList saveModifications] == 0)
- return self;
- return nil;
- }
-
- /* Get the user input from the text fields. Note that if a field is empty,
- * the operation (either insert or update) would fail. Also, for simplicity,
- * an arbitrary contract number is assigned to new records.
- */
- - setNewRecordFrom:sender at:(unsigned)index
- {
- DBRecordList *aRecList;
- List *aPropList;
- const char *inputString;
- const char *lastName;
-
- aRecList = (DBRecordList *)[controller getRecordList];
- aPropList = (List *)[controller getPropertyList];
-
- /* get the ssn or author id */
-
- inputString = (const char *)[ssnField stringValue];
-
- /* If the string is empty, abort the operation */
- if ( !strcmp(inputString,"")){
- NXRunAlertPanel (NULL,EMPTY_STRING,NULL, NULL, NULL);
- return nil;
- }
- else {
- [aValue setStringValue:inputString];
- [aRecList setValue:aValue forProperty:[aPropList objectAt:0] at:index];
- }
-
-
- /* set last name */
- lastName = (const char *)[lnameField stringValue];
- if ( !strcmp(lastName,"")){
- NXRunAlertPanel (NULL,EMPTY_STRING,NULL, NULL, NULL);
- return nil;
- }
- else {
- [aValue setStringValue:lastName];
- [aRecList setValue:aValue forProperty:[aPropList objectAt:1] at:index];
- }
-
-
- /* set first name */
- inputString = (const char *)[fnameField stringValue];
- if ( !strcmp(inputString,"")){
- NXRunAlertPanel (NULL, EMPTY_STRING, NULL, NULL, NULL);
- return nil;
- }
- else {
- [aValue setStringValue:(const char *)inputString];
- [aRecList setValue:aValue forProperty:[aPropList objectAt:2] at:index];
- sprintf( cellName, "%s %s", lastName, inputString);
- }
-
- /* set phone number */
- inputString = (const char *)[phoneField stringValue];
- if ( !strcmp(inputString,"")){
- NXRunAlertPanel (NULL,EMPTY_STRING,NULL, NULL, NULL);
- return nil;
- }
- else {
- [aValue setStringValue: inputString];
- [aRecList setValue:aValue forProperty:[aPropList objectAt:3] at:index];
- }
-
- /* set address */
- inputString = (const char *)[addressField stringValue];
- if ( !strcmp(inputString,"")){
- NXRunAlertPanel (NULL,EMPTY_STRING,NULL, NULL, NULL);
- return nil;
- }
- else {
- [aValue setStringValue: inputString];
- [aRecList setValue:aValue forProperty:[aPropList objectAt:4] at:index];
- }
-
- /* set city name */
- inputString = (const char *)[cityField stringValue];
- if ( !strcmp(inputString,"")){
- NXRunAlertPanel (NULL,EMPTY_STRING,NULL, NULL, NULL);
- return nil;
- }
- else {
- [aValue setStringValue: inputString];
- [aRecList setValue:aValue forProperty:[aPropList objectAt:5] at:index];
- }
-
- /* set state */
- inputString = (const char *)[stateField stringValue];
- if ( !strcmp(inputString,"")){
- NXRunAlertPanel (NULL,EMPTY_STRING,NULL, NULL, NULL);
- return nil;
- }
- else {
- [aValue setStringValue: inputString];
- [aRecList setValue:aValue forProperty:[aPropList objectAt:6] at:index];
- }
-
- /* set zip code */
- inputString = (const char *)[zipField stringValue];
- if ( !strcmp(inputString,"")){
- NXRunAlertPanel (NULL,EMPTY_STRING,NULL, NULL, NULL);
- return nil;
- }
- else {
- [aValue setStringValue: inputString];
- [aRecList setValue:aValue forProperty:[aPropList objectAt:7] at:index];
- }
-
-
- /* assign an arbitrary contract number 1 to the new record */
- [aRecList getValue:aValue forProperty:[aPropList objectAt:8] at:index];
-
- if ( ![aValue intValue]) {
- [aValue setIntValue:1];
- [aRecList setValue:aValue forProperty:[aPropList objectAt:8] at:index];
- }
-
- return self;
- }
-
-
-
- - deleteSelectedRecord:sender
- {
- int row;
- DBRecordList * recordList;
-
- row = [cellMatrix selectedRow];
- recordList = (DBRecordList *)[controller getRecordList];
- [recordList deleteRecordAt:row];
- if ([recordList saveModifications] == 0)
- return self;
- else
- return nil;
- }
-
- @end
-