This is MultiView.m in view mode; [Download] [Up]
#import "NiftyMatrix.h" #import "MultiView.h" #import <math.h> @implementation MultiView - initFrame:(const NXRect *)frm { [super initFrame:frm]; sel_list = [matrix getSelectedCells:nil]; num = [sel_list count]; if (num > MAX_VIEWS) num = MAX_VIEWS; currentLay = 0; [self initLayouts]; return self; } // // deal with defaults // - readDefaults { int i = 0, j; char *def; const char *tmp; char *current; tmp = NXGetDefaultValue([NXApp appName],"MultiViews"); if (tmp) { def = malloc(strlen(tmp) + 1); strcpy (def,tmp); while (def) { current = rindex(def,':'); if (!current) { views[i] = [self viewNamed:def]; j = [self cellNamed:def]; [matrix setSelectionFrom:j to:j anchor:j lit:YES]; break; } views[i] = [self viewNamed:(current+1)]; i++; j = [self cellNamed:(current+1)]; [matrix setSelectionFrom:j to:j anchor:j lit:YES]; *current = '\0'; } free(def); } tmp = NXGetDefaultValue([NXApp appName],"MultiLayout"); if (tmp) currentLay = atoi(tmp); printf("%s : %d\n",tmp,currentLay); return self; } - writeDefaults:sender { int i; const char *name; char def[1024]; // more than we should ever need if (num > 0) { def[0] = '\0'; for (i = 0; i < num; i++) { if (i) strcat(def,":"); name = [[sel_list objectAt:i] stringValue]; strcat(def,name); } NXWriteDefault([NXApp appName], "MultiViews", def); } sprintf(def,"%d",currentLay); NXWriteDefault([NXApp appName], "MultiLayout",def); return self; } // // whenever we receive a newWindow message, it's a good time to // check the list and reinitialize everything // this method is called internally everytime a new selection is made - newWindow { int i, n, lays; int x,y,w,h; NXRect frm; // clean up all of the old views. reset their origins NXSetRect(&frm,0,0,50,50); for (i = 0; i < num; i++) [[views[i] setFrame:&frm] removeFromSuperview]; // clean up the screen... what a mess! [self display]; // [self lockFocus]; // [self drawSelf:&frame :1]; // [self unlockFocus]; // find out what was selected, and get the appropriate views sel_list = [matrix getSelectedCells:nil]; num = [sel_list count]; lays = lay_defs[currentLay].num; n = MIN(lays,num); num = n; for (i = 0; i < n; i++) { views[i] = [self viewFrom:[sel_list objectAt:i]]; if (NX_X(&lay_defs[currentLay].pos[i]) == 0) x = 0; else x = NX_WIDTH(&frame) / NX_X(&lay_defs[currentLay].pos[i]); if (NX_Y(&lay_defs[currentLay].pos[i]) == 0) y = 0; else y = NX_HEIGHT(&frame) / NX_Y(&lay_defs[currentLay].pos[i]); w = NX_WIDTH(&frame) / NX_WIDTH(&lay_defs[currentLay].pos[i]); h = NX_HEIGHT(&frame) / NX_HEIGHT(&lay_defs[currentLay].pos[i]); NXSetRect(&frm,x,y,w,h); [[views[i] setFrame:&frm] setClipping:YES]; [self addSubview:views[i]]; // we need to make sure that they draw themselves once first // [views[i] lockFocus]; [views[i] display]; // [views[i] unlockFocus]; } return self; } // // rather than call oneStep on every method at once, // just call it on one, then next time, call it on the next one. // for some reason, this seemed to improve performance // (I'm not sure why though) // - oneStep { static int cur = 0; [views[cur] lockFocus]; // this is necessary for some views (such as Space) to function properly if ([views[cur] respondsTo:@selector(didLockFocus)]) [views[cur] didLockFocus]; [views[cur] oneStep]; [views[cur] unlockFocus]; cur++; if (cur >= num) cur = 0; return self; } // // when this is called, we know that we've just been loaded up // so we take advantage of that fact and do a lot of initialization // - inspector:sender { char buf[MAXPATHLEN]; NXRect frm, scrollRect; NXSize matSize, cellSize; thinker = sender; pub = (struct thinkerDef *)thinker; modList = pub->moduleList; if (!inspectorPanel) { // // Time to make the matrix... time to make the matrix // sprintf(buf,"%s/Multi.nib",(char *)[sender moduleDirectory:"Multi"]); [NXApp loadNibFile:buf owner:self withNames:NO]; [scrollView getFrame:&frm]; matrix = [[NiftyMatrix alloc] initFrame:&frm mode:NX_LISTMODE cellClass:[Cell class] numRows:0 numCols:1]; [self fillMatrix]; [scrollView getFrame:&scrollRect]; [ScrollView getContentSize:&matSize forFrameSize:&scrollRect.size horizScroller:NO vertScroller:YES borderType:NX_BEZEL]; [matrix getCellSize:&cellSize]; cellSize.width = matSize.width; [matrix setCellSize:&cellSize]; [matrix sizeToCells]; [matrix setAutosizeCells:YES]; [matrix setAutoscroll:YES]; [scrollView setDocView:matrix]; [[matrix superview] setAutoresizeSubviews:YES]; [matrix setAutosizing:NX_WIDTHSIZABLE]; [matrix setTarget:self]; [matrix setAction:@selector(select:)]; [matrix setDoubleAction:@selector(inspect:)]; [self readDefaults]; // // time to make the funky layout thingie // // yuck... there must be a better way to initialize arrays like this layouts[0] = lay1; layouts[1] = lay2; layouts[2] = lay3; layouts[3] = lay4; layouts[4] = lay5; layouts[5] = lay6; layouts[6] = lay7; layouts[7] = lay8; layouts[8] = lay9; layouts[9] = lay10; layouts[10] = lay11; [layouts[currentLay] getFrame:&frm]; NXSetRect(&frm,0,0,NX_WIDTH(&frm),NX_HEIGHT(&frm)); [layouts[currentLay] setFrame:&frm]; [[layout addSubview:layouts[currentLay]] display]; } return inspectorPanel; } // // clean up the "multi inspector" // - inspectorWillBeRemoved { int i; NXRect foo; NXSetRect(&foo,0,0,0,0); for (i = 0; i < num; i++) [views[i] setFrame:&foo]; if (otherInspector) [otherInspector close]; return self; } - setImage:image { int i; for (i = 0; i < num; i++) if ([views[i] respondsTo:@selector(setImage:)]) [views[i] setImage:image]; return self; } // // helper function to -fillMatrix // - addCellWithString:(const char *)str at:(int)row { id theCell; [matrix insertRowAt:row]; theCell = [matrix cellAt:row :0]; [theCell setStringValue:str]; return self; } // // fill the matrix with the view names /// - fillMatrix { int i, n, j; n = [modList count]; for (i = j = 0; i < n; i++) { if (strcmp([modList nameAt: i], "Multi")) #ifdef MULTI_LOCALIZED [self addCellWithString:NXLocalString([modList nameAt: i], 0, 0) #else [self addCellWithString:[modList nameAt:i] #endif at:(j++)]; } return self; } // // called whenever an item in the matrix is clicked on // - select:sender { [self newWindow]; [[self window] flushWindow]; return self; } // // funky layout selection interface code // - layoutUp:sender { NXRect frm; [layouts[currentLay] removeFromSuperview]; currentLay --; if (currentLay < 0) currentLay = 10; [layouts[currentLay] getFrame:&frm]; NXSetRect(&frm,0,0,NX_WIDTH(&frm),NX_HEIGHT(&frm)); [layouts[currentLay] setFrame:&frm]; [[layout addSubview:layouts[currentLay]] display]; [self newWindow]; [[self window] flushWindow]; return self; } - layoutDown:sender { NXRect frm; [layouts[currentLay] removeFromSuperview]; currentLay ++; if (currentLay > 10) currentLay = 0; [layouts[currentLay] getFrame:&frm]; NXSetRect(&frm,0,0,NX_WIDTH(&frm),NX_HEIGHT(&frm)); [layouts[currentLay] setFrame:&frm]; [[layout addSubview:layouts[currentLay]] display]; [self newWindow]; [[self window] flushWindow]; return self; } // // initialize all of the layout definitions. // this is ugly because it's all hardcoded. If I ever mess with the // layouts in the interface, I'll also have to change this. Unfortunately, // I didn't see a straightforward way of doing it automatically from the drawn // layouts. Maybe I should do it the other way, and draw the layouts by hand. // that probably makes sense if I ever do any future development on this // - initLayouts { lay_defs[0].num = 1; [self allocLayout:0]; NXSetRect(&lay_defs[0].pos[0],0,0,1,1); lay_defs[1].num = 2; [self allocLayout:1]; NXSetRect(&lay_defs[1].pos[0],0,2,1,2); NXSetRect(&lay_defs[1].pos[1],0,0,1,2); lay_defs[2].num = 2; [self allocLayout:2]; NXSetRect(&lay_defs[2].pos[0],0,0,2,1); NXSetRect(&lay_defs[2].pos[1],2,0,2,1); lay_defs[3].num = 3; [self allocLayout:3]; NXSetRect(&lay_defs[3].pos[0],0,0,2,1); NXSetRect(&lay_defs[3].pos[1],2,2,2,2); NXSetRect(&lay_defs[3].pos[2],2,0,2,2); lay_defs[4].num = 3; [self allocLayout:4]; NXSetRect(&lay_defs[4].pos[0],0,0,2,2); NXSetRect(&lay_defs[4].pos[1],0,2,2,2); NXSetRect(&lay_defs[4].pos[2],2,0,2,1); lay_defs[5].num = 3; [self allocLayout:5]; NXSetRect(&lay_defs[5].pos[0],0,2,1,2); NXSetRect(&lay_defs[5].pos[1],0,0,2,2); NXSetRect(&lay_defs[5].pos[2],2,0,2,2); lay_defs[6].num = 3; [self allocLayout:6]; NXSetRect(&lay_defs[6].pos[0],0,0,1,2); NXSetRect(&lay_defs[6].pos[1],0,2,2,2); NXSetRect(&lay_defs[6].pos[2],2,2,2,2); lay_defs[7].num = 4; [self allocLayout:7]; NXSetRect(&lay_defs[7].pos[0],0,0,2,2); NXSetRect(&lay_defs[7].pos[1],2,2,2,2); NXSetRect(&lay_defs[7].pos[2],0,2,2,2); NXSetRect(&lay_defs[7].pos[3],2,0,2,2); lay_defs[8].num = 6; [self allocLayout:8]; NXSetRect(&lay_defs[8].pos[0],0,0,2,3); NXSetRect(&lay_defs[8].pos[1],2,0,2,3); NXSetRect(&lay_defs[8].pos[2],0,3,2,3); NXSetRect(&lay_defs[8].pos[3],2,3,2,3); NXSetRect(&lay_defs[8].pos[4],0,1.5,2,3); NXSetRect(&lay_defs[8].pos[5],2,1.5,2,3); lay_defs[9].num = 6; [self allocLayout:9]; NXSetRect(&lay_defs[9].pos[0],0,0,3,2); NXSetRect(&lay_defs[9].pos[1],3,0,3,2); NXSetRect(&lay_defs[9].pos[2],1.5,0,3,2); NXSetRect(&lay_defs[9].pos[3],0,2,3,2); NXSetRect(&lay_defs[9].pos[4],3,2,3,2); NXSetRect(&lay_defs[9].pos[5],1.5,2,3,2); lay_defs[10].num = 9; [self allocLayout:10]; NXSetRect(&lay_defs[10].pos[0],0,0,3,3); NXSetRect(&lay_defs[10].pos[1],3,3,3,3); NXSetRect(&lay_defs[10].pos[2],1.5,1.5,3,3); NXSetRect(&lay_defs[10].pos[3],0,3,3,3); NXSetRect(&lay_defs[10].pos[4],3,0,3,3); NXSetRect(&lay_defs[10].pos[5],0,1.5,3,3); NXSetRect(&lay_defs[10].pos[6],1.5,0,3,3); NXSetRect(&lay_defs[10].pos[7],3,1.5,3,3); NXSetRect(&lay_defs[10].pos[8],1.5,3,3,3); return self; } - allocLayout:(int)index { int n; n = lay_defs[index].num; lay_defs[index].pos = malloc(sizeof(NXRect) * n); return self; } // // BackSpace Thinker emulation code // - performMethodOnViews:(SEL)sel { int i; for (i = 0; i < num; i++) if ([views[i] respondsTo:sel]) [views[i] perform:sel]; return self; } - enteredScreenSaverMode { [self performMethodOnViews:@selector(enteredScreenSaverMode)]; return self; } - willExitScreenSaverMode { [self performMethodOnViews:@selector(willExitScreenSaverMode)]; return self; } - inspect:sender { id insp = nil; NXRect frm; if ([[self viewFrom:sender] respondsTo:@selector(inspector:)]) insp = [[self viewFrom:sender] inspector:thinker]; if (insp == nil) insp = [thinker nullInspector]; [insp getFrame:&frm]; [otherInspector setContentView:insp]; [otherInspector makeKeyAndOrderFront:self]; [otherInspector sizeWindow:NX_WIDTH(&frm) :NX_HEIGHT(&frm)]; [[otherInspector contentView] display]; return self; } // // these methods walk the list of views to match names and cells with // the views that go with them // - viewFrom:sender { const char *name; int i, n; id view = nil; name = [sender stringValue]; n = [modList count]; for (i = 0; i < n; i++) if (!strcmp([modList nameAt: i], name)) view = [modList viewAt: i]; if (view == nil) view = [self loadView:name]; if (view == nil) fprintf(stderr,"returned nil: %s\n",name); return view; } - viewNamed:(const char *)name { int i, n; id view = nil; n = [modList count]; for (i = 0; i < n; i++) if (!strcmp([modList nameAt: i], name)) view = [modList viewAt: i]; if (!view) view = [self loadView:name]; return view; } - objectNamed:(const char *)name { int i, n; n = [modList count]; for (i = 0; i < n; i++) if (!strcmp([modList nameAt: i], name)) return [modList objectAt: i]; return nil; } - (int)cellNamed:(const char *)name { int i, n; n = [matrix cellCount]; for (i = 0; i < n; i++) if (!strcmp([[matrix cellAt: i :0] stringValue], name)) return i; return -1; } // this is pretty much a duplicate of - backView from ThinkMore.m // I couldn't just call that directly because it relies on its own state // to know what view to load - loadView:(const char *)name { NXRect aFrame = {{0,0},{200,200}}; id theView = nil; char path[MAXPATHLEN]; id myClass; char *filenames[] = {path, NULL}; ModuleInfo *mp; struct mach_header *header; //if (index(name,' ')) // name = strip_spaces(name); mp = [self objectNamed:name]; if ([mp path]) { long ret; while (1) { sprintf(path, "%s/%sView.BackO", [mp path], name); ret = objc_loadModules(filenames, NULL, NULL, &header, NULL); if (ret && [mp respondsTo:@selector(useNextPath)]) if ([mp useNextPath]) continue; break; } if (ret) { NXRunAlertPanel([NXApp appName], NXLocalString("Could not dynamically load class: %sView",0,0), NULL, NULL, NULL, name); return nil; } else { [mp setHeader:header]; } //at this point we must have a valid name for a loaded class } sprintf(path,"%sView", name); myClass = objc_getClass(path); // heh... god I love @defs! :-) theView = [[myClass allocFromZone:pub->backZone] initFrame:&aFrame]; [mp setView:theView]; // fake 'em out by passing thinker instead of self if ([theView respondsTo:@selector(inspector:)]) [theView inspector:thinker]; return theView; } - drawSelf:(const NXRect *)frm :(int)count { PSsetgray(0.0); NXRectFillList(frm,count); return self; } - (BOOL)useBufferedWindow { return YES; } - (const char *)windowTitle { return "MultiView"; } - sizeTo:(NXCoord)width :(NXCoord)height { [super sizeTo:width :height]; [self newWindow]; return self; } // // handoff methods... these all just call the equivalent in Thinker // some of the modules depend on them // - commonImageInspector { return [thinker commonImageInspector]; } - nullInspector { return [thinker nullInspector]; } - spaceInspector { return [thinker spaceInspector]; } - boinkInspector { return [thinker boinkInspector]; } - (const char *)moduleDirectory:(const char *)name { return [thinker moduleDirectory:name]; } @end
These are the contents of the former NiCE NeXT User Group NeXTSTEP/OpenStep software archive, currently hosted by Netfuture.ch.