This is IKBrowser.m in view mode; [Download] [Up]
#pragma .h #import <AppKit/NSBrowser.h> #pragma .h #pragma .h @protocol IKBrowserDelegate #pragma .h - (void)browser:(NSBrowser *)sender createRowsForColumn:(int)column inMatrix:(NSMatrix *)matrix; #pragma .h - browser:sender setColumnIcon:cell for:(int) column; #pragma .h @end #pragma .h #pragma .h @interface NSObject (IKBrowserDelegateOptionalMethods) #pragma .h - browser:sender emptyMatrix:matrix inColumn: (int) column; #pragma .h - browser:sender removeColumnIcon:cell for: (int) column; #pragma .h - browserWillFinishChange:sender; #pragma .h - browserDidChange:sender; #pragma .h - browserClicked:sender; #pragma .h - browserDoubleClicked:sender; #pragma .h @end #pragma .h #import <AppKit/AppKit.h> #import <InterfaceBuilder/InterfaceBuilder.h> #import <math.h> #import "IKBrowserCell.h" #import "IKIconPath.h" #import "IKBrowser.h" @implementation IKBrowser: NSBrowser { id iconPath; id scrollView; BOOL autoSynchronize; SEL scroll; } #ifndef max #define max(a,b) ((a) > (b) ? (a):(b)) #endif - initWithFrame:(NSRect)frameRect { [super initWithFrame:frameRect]; [self setHasHorizontalScroller:NO]; [self setAllowsMultipleSelection:YES]; [self setAcceptsArrowKeys:YES]; [self setSendsActionOnArrowKeys:YES]; [self setAutoSynchronize:YES]; [self setReusesColumns:YES]; [self setCellClass: [IKBrowserCell class]]; [self setTitled:NO]; return self; } - (void)doAwake { id scroller; [self sizeCells]; if (!scroll) { scroll = [scroller = [scrollView horizontalScroller] action]; [scroller setAction:@selector(scrolling:)]; [scroller setTarget:self]; } [iconPath setTarget:self]; [iconPath setAction:@selector(doClick:)]; [iconPath setDoubleAction:@selector(doDoubleClick:)]; [iconPath setBackgroundColor:[NSColor lightGrayColor]]; [[self window] makeFirstResponder:self]; } - (NSString *) inspectorClassName { return @"IKBrowserInspector"; } - iconPath { return iconPath; } - scrollView { return scrollView; } - (void)removeAllFolders { int i; [[iconPath cells] makeObjectsPerform:@selector(setDelegate:) withObject:nil]; for(i = [self lastColumn]; i >= 0; i--) { [[[self matrixInColumn:i] cells] makeObjectsPerform:@selector(setDelegate:) withObject:nil]; } } - (void)setIconPath: theIconPath { if(iconPath) [iconPath release]; iconPath = theIconPath ? [theIconPath retain] : nil; [self doAwake]; } - (void)setScrollView: theScrollView { if(scrollView) [scrollView release]; scrollView = theScrollView ? [theScrollView retain] : nil; [self doAwake]; } - (id)initWithCoder:(NSCoder *)aDecoder { [super initWithCoder:aDecoder]; iconPath = [[aDecoder decodeObject] retain]; scrollView = [[aDecoder decodeObject] retain]; [aDecoder decodeValuesOfObjCTypes:"c", &autoSynchronize]; [self doAwake]; return self; } - (void)encodeWithCoder:(NSCoder *)aCoder { [super encodeWithCoder:aCoder]; [aCoder encodeObject:iconPath]; [aCoder encodeObject:scrollView]; [aCoder encodeValuesOfObjCTypes:"c", &autoSynchronize]; } - (void)setFrameSize:(NSSize)_newSize { int first = [self firstVisibleColumn]; [super setFrameSize:(NSSize)_newSize]; [self scrollColumnToVisible:first]; [self sizeCells]; } - (void)sizeCells { NSSize size = [scrollView contentSize]; size.width = floor(size.width / [self numberOfVisibleColumns]); [iconPath setCellSize:size]; [self synchronizePath]; [scrollView setLineScroll:size.width]; [scrollView setPageScroll:0.0]; } - (void)synchronizePath { id clipView; NSPoint origin; NSSize size; int cells, i, last; if (autoSynchronize) { size = [iconPath cellSize]; cells = max([self firstVisibleColumn] + [self numberOfVisibleColumns], [self lastColumn]+1); if([iconPath numberOfColumns] != cells) { [iconPath renewRows:1 columns:cells]; [iconPath sizeToCells]; } last = [self lastColumn]; [iconPath deselectSelectedCell]; [iconPath selectCellAtRow:0 column:last]; for(i = 0; i < last; i++) [[iconPath cellAtRow:0 column:i] setBranch:YES]; for(i = last; i < cells; i++) [[iconPath cellAtRow:0 column:i] setBranch:NO]; [iconPath setNeedsDisplay:YES]; origin.x = floor(size.width) * [self firstVisibleColumn]; origin.y = 0.0; clipView = [scrollView contentView]; [clipView scrollToPoint:origin]; [scrollView reflectScrolledClipView:clipView]; } } - (void)setAutoSynchronize: (BOOL) flag; { autoSynchronize = flag; } - (void)newSelection { if (autoSynchronize) { id del = [self delegate]; if (del && [del respondsToSelector: @selector(browser:setColumnIcon:for:)]) { [del browser:self setColumnIcon:[iconPath selectedCell] for: [self lastColumn]]; } } } - (void)beginUpdate { [iconPath endEditing]; [[self window] disableFlushWindow]; } - (void)endUpdate { id del = [self delegate]; [iconPath displayIfNeeded]; if (del && [del respondsToSelector: @selector(browserWillFinishChange:)]) [del browserWillFinishChange: self]; [[self window] enableFlushWindow]; [[self window] makeFirstResponder:self]; if (del && [del respondsToSelector: @selector(browserDidChange:)]) [del browserDidChange: self]; } - (void)addColumn { [super addColumn]; [self synchronizePath]; [self newSelection]; } - (void)setLastColumn:(int)n { NSMutableArray *columnMatrices = [[NSMutableArray alloc] init], *pathCells = [[NSMutableArray alloc] init]; int i = n, m = [self lastColumn]; id del = [self delegate]; while (i++ < m) { [columnMatrices addObject:[self matrixInColumn:i]]; [pathCells addObject:[iconPath cellAtRow:0 column:i]]; } [super setLastColumn:n]; [self synchronizePath]; i = [columnMatrices count]; while (i--) { if (del && [del respondsToSelector:@selector(browser:emptyMatrix:inColumn:)]) [del browser:self emptyMatrix:[columnMatrices objectAtIndex:i] inColumn: n + i + 1]; if (del && [del respondsToSelector:@selector(browser:removeColumnIcon:for:)]) [del browser: self removeColumnIcon: [pathCells objectAtIndex: i] for: n + i + 1]; } [columnMatrices release]; [pathCells release]; } - (void)setReusesColumns:(BOOL)flag { if (flag == YES) [super setReusesColumns:flag]; } - (BOOL)setPath:(NSString *)path { int n; id current = nil; id del = [self delegate]; [self setAutoSynchronize:NO]; [self beginUpdate]; [super setPath:path]; if ([self lastColumn] == [self selectedColumn]) [self addColumn]; [self setAutoSynchronize:YES]; [self synchronizePath]; for (n = 0; n <= [self lastColumn]; n++) { current = [iconPath cellAtRow:0 column:n]; [current setBranch:YES]; if (del && [del respondsToSelector: @selector(browser:setColumnIcon:for:)]) [del browser: self setColumnIcon: current for: n]; } [current setBranch:NO]; [iconPath setNeedsDisplay:YES]; [[scrollView horizontalScroller] setNeedsDisplay:YES]; [self endUpdate]; return YES; } - takePathFrom: sender { [self setPath: [sender stringValue]]; return self; } - resetColumn:(int)n usingPath: (NSString *) path { [self reloadColumn:n]; if (path) { [self setPath:path]; } else { [self beginUpdate]; [self setLastColumn:n]; [[self matrixInColumn:n] selectCellAtRow:-1 column:-1]; [self endUpdate]; } return self; } - scrolling: sender { if ([sender hitPart] != NSScrollerKnob) { [self scrollViaScroller:sender]; [self synchronizePath]; } else [scrollView performSelector:scroll withObject:sender]; return self; } - iconSelected: sender { [self setAutoSynchronize:NO]; [self beginUpdate]; [self setLastColumn:[iconPath selectedColumn]]; [[self matrixInColumn:[self lastColumn]] selectCellAtRow:-1 column:-1]; [self setAutoSynchronize:YES]; [self synchronizePath]; [self endUpdate]; [self sendAction]; return self; } - (void)doClick:(id)sender { id del = [self delegate]; int col = -1; [self setAutoSynchronize:NO]; [self beginUpdate]; if(sender == iconPath) { col = [sender selectedColumn]; [self setLastColumn:col]; } else { [super doClick:sender]; if ([self lastColumn] == [self selectedColumn]) [self addColumn]; } [self setAutoSynchronize:YES]; [self synchronizePath]; [self newSelection]; [self endUpdate]; if(col != -1) [[self matrixInColumn:col] deselectAllCells]; // das darf nicht frueher kommen !?!?!? if(del && [del respondsToSelector:@selector(browserClicked:)]) { [del browserClicked:self]; } } - (void)doDoubleClick:(id)sender { id del = [self delegate]; if(del && [del respondsToSelector:@selector(browserDoubleClicked:)]) { [del browserDoubleClicked:self]; } [super doDoubleClick:sender]; } - (void)keyDown:(NSEvent *)theEvent { int r, c = [self selectedColumn], n, m; id matrix; BOOL clickNow; NSString *chars = [theEvent characters]; switch ([chars characterAtIndex:0]) { case NSLeftArrowFunctionKey: matrix = [self matrixInColumn: c - 1]; r = [matrix selectedRow]; clickNow = YES; break; case NSRightArrowFunctionKey: matrix = [self matrixInColumn: c + 1]; r = 0; clickNow = YES; break; case NSUpArrowFunctionKey: [matrix = [self matrixInColumn: c] getNumberOfRows: &n columns: &m]; r = ([matrix selectedRow] + n - 1) % n; clickNow = NO; break; case NSDownArrowFunctionKey: [matrix = [self matrixInColumn: c] getNumberOfRows: &n columns: &m]; r = ([matrix selectedRow] + 1) % n; clickNow = NO; break; default: return; break; } [matrix scrollCellToVisibleAtRow:r column:0]; [matrix selectCellAtRow:r column:0]; if (matrix && ([matrix selectedRow] != -1) && clickNow) [self doClick:matrix]; } /* The empty extra column that an IKBrowser puts in for a leaf selection messes up the selectAll: message, so that gets fixed here. */ - (void)selectAll:(id)sender { int r, c; [[self matrixInColumn: [self lastColumn]] getNumberOfRows: &r columns: &c]; if (r == 0) [self setLastColumn: [self lastColumn] - 1]; [super selectAll:sender]; if ([self lastColumn] == [self selectedColumn]) [self addColumn]; } - (NSArray *)selectionInColumn: (int) column { NSArray *selection = nil; NSMatrix *matrix = [self matrixInColumn: column]; int i; if (matrix != nil) { NSMutableArray *a = [NSMutableArray array]; selection = [matrix selectedCells]; for (i = 0; i < [selection count]; i++) [a addObject:[[selection objectAtIndex:i] delegate]]; selection = a; } return selection; } @end
These are the contents of the former NiCE NeXT User Group NeXTSTEP/OpenStep software archive, currently hosted by Netfuture.ch.