/* GormInspectorsManager.m * * Copyright (C) 1999 Free Software Foundation, Inc. * * Author: Richard Frith-Macdonald * Date: 1999 * * This file is part of GNUstep. * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02111 USA. */ #include #include #include #include #include #include #include "GormPrivate.h" #include "GormImage.h" #include "GormSound.h" #define NUM_DEFAULT_INSPECTORS 5 /* * The GormEmptyInspector is a placeholder for an empty selection. */ @interface GormEmptyInspector : IBInspector @end @implementation GormEmptyInspector - (void) dealloc { [super dealloc]; } - (id) init { self = [super init]; if (self != nil) { NSView *contents; NSButton *button; window = [[NSWindow alloc] initWithContentRect: NSMakeRect(0, 0, IVW, IVH) styleMask: NSBorderlessWindowMask backing: NSBackingStoreRetained defer: NO]; contents = [window contentView]; button = [[NSButton alloc] initWithFrame: [contents bounds]]; [button setAutoresizingMask: NSViewHeightSizable | NSViewWidthSizable]; [button setStringValue: _(@"Empty Selection")]; [button setBordered: NO]; [button setEnabled: NO]; [contents addSubview: button]; RELEASE(button); } return self; } @end /* * The GormMultipleInspector is a placeholder for a multiple selection. */ @interface GormMultipleInspector : IBInspector @end @implementation GormMultipleInspector - (void) dealloc { [super dealloc]; } - (id) init { self = [super init]; if (self != nil) { NSView *contents; NSButton *button; window = [[NSWindow alloc] initWithContentRect: NSMakeRect(0, 0, IVW, IVH) styleMask: NSBorderlessWindowMask backing: NSBackingStoreRetained defer: NO]; contents = [window contentView]; button = [[NSButton alloc] initWithFrame: [contents bounds]]; [button setAutoresizingMask: NSViewHeightSizable | NSViewWidthSizable]; [button setStringValue: _(@"Multiple Selection")]; [button setBordered: NO]; [button setEnabled: NO]; [contents addSubview: button]; RELEASE(button); } return self; } @end /* * The GormNotApplicableInspector is a uitility for odd objects. */ @interface GormNotApplicableInspector : IBInspector @end @implementation GormNotApplicableInspector - (void) dealloc { [super dealloc]; } - (id) init { self = [super init]; if (self != nil) { NSView *contents; NSButton *button; window = [[NSWindow alloc] initWithContentRect: NSMakeRect(0, 0, IVW, IVH) styleMask: NSBorderlessWindowMask backing: NSBackingStoreRetained defer: NO]; contents = [window contentView]; button = [[NSButton alloc] initWithFrame: [contents bounds]]; [button setAutoresizingMask: NSViewHeightSizable | NSViewWidthSizable]; [button setStringValue: _(@"Not Applicable")]; [button setBordered: NO]; [button setEnabled: NO]; [contents addSubview: button]; RELEASE(button); } return self; } @end @implementation GormInspectorsManager - (void) dealloc { [[NSNotificationCenter defaultCenter] removeObserver: self]; RELEASE(oldInspector); RELEASE(cache); RELEASE(panel); [super dealloc]; } - (void) handleNotification: (NSNotification*)aNotification { NSString *name = [aNotification name]; if ([name isEqual: IBWillBeginTestingInterfaceNotification] == YES) { if ([panel isVisible] == YES) { hiddenDuringTest = YES; [panel orderOut: self]; } } else if ([name isEqual: IBWillEndTestingInterfaceNotification] == YES) { if (hiddenDuringTest == YES) { hiddenDuringTest = NO; [panel orderFront: self]; } } } - (id) init { NSDebugLog(@"====== init ======"); if((self = [super init]) != nil) { NSNotificationCenter *nc = [NSNotificationCenter defaultCenter]; NSBox *bar; NSMenuItem *item; NSRect contentRect = {{0, 0}, {IVW, 420}}; NSRect popupRect = {{60, 5}, {152, 20}}; NSRect selectionRect = {{0, 390}, {IVW, 30}}; NSRect inspectorRect = {{0, 0}, {IVW, IVH}}; unsigned int style = NSTitledWindowMask | NSClosableWindowMask | NSResizableWindowMask; cache = [[NSMutableDictionary alloc] init]; panel = [[NSPanel alloc] initWithContentRect: contentRect styleMask: style backing: NSBackingStoreRetained defer: NO]; [panel setTitle: _(@"Inspector")]; [panel setMinSize: [panel frame].size]; /* * The selection view sits at the top of the panel and is always the * same height. */ selectionView = [[NSView alloc] initWithFrame: selectionRect]; [selectionView setAutoresizingMask: NSViewMinYMargin | NSViewWidthSizable]; [[panel contentView] addSubview: selectionView]; RELEASE(selectionView); /* * The selection view contains a popup menu identifying the type of * inspector being used. */ popup = [[NSPopUpButton alloc] initWithFrame: popupRect pullsDown: NO]; [popup setAutoresizingMask: NSViewMinXMargin | NSViewMaxXMargin]; [selectionView addSubview: popup]; RELEASE(popup); [popup addItemWithTitle: _(@"Attributes")]; item = (NSMenuItem *)[popup itemAtIndex: 0]; [item setTarget: self]; [item setAction: @selector(setCurrentInspector:)]; [item setKeyEquivalent: @"1"]; [item setTag: 0]; [popup addItemWithTitle: _(@"Connections")]; item = (NSMenuItem *)[popup itemAtIndex: 1]; [item setTarget: self]; [item setAction: @selector(setCurrentInspector:)]; [item setKeyEquivalent: @"2"]; [item setTag: 1]; [popup addItemWithTitle: _(@"Size")]; item = (NSMenuItem *)[popup itemAtIndex: 2]; [item setTarget: self]; [item setAction: @selector(setCurrentInspector:)]; [item setKeyEquivalent: @"3"]; [item setTag: 2]; [popup addItemWithTitle: _(@"Help")]; item = (NSMenuItem *)[popup itemAtIndex: 3]; [item setTarget: self]; [item setAction: @selector(setCurrentInspector:)]; [item setKeyEquivalent: @"4"]; [item setTag: 3]; [popup addItemWithTitle: _(@"Custom Class")]; item = (NSMenuItem *)[popup itemAtIndex: 4]; [item setTarget: self]; [item setAction: @selector(setCurrentInspector:)]; [item setKeyEquivalent: @"5"]; [item setTag: 4]; [item setEnabled: NO]; bar = [[NSBox alloc] initWithFrame: NSMakeRect (0, 0, IVW, 2)]; [bar setBorderType: NSGrooveBorder]; [bar setTitlePosition: NSNoTitle]; [bar setAutoresizingMask: NSViewWidthSizable|NSViewMinYMargin]; [selectionView addSubview: bar]; RELEASE(bar); /* * The inspector view fills the area below the selection view. */ inspectorView = [[NSView alloc] initWithFrame: inspectorRect]; [inspectorView setAutoresizingMask: NSViewHeightSizable | NSViewWidthSizable]; [[panel contentView] addSubview: inspectorView]; RELEASE(inspectorView); [panel setFrameUsingName: @"Inspector"]; [panel setFrameAutosaveName: @"Inspector"]; current = -1; inspector = [[GormEmptyInspector alloc] init]; [cache setObject: inspector forKey: @"GormEmptyInspector"]; RELEASE(inspector); inspector = [[GormMultipleInspector alloc] init]; [cache setObject: inspector forKey: @"GormMultipleInspector"]; DESTROY(inspector); [self setCurrentInspector: 0]; [nc addObserver: self selector: @selector(handleNotification:) name: IBWillBeginTestingInterfaceNotification object: nil]; [nc addObserver: self selector: @selector(handleNotification:) name: IBWillEndTestingInterfaceNotification object: nil]; } return self; } - (NSPanel*) panel { return panel; } - (void) updateSelection { if ([NSApp isConnecting] == YES) { [popup selectItemAtIndex: 1]; [popup setNeedsDisplay: YES]; [panel makeKeyAndOrderFront: self]; current = 1; } else if (current >= [popup numberOfItems]) { current = 1; } [self setCurrentInspector: self]; } - (void) setClassInspector { current = 4; [self setCurrentInspector: self]; } - (void) setEmptyInspector { NSString *newInspector = @"GormEmptyInspector"; NSView *newView = nil; // current = 1; [panel setTitle: @"Inspector"]; inspector = [cache objectForKey: newInspector]; if(inspector == nil) { Class c = NSClassFromString(newInspector); inspector = [[c alloc] init]; } newView = [[inspector window] contentView]; if (newView != nil) { NSView *outer = [panel contentView]; NSRect rect = [outer bounds]; if (buttonView != nil) { [buttonView removeFromSuperview]; buttonView = nil; } rect.size.height = [selectionView frame].origin.y; /* * Make the inspector view the correct size for the viewable panel, * and set the frame size for the new contents before adding them. */ [inspectorView setFrame: rect]; rect.origin = NSZeroPoint; [newView setFrame: rect]; [inspectorView addSubview: newView]; } } - (void) _addDefaultModes { // remove all items... clear out current state [modes removeAllObjects]; currentMode = nil; // Attributes inspector... [self addInspectorModeWithIdentifier: @"AttributesInspector" forObject: selectedObject localizedLabel: _(@"Attributes") inspectorClassName: [selectedObject inspectorClassName] ordering: 0.0]; // Connection inspector... [self addInspectorModeWithIdentifier: @"ConnectionInspector" forObject: selectedObject localizedLabel: _(@"Connections") inspectorClassName: [selectedObject connectInspectorClassName] ordering: 1.0]; // Size inspector... [self addInspectorModeWithIdentifier: @"SizeInspector" forObject: selectedObject localizedLabel: _(@"Size") inspectorClassName: [selectedObject sizeInspectorClassName] ordering: 2.0]; // Help inspector... [self addInspectorModeWithIdentifier: @"HelpInspector" forObject: selectedObject localizedLabel: _(@"Help") inspectorClassName: [selectedObject helpInspectorClassName] ordering: 3.0]; // Custom class inspector... [self addInspectorModeWithIdentifier: @"CustomClassInspector" forObject: selectedObject localizedLabel: _(@"Custom Class") inspectorClassName: [selectedObject classInspectorClassName] ordering: 4.0]; } - (void) _refreshPopUp { NSEnumerator *en = [modes objectEnumerator]; int index = 0; id obj = nil; [popup removeAllItems]; while((obj = [en nextObject]) != nil) { int tag = index + 1; NSMenuItem *item; [popup addItemWithTitle: [obj localizedLabel]]; item = (NSMenuItem *)[popup itemAtIndex: index]; [item setTarget: self]; [item setAction: @selector(setCurrentInspector:)]; [item setKeyEquivalent: [NSString stringWithFormat: @"%d",tag]]; [item setTag: tag]; index++; } } - (void) setCurrentInspector: (id)anObj { NSNotificationCenter *nc = [NSNotificationCenter defaultCenter]; NSArray *selection = [[(id)NSApp selectionOwner] selection]; unsigned count = [selection count]; id obj = [selection lastObject]; NSView *newView = nil; NSString *newInspector = nil; int tag = 0; if (anObj != self) { tag = [anObj tag]; current = ((tag > 0)?(tag - 1):tag); } // reset current under certain conditions. if(current < 0) { current = 0; } NSDebugLog(@"current %i",current); // Operate on the document view if the selected object is a NSScrollView if ([obj isKindOfClass: [NSScrollView class]] && ([(NSScrollView *)obj documentView] != nil) && ([[(NSScrollView *)obj documentView] isKindOfClass: [NSTableView class]] || [[(NSScrollView *)obj documentView] isKindOfClass: [NSTextView class]])) { obj = [(NSScrollView *)obj documentView]; if ([obj isKindOfClass: [NSTableView class]]) if ([obj selectedColumn] != -1) obj = [[obj tableColumns] objectAtIndex:[obj selectedColumn]]; } // if(obj != selectedObject) { selectedObject = obj; // remove any items beyond the original items on the list.. [self _addDefaultModes]; // inform the world that the object is about to be inspected. [nc postNotificationName: IBWillInspectObjectNotification object: obj]; // set key equivalent [self _refreshPopUp]; if([modes count] == NUM_DEFAULT_INSPECTORS) { if(current > (NUM_DEFAULT_INSPECTORS - 1)) { current = 0; } } } if (count == 0) { newInspector = @"GormEmptyInspector"; } else if (count > 1) { newInspector = @"GormMultipleInspector"; } else { currentMode = [modes objectAtIndex: current]; newInspector = [currentMode inspectorClassName]; } /* * Set panel title for the type of object being inspected. */ if (selectedObject == nil) { [panel setTitle: _(@"Inspector")]; } else if([selectedObject isKindOfClass: [GormClassProxy class]]) { [panel setTitle: [NSString stringWithFormat: @"Class Edit Inspector:%@", [selectedObject className]]]; } else { NSString *newTitle = [selectedObject objectNameForInspectorTitle]; [panel setTitle: [NSString stringWithFormat:_(@"%@ Inspector"), newTitle]]; } if (newInspector == nil) newInspector = @"GormNotApplicableInspector"; if ([oldInspector isEqual: newInspector] == NO) { /* * Return the inspector view to its original window and release the old * inspector. */ [[inspector okButton] removeFromSuperview]; [[inspector revertButton] removeFromSuperview]; [[inspector window] setContentView: [[inspectorView subviews] lastObject]]; ASSIGN(oldInspector, newInspector); inspector = [cache objectForKey: newInspector]; if (inspector == nil) { Class c = NSClassFromString(newInspector); inspector = [[c alloc] init]; /* Try to gracefully handle an inspector creation error */ while (inspector == nil && (obj = [obj superclass]) && current == 0) { NSDebugLog(@"Error loading %@ inspector", newInspector); newInspector = [obj inspectorClassName]; inspector = [[NSClassFromString(newInspector) alloc] init]; } [cache setObject: inspector forKey: newInspector]; RELEASE(inspector); } newView = [[inspector window] contentView]; if (newView != nil) { /* Keep the initialFirstResponder */ id initialResponder = [[inspector window] initialFirstResponder]; NSView *outer = [panel contentView]; NSRect rect = [outer bounds]; /* Set initialFirstResponder */ if (buttonView != nil) { [buttonView removeFromSuperview]; buttonView = nil; } rect.size.height = [selectionView frame].origin.y; if ([inspector wantsButtons] == YES) { NSRect buttonsRect; NSRect bRect = NSMakeRect(0, 0, 60, 20); NSButton *ok; NSButton *revert; buttonsRect = rect; buttonsRect.size.height = IVB; rect.origin.y += IVB; rect.size.height -= IVB; buttonView = [[NSView alloc] initWithFrame: buttonsRect]; [buttonView setAutoresizingMask: NSViewHeightSizable | NSViewWidthSizable]; [outer addSubview: buttonView]; RELEASE(buttonView); ok = [inspector okButton]; if (ok != nil) { bRect = [ok frame]; bRect.origin.y = 10; bRect.origin.x = buttonsRect.size.width-10-bRect.size.width; [ok setFrame: bRect]; [buttonView addSubview: ok]; } revert = [inspector revertButton]; if (revert != nil) { bRect = [revert frame]; bRect.origin.y = 10; bRect.origin.x = 10; [revert setFrame: bRect]; [buttonView addSubview: revert]; } } else { [buttonView removeFromSuperview]; } /* * Make the inspector view the correct size for the viewable panel, * and set the frame size for the new contents before adding them. */ [inspectorView setFrame: rect]; rect.origin = NSZeroPoint; [newView setFrame: rect]; [inspectorView addSubview: newView]; /* Set the default First responder to the new View */ if ( initialResponder ) [panel setInitialFirstResponder:initialResponder]; } } // reset the popup.. [popup selectItemAtIndex: current]; // inspect the object. [inspector setObject: [currentMode object]]; } @end