This is MiscSplitBrowser.m in view mode; [Download] [Up]
// Tue Mar 5 20:28:08 MET 1996 #import "MiscSplitBrowser.h" /* toDo fix graphicbug in initial display (on the right) * (which diappears by ther way after niling out a view and then move the divider * back to the middle) */ enum {MiscLeft=0,MiscRight=1}; # define MISCSPLITBROWSER_VERSION 1 @implementation MiscSplitBrowser + initialize { if(self == [MiscSplitBrowser class]) { [self setVersion:MISCSPLITBROWSER_VERSION]; } [self setMatrixClass:[Matrix class]]; return self; } static id matrixClass; + matrixClass { return matrixClass; } + setMatrixClass:theMatrixClass { return matrixClass=theMatrixClass; } #if 0 - getBounds:(NXRect *)lr { NXCoord borderWidth=-5; [super getBounds:lr]; lr->origin.x+=borderWidth,lr->origin.y+=borderWidth; lr->size.width-=(borderWidth*2),lr->size.height-=(borderWidth*2); return self; } #endif -(Matrix*) createMatrix:(NXRect *) theRect { Matrix *theMatrix=[[MiscSplitBrowser matrixClass] alloc]; theMatrix=[theMatrix initFrame:theRect]; [theMatrix setAutoscroll:YES]; [theMatrix setEmptySelectionEnabled:NO]; [theMatrix setCellClass:[NXBrowserCell class]]; [theMatrix setTarget:self],[theMatrix setAction:@selector(didClick:)]; return theMatrix; } - initFrame:(NXRect *) theRect { NXRect halfRect=*theRect; ScrollView *leftScroll=[ScrollView alloc],*rightScroll=[ScrollView alloc]; halfRect.size.width/=2; leftScroll=[leftScroll initFrame:&halfRect], rightScroll=[rightScroll initFrame:&halfRect]; [leftScroll setVertScrollerRequired:YES]; [leftScroll setBorderType:NX_BEZEL]; [rightScroll setVertScrollerRequired:YES]; [rightScroll setBorderType:NX_BEZEL]; [leftScroll setDocView: leftMatrix=[self createMatrix:&halfRect]]; [rightScroll setDocView:rightMatrix=[self createMatrix:&halfRect]]; [super initFrame:theRect]; [self setLeftView:leftScroll]; [self setRightView:rightScroll]; [self initViews]; pathSeparator='/'; return self; } - setSizeForMatrix:(Matrix *)theMatrix { NXRect theRect; NXSize cellSize; [theMatrix getCellSize:&cellSize]; [[theMatrix superview] getFrame:&theRect]; cellSize.width= theRect.size.width; [theMatrix setCellSize:&cellSize]; [theMatrix sizeToCells]; return self; } - sideSplitViewDidResizeSubviews: sender { [self setSizeForMatrix:leftMatrix]; [self setSizeForMatrix:rightMatrix]; return self; } - selectCellNamed:(const char*)theName inMatrix:(Matrix*)theMatrix { List *cellList=[theMatrix cellList]; Cell *currCell; int i; for(i=0; currCell=[cellList objectAt:i];i++) { if(!strcmp([currCell stringValue],theName)) { [theMatrix selectCellAt:i:0]; [theMatrix scrollCellToVisible:i:0]; return self; } } return nil; } - setPath:(const char *)thePath { char *str=NXCopyStringBuffer(thePath), *ps=strchr(str,pathSeparator),*ps1; if(ps) *ps=0; [self selectCellNamed:str inMatrix:leftMatrix]; [self reloadColumn:1]; if(ps) { ps1=strchr(ps+1,pathSeparator); if(ps1) *ps1=0; [self selectCellNamed:ps+1 inMatrix:rightMatrix]; } [self sendAction]; free((void*) str); return self; } -(char *) getPath:(char *)pathString toColumn:(int) column { switch(MAX(column-1,0)) { case MiscLeft: sprintf(pathString,"%c%s",pathSeparator,[[leftMatrix selectedCell] stringValue]); if(strlen(pathString) == 1) pathString[0]=0; break; case MiscRight: { const char *rptr=[[rightMatrix selectedCell] stringValue]; sprintf(pathString,"%c%s%c%s",pathSeparator,[[leftMatrix selectedCell] stringValue], rptr? pathSeparator:0,rptr? rptr:""); } break; } return pathString; } - sendAction { if(target && action) [NXApp sendAction:action to:target from:self]; return self; } - reloadColumn:(int) theColumn { int numRows; Matrix *theMatrix=nil; [window disableFlushWindow]; switch(theColumn) // [self matrixOfColumn { case MiscLeft: theMatrix=leftMatrix; break; case MiscRight: theMatrix=rightMatrix; break; default: return nil; } numRows=[browserDelegate browser:self fillMatrix:theMatrix inColumn:theColumn]; [theMatrix renewRows:numRows cols:1]; [self setSizeForMatrix:theMatrix]; [theMatrix display]; [[window reenableFlushWindow] flushWindow]; return self; } - didClick:sender { if(sender == leftMatrix) { [self reloadColumn:1]; } return [self sendAction]; } -(int) indexOfSelectedCellInMatrix:(Matrix*) theMatrix { int x,y; if(!theMatrix) return -1; [theMatrix getRow:&y andCol:&x ofCell:[theMatrix selectedCell]]; return y; } - loadColumnZeroPreserveSel:(BOOL)preserve { int leftSel=[self indexOfSelectedCellInMatrix:leftMatrix], rightSel=[self indexOfSelectedCellInMatrix:rightMatrix]; if(preserve) [window disableFlushWindow]; [self reloadColumn:0]; if(preserve && leftSel >=0) [leftMatrix selectCellAt:leftSel:0]; if([leftMatrix selectedCell]) [self reloadColumn:1]; if(preserve && rightSel >=0) [rightMatrix selectCellAt:rightSel:0]; if(preserve) [[window reenableFlushWindow] flushWindow]; [self sendAction]; return self; } - loadColumnZero { return [self loadColumnZeroPreserveSel:NO]; } -(Matrix*) matrixInColumn:(int) col { switch(col) { case MiscLeft: return leftMatrix; case MiscRight: return rightMatrix; } return nil; } -(int) selectedColumn { if([rightMatrix selectedCell]) return MiscRight; if([leftMatrix selectedCell]) return MiscLeft; return -1; } -(int) selectedRow { Matrix *theMatrix=[self matrixInColumn:[self selectedColumn]]; if(!theMatrix) return -1; else return [self indexOfSelectedCellInMatrix:theMatrix]; } -(int) lastColumn { if(![rightMatrix cellCount]) return MiscLeft; else return MiscRight; } -(Matrix*) selectedMatrix { int selCol=[self selectedColumn]; if(selCol == -1) return nil; return [self matrixInColumn:selCol]; } -(Cell *) selectedCell { return [[self selectedMatrix] selectedCell]; } - emptyValidationForRow:(int)y inMatrix:(Matrix *) theMatrix minCount:(int)min { if([theMatrix cellCount] > min) { if(y == [theMatrix cellCount]-1) [theMatrix selectCellAt:MAX(y-1,0):0]; return self; } return nil; } - reestablishSelection { [window disableFlushWindow]; if(([self selectedColumn] == MiscLeft) || ![self emptyValidationForRow:[self indexOfSelectedCellInMatrix:rightMatrix] inMatrix:rightMatrix minCount:1]) { [self emptyValidationForRow:[self indexOfSelectedCellInMatrix:leftMatrix] inMatrix:leftMatrix minCount:0]; } [[window reenableFlushWindow] flushWindow]; return self; } - selectPrevious { return self; } - selectNext { return self; } - acceptArrowKeys:(BOOL) doAccept andSendActionMessages:(BOOL) doSendActions { return self; } - (id)target { return target; } - setTarget:(id)aTarget { target=aTarget; return self; } - (SEL)action { return action; } - setAction:(SEL)aAction { action=aAction; return self; } - (unsigned short)pathSeparator { return pathSeparator; } - setPathSeparator:(unsigned short)aPathSeparator { pathSeparator=aPathSeparator; return self; } - (SEL)doubleAction { return doubleAction; } - setDoubleAction:(SEL)aDoubleAction { doubleAction=aDoubleAction; return self; } - (id)browserDelegate { return browserDelegate; } - setBrowserDelegate:(id)aBrowserDelegate { browserDelegate=aBrowserDelegate; return self; } - setDelegate:theDelegate { [super setDelegate:theDelegate]; if(![self browserDelegate]) [self setBrowserDelegate:theDelegate]; return self; } - leftView { return leftView; } - rightView { return rightView; } - setDivider:(NXCoord) divx { dividerRect.origin.x =divx; [window disableFlushWindow]; [self adjustSubviews]; [self display]; [[window reenableFlushWindow] flushWindow]; return self; } - awake { [super awake]; return self; } - read:(NXTypedStream *)stream { int version; [super read:stream]; version = NXTypedStreamClassVersion(stream, "MiscSplitBrowser"); /* * **** Archiving: READ ME **** This code (and its analogue in write:) is * critical. When you bump MISC_DRAG_VIEW_VERSION, copy the whole _current_ * case ("case MISC_DRAG_VIEW_VERSION: ... break;"), and duplicate it. * Change the "MISC_DRAG_VIEW_VERSION" in the old case to the OLD * (pre-bump) version number. Now, dork the "new current" version into * whatever you want. See how this code can now read EITHER version out of * the typed stream? * * If you are adding yet another version, leave the previous versions in * place. That way you can still read archived objects that are more than * one version old. Don't forget to take whatever actions are necessary to * harmonize those old values. For example, if you converted an "int" ivar * to "double", you'd need to (in the old version) to read the int version * into a temp variable, and convert it in to the double var. BJM 5/24/94 */ switch (version) { case 1: NXReadTypes(stream,"@::I@",&target,&action,&doubleAction,&pathSeparator, &browserDelegate); leftMatrix=NXReadObject(stream); rightMatrix=NXReadObject(stream); break; } return self; } - write:(NXTypedStream *)stream { [super write:stream]; /* * **** Archiving: READ ME **** Home stretch. Now (just like read:) * duplicate the current case ("case MISC_DRAG_VIEW_VERSION: ... break;"). * Once again, change the "MISC_DRAG_VIEW_VERSION" of the first one to the * OLD version number. Now adjust the new/current MISC_DRAG_VIEW_VERSION * (remember, you've bumped it) to the new way of writing vars. See how * this code (because the constant is in the switch statement) always * writes out ONLY the current version, but leaves the old version(s) * around to posterity. DO NOT DELETE THE OLD VERSIONS. Leave them to * clutter up the world. BJM 5/24/94 */ switch (MISCSPLITBROWSER_VERSION) { case MISCSPLITBROWSER_VERSION: NXWriteTypes(stream,"@::I@",&target,&action,&doubleAction,&pathSeparator, &browserDelegate); NXWriteObject(stream,leftMatrix); // was writing references NXWriteObject(stream,rightMatrix); // was writing references break; } return self; } @end
These are the contents of the former NiCE NeXT User Group NeXTSTEP/OpenStep software archive, currently hosted by Netfuture.ch.