This is InspectorManager.m in view mode; [Download] [Up]
// InspectorManager.m // By Kevin Brain (ksbrain@zeus.UWaterloo.ca) // A class that manages the displaying of elements of a list of view // objects that are periodically displayed and removed from a window. // 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" @implementation InspectorManager /* Private functions */ static void compositeToBuffer(InspectorManager *self,Window *bufferWindow, float srcX, float srcY, float width, float height, float dstX, float dstY) { [[bufferWindow contentView] lockFocus]; PScomposite(srcX, srcY, width, height, [[self->inspectorPanel contentView] gState], dstX, dstY, NX_SOVER); [[bufferWindow contentView] unlockFocus]; } static void compositeToScreen(InspectorManager *self, Window *bufferWindow, float srcX, float srcY, float width, float height, float dstX, float dstY) { [[self->inspectorPanel contentView] lockFocus]; PScomposite(srcX, srcY, width, height, [[bufferWindow contentView] gState], dstX, dstY, NX_SOVER); [self->inspectorPanel flushWindow]; [[self->inspectorPanel contentView] unlockFocus]; } /* instance methods */ - init { return [self initFromNib: "Inspector.nib"]; } - initFromNib:(const char *) nibFile { [super init]; if ([NXApp loadNibSection: nibFile owner:self] == nil) NXRunAlertPanel(NULL,"Couldn't load %s","OK",NULL,NULL, nibFile); useKeyEquivalents = YES; inspectorList = [[Storage alloc] initCount:0 elementSize:sizeof(struct inspectorListEntry) description:@encode(struct inspectorListEntry)]; groupList = [[Storage alloc] initCount:0 elementSize:sizeof(char *) description:"*"]; visibleInspectors = [[Storage alloc] initCount:0 elementSize:sizeof(unsigned int) description:"i"]; [revertOKOut removeFromSuperview]; [popupOut removeFromSuperview]; [inspectorPanel display]; // to actually remove the controls [[inspectorPanel contentView] allocateGState]; /* 'messagePanel' is created in IB as the window containing the message inspector*/ /* This window is non-deferred and always kept off-screen */ [self addInspector: messageBox title:[inspectorStrings valueForStringKey: "MessageInspector"] atLocation:LOWERLEFTX :LOWERLEFTY cached:NO cacheWindow:messagePanel]; /* Initialize the Inspector to display "Unapplicable Inspector" message */ [self showMessage:(const char *)"Not\nApplicable"]; return self; } - (unsigned int)addInspector:(id)theView title:(const char *)theTitle { return [self addInspector:theView title:theTitle atLocation:LOWERLEFTX :LOWERLEFTY cached:YES cacheWindow:nil]; } - (unsigned int)addInspector:(id)theView title:(const char *)theTitle atLocation:(NXCoord)xLoc :(NXCoord)yLoc cached:(BOOL)isCached cacheWindow:(id)theCacheWindow { struct inspectorListEntry tempInspectorEntry; NXRect theViewRect; tempInspectorEntry.view = theView; tempInspectorEntry.showing = NO; tempInspectorEntry.cached = isCached; tempInspectorEntry.title = malloc(sizeof(char)*(strlen((char *)theTitle))); strcpy(tempInspectorEntry.title,theTitle); if (isCached) { if (theCacheWindow == nil) { [theView getFrame:&theViewRect]; theViewRect.origin.x = [inspectorList count]; tempInspectorEntry.cacheWindow = [[Window alloc] initContent:(const NXRect *)&theViewRect style:(int)NX_PLAINSTYLE backing:(int)NX_RETAINED buttonMask:(int)0 defer:(BOOL)NO]; } else tempInspectorEntry.cacheWindow = theCacheWindow; /* The lockFocus forces the gState to become defined */ [[[tempInspectorEntry.cacheWindow contentView] allocateGState] lockFocus]; [[tempInspectorEntry.cacheWindow contentView] addSubview:theView]; if (theCacheWindow == nil) { [theView moveTo:0 :0]; // move view to origin of offscreen buffer content view [tempInspectorEntry.cacheWindow display]; } [theView getFrame:&tempInspectorEntry.offscreenRect]; // [theView display]; // draw in offscreen buffer [[tempInspectorEntry.cacheWindow contentView] unlockFocus]; } [inspectorList addElement:&tempInspectorEntry]; [theView moveTo:xLoc :yLoc]; [theView removeFromSuperview]; return [inspectorList count]-1; } - (unsigned int)addGroup:(const char *)theTitle { char *tempTitle; unsigned short temp; id tempView; // add item to PopUpList // command-key equivalents for first 9 if (([groupList count] < 9) && (useKeyEquivalents == YES)) temp = (unsigned short)[groupList count]+(unsigned short)'1'; else temp = 0; // no command-key equivalent for rest tempView = [[popupOut target] addItem:theTitle action:@selector(selectGroup:) keyEquivalent:temp]; [tempView 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]; tempTitle = NXCopyStringBuffer((const char *)theTitle); [groupList addElement:&tempTitle]; return [groupList count]-1; } - setUseKeyEquivalents:(BOOL)use { useKeyEquivalents = use; return self; } - switchToInspector:(unsigned int)newInspectorNum { struct inspectorListEntry *new,*tempOld; View *tempView; NXRect tempFrame; int i,*tempShowing; unsigned cnt = [visibleInspectors count]; new = [inspectorList elementAt:newInspectorNum]; 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]; if (tempOld->cached) compositeToBuffer(self, tempOld->cacheWindow, 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]; if (new->cached) { // Now composite the new inspector view from the offscreen window // into the inspector panel [new->view getFrame:&tempFrame]; compositeToScreen(self, new->cacheWindow, new->offscreenRect.origin.x, new->offscreenRect.origin.y, NX_WIDTH(&tempFrame), NX_HEIGHT(&tempFrame), tempFrame.origin.x, tempFrame.origin.y); } else [new->view display]; [inspectorPanel setTitle:new->title]; new->showing = YES; i=(int)newInspectorNum; [visibleInspectors addElement:&i]; return self; } - showInspector:(unsigned int)inspectorNum { struct inspectorListEntry *new; NXRect tempFrame; int tempNum; new = [inspectorList elementAt:inspectorNum]; if (!new) return self; // not a valid inspector if ([self showing:inspectorNum] == YES) return self; // if already showing [inspectorPanel disableFlushWindow]; [[inspectorPanel contentView] addSubview:new->view]; if (new->cached) { // Now composite the new inspector view from the offscreen window // into the inspector panel [new->view getFrame:&tempFrame]; compositeToScreen(self, new->cacheWindow, new->offscreenRect.origin.x, new->offscreenRect.origin.y, NX_WIDTH(&tempFrame), NX_HEIGHT(&tempFrame), tempFrame.origin.x, tempFrame.origin.y); } else [new->view display]; [inspectorPanel setTitle:new->title]; [inspectorPanel reenableFlushWindow]; [inspectorPanel flushWindowIfNeeded]; new->showing = YES; tempNum = (int)inspectorNum; [visibleInspectors addElement:&tempNum]; return self; } - hideInspector:(unsigned int)inspectorNum { struct inspectorListEntry *inspector; View *tempView; NXRect tempFrame; int i,cnt = [visibleInspectors count],*tempNum; inspector = [inspectorList elementAt:inspectorNum]; if (!inspector) 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]; inspector->showing = NO; tempView = inspector->view; if (tempView != NULL) { [tempView getFrame:&tempFrame]; if (inspector->cached) compositeToBuffer(self, inspector->cacheWindow, tempFrame.origin.x, tempFrame.origin.y, NX_WIDTH(&tempFrame),NX_HEIGHT(&tempFrame), inspector->offscreenRect.origin.x, inspector->offscreenRect.origin.y); [tempView removeFromSuperview]; } } } return self; } - (BOOL)showing:(unsigned int)inspectorNum { struct inspectorListEntry *inspector; if (inspectorNum >= [inspectorList count]) return NO; // not a valid inspector else inspector = [inspectorList elementAt:(unsigned)inspectorNum]; if (inspector->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]]; } - showMessage:(const char *)theMessage { [inspectorPanel disableFlushWindow]; [self switchToInspector:MESSAGE]; [messageTextField setStringValue:theMessage]; [messageTextField display]; [[inspectorPanel reenableFlushWindow] flushWindowIfNeeded]; return self; } - messageTextField {return messageTextField; } - 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 // (otherwise the image of the buttons will still be visible) // [[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.