home *** CD-ROM | disk | FTP | other *** search
- /*--------------------------------------------------------------------------
- *
- * You may freely copy, distribute, and reuse the code in this example.
- * SHL Systemhouse disclaims any warranty of any kind, expressed or
- * implied, as to its fitness for any particular use.
- *
- *
- * SlidingMatrix
- *
- * Inherits From: Matrix
- *
- * Conforms To: None.
- *
- * Declared In: SlidingMatrix.h
- *
- *
- *------------------------------------------------------------------------*/
- #import "SlidingMatrix.h"
-
-
- static int rowDropped;
- static int rowDragged;
- static BOOL isDragging;
- static NXPoint currentMouse;
-
-
- #define BOUND(__a,__low,__high) MIN(MAX((__a),(__low)),(__high))
-
-
-
-
- @implementation SlidingMatrix
-
- /*--------------------------------------------------------------------------
- * Private Methods
- *------------------------------------------------------------------------*/
- - _exchangeRowAt: (int) source with: (int) destination
- {
- int iterator;
- id sourceCell, destinationCell;
-
- for (iterator = 0; iterator < numCols; iterator++)
- {
- sourceCell = [self cellAt: source : iterator];
- destinationCell = [self cellAt: destination : iterator];
- [self putCell: sourceCell at: destination : iterator];
- [self putCell: destinationCell at: source : iterator];
- }
-
- return self;
- }
-
-
- - _reflectScroll
- {
- // If in a ScrollView, reflect scroll if drag is beyond visibleRect...
-
- id scrollView = [superview superview];
- id clipView = superview;
- NXRect visibleRect, clipViewBoundsRect;
- NXCoord delta;
-
- [self getVisibleRect: &visibleRect];
- delta = (currentMouse.y + cellSize.height) - (NX_HEIGHT (&visibleRect) + NX_Y
- (&visibleRect));
-
- if (delta > 0.0)
- {
- [clipView getBounds: &clipViewBoundsRect];
- NX_Y (&clipViewBoundsRect) += delta;
- [clipView rawScroll: &clipViewBoundsRect.origin];
- [scrollView reflectScroll: clipView];
- }
- else
- {
- delta = NX_Y (&visibleRect) - currentMouse.y;
- if (delta > 0.0)
- {
- [clipView getBounds: &clipViewBoundsRect];
- NX_Y (&clipViewBoundsRect) -= delta;
- [clipView rawScroll: &clipViewBoundsRect.origin];
- [scrollView reflectScroll: clipView];
- }
- }
-
- return self;
- }
-
-
- - _reflectSlide
- {
- // Here's where we actually adjust the cells to reflect the slide. Insert
- // a new cell at the drop row (this moves any rows > than drop row by
- // one). Exchange the dragged cell with the newly inserted cell. Remove
- // the original dragged row. If user has dragged beyond last cell, add to
- // end.
-
- int rowDraggedOffset = 0;
- NXRect rect;
- NXPoint mouseLocation;
-
- [window getMouseLocation: &mouseLocation];
- [self getBounds: &rect];
- [self convertRect: &rect toView: nil];
- if (rowDropped == numRows -1 && mouseLocation.y < NX_Y (&rect))
- rowDropped++;
-
- [window disableFlushWindow];
-
- [self insertRowAt: rowDropped];
- if (rowDropped < rowDragged) { rowDragged++; rowDraggedOffset = 1; }
- selectedRow = rowDropped;
- [self _exchangeRowAt: rowDragged with: rowDropped];
- [self removeRowAt: rowDragged andFree: YES];
-
- rowDragged -= rowDraggedOffset;
-
- [self display];
- [window reenableFlushWindow];
- [window flushWindow];
- return self;
- }
-
-
- - (BOOL) _notifyDelegateWillSlideFromRow: (int) sourceRow
- {
- if (delegate && [delegate respondsTo:
- @selector (slidingMatrix:willSlideFromRow:)])
- return [delegate slidingMatrix: self willSlideFromRow: sourceRow ];
-
- return YES;
- }
-
-
- - (BOOL) _notifyDelegateWillSlideToRow: (int) destinationRow
- {
- if (delegate && [delegate respondsTo:
- @selector (slidingMatrix:willSlideToRow:)])
- return [delegate slidingMatrix: self willSlideToRow: destinationRow];
-
- return YES;
- }
-
-
- - _notifyDelegateDidSlideFromRow: (int) sourceRow toRow: (int) destinationRow
- {
- if (delegate && [delegate respondsTo:
- @selector (slidingMatrix:didSlideFromRow:toRow:)])
- [delegate slidingMatrix:self didSlideFromRow:sourceRow
- toRow:destinationRow];
-
- return self;
- }
-
-
- /*--------------------------------------------------------------------------
- * Initialization and Freeing
- *------------------------------------------------------------------------*/
- - initFrame: (const NXRect*) frameRect
- {
- id buttonCellPrototype = [[ButtonCell allocFromZone: [self zone]]
- initTextCell:"empty"];
- [buttonCellPrototype setIconPosition:NX_ICONLEFT];
- [buttonCellPrototype setBordered:NO];
- [buttonCellPrototype setIcon:"empty"];
- [buttonCellPrototype setAlignment:NX_LEFTALIGNED];
- [buttonCellPrototype setType:NX_ONOFF];
-
- [super initFrame:(const NXRect *)frameRect mode:NX_RADIOMODE
- prototype:buttonCellPrototype numRows:0 numCols:0];
-
- return self;
- }
-
-
- /*--------------------------------------------------------------------------
- * Accessing the deleagate
- *------------------------------------------------------------------------*/
- - delegate
- {
- return delegate;
- }
-
-
- - setDelegate: anObject
- {
- delegate = anObject;
- return self;
- }
-
-
- /*--------------------------------------------------------------------------
- * Event Handling
- *------------------------------------------------------------------------*/
- - mouseDown: (NXEvent*) theEvent
- {
- int column, originalEventMask;
- BOOL scrollViewFlag;
- NXRect cellFrame, visibleRect;
- NXCoord offset;
- NXEvent* nextEvent;
-
- // Is user control-dragging...
- if ( ! (theEvent->flags & NX_CONTROLMASK))
- return [super mouseDown: theEvent];
-
- // Is there a valid row under the mouse...
- currentMouse = theEvent->location;
- [self convertPoint: ¤tMouse fromView: nil];
- [self getRow: &rowDragged andCol: &column forPoint: ¤tMouse];
- if (rowDragged == -1) return [super mouseDown: theEvent];
- if ([self _notifyDelegateWillSlideFromRow: rowDragged] == NO)
- return [super mouseDown: theEvent];
- [self selectCellAt: rowDragged : column];
-
- // Calculate offset (difference between mouse hit y coord and
- // cellFrame y coord).
- [self getCellFrame: &cellFrame at: rowDragged : column];
- offset = currentMouse.y - NX_Y (&cellFrame);
-
- // Adjust currentMouse.y to cell frame boundary.
- currentMouse.y -= offset;
-
- // Prepare for event loop...
- [window makeFirstResponder: window];
- originalEventMask = [window addToEventMask: NX_MOUSEDRAGGEDMASK];
- scrollViewFlag = ([[superview superview] isKindOf:
- [ScrollView class]] ? YES : NO);
- isDragging = YES;
-
- while (isDragging)
- {
- nextEvent = [NXApp getNextEvent:NX_MOUSEUPMASK | NX_MOUSEDRAGGEDMASK];
-
- switch (nextEvent->type)
- {
- case NX_MOUSEDRAGGED:
- isDragging = YES;
- currentMouse = nextEvent->location;
- [self convertPoint: ¤tMouse fromView: nil];
- currentMouse.y -= offset;
- currentMouse.y = BOUND (currentMouse.y, NX_Y (&bounds),
- (NX_Y (&bounds) + NX_HEIGHT (&bounds) - cellSize.height));
- if ([self getVisibleRect: &visibleRect] && scrollViewFlag)
- [self _reflectScroll];
- [self displayFromOpaqueAncestor: &visibleRect :1 :YES];
- break;
-
- case NX_MOUSEUP:
- isDragging = NO;
- currentMouse.y += cellSize.height / 2.0;
-
- if ( ! [self getRow:&rowDropped andCol:&column
- forPoint:¤tMouse])
- {
- currentMouse.y += cellSize.height / 4.0;
- if ( ! [self getRow:&rowDropped andCol:&column
- forPoint:¤tMouse])
- break;
- }
-
- if ([self _notifyDelegateWillSlideToRow: rowDropped])
- {
- [self _reflectSlide];
- [self selectCellAt: rowDropped : column];
- [self _notifyDelegateDidSlideFromRow:rowDragged
- toRow:rowDropped];
- }
-
- break;
- }
- }
-
- [self display];
- [window setEventMask: originalEventMask];
- return self;
- }
-
-
- /*--------------------------------------------------------------------------
- * Drawing Methods
- *------------------------------------------------------------------------*/
- - drawSelf: (const NXRect*)rects : (int) rectCount
- {
- int iterator;
- NXRect rect;
-
- if (! isDragging) return [super drawSelf: rects : rectCount];
-
- [super drawSelf: rects : rectCount];
-
- PSgsave ();
- PSsetgray ([window backgroundGray]);
- for (iterator = 0; iterator < numCols; iterator++)
- {
- [self getCellFrame: &rect at: rowDragged : iterator];
- NXRectFill (&rect);
- }
- PSgrestore();
-
-
- for (iterator = 0; iterator < numCols; iterator++)
- {
- [self getCellFrame: &rect at: rowDragged : iterator];
- NX_Y (&rect) = currentMouse.y;
- [[self cellAt: rowDragged : iterator] drawSelf: &rect inView: self];
- }
-
- return self;
- }
-
-
- @end
-