This is InspectorManager.m in view mode; [Download] [Up]
// InspectorManager.m // By Kevin Brain // A class for managing an inspector. // Compositing techniques and functions from the ToolInspector example // by Sharon Biocca Zakhour, NeXT Developer Support Team // You may freely copy, distribute and reuse the code in this example. // *Everybody involved* disclaims any warranty of any kind, expressed // or implied, as to its fitness for any particular use. #import <objc/NXStringTable.h> #import <appkit/Panel.h> #import <appkit/View.h> #import <appkit/PopUpList.h> #import <appkit/Matrix.h> #import <objc/Storage.h> #import <objc/List.h> #import <appkit/Application.h> // for NXApp #import <dpsclient/wraps.h> // PScomposite #import <libc.h> #import "InspectorManager.h" #define INTERVIEWSPACING 2 @implementation InspectorManager /* Private functions */ static void compositeToBuffer(InspectorManager *self, float srcX, float srcY, float width, float height, float dstX, float dstY) { [[self->layouts contentView] lockFocus]; PScomposite(srcX, srcY, width, height, [[self->inspectorPanel contentView] gState], dstX, dstY, NX_COPY); [[self->layouts contentView] unlockFocus]; } static void compositeToScreen(InspectorManager *self, float srcX, float srcY, float width, float height, float dstX, float dstY) { [[self->inspectorPanel contentView] lockFocus]; PScomposite(srcX, srcY, width, height, [[self->layouts contentView] gState], dstX, dstY, NX_COPY); [self->inspectorPanel flushWindow]; [[self->inspectorPanel contentView] unlockFocus]; } /* instance methods */ - init { [super init]; if ([NXApp loadNibSection:"Inspector.nib" owner:self] == nil) NXRunAlertPanel(NULL,"Couldn't load Inspector.nib","OK",NULL,NULL); /* Tell the Inspector & Palette panels not to become the key window */ [inspectorPanel setBecomeKeyOnlyIfNeeded: YES]; /* This will only */ /* work if you don't miniaturize the panel. */ [inspectorPanel setFloatingPanel:(BOOL)YES]; useKeyEquivalents = YES; inspectorList = [[Storage alloc] initCount:0 elementSize:sizeof(struct inspectorListEntry) description:"@*"]; groupList = [[Storage alloc] initCount:0 elementSize:sizeof(struct inspectorListEntry) description:"@*"]; visibleInspectors = [[Storage alloc] initCount:0 elementSize:sizeof(unsigned int) description:"i"]; [revertOKOut removeFromSuperview]; [popupOut removeFromSuperview]; [inspectorPanel display]; // to actually remove the controls /* 'layouts' is created in IB as the window containing all the */ /* default inspectors side by side. */ /* This window is non-deferred and always kept off-screen */ [[[layouts contentView] allocateGState] lockFocus]; /* The lockFocus forces the */ [[layouts contentView] unlockFocus]; /* gState to become defined */ [[inspectorPanel contentView] allocateGState]; [self addInspector: noInspectorBox title:[inspectorStrings valueForStringKey: "NoSelectionInspector"]]; [self addInspector: multiInspectorBox title:[inspectorStrings valueForStringKey: "MultiSelectionInspector"]]; [self addInspector: unapplicableInspectorBox title:[inspectorStrings valueForStringKey: "UnapplicableInspector"]]; /* Initialize the Inspector to the "Unapplicable Inspector" state */ [self switchToInspector:(unsigned int)NOTAPPLICABLE]; return self; } - (unsigned int)addInspector:(id)theView title:(const char *)theTitle { return [self addInspector:theView title:theTitle atLocation:LOWERLEFTX :LOWERLEFTY]; } - (unsigned int)addInspector:(id)theView title:(const char *)theTitle atLocation:(NXCoord)xLoc :(NXCoord)yLoc { struct inspectorListEntry tempInspectorEntry; NXRect theViewRect, cvRect; tempInspectorEntry.view = theView; tempInspectorEntry.showing = NO; tempInspectorEntry.title = malloc(sizeof(char)*(strlen((char *)theTitle))); strcpy(tempInspectorEntry.title,theTitle); [theView getFrame:&theViewRect]; [[layouts contentView] getFrame:&cvRect]; [[layouts contentView] addSubview:theView]; if ((lastRect.origin.y+lastRect.size.height+ theViewRect.size.height+INTERVIEWSPACING) >= cvRect.size.height) { [layouts sizeWindow:(NXCoord)(cvRect.size.width + theViewRect.size.width + INTERVIEWSPACING) :(NXCoord)cvRect.size.height]; lastRect.origin.x = cvRect.size.width; lastRect.origin.y = 0; } else { if ((lastRect.origin.x + theViewRect.size.width + INTERVIEWSPACING) >= cvRect.size.width) [layouts sizeWindow:(NXCoord)(lastRect.origin.x + theViewRect.size.width + INTERVIEWSPACING) :(NXCoord)cvRect.size.height]; lastRect.origin.y = lastRect.origin.y + lastRect.size.height + INTERVIEWSPACING; } lastRect.size = theViewRect.size; [theView moveTo:lastRect.origin.x :lastRect.origin.y]; [theView display]; [theView getFrame:&tempInspectorEntry.offscreenRect]; [inspectorList addElement:&tempInspectorEntry]; [theView moveTo:xLoc :yLoc]; [theView removeFromSuperview]; return [inspectorList count]-1; } - (unsigned int)addGroup:(const char *)theTitle { struct inspectorListEntry tempGroupEntry; unsigned short temp; // add item to PopUpList if (([groupList count] < 9) && (useKeyEquivalents == YES)) // command-key equivalents for first 9 temp = (unsigned short)[groupList count]+(unsigned short)'1'; else temp = 0; // no command-key equivalent for rest tempGroupEntry.view = [[popupOut target] addItem:theTitle action:@selector(selectGroup:) keyEquivalent:temp]; [tempGroupEntry.view setTarget:self]; if ([groupList count] == 0) { // remove the default 'None' item in PopUpList [[popupOut target] removeItemAt:(unsigned int)0]; [popupOut setTitle:theTitle]; } if ([groupList count] == 1) [self showGroupPopUp]; tempGroupEntry.title = malloc(sizeof(char)*(strlen((char *)theTitle))); strcpy(tempGroupEntry.title,theTitle); [groupList addElement:&tempGroupEntry]; return [groupList count]-1; } - setUseKeyEquivalents:(BOOL)use { useKeyEquivalents = use; return self; } - switchToInspector:(unsigned int)newInspector { struct inspectorListEntry *new,*tempOld; View *tempView; NXRect tempFrame; int i,*tempShowing; unsigned cnt = [visibleInspectors count]; new = [inspectorList elementAt:newInspector]; if (!new) return self; // not a valid inspector if (new->showing == YES) return self; // if already showing /* remove all other inspectors */ if (cnt) for (i=(int)cnt; i > 0;i--) { tempShowing = [visibleInspectors elementAt:i-1]; tempOld = [inspectorList elementAt:(unsigned int)*tempShowing]; tempOld->showing = NO; tempView = tempOld->view; if (tempView != NULL) { [tempView getFrame:&tempFrame]; compositeToBuffer(self, tempFrame.origin.x, tempFrame.origin.y, NX_WIDTH(&tempFrame), NX_HEIGHT(&tempFrame), tempOld->offscreenRect.origin.x, tempOld->offscreenRect.origin.y); [tempView removeFromSuperview]; } } [visibleInspectors empty]; [[inspectorPanel contentView] addSubview:new->view]; /* Now composite the new tool view from the offscreen window into the */ /* toolInspector */ [new->view getFrame:&tempFrame]; compositeToScreen(self, new->offscreenRect.origin.x, new->offscreenRect.origin.y, NX_WIDTH(&tempFrame), NX_HEIGHT(&tempFrame), tempFrame.origin.x, tempFrame.origin.y); [inspectorPanel setTitle:new->title]; new->showing = YES; i=(int)newInspector; [visibleInspectors addElement:&i]; return self; } - showInspector:(unsigned int)newInspector { struct inspectorListEntry *new; NXRect tempFrame; int tempNum; new = [inspectorList elementAt:newInspector]; if (!new) return self; // not a valid inspector if ([self showing:newInspector] == YES) return self; // if already showing [inspectorPanel disableFlushWindow]; [[inspectorPanel contentView] addSubview:new->view]; /* Now composite the new tool view from the offscreen window into the */ /* toolInspector */ [new->view getFrame:&tempFrame]; compositeToScreen(self, new->offscreenRect.origin.x, new->offscreenRect.origin.y, NX_WIDTH(&tempFrame), NX_HEIGHT(&tempFrame), tempFrame.origin.x, tempFrame.origin.y); [inspectorPanel setTitle:new->title]; [inspectorPanel reenableFlushWindow]; [inspectorPanel flushWindowIfNeeded]; new->showing = YES; tempNum = (int)newInspector; [visibleInspectors addElement:&tempNum]; return self; } - hideInspector:(unsigned int)inspectorNum { struct inspectorListEntry *new; View *tempView; NXRect tempFrame; int i,cnt = [visibleInspectors count],*tempNum; new = [inspectorList elementAt:inspectorNum]; if (!new) return self; // not a valid inspector if(cnt) // find inspectorNum is visibleInspectors list for (i=cnt; i > 0;i--) { tempNum = [visibleInspectors elementAt:i-1]; if (inspectorNum == (unsigned)*tempNum) { [visibleInspectors removeAt:(unsigned)i-1]; new->showing = NO; tempView = new->view; if (tempView != NULL) { [tempView getFrame:&tempFrame]; compositeToBuffer(self, tempFrame.origin.x, tempFrame.origin.y, NX_WIDTH(&tempFrame), NX_HEIGHT(&tempFrame), new->offscreenRect.origin.x, new->offscreenRect.origin.y); [tempView removeFromSuperview]; } } } return self; } - (BOOL)showing:(unsigned int)inspectorNum { struct inspectorListEntry *new; if (inspectorNum >= [inspectorList count]) return NO; // not a valid inspector else new = [inspectorList elementAt:(unsigned)inspectorNum]; if (new->showing == YES) return YES; else return NO; } - (int)group { // check if a group is selected (none is initially) if ([[popupOut target] selectedItem] == NULL) return 0; // if no group selected, return default group (first group added) else return [[popupOut target] indexOfItem:[[popupOut target] selectedItem]]; } - panel { return inspectorPanel; } - popUpListButton { return popupOut; } - revertOKMatrix { return revertOKOut; } - setDelegate:(id)anObject { delegate = anObject; return self; } - delegate { return delegate; } - selectGroup:sender // target of inspector panel group selector PopUpList { [popupOut setTitle:[[sender selectedCell] title]]; [inspectorPanel orderFront:self]; if ([delegate respondsTo:@selector(groupChanged:to:)]) { [delegate groupChanged:self to:[sender selectedRow]]; } return self; } - revertPressed:sender // target of inspector panel Revert button { if ([delegate respondsTo:@selector(inspectRevert)]) { [delegate inspectRevert:self]; } return self; } - okPressed:sender // target of inspector panel OK button { if ([delegate respondsTo:@selector(inspectOK)]) { [delegate inspectOK:self]; } return self; } - showRevertOK { [[inspectorPanel contentView] addSubview:revertOKOut]; [revertOKOut display]; return self; } - hideRevertOK { [revertOKOut removeFromSuperview]; // uncomment the following line to have the Revert/OK buttons // automatically removed by displaying the contentView // [[inspectorPanel contentView] display]; return self; } - showGroupPopUp { [[inspectorPanel contentView] addSubview:popupOut]; [popupOut display]; return self; } - hideGroupPopUp { [popupOut removeFromSuperview]; [[inspectorPanel contentView] display]; return self; } @end
These are the contents of the former NiCE NeXT User Group NeXTSTEP/OpenStep software archive, currently hosted by Netfuture.ch.