|
|
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.