00001
00002
00003
00004
00005
00006
00007
00008 #ifndef INCLUDED_NIBCONTROLLER_H
00009 #import "NIBController.h"
00010 #endif
00011 #ifndef INCLUDED_NIBMANAGER_H
00012 #import "NIBManager.h"
00013 #endif
00014 #ifndef INCLUDED_NIBMANAGERHANDLER_H
00015 #import "NIBManagerHandler.h"
00016 #endif
00017 #ifndef INCLUDED_AZARRAYCONTROLLER_H
00018 #import "AZArrayController.h"
00019 #endif
00020 #ifndef INCLUDED_AZOBJECTCONTROLLER_H
00021 #import "AZObjectController.h"
00022 #endif
00023 #ifndef INCLUDED_AZTREECONTROLLER_H
00024 #import "AZTreeController.h"
00025 #endif
00026 #ifndef INCLUDED_AZVIEW_H
00027 #import "AZView.h"
00028 #endif
00029 #ifndef INCLUDED_OUTLINEVIEWDELEGATE_H
00030 #import "OutlineViewDelegate.h"
00031 #endif
00032
00033
00034
00035 @implementation NIBController
00036
00037
00038 - (id)init {
00039 self = [super init];
00040 if (self) {
00041 controllers = [[[NSMutableArray alloc] init] retain];
00042 menus = [[[NSMutableDictionary alloc] init] retain];
00043 manager = nil;
00044 window = nil;
00045 model = nil;
00046 }
00047 return self;
00048 }
00049
00050
00051 - (void)dealloc {
00052 if (manager)
00053 [manager removeController:self];
00054 if (model)
00055 [model release];
00056 if (controllers)
00057 [controllers release];
00058 if (menus)
00059 [menus release];
00060 if (window)
00061 [window release];
00062 [super dealloc];
00063 }
00064
00065
00066 -(void)awakeFromNib {
00067 if (manager)
00068 [manager addController:self];
00069 }
00070
00071
00072 - (void)setEditable:(BOOL)editable withContext:(NIBContext *)context forContext:(NSString *)name {
00073 [self setEditable:editable withContext:context forEntity:name forFilter:name];
00074 }
00075
00076
00077 - (void)setEditable:(BOOL)editable withContext:(NIBContext *)context forEntity:(NSString *)entity forFilter:(NSString *)filter {
00078 NSObjectController * controller;
00079 NSMutableArray * array = (filter ? [[context getMetadata] getMembers:filter] : nil);
00080 NSString * name;
00081 int i;
00082
00083 for (i = 0; i < [[self controllers] count]; i++) {
00084 controller = [self getController:i];
00085 name = [controller entityName];
00086 if ((entity && [entity isEqualTo:name]) || (!filter && (!entity || [entity isEqualTo:name]))) {
00087 if ([NIBManagerHandler getLoggingLevel] >= LOGGING_DEBUG)
00088 NSLog(@"NIBController enabling controller: %s [%s]", [name UTF8String], (editable ? "YES" : "NO"));
00089 [controller setEditable:editable];
00090 }
00091 }
00092
00093 if (!array)
00094 return;
00095 if ([array count] == 0)
00096 [array addObject:filter];
00097 for (i = 0; i < [array count]; i++)
00098 [NIBManager setEnabled:editable withView:[self window] withFilter:[array objectAtIndex:i]];
00099 }
00100
00101
00102 - (NSMutableArray *)controllers {
00103 return controllers;
00104 }
00105
00106
00107 - (void)setControllers:(NSMutableArray *)myControllers {
00108 if (controllers)
00109 [controllers release];
00110 controllers = myControllers;
00111 }
00112
00113
00114 - (void)addController:(NSObjectController *)myController withContext:(NIBContext *)context {
00115 if ([myController isKindOfClass:[AZObjectController class]]) {
00116 [(AZObjectController *) myController setCallback:[[self manager] callback]];
00117 [(AZObjectController *) myController setContext:context];
00118 }
00119 if ([myController isKindOfClass:[AZArrayController class]]) {
00120 [(AZArrayController *) myController setCallback:[[self manager] callback]];
00121 [(AZArrayController *) myController setContext:context];
00122 }
00123 if ([myController isKindOfClass:[AZTreeController class]]) {
00124 [(AZTreeController *) myController setCallback:[[self manager] callback]];
00125 [(AZTreeController *) myController setContext:context];
00126 }
00127 [[self controllers] addObject:myController];
00128 }
00129
00130
00131 - (NSObjectController *)getController:(int)index {
00132 return [[self controllers] objectAtIndex:index];
00133 }
00134
00135
00136 - (NSMutableDictionary *)menus {
00137 return menus;
00138 }
00139
00140
00141 - (void)setMenus:(NSMutableDictionary *)myMenus {
00142 if (menus)
00143 [menus release];
00144 menus = myMenus;
00145 }
00146
00147
00148 - (NSMenu *)getMenu:(NSString *)context {
00149 return [[self menus] valueForKey:context];
00150 }
00151
00152
00153 - (NIBManager *)manager {
00154 return manager;
00155 }
00156
00157
00158 - (void)setManager:(NIBManager *)myManager {
00159 manager = myManager;
00160 }
00161
00162
00163 - (NSView *)window {
00164 return window;
00165 }
00166
00167
00168 - (void)setWindow:(NSView *)myWindow {
00169 window = [[self processWindow:[self determineWindow:myWindow]] retain];
00170 }
00171
00172
00173 - (NSView *)determineWindow:(NSView *)myWindow {
00174
00175
00176
00177
00178
00179
00180
00181
00182
00183
00184
00185
00186
00187
00188
00189 return myWindow;
00190 }
00191
00192
00193 - (NSView *)processWindow:(NSView *)myWindow {
00194 if ([[self manager] displayMode] == WINDOWED)
00195 return myWindow;
00196
00197 if ([[self manager] displayMode] == EMBEDDED) {
00198
00199 if ([myWindow isKindOfClass:[NSBox class]]) {
00200 [[(NSBox *)myWindow contentView] setMenu:[myWindow menu]];
00201 if (![[self manager] decorated]) {
00202 [(NSBox *)myWindow setTitlePosition:NSNoTitle];
00203 [(NSBox *)myWindow setBorderType:NSNoBorder];
00204 }
00205 }
00206
00207 NSRect * bounds = [[self manager] bounds];
00208 NSRect myBounds = [myWindow bounds];
00209
00210 if ([[myWindow subviews] count] == 0) {
00211 [myWindow setFrame:*bounds];
00212 [myWindow setBounds:*bounds];
00213 [myWindow setNeedsDisplay:YES];
00214 } else if ([[self manager] scrolling]) {
00215 return [NIBManager makeScrollView:myWindow withBounds:(bounds ? *bounds : myBounds) withFlipped:[[self manager] flipped]];
00216 } else if ([[self manager] flipped]) {
00217 return [NIBManager makeFlippedView:myWindow];
00218 }
00219 }
00220 return myWindow;
00221 }
00222
00223
00224 - (NSManagedObjectModel *)model {
00225 return model;
00226 }
00227
00228
00229 - (void)setModel:(NSManagedObjectModel *)myModel {
00230 model = myModel;
00231 }
00232
00233
00234 - (NSManagedObject *)getObject:(NSString *)context {
00235 NSObjectController * controller;
00236 NSManagedObject * object;
00237 NSString * name;
00238 int i = 0;
00239
00240 for (i = 0; i < [[self controllers] count]; i++) {
00241 controller = [self getController:i];
00242 name = [controller entityName];
00243 if (name && (!context || [context isEqualTo:name])) {
00244 object = [controller content];
00245 if (object)
00246 return object;
00247 if ([NIBManagerHandler getLoggingLevel] >= LOGGING_DEBUG)
00248 NSLog(@"NIBController creating new NSManagedObject of name: %s", [[controller entityName] UTF8String]);
00249 [controller setContent:[controller newObject]];
00250 return [controller content];
00251 }
00252 }
00253 return nil;
00254 }
00255
00256
00257 - (NSMutableDictionary *)doParse:(MetadataParser *)parser {
00258 return [self doParse:parser withEntity:nil];
00259 }
00260
00261
00262 - (NSMutableDictionary *)doParse:(MetadataParser *)parser stringifyDates:(BOOL)stringify {
00263 return [self doParse:parser withEntity:nil stringifyDates:stringify];
00264 }
00265
00266
00267 - (NSMutableDictionary *)doParse:(MetadataParser *)parser withEntity:(NSString *)context {
00268 return [self doParse:parser withEntity:context stringifyDates:YES];
00269 }
00270
00271
00272 - (NSMutableDictionary *)doParse:(MetadataParser *)parser withEntity:(NSString *)context stringifyDates:(BOOL)stringify {
00273 NSMutableDictionary * masterDictionary = [[NSMutableDictionary dictionary] retain];
00274 id object;
00275
00276 if (!context) {
00277 object = [self getObject:nil];
00278 if ([object isKindOfClass:[NSManagedObject class]])
00279 [masterDictionary addEntriesFromDictionary:[self doParse:parser withObject:object stringifyDates:stringify]];
00280 return masterDictionary;
00281 }
00282
00283
00284
00285 NSArray * contextList = [context componentsSeparatedByString:@","];
00286 NSString * entity;
00287 int i;
00288
00289 for (i = 0; i < [contextList count]; i++) {
00290 entity = [contextList objectAtIndex:i];
00291 object = [self getObject:entity];
00292 if ([object isKindOfClass:[NSManagedObject class]]) {
00293 [masterDictionary addEntriesFromDictionary:[self doParse:parser withObject:object stringifyDates:stringify]];
00294 } else {
00295 object = [self getObject:nil];
00296 if ([object isKindOfClass:[NSManagedObject class]])
00297 [masterDictionary addEntriesFromDictionary:[self doParse:parser withObject:object stringifyDates:stringify]];
00298 }
00299 }
00300 return masterDictionary;
00301 }
00302
00303
00304 - (NSMutableDictionary *)doParse:(MetadataParser *)parser withObject:(NSManagedObject *)object stringifyDates:(BOOL)stringify {
00305 NSMutableDictionary * dictionary = [[NSMutableDictionary dictionary] retain];
00306 NSDictionary * properties = [[object entity] propertiesByName];
00307 NSArray * keys = [properties allKeys];
00308 NSString * key;
00309 id value;
00310 id temp;
00311 int i;
00312
00313 for (i = 0; i < [keys count]; i++) {
00314 key = [keys objectAtIndex:i];
00315 temp = [properties objectForKey:key];
00316 if (temp && [temp isKindOfClass:[NSAttributeDescription class]]) {
00317 value = [object valueForKey:key];
00318
00319
00320 id component = [NIBManager getComponentForBinding:key fromParent:[self window]];
00321 if ([component isKindOfClass:[NSPopUpButton class]]) {
00322
00323 NSString *listValue = [parser metadataListValueAtIndex:[component indexOfSelectedItem] forIdentifier:key forLocale:@"jp"];
00324 if (listValue) {
00325 if ([NIBManagerHandler getLoggingLevel] >= LOGGING_DEBUG)
00326 NSLog(@"NIBController found list value for component: %s, value: %s", [key UTF8String], [listValue UTF8String]);
00327 value = listValue;
00328 }
00329 }
00330
00331 if ([parser isDate:value forKey:key withAttribute:(NSAttributeDescription *)temp]) {
00332 [dictionary setValue:(stringify ? [parser parseAndFormatDate:value] : value) forKey:key];
00333 } else if ([parser isDecimalNumber:value forKey:key withAttribute:(NSAttributeDescription *)temp]) {
00334 [dictionary setValue:(value ? [value stringValue] : @"0") forKey:key];
00335 } else if ([parser isNumber:value forKey:key withAttribute:(NSAttributeDescription *)temp]) {
00336 [dictionary setValue:(value ? [value stringValue] : @"0") forKey:key];
00337 } else if ([parser isString:value forKey:key withAttribute:(NSAttributeDescription *)temp]) {
00338 [dictionary setValue:(value ? value : @"") forKey:key];
00339 } else if (value && [NIBManagerHandler getLoggingLevel] >= LOGGING_INFO)
00340 NSLog(@"NIBController unknown datatype for key: %s", [key UTF8String]);
00341 }
00342 }
00343 return dictionary;
00344 }
00345
00346
00347 - (void)doPopulate:(NSDictionary *)data withMetadata:(MetadataParser *)parser {
00348 [self doPopulate:data withMetadata:parser withEntity:nil];
00349 }
00350
00351
00352 - (void)doPopulate:(NSDictionary *)data withMetadata:(MetadataParser *)parser withEntity:(NSString *)context {
00353 [self doPopulate:data withMetadata:parser withObject:[self getObject:context]];
00354 }
00355
00356 - (void)doPopulateForKey:(NSString*)key withData:(NSDictionary *)data withMetadata:(MetadataParser *)parser withObject:(NSManagedObject *)object {
00357 NSDictionary * properties = [[object entity] propertiesByName];
00358 id value;
00359 id temp;
00360
00361 temp = [properties objectForKey:key];
00362 if (temp && [temp isKindOfClass:[NSAttributeDescription class]]) {
00363 value = [data objectForKey:key];
00364
00365
00366 id component = [NIBManager getComponentForBinding:key fromParent:[self window]];
00367 if ([component isKindOfClass:[NSPopUpButton class]]) {
00368 NSArray *listValues = [parser metadataListValues:key forLocale:@"jp"];
00369 if (listValues && [listValues indexOfObject:value] != NSNotFound) {
00370 value = [component itemTitleAtIndex:[listValues indexOfObject:value]];
00371 if ([NIBManagerHandler getLoggingLevel] >= LOGGING_DEBUG)
00372 NSLog(@"NIBController found list title for component: %s, value: %s", [key UTF8String], [value UTF8String]);
00373 }
00374
00375
00376 if ([NIBController isDynamicPopUp:key withMetadata:parser]) {
00377 NSString *parentWidgetName = [[parser getValue:key] substringFromIndex:9];
00378 parentWidgetName = [parentWidgetName substringToIndex:[parentWidgetName length]-1];
00379 id parentWidget = [NIBManager getComponentForBinding:parentWidgetName fromParent:[self window]];
00380 if (parentWidget && [parentWidget isKindOfClass:[NSPopUpButton class]]) {
00381 [[[self manager] handler] onPopUpChange:parentWidget];
00382 }
00383 }
00384 }
00385 if ([NIBManagerHandler getLoggingLevel] >= LOGGING_DEBUG)
00386 NSLog(@"NIBController assigning object: %s = %s", [key UTF8String], [[value description] UTF8String]);
00387 [object setValue:[parser formatObject:value forKey:key withAttribute:(NSAttributeDescription *)temp] forKey:key];
00388 }
00389 }
00390
00391 - (void)doPopulate:(NSDictionary *)data withMetadata:(MetadataParser *)parser withObject:(NSManagedObject *)object {
00392 NSArray * keys = [data allKeys];
00393 NSArray * subviews = [NIBManager getComponents:[self window]];
00394 NSMutableArray * childrenPopUpKeys = [[NSMutableArray alloc] init];
00395 NSString * key;
00396 id temp;
00397 int i;
00398
00399
00400 for (i = 0; i < [keys count]; i++) {
00401 key = [keys objectAtIndex:i];
00402
00403
00404 if([NIBController isDynamicPopUp:key withMetadata:parser]) {
00405 [childrenPopUpKeys addObject:key];
00406
00407 }
00408 else
00409 [self doPopulateForKey:key withData:data withMetadata:parser withObject:object];
00410 }
00411
00412
00413 for (i = 0; i < [childrenPopUpKeys count]; i++) {
00414 key = [childrenPopUpKeys objectAtIndex:i];
00415 [self doPopulateForKey:key withData:data withMetadata:parser withObject:object];
00416 }
00417
00418
00419 for (i = 0; i < [subviews count]; i++) {
00420 temp = [subviews objectAtIndex:i];
00421 if ([temp isKindOfClass:[NSOutlineView class]] && [[temp delegate] isKindOfClass:[OutlineViewDelegate class]])
00422 [[temp delegate] doPopulate];
00423 }
00424 }
00425
00426 + (BOOL)isDynamicPopUp:(NSString*)key withMetadata:(MetadataParser *)parser {
00427 NSString *drop = [parser getValue:key];
00428 return [drop hasPrefix:@"<DYNAMIC_"];
00429 }
00430
00431 - (BOOL)doMerge:(NIBController *)myController {
00432 NSObjectController * controller;
00433 NSObjectController * temp;
00434 int i, j;
00435 BOOL found = NO;
00436
00437 for (i = 0; i < [[self controllers] count]; i++) {
00438 controller = [self getController:i];
00439 if ([controller entityName])
00440 for (j = 0; j < [[myController controllers] count]; j++) {
00441 temp = [myController getController:j];
00442 if ([[controller entityName] isEqualTo:[temp entityName]]) {
00443 if ([NIBManagerHandler getLoggingLevel] >= LOGGING_DEBUG)
00444 NSLog(@"NIBController merging NSObjectController entity: %s", [[controller entityName] UTF8String]);
00445 if ([temp isKindOfClass:[NSArrayController class]] && [controller isKindOfClass:[NSArrayController class]]) {
00446 [(NSArrayController *)controller removeObjects:[(NSArrayController *)controller arrangedObjects]];
00447 [(NSArrayController *)controller addObjects:[(NSArrayController *)temp arrangedObjects]];
00448 found = YES;
00449 } else if ([temp isKindOfClass:[NSTreeController class]] && [controller isKindOfClass:[NSTreeController class]]) {
00450 NSMutableArray *tempContent = [[NSMutableArray alloc] init];
00451 [tempContent addObjectsFromArray: [(NSTreeController *)temp content]];
00452 [(NSTreeController *)controller setContent:tempContent];
00453 found = YES;
00454 } else if ([[temp content] isKindOfClass:[NSManagedObject class]] && [[controller content] isKindOfClass:[NSManagedObject class]]) {
00455 [NIBController doMerge:[temp content] toObject:[controller content]];
00456 found = YES;
00457 }
00458 }
00459 }
00460 }
00461 return NO;
00462 }
00463
00464
00465 + (BOOL)doMerge:(NSManagedObject *)source toObject:(NSManagedObject *)destination {
00466 NSDictionary * prop1 = [[source entity] propertiesByName];
00467 NSDictionary * prop2 = [[destination entity] propertiesByName];
00468 NSArray * keys1 = [prop1 allKeys];
00469 NSArray * keys2 = [prop2 allKeys];
00470 NSString * key;
00471 id temp;
00472 int i;
00473
00474 for (i = 0; i < [keys1 count]; i++) {
00475 key = [keys1 objectAtIndex:i];
00476 temp = [prop1 objectForKey:key];
00477 if (temp && [temp isKindOfClass:[NSAttributeDescription class]] && [keys2 containsObject:key]) {
00478 [destination setValue:[source valueForKey:key] forKey:key];
00479 }
00480 }
00481 return YES;
00482 }
00483
00484
00485 - (IBAction)doExecute:(id)sender {
00486 if ([NIBManagerHandler getLoggingLevel] >= LOGGING_DEBUG)
00487 NSLog(@"NIBController received execute event...");
00488 [self doCallback: sender];
00489 }
00490
00491
00492 - (IBAction)doCallback:(id)sender {
00493 if ([NIBManagerHandler getLoggingLevel] >= LOGGING_DEBUG)
00494 NSLog(@"NIBController received callback event...");
00495 if ([self isValid:nil]) {
00496 int i = 0;
00497
00498 for (i = 0; i < [[self controllers] count]; i++)
00499 [[self manager] doCallback:self withObject:[self getController:i]];
00500 }
00501 }
00502
00503
00504 - (void)doValidate {
00505 int i;
00506
00507 for (i = 0; i < [[self controllers] count]; i++)
00508 [[self getController:i] commitEditing];
00509 }
00510
00511
00512 - (void)doSetup {
00513 NSObjectController * controller;
00514 int i = 0;
00515
00516 for (i = 0; i < [[self controllers] count]; i++) {
00517 controller = [self getController:i];
00518 if ([controller entityName] && ![controller isKindOfClass:[NSArrayController class]]) {
00519 if ([NIBManagerHandler getLoggingLevel] >= LOGGING_DEBUG)
00520 NSLog(@"NIBController creating new NSManagedObject of name: %s", [[controller entityName] UTF8String]);
00521 [controller setContent:[controller newObject]];
00522 }
00523 }
00524 }
00525
00526
00527 - (void)doInitialise {
00528 [self doSetup];
00529 }
00530
00531
00532 - (void)doInitialiseWith:(NIBManager *)myManager {
00533 NSString * directory = nil;
00534 NSString * store = [[myManager backingStore] lastPathComponent];
00535 NSArray * paths = NSSearchPathForDirectoriesInDomains(NSLibraryDirectory, NSUserDomainMask, YES);
00536 NSMutableArray * path = [NSMutableArray arrayWithArray:[[myManager backingStore] pathComponents]];
00537 NSFileManager * fileManager = [NSFileManager defaultManager];
00538 BOOL isDirectory = NO;
00539
00540 [path removeLastObject];
00541 if ([paths count] == 1) {
00542 directory = [[[paths objectAtIndex:0] stringByAppendingPathComponent:[path componentsJoinedByString:@"/"]] retain];
00543 if (![fileManager fileExistsAtPath:directory isDirectory:&isDirectory]) {
00544
00545 NSString* dir = [[paths objectAtIndex:0] retain];
00546 int i;
00547 for(i = 0 ; i < [path count] ; i++) {
00548 NSString* pathElement = [path objectAtIndex:i];
00549 dir = [dir stringByAppendingPathComponent:pathElement];
00550 if (![fileManager fileExistsAtPath:dir isDirectory:&isDirectory]) {
00551 if (![fileManager createDirectoryAtPath:dir attributes:nil]) {
00552 [dir release];
00553 dir = nil;
00554 return;
00555 }
00556 }
00557 }
00558 } else if (!isDirectory) {
00559 [directory release];
00560 directory = nil;
00561 }
00562 }
00563
00564 id newStore;
00565 NSError * error;
00566 NSURL * url = [NSURL fileURLWithPath: [directory stringByAppendingPathComponent:store]];
00567 NSPersistentStoreCoordinator * coordinator = [[NSPersistentStoreCoordinator alloc] initWithManagedObjectModel: model];
00568 NSObjectController * controller;
00569 int i;
00570
00571 for (i = 0; i < [[self controllers] count]; i++) {
00572 controller = [self getController:i];
00573 if ([controller entityName]) {
00574 if ([NIBManagerHandler getLoggingLevel] >= LOGGING_DEBUG)
00575 NSLog(@"NIBController configuring CoreData coordinator/store for: %s", [[controller entityName] UTF8String]);
00576 [[controller managedObjectContext] setPersistentStoreCoordinator: coordinator];
00577 if (newStore == nil)
00578 newStore = [coordinator addPersistentStoreWithType:[manager backingType]
00579 configuration:nil
00580 URL:url
00581 options:nil
00582 error:&error];
00583 if (newStore == nil)
00584 NSLog(@"NIBController store configuration failure: %@", ([error localizedDescription] != nil) ? [error localizedDescription] : @"Unknown Error");
00585 }
00586 }
00587 [coordinator release];
00588 }
00589
00590
00591 - (BOOL)isValid:(NSError **)error {
00592 NSObjectController * controller;
00593 BOOL valid = YES;
00594 int i = 0;
00595
00596 for (i = 0; i < [[self controllers] count]; i++) {
00597 controller = [self getController:i];
00598 if ([[controller content] isKindOfClass:[NSManagedObject class]])
00599 valid = [[controller content] validateForUpdate:error];
00600 if (!valid)
00601 return NO;
00602 }
00603 return valid;
00604 }
00605
00606
00607 - (BOOL)isValid:(NSError **)error forEntity:(NSString *)context {
00608 id object = [self getObject:context];
00609 return ([object isKindOfClass:[NSManagedObject class]] ? [object validateForUpdate:error] : NO);
00610 }
00611
00612
00613 - (BOOL)isEnabled {
00614 return ([[self controllers] count] > 0);
00615 }
00616
00617
00618 @end