home *** CD-ROM | disk | FTP | other *** search
- /*--------------------------------------------------------------------------
- *
- * You may freely copy, distribute, and reuse the code in this example.
- * SHL Systemhouse disclaims any warranty of any kind, expressed or
- * implied, as to its fitness for any particular use.
- *
- *
- * EOModelInspector
- *
- * Inherits From: WMInspector
- *
- * Conforms To: none
- *
- * Declared In: EOModelInspector.h
- *
- *------------------------------------------------------------------------*/
-
- #import "EOModelInspector.h"
- #import "EOModelBrowserCell.h"
- #import "SwapView.h"
- #import "EntityPropertiesCategory.h"
-
-
-
- /*--------------------------------------------------------------------------
- * Some basic macros for the cells of our matrices
- *------------------------------------------------------------------------*/
- #define ADAPTOR [connectionDictionaryMatrix cellAt:0 :0]
- #define DB_AND_HOST [connectionDictionaryMatrix cellAt:1 :0]
- #define USER_AND_PASSWORD [connectionDictionaryMatrix cellAt:2 :0]
-
- #define VALUE_CLASS_AND_TYPE [attributeSettingsMatrix cellAt:0 :0]
- #define EXTERN_TYPE [attributeSettingsMatrix cellAt:1 :0]
- #define ATTRIBUTE_EXTERN_NAME [attributeSettingsMatrix cellAt:2 :0]
-
- #define CLASS [entitySettingsMatrix cellAt:0 :0]
- #define ENTITY_EXTERN_NAME [entitySettingsMatrix cellAt:1 :0]
-
-
- static id
- _SELF = nil;
-
-
- @implementation EOModelInspector
-
- + new
- {
- char
- path[MAXPATHLEN+1];
- id
- bundle;
-
- if (_SELF)
- {
- return _SELF;
- }
-
- _SELF = self = [super new];
-
- if (!(bundle = [NXBundle bundleForClass:[self class]]))
- {
- return nil;
- }
-
- if (![bundle getPath:path forResource:[(Object *)[self class] name] ofType:"nib"])
- {
- return nil;
- }
-
- [NXApp loadNibFile:path owner:self withNames:NO fromZone:[(Object *)self zone]];
-
- /*
- * Let's load in a bunch of images to be used in our inspector...
- */
-
- if ([bundle getPath:path forResource:"SymbolKey" ofType:"tiff"])
- {
- keyImage = [[NXImage alloc] initFromFile:path];
- }
- else
- {
- NSLog (@"no key image: %s", path);
- }
-
- if ([bundle getPath:path forResource:"SymbolClass" ofType:"tiff"])
- {
- classImage = [[NXImage alloc] initFromFile:path];
- }
- else
- {
- NSLog (@"no class image: %s", path);
- }
-
- if ([bundle getPath:path forResource:"SymbolLock" ofType:"tiff"])
- {
- lockImage = [[NXImage alloc] initFromFile:path];
- }
- else
- {
- NSLog (@"no lock image: %s", path);
- }
-
- /*
- * Let's setup the splitview
- */
- [splitView addSubview:connectionDictionaryView];
- [splitView addSubview:browser];
- [splitView addSubview:propertySwapView];
-
- /*
- * Use our custom browser cell
- */
- [browser setCellClass:[EOModelBrowserCell class]];
-
- /*
- * We'll determine the column titles, thank you very much.
- */
- [browser getTitleFromPreviousColumn:NO];
- return _SELF;
- }
-
-
- - _entityForCurrentSelectionInColumn: (int) theColumn
- /*--------------------------------------------------------------------------
- * Walks the browser from theColumn and finds/returns the entity that
- * corresponds to the current selection. Let's say I have a relationship
- * selected...I need to find out it's destination entity.
- *
- * NOTE: The reason this seems to be necessary is that when we go to
- * fill in a matrix column (after a relationship selection), all we
- * know is that we've got a selected cell, it has a name and a tag.
- *
- * More explanation of what we're doing here...
- *------------------------------------------------------------------------*/
- {
- id
- /*
- * First let's get the "root" entity...that is the entity selected
- * the first column.
- */
- myEntity = [[model entities] objectAtIndex:[[[browser matrixInColumn:0] selectedCell] tag]];
- int
- x;
-
- /*
- * Now, let's walk from column 1, until we get to the
- * column that's selected...
- */
- for (x = 1; x < theColumn; x++)
- {
- id
- myProperty;
-
- /*
- * Get the property
- */
- myProperty = [[myEntity properties] objectAtIndex:[[[browser matrixInColumn:x] selectedCell] tag]];
-
- if ([myProperty isKindOfClass:[EOAttribute class]])
- {
- myEntity = [myProperty entity];
- }
- else
- {
- myEntity = [myProperty destinationEntity];
- }
- }
-
- return myEntity;
- }
-
-
- - (int) _fillInBrowserMatrix: theMatrix
- withEntities: (NSArray *) theEntities
- /*--------------------------------------------------------------------------
- * Called by our browser delegate method, to fill in the given matrix
- * with "theEntities". This is only called for the first column.
- *------------------------------------------------------------------------*/
- {
- int
- x = 0;
- id
- myCell,
- myEntity,
- myString;
-
- while (x < [theEntities count])
- {
- myEntity = [theEntities objectAtIndex:x];
- [theMatrix addRow];
- myCell = [theMatrix cellAt:x :0];
- [myCell setTag:x];
- myString = [NSString stringWithFormat:@"%@", [(EOEntity *)myEntity name]];
- [myCell setStringValue:[myString cString]];
-
- if ([myEntity isReadOnly])
- {
- [myCell setTextColor:NX_COLORDKGRAY];
- }
-
- [myCell setLeaf:NO];
- [myCell setLoaded:YES];
- x++;
- }
-
- return x;
- }
-
-
- - (int) _fillInBrowserMatrix: theMatrix
- withPropertiesFromEntity: (EOEntity *) theEntity
- /*--------------------------------------------------------------------------
- * Called by our browser delegate method, to fill in the given matrix
- * with the properties (attributes & relationships) for "theEntity".
- * This is called many times, particularly for a selected relationship
- * that must display the properties for its destination entity.
- *------------------------------------------------------------------------*/
- {
- int
- x = 0;
- id
- myCell,
- myProperties = [theEntity properties],
- myProperty,
- myString;
-
- while (x < [myProperties count])
- {
- myProperty = [myProperties objectAtIndex:x];
- [theMatrix addRow];
- myCell = [theMatrix cellAt:x :0];
- [myCell setTag:x];
-
- if ([myProperty isKindOfClass:[EOAttribute class]])
- {
- myString = [NSString stringWithFormat:@"%@", [(EOAttribute *)myProperty name]];
-
- if ([myProperty isReadOnly])
- {
- [myCell setTextColor:NX_COLORDKGRAY];
- }
-
- [myCell setLeaf:YES];
- }
- else
- {
- myString = [NSString stringWithFormat:@"%@", [(EORelationship *)myProperty name]];
- [myCell setIsRelationship:YES];
- [myCell setIsToManyRelationship:[myProperty isToMany]];
- [myCell setLeaf:NO];
- }
-
- [myCell setStringValue:[myString cString]];
- [myCell setLoaded:YES];
- x++;
- }
-
- return x;
- }
-
-
- - revert: sender
- {
- char
- myPath[MAXPATHLEN+1];
-
- /*
- * Let's get the path of the selected item
- */
- [self selectionPathsInto:myPath separator:'\0'];
-
- /*
- * Let's get rid of the old model
- */
- if (model)
- {
- [model release];
- model = nil;
- }
-
- /*
- * Now create a model from our (.eomodel) file
- */
- if (model = [[EOModel alloc] initWithContentsOfFile:[NSString stringWithCString:myPath]])
- {
- id
- myConnectionDictionary,
- myString,
- myStringA,
- myStringB,
- myDatabaseKey,
- myHostKey,
- myPasswordKey,
- myUserNameKey,
- myStringTable;
- char
- myPath[MAXPATHLEN+1];
-
- /*
- * Let's display the viewer
- */
- [swapView swapView:[viewerPanel contentView]];
-
- /*
- * Let's set the strings for the main model attributes
- *
- * adaptor name, database/server name, host name/machine, user name & password
- */
-
- /*
- * First the adaptor name
- */
- [ADAPTOR setStringValue:[[model adaptorName] cString]];
-
- /*
- * Now we need the "connectionDictionary" to get the rest
- */
- myConnectionDictionary = [model connectionDictionary];
-
- /*
- * database/server name, host name/machine, get 'em then set 'em...
- *
- * Like: database/server_name (host_name/machine)
- *
- * NOTE: This is tricky, since the Sybase and Oracle adaptors use
- * slightly different keys (ARRRGGGHHH!).
- *
- * Sybase uses: databaseName & hostName
- * Oracle uses: serverId & hostMachine
- *
- * Okay...ready? Here's what we're gonna do. Assuming that these two
- * keys could be different for any adaptor (since NeXT was too stupid
- * to force 'em all to be the same), we'll simply gave a (string) table
- * for each kind of adaptor. This table will contain the keys:
- * "database" and "host" which will map to that specific adaptor's key
- * name. Then we'll use that value as a key to our dictionary to get
- * the real value that we want. Whew...follow?
- */
-
- /*
- * Let's use Sybase's key names as a default...
- */
- myDatabaseKey = [NSString stringWithCString:"databaseName"];
- myHostKey = [NSString stringWithCString:"hostName"];
- myPasswordKey = [NSString stringWithCString:"password"];
- myUserNameKey = [NSString stringWithCString:"userName"];
-
- /*
- * Now, let's get a ".strings" file of the same name as the adaptor
- * (according to the model)...
- */
- [[NXBundle bundleForClass:[self class]] getPath:myPath
- forResource:[[model adaptorName] cString]
- ofType:"strings"];
-
- /*
- * If there's such a file...
- */
- if (*myPath)
- {
- /*
- * make a string table
- */
- myStringTable = [[NXStringTable alloc] init];
-
- /*
- * read from the file
- */
- if ([myStringTable readFromFile:myPath])
- {
- /*
- * get the values for our standard keys: "database" and "host"
- */
- myDatabaseKey = [NSString stringWithCString:[myStringTable valueForStringKey:"database"]];
- myHostKey = [NSString stringWithCString:[myStringTable valueForStringKey:"host"]];
- myPasswordKey = [NSString stringWithCString:[myStringTable valueForStringKey:"password"]];
- myUserNameKey = [NSString stringWithCString:[myStringTable valueForStringKey:"username"]];
- }
-
- [myStringTable free];
- }
-
- /*
- * Now we get a couple of strings based on our keys.
- * remember, is there was no file for this adaptor, we used defaults
- * which are Sybase (for now).
- */
- myStringA = [myConnectionDictionary objectForKey:myDatabaseKey];
- myStringB = [myConnectionDictionary objectForKey:myHostKey];
- myString = [NSString stringWithFormat:@"%@ (%@)", myStringA, myStringB];
- [DB_AND_HOST setStringValue:[myString cString]];
-
- /*
- * user name & password, get 'em then set 'em...
- *
- * Like: user_name (password)
- */
- myStringA = [myConnectionDictionary objectForKey:myUserNameKey];
- myStringB = [myConnectionDictionary objectForKey:myPasswordKey];
- myString = [NSString stringWithFormat:@"%@ (%@)", myStringA, myStringB];
- [USER_AND_PASSWORD setStringValue:[myString cString]];
-
- /*
- * Let's tell the browser to fill up, and force a click...
- */
- [browser loadColumnZero];
- [self itemSelect:nil];
- }
- else
- {
- /*
- * If there was an error reading the file, let's display the error view
- */
- [swapView swapView:[errorPanel contentView]];
- }
-
- [super revert:sender];
- return self;
- }
-
-
- - itemSelect: sender
- {
- if ([sender selectedColumn] > 0)
- {
- id
- myEntity = [self _entityForCurrentSelectionInColumn:[sender selectedColumn]],
- myProperty = [[myEntity properties] objectAtIndex:[[sender selectedCell] tag]];
-
- if ([myProperty isKindOfClass:[EOAttribute class]])
- {
- /*
- * Get the proper attribute (the for this column's selected cell).
- */
- id
- myString;
-
- /*
- * Swap in the attribute view
- */
- [propertySwapView swapView:[attributePanel contentView]];
- [propertySwapView display];
-
- if ([[[myProperty entity] primaryKeyAttributes] containsObject:myProperty])
- {
- [attributeKeyButton setImage:[keyImage copy]];
- }
- else
- {
- [attributeKeyButton setImage:nil];
- }
-
- if ([[[myProperty entity] attributesUsedForLocking] containsObject:myProperty])
- {
- [attributeLockingButton setImage:[lockImage copy]];
- }
- else
- {
- [attributeLockingButton setImage:nil];
- }
-
- if ([[[myProperty entity] classProperties] containsObject:myProperty])
- {
- [attributeClassButton setImage:[classImage copy]];
- }
- else
- {
- [attributeClassButton setImage:nil];
- }
-
- /*
- * Set the "value classname" & "value type" string
- *
- * We don't want anything in parenthesis is there is no "value
- * type" (which is most cases). But, if I don't do the "if" here,
- * I get a string like:
- *
- * NSString (nil)
- *
- * Which isn't what I want.
- */
- myString = [NSString stringWithFormat:@"%s", [myProperty valueClassName]];
-
- if ([myProperty valueType])
- {
- myString = [myString stringByAppendingFormat:@" (%@)", [myProperty valueType]];
- }
-
- [VALUE_CLASS_AND_TYPE setStringValue:[myString cString]];
-
- /*
- * Set the "external type" string
- */
- [EXTERN_TYPE setStringValue:[[myProperty externalType] cString]];
-
- if ([myProperty isDerived] || [myProperty isFlattened])
- {
- [ATTRIBUTE_EXTERN_NAME setStringValue:[(NSString *)[myProperty definition] cString]];
- }
- else
- {
- [ATTRIBUTE_EXTERN_NAME setStringValue:[(NSString *)[myProperty columnName] cString]];
- }
- }
- else
- {
- /*
- * Swap in the relationship view
- */
- [propertySwapView swapView:[relationshipPanel contentView]];
- [propertySwapView display];
-
- /*
- * Set our radio button to reflect the "manyness" of the
- * relationship.
- */
- [relationshipManynessMatrix selectCellAt:0 :([myProperty isToMany] ? 1 : 0)];
- }
- }
- else
- {
- /*
- * If there is no selected column, or it is the entities column,
- * there ARE NO attribute settings.
- */
- id
- myEntity = [self _entityForCurrentSelectionInColumn:[sender selectedColumn]];
-
- [propertySwapView swapView:[entityPanel contentView]];
- [propertySwapView display];
-
- [CLASS setStringValue:[myEntity className]];
- [ENTITY_EXTERN_NAME setStringValue:[(NSString *)[myEntity externalName] cString]];
- }
-
- return self;
- }
-
-
-
- /*--------------------------------------------------------------------------
- * NXBrowser delegate methods
- *------------------------------------------------------------------------*/
-
- - (int) browser: sender
- fillMatrix: matrix
- inColumn: (int) column
- {
- int
- x = 0;
-
- if (column == 0)
- {
- /*
- * If we're the "root" column...
- */
- x = [self _fillInBrowserMatrix:matrix
- withEntities:[model entities]];
- }
- else
- {
- /*
- * Otherwise...
- */
- x = [self _fillInBrowserMatrix:matrix
- withPropertiesFromEntity:[self _entityForCurrentSelectionInColumn:column]];
- }
-
- return x;
- }
-
-
- - (const char *) browser: sender
- titleOfColumn: (int) column
- {
- NSString
- *columnTitle;
-
- if (column == 0)
- {
- columnTitle = [NSString stringWithCString:"Entities"];
- }
- else
- {
- columnTitle = [(EOEntity *)[self _entityForCurrentSelectionInColumn:column] name];
- }
-
- return [columnTitle cString];
- }
-
-
- /*--------------------------------------------------------------------------
- * NXSplitView delegate methods
- *------------------------------------------------------------------------*/
-
- - splitView:sender
- getMinY: (NXCoord *) minY
- maxY: (NXCoord *) maxY
- ofSubviewAt: (int) offset
- {
- switch (offset)
- {
- case 0:
- *minY = 0.0;
- *maxY = 45.0;
- break;
-
- case 1:
- *minY = 155.0;
- *maxY = 225.0;
- break;
- }
-
- return self;
- }
-
-
- @end
-