This is MoveMatrix.m in view mode; [Download] [Up]
/* Generated by Interface Builder */ #import "MoveMatrix.h" #import "MyCell.h" #import <appkit/Cell.h> #import <appkit/TextFieldCell.h> #import <appkit/SelectionCell.h> #import <appkit/MenuCell.h> #import <appkit/defaults.h> #import <appkit/nextstd.h> #import <appkit/tiff.h> #import <appkit/timer.h> #import <dpsclient/wraps.h> @implementation MoveMatrix - initFrame: (const NXRect *) frameRect { [self setCellClass:[ButtonCell class]]; self = [super initFrame: frameRect]; [self setBackgroundGray:0.5]; return self; } - initFrame: (const NXRect *) frameRect mode: (int) mode prototype: anObject numRows: (int) nRows numCols: (int) nCols { self = [super initFrame: frameRect mode: mode prototype: anObject numRows: nRows numCols: nCols]; return self; } // MoveMatrix delegate. // The delegate should prepare following methods: // - matrixDidExchange: (int) index1 : (int) index2 // - setMoveDelegate: anObject { moveDelegate = anObject; } - moveDelegate { return moveDelegate; } - mouseDown:(NXEvent *) event { BOOL gotHit; int oldMask; oldMask = [window addToEventMask:NX_MOUSEDRAGGEDMASK|NX_MOUSEUPMASK]; gotHit = [self move:event]; [window setEventMask:oldMask]; if (!gotHit) { [super mouseDown: event]; } return self; } - selectionCache /* * Shares an off-screen window used to draw the selection in so that it * can be dragged around. If the current off-screen window is equal in * size or larger than the passed size, then it is simply returned. * Otherwise, it is resized to be the specified size. */ { NXRect rect; static id selectioncache = nil; NXRect defaultRect = {{0.0, 0.0}, {300.0, 300.0}}; if (!selectioncache) { rect = defaultRect; selectioncache = [[Window alloc] initContent:&rect style:NX_PLAINSTYLE backing:NX_RETAINED buttonMask:0 defer:NO]; [selectioncache reenableDisplay]; } else { [selectioncache getFrame:&rect]; if (rect.size.width < bounds.size.width || rect.size.height < bounds.size.height) { [selectioncache sizeWindow:MAX(rect.size.width, bounds.size.width) :MAX(rect.size.height, bounds.size.height)]; } } return selectioncache; } -(int)cacheCell:aCell in:(NXRect *)sbounds inView:aView { int i; id selectionCache; if (!aView) aView = self; selectionCache = [aView selectionCache]; [[selectionCache contentView] lockFocus]; PSsetgray(NX_WHITE); PSsetalpha(0.0); /* fully transparent */ PStranslate(- NX_X(sbounds), - NX_Y(sbounds)); NX_WIDTH(sbounds) += 1.0; NX_HEIGHT(sbounds) += 1.0; NXRectFill(sbounds); NX_WIDTH(sbounds) -= 1.0; NX_HEIGHT(sbounds) -= 1.0; PSsetalpha(1.0); /* fully opaque */ [aCell drawSelf:sbounds inView:[selectionCache contentView]]; PStranslate(NX_X(sbounds), NX_Y(sbounds)); [[selectionCache contentView] unlockFocus]; return [selectionCache gState]; } - compositeSelection:(const NXRect *)sbounds from:(int)gstate /* * Composites from the specified gstate whatever part of sbounds is * currently visible in the View. */ { //y position modified to work with a flipped destination view PScomposite(0.0, 0.0, NX_WIDTH(sbounds), NX_HEIGHT(sbounds), gstate, NX_X(sbounds), NX_Y(sbounds)+NX_HEIGHT(sbounds), NX_SOVER); [window flushWindow]; NXPing(); return self; } #define stopTimer(timer) if (timer) { \ NXEndTimer(timer); \ timer = NULL; \ } #define startTimer(timer) if (!timer) timer = NXBeginTimer(NULL, 0.1, 0.1); #define MOVE_MASK NX_MOUSEUPMASK|NX_MOUSEDRAGGEDMASK - (BOOL) move: (NXEvent *) event { int gstate; int row, col; static int originalRow, originalCol; static id aCell; NXCoord dx, dy; NXEvent peek; NXPoint p, last, center; NXRect sbounds, visibleRect, cellFrame; NXTrackingTimer *timer = NULL; BOOL canScroll, tracking = YES; static MyCell *substituteCell = nil; if (!substituteCell) substituteCell = [MyCell new]; last = event->location; [self convertPoint:&last fromView:nil]; [self lockFocus]; //unhighlight previously highlit cell (aCell is static and is saved from //last entry into method if (aCell == nil) { // [self highlightCellAt:originalRow:originalCol lit:NO]; } else { [self getRow:&row andCol:&col ofCell:aCell]; // [self highlightCellAt:row:col lit:NO]; } //highlight cell clicked on [self getRow:&originalRow andCol:&originalCol forPoint:&last]; // [self highlightCellAt:originalRow:originalCol lit:YES]; event = [NXApp getNextEvent:MOVE_MASK]; if (event->type == NX_MOUSEUP) { aCell = nil; [self unlockFocus]; return NO; } // cache the image of the selected cell [self getCellFrame:&sbounds at:originalRow:originalCol]; aCell = [self cellAt:originalRow:originalCol]; gstate = [self cacheCell:aCell in:&sbounds inView: self]; [self compositeSelection:&sbounds from:gstate]; [self putCell:substituteCell at:originalRow:originalCol]; [self getVisibleRect:&visibleRect]; canScroll = !NXEqualRect(&visibleRect, &bounds); while (tracking) { p = event->location; [self convertPoint:&p fromView:nil]; // only moving in horizontal direction dx = p.x - last.x; if (dx) { [self drawSelf:&sbounds :1]; NXOffsetRect(&sbounds, dx, 0.0); //set up so cell image stays within matrix bounds if (!canScroll || (visibleRect.origin.x == 0.0) || ((visibleRect.origin.x + visibleRect.size.width)==bounds.size.width)) { //assuming a flipped view //lefthand of the matrix if (sbounds.origin.x < bounds.origin.x) { p.x += bounds.origin.x - sbounds.origin.x; sbounds.origin.x = bounds.origin.x; } else if ((sbounds.origin.x + sbounds.size.width) > (bounds.origin.x + bounds.size.width)) { //righthand of the matrix p.x -= sbounds.origin.x - ((bounds.origin.x + bounds.size.width) - sbounds.size.width); sbounds.origin.x = (bounds.origin.x + bounds.size.width) - sbounds.size.width + 1; } } if (!canScroll || NXContainsRect(&visibleRect, &sbounds)) { [self compositeSelection:&sbounds from:gstate]; stopTimer(timer); } last = p; } tracking = (event->type != NX_MOUSEUP); if (tracking) { if (canScroll && !NXContainsRect(&visibleRect, &sbounds)) { [window disableFlushWindow]; [self scrollRectToVisible:&sbounds]; [self getVisibleRect:&visibleRect]; [self compositeSelection:&sbounds from:gstate]; [[window reenableFlushWindow] flushWindow]; startTimer(timer); } p = event->location; if (![NXApp peekNextEvent:MOVE_MASK into:&peek]) { event = [NXApp getNextEvent:MOVE_MASK|NX_TIMERMASK]; } else { event = [NXApp getNextEvent:MOVE_MASK]; } if (event->type == NX_TIMER) event->location = p; } } if (canScroll) stopTimer(timer); //set up p so that the y dimension isn't affecting inclusion in matrix p.y = 0.0; center.x = sbounds.origin.x + sbounds.size.width / 2.0; center.y = 0.0; // make sure we're dealing with a valid column if (![self getRow:&row andCol:&col forPoint:¢er]) { row = 0; if (center.x < 0) col = 0; else col = [self cellCount]-1; } [self drawSelf: &sbounds :1]; //whole bunch of finetuning to get this to look right if (col == originalCol) { [self putCell: aCell at: row : col]; [super selectCellAt: row : col]; [super sendAction]; } else { aCell = [self putCell: aCell at: row : col]; [self putCell: aCell at: originalRow : originalCol]; if (moveDelegate) { [moveDelegate matrixDidExchange: originalCol : col]; } } [self display]; [window flushWindow]; [self unlockFocus]; return YES; } @end
These are the contents of the former NiCE NeXT User Group NeXTSTEP/OpenStep software archive, currently hosted by Netfuture.ch.