|
|
Sample Programs from NeXSTEP 3.3
/*--------------------------------------------------------------------------
*
* 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
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.