|
|
1.1 ! root 1: /*-------------------------------------------------------------------------- ! 2: * ! 3: * You may freely copy, distribute, and reuse the code in this example. ! 4: * SHL Systemhouse disclaims any warranty of any kind, expressed or ! 5: * implied, as to its fitness for any particular use. ! 6: * ! 7: * ! 8: * SlidingMatrix ! 9: * ! 10: * Inherits From: Matrix ! 11: * ! 12: * Conforms To: None. ! 13: * ! 14: * Declared In: SlidingMatrix.h ! 15: * ! 16: * ! 17: *------------------------------------------------------------------------*/ ! 18: #import "SlidingMatrix.h" ! 19: ! 20: ! 21: static int rowDropped; ! 22: static int rowDragged; ! 23: static BOOL isDragging; ! 24: static NXPoint currentMouse; ! 25: ! 26: ! 27: #define BOUND(__a,__low,__high) MIN(MAX((__a),(__low)),(__high)) ! 28: ! 29: ! 30: ! 31: ! 32: @implementation SlidingMatrix ! 33: ! 34: /*-------------------------------------------------------------------------- ! 35: * Private Methods ! 36: *------------------------------------------------------------------------*/ ! 37: - _exchangeRowAt: (int) source with: (int) destination ! 38: { ! 39: int iterator; ! 40: id sourceCell, destinationCell; ! 41: ! 42: for (iterator = 0; iterator < numCols; iterator++) ! 43: { ! 44: sourceCell = [self cellAt: source : iterator]; ! 45: destinationCell = [self cellAt: destination : iterator]; ! 46: [self putCell: sourceCell at: destination : iterator]; ! 47: [self putCell: destinationCell at: source : iterator]; ! 48: } ! 49: ! 50: return self; ! 51: } ! 52: ! 53: ! 54: - _reflectScroll ! 55: { ! 56: // If in a ScrollView, reflect scroll if drag is beyond visibleRect... ! 57: ! 58: id scrollView = [superview superview]; ! 59: id clipView = superview; ! 60: NXRect visibleRect, clipViewBoundsRect; ! 61: NXCoord delta; ! 62: ! 63: [self getVisibleRect: &visibleRect]; ! 64: delta = (currentMouse.y + cellSize.height) - (NX_HEIGHT (&visibleRect) + NX_Y ! 65: (&visibleRect)); ! 66: ! 67: if (delta > 0.0) ! 68: { ! 69: [clipView getBounds: &clipViewBoundsRect]; ! 70: NX_Y (&clipViewBoundsRect) += delta; ! 71: [clipView rawScroll: &clipViewBoundsRect.origin]; ! 72: [scrollView reflectScroll: clipView]; ! 73: } ! 74: else ! 75: { ! 76: delta = NX_Y (&visibleRect) - currentMouse.y; ! 77: if (delta > 0.0) ! 78: { ! 79: [clipView getBounds: &clipViewBoundsRect]; ! 80: NX_Y (&clipViewBoundsRect) -= delta; ! 81: [clipView rawScroll: &clipViewBoundsRect.origin]; ! 82: [scrollView reflectScroll: clipView]; ! 83: } ! 84: } ! 85: ! 86: return self; ! 87: } ! 88: ! 89: ! 90: - _reflectSlide ! 91: { ! 92: // Here's where we actually adjust the cells to reflect the slide. Insert ! 93: // a new cell at the drop row (this moves any rows > than drop row by ! 94: // one). Exchange the dragged cell with the newly inserted cell. Remove ! 95: // the original dragged row. If user has dragged beyond last cell, add to ! 96: // end. ! 97: ! 98: int rowDraggedOffset = 0; ! 99: NXRect rect; ! 100: NXPoint mouseLocation; ! 101: ! 102: [window getMouseLocation: &mouseLocation]; ! 103: [self getBounds: &rect]; ! 104: [self convertRect: &rect toView: nil]; ! 105: if (rowDropped == numRows -1 && mouseLocation.y < NX_Y (&rect)) ! 106: rowDropped++; ! 107: ! 108: [window disableFlushWindow]; ! 109: ! 110: [self insertRowAt: rowDropped]; ! 111: if (rowDropped < rowDragged) { rowDragged++; rowDraggedOffset = 1; } ! 112: selectedRow = rowDropped; ! 113: [self _exchangeRowAt: rowDragged with: rowDropped]; ! 114: [self removeRowAt: rowDragged andFree: YES]; ! 115: ! 116: rowDragged -= rowDraggedOffset; ! 117: ! 118: [self display]; ! 119: [window reenableFlushWindow]; ! 120: [window flushWindow]; ! 121: return self; ! 122: } ! 123: ! 124: ! 125: - (BOOL) _notifyDelegateWillSlideFromRow: (int) sourceRow ! 126: { ! 127: if (delegate && [delegate respondsTo: ! 128: @selector (slidingMatrix:willSlideFromRow:)]) ! 129: return [delegate slidingMatrix: self willSlideFromRow: sourceRow ]; ! 130: ! 131: return YES; ! 132: } ! 133: ! 134: ! 135: - (BOOL) _notifyDelegateWillSlideToRow: (int) destinationRow ! 136: { ! 137: if (delegate && [delegate respondsTo: ! 138: @selector (slidingMatrix:willSlideToRow:)]) ! 139: return [delegate slidingMatrix: self willSlideToRow: destinationRow]; ! 140: ! 141: return YES; ! 142: } ! 143: ! 144: ! 145: - _notifyDelegateDidSlideFromRow: (int) sourceRow toRow: (int) destinationRow ! 146: { ! 147: if (delegate && [delegate respondsTo: ! 148: @selector (slidingMatrix:didSlideFromRow:toRow:)]) ! 149: [delegate slidingMatrix:self didSlideFromRow:sourceRow ! 150: toRow:destinationRow]; ! 151: ! 152: return self; ! 153: } ! 154: ! 155: ! 156: /*-------------------------------------------------------------------------- ! 157: * Initialization and Freeing ! 158: *------------------------------------------------------------------------*/ ! 159: - initFrame: (const NXRect*) frameRect ! 160: { ! 161: id buttonCellPrototype = [[ButtonCell allocFromZone: [self zone]] ! 162: initTextCell:"empty"]; ! 163: [buttonCellPrototype setIconPosition:NX_ICONLEFT]; ! 164: [buttonCellPrototype setBordered:NO]; ! 165: [buttonCellPrototype setIcon:"empty"]; ! 166: [buttonCellPrototype setAlignment:NX_LEFTALIGNED]; ! 167: [buttonCellPrototype setType:NX_ONOFF]; ! 168: ! 169: [super initFrame:(const NXRect *)frameRect mode:NX_RADIOMODE ! 170: prototype:buttonCellPrototype numRows:0 numCols:0]; ! 171: ! 172: return self; ! 173: } ! 174: ! 175: ! 176: /*-------------------------------------------------------------------------- ! 177: * Accessing the deleagate ! 178: *------------------------------------------------------------------------*/ ! 179: - delegate ! 180: { ! 181: return delegate; ! 182: } ! 183: ! 184: ! 185: - setDelegate: anObject ! 186: { ! 187: delegate = anObject; ! 188: return self; ! 189: } ! 190: ! 191: ! 192: /*-------------------------------------------------------------------------- ! 193: * Event Handling ! 194: *------------------------------------------------------------------------*/ ! 195: - mouseDown: (NXEvent*) theEvent ! 196: { ! 197: int column, originalEventMask; ! 198: BOOL scrollViewFlag; ! 199: NXRect cellFrame, visibleRect; ! 200: NXCoord offset; ! 201: NXEvent* nextEvent; ! 202: ! 203: // Is user control-dragging... ! 204: if ( ! (theEvent->flags & NX_CONTROLMASK)) ! 205: return [super mouseDown: theEvent]; ! 206: ! 207: // Is there a valid row under the mouse... ! 208: currentMouse = theEvent->location; ! 209: [self convertPoint: ¤tMouse fromView: nil]; ! 210: [self getRow: &rowDragged andCol: &column forPoint: ¤tMouse]; ! 211: if (rowDragged == -1) return [super mouseDown: theEvent]; ! 212: if ([self _notifyDelegateWillSlideFromRow: rowDragged] == NO) ! 213: return [super mouseDown: theEvent]; ! 214: [self selectCellAt: rowDragged : column]; ! 215: ! 216: // Calculate offset (difference between mouse hit y coord and ! 217: // cellFrame y coord). ! 218: [self getCellFrame: &cellFrame at: rowDragged : column]; ! 219: offset = currentMouse.y - NX_Y (&cellFrame); ! 220: ! 221: // Adjust currentMouse.y to cell frame boundary. ! 222: currentMouse.y -= offset; ! 223: ! 224: // Prepare for event loop... ! 225: [window makeFirstResponder: window]; ! 226: originalEventMask = [window addToEventMask: NX_MOUSEDRAGGEDMASK]; ! 227: scrollViewFlag = ([[superview superview] isKindOf: ! 228: [ScrollView class]] ? YES : NO); ! 229: isDragging = YES; ! 230: ! 231: while (isDragging) ! 232: { ! 233: nextEvent = [NXApp getNextEvent:NX_MOUSEUPMASK | NX_MOUSEDRAGGEDMASK]; ! 234: ! 235: switch (nextEvent->type) ! 236: { ! 237: case NX_MOUSEDRAGGED: ! 238: isDragging = YES; ! 239: currentMouse = nextEvent->location; ! 240: [self convertPoint: ¤tMouse fromView: nil]; ! 241: currentMouse.y -= offset; ! 242: currentMouse.y = BOUND (currentMouse.y, NX_Y (&bounds), ! 243: (NX_Y (&bounds) + NX_HEIGHT (&bounds) - cellSize.height)); ! 244: if ([self getVisibleRect: &visibleRect] && scrollViewFlag) ! 245: [self _reflectScroll]; ! 246: [self displayFromOpaqueAncestor: &visibleRect :1 :YES]; ! 247: break; ! 248: ! 249: case NX_MOUSEUP: ! 250: isDragging = NO; ! 251: currentMouse.y += cellSize.height / 2.0; ! 252: ! 253: if ( ! [self getRow:&rowDropped andCol:&column ! 254: forPoint:¤tMouse]) ! 255: { ! 256: currentMouse.y += cellSize.height / 4.0; ! 257: if ( ! [self getRow:&rowDropped andCol:&column ! 258: forPoint:¤tMouse]) ! 259: break; ! 260: } ! 261: ! 262: if ([self _notifyDelegateWillSlideToRow: rowDropped]) ! 263: { ! 264: [self _reflectSlide]; ! 265: [self selectCellAt: rowDropped : column]; ! 266: [self _notifyDelegateDidSlideFromRow:rowDragged ! 267: toRow:rowDropped]; ! 268: } ! 269: ! 270: break; ! 271: } ! 272: } ! 273: ! 274: [self display]; ! 275: [window setEventMask: originalEventMask]; ! 276: return self; ! 277: } ! 278: ! 279: ! 280: /*-------------------------------------------------------------------------- ! 281: * Drawing Methods ! 282: *------------------------------------------------------------------------*/ ! 283: - drawSelf: (const NXRect*)rects : (int) rectCount ! 284: { ! 285: int iterator; ! 286: NXRect rect; ! 287: ! 288: if (! isDragging) return [super drawSelf: rects : rectCount]; ! 289: ! 290: [super drawSelf: rects : rectCount]; ! 291: ! 292: PSgsave (); ! 293: PSsetgray ([window backgroundGray]); ! 294: for (iterator = 0; iterator < numCols; iterator++) ! 295: { ! 296: [self getCellFrame: &rect at: rowDragged : iterator]; ! 297: NXRectFill (&rect); ! 298: } ! 299: PSgrestore(); ! 300: ! 301: ! 302: for (iterator = 0; iterator < numCols; iterator++) ! 303: { ! 304: [self getCellFrame: &rect at: rowDragged : iterator]; ! 305: NX_Y (&rect) = currentMouse.y; ! 306: [[self cellAt: rowDragged : iterator] drawSelf: &rect inView: self]; ! 307: } ! 308: ! 309: return self; ! 310: } ! 311: ! 312: ! 313: @end
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.