home *** CD-ROM | disk | FTP | other *** search
- //=============================================================================
- //
- // Copyright (C) 1995, 1996 by Paul S. McCarthy and Eric Sunshine.
- // Written by Paul S. McCarthy and Eric Sunshine.
- // All Rights Reserved.
- //
- // This notice may not be removed from this source code.
- //
- // This object is included in the MiscKit by permission from the authors
- // and its use is governed by the MiscKit license, found in the file
- // "License.rtf" in the MiscKit distribution. Please refer to that file
- // for a list of all applicable permissions and restrictions.
- //
- //=============================================================================
- //-----------------------------------------------------------------------------
- // MiscTableView.M
- //
- // General-purpose 2-D display object that works with the
- // MiscTableScroll to provide row/column sizing and dragging.
- //
- // This object is responsible for drawing, mouse and keyboard
- // events in the content portion of the display.
- //
- //-----------------------------------------------------------------------------
- //-----------------------------------------------------------------------------
- // $Id: MiscTableView.M,v 1.8 96/01/13 23:46:17 zarnuk Exp $
- // $Log: MiscTableView.M,v $
- // Revision 1.8 96/01/13 23:46:17 zarnuk
- // All allocations are now done from [self zone].
- //
- // Revision 1.7 95/10/20 00:13:39 sunshine
- // Was including MiscTableScroll.h with "" instead of <>.
- //
- // Revision 1.6 95/10/19 05:42:00 sunshine
- // Now sends -setSelFont: to FontManager at appropriate times so that font
- // selection in FontManager is up-to-date.
- //
- // Revision 1.5 95/10/08 16:12:30 zarnuk
- // Cell* --> id.
- //-----------------------------------------------------------------------------
- #import "MiscTableView.h"
- #import "MiscHighlightTracker.h"
- #import "MiscListTracker.h"
- #import "MiscRadioTracker.h"
- #import "MiscSparseSet.h"
- #import "MiscTableBorder.h"
- #import "MiscTableFocus.h"
- #import <misckit/MiscTableScroll.h>
-
- #import <new.h>
-
- extern "Objective-C" {
- #import <appkit/Application.h>
- #import <appkit/Cell.h>
- #import <appkit/FontManager.h>
- #import <appkit/timer.h>
- }
-
- extern "C" {
- #import <math.h> // for floor()
- }
-
-
- //----------------------------------------------------------------------------
- // startTimer
- //----------------------------------------------------------------------------
- static inline void startTimer( NXTrackingTimer*& timer )
- {
- if (timer == 0)
- timer = NXBeginTimer( 0, 0.1, 0.1 );
- }
-
-
- //----------------------------------------------------------------------------
- // stopTimer
- //----------------------------------------------------------------------------
- static inline void stopTimer( NXTrackingTimer*& timer )
- {
- if (timer)
- {
- NXEndTimer( timer );
- timer = 0;
- }
- }
-
-
-
- //=============================================================================
- // IMPLEMENTATION
- //=============================================================================
- @implementation MiscTableView
-
- //-----------------------------------------------------------------------------
- // - initFrame:
- //
- // NOTE *1*: Default behavior is to take keyboard-cursor information from
- // the row-border.
- //-----------------------------------------------------------------------------
- - initFrame:(NXRect const*)frameRect
- scroll:(MiscTableScroll*)i_scroll
- colInfo:(MiscTableBorder*)i_col_border
- rowInfo:(MiscTableBorder*)i_row_border
- {
- NXZone* const z = [self zone];
- NXRect rect;
- if (frameRect != 0)
- rect.origin = frameRect->origin;
- else
- {
- rect.origin.x = 0;
- rect.origin.y = 0;
- }
-
- rect.size.width = i_col_border->totalSize();
- rect.size.height = i_row_border->totalSize();
-
- [super initFrame:&rect];
- [self setFlipped:YES];
- [self setClipping:NO];
- [self setOpaque:YES];
-
- scroll = i_scroll;
- col_border = i_col_border;
- row_border = i_row_border;
- tracker_border = MISC_ROW_BORDER; // NOTE *1*
-
- oldColSel = new( NXZoneMalloc(z,sizeof(*oldColSel)) ) MiscSparseSet;
- oldRowSel = new( NXZoneMalloc(z,sizeof(*oldRowSel)) ) MiscSparseSet;
- [self setSelectionMode: [scroll selectionMode]];
-
- focuser = [[MiscTableFocus allocFromZone:z] initOwner: self];
- return self;
- }
-
-
- //-----------------------------------------------------------------------------
- // - free
- //-----------------------------------------------------------------------------
- - free
- {
- [focuser free];
- [tracker free];
- NXZone* const z = [self zone];
- if (oldColSel != 0)
- {
- oldColSel->MiscSparseSet::~MiscSparseSet();
- NXZoneFree( z, oldColSel );
- }
- if (oldRowSel != 0)
- {
- oldRowSel->MiscSparseSet::~MiscSparseSet();
- NXZoneFree( z, oldRowSel );
- }
- return [super free];
- }
-
-
- //-----------------------------------------------------------------------------
- // TYPE VARIATIONS
- //-----------------------------------------------------------------------------
-
- - (MiscTableBorder*) borderFor: (MiscBorderType)b
- { return (b == MISC_ROW_BORDER ? row_border : col_border); }
- - (MiscBorderType) otherBorder: (MiscBorderType)b
- { return (b == MISC_ROW_BORDER ? MISC_COL_BORDER : MISC_ROW_BORDER); }
- - (BOOL) isHorz: (MiscBorderType)b { return (b == MISC_COL_BORDER); }
-
- - (NXCoord) border:(MiscBorderType)b pointX: (NXPoint const*) point
- { return [self isHorz:b] ? point->x : point->y; }
- - (NXCoord) border:(MiscBorderType)b pointY: (NXPoint const*) point
- { return [self isHorz:b] ? point->y : point->x; }
-
- - (NXCoord) border:(MiscBorderType)b rectMinX:(NXRect const*)frameRect
- { return [self isHorz:b] ? NX_X(frameRect) : NX_Y(frameRect); }
- - (NXCoord) border:(MiscBorderType)b rectMaxX:(NXRect const*)frameRect
- { return [self isHorz:b] ? NX_MAXX(frameRect) : NX_MAXY(frameRect); }
- - (NXCoord) border:(MiscBorderType)b rectMinY:(NXRect const*)frameRect
- { return [self isHorz:b] ? NX_Y(frameRect) : NX_X(frameRect); }
- - (NXCoord) border:(MiscBorderType)b rectMaxY:(NXRect const*)frameRect
- { return [self isHorz:b] ? NX_MAXY(frameRect) : NX_MAXX(frameRect); }
- - (NXCoord) border:(MiscBorderType)b rectWidth:(NXRect const*)frameRect
- { return [self isHorz:b] ? NX_WIDTH(frameRect) : NX_HEIGHT(frameRect); }
- - (NXCoord) border:(MiscBorderType)b rectHeight:(NXRect const*)frameRect
- { return [self isHorz:b] ? NX_HEIGHT(frameRect) : NX_WIDTH(frameRect); }
-
- - (void) border:(MiscBorderType)b setRect:(NXRect*)rect minX:(NXCoord)x
- { if ([self isHorz:b]) NX_X(rect) = x; else NX_Y(rect) = x; }
- - (void) border:(MiscBorderType)b setRect:(NXRect*)rect minY:(NXCoord)y
- { if ([self isHorz:b]) NX_Y(rect) = y; else NX_X(rect) = y; }
- - (void) border:(MiscBorderType)b setRect:(NXRect*)rect width:(NXCoord)width
- { if ([self isHorz:b]) NX_WIDTH(rect) = width;
- else NX_HEIGHT(rect) = width; }
- - (void) border:(MiscBorderType)b setRect:(NXRect*)rect height:(NXCoord)height
- { if ([self isHorz:b]) NX_HEIGHT(rect) = height;
- else NX_WIDTH(rect) = height; }
-
-
- //-----------------------------------------------------------------------------
- // drewCellAt:border:oldSel:
- //
- // Keeps the old selection sets up to date whenever we draw a cell. This
- // way -reflectSelection has valid data to work from.
- //-----------------------------------------------------------------------------
- - (void) drewCellAt: (MiscCoord_V)slot border: (MiscTableBorder*)b
- oldSel: (MiscSparseSet*)oldSel
- {
- BOOL isSelected = b->selectionSet().contains( slot );
- if (isSelected != oldSel->contains(slot))
- {
- if (isSelected)
- oldSel->add( slot );
- else
- oldSel->remove( slot );
- }
- }
-
-
- //-----------------------------------------------------------------------------
- // drewCellAt::
- //-----------------------------------------------------------------------------
- - (void) drewCellAt: (MiscCoord_V)r : (MiscCoord_V)c
- {
- [self drewCellAt:r border:row_border oldSel: oldRowSel];
- [self drewCellAt:c border:col_border oldSel: oldColSel];
- }
-
-
- //-----------------------------------------------------------------------------
- // - getCellFrame:at:: -- Visual coords
- //-----------------------------------------------------------------------------
- - getCellFrame: (NXRect*)r at: (int)row : (int)col
- {
- if (row < 0 || row >= row_border->count() ||
- col < 0 || col >= col_border->count())
- NXSetRect( r, 0, 0, 0, 0 );
- else
- NXSetRect( r, col_border->getOffset(col), row_border->getOffset(row),
- col_border->effectiveSize(col),row_border->effectiveSize(row) );
- return self;
- }
-
-
- //-----------------------------------------------------------------------------
- // - getVisFrame:at:from:
- //-----------------------------------------------------------------------------
- - (void) getVisFrame:(NXRect*)r at:(MiscCoord_V)slot from:(MiscBorderType)bdr
- {
- MiscTableBorder* const b = [self borderFor:bdr];
- [self getVisibleRect: r];
- [self border:bdr setRect:r minX:b->getOffset(slot)];
- [self border:bdr setRect:r width:b->effectiveSize(slot)];
- }
-
-
- //-----------------------------------------------------------------------------
- // - firstVisibleSlot:
- //-----------------------------------------------------------------------------
- - (MiscCoord_V) firstVisibleSlot: (MiscBorderType)bdr
- {
- MiscCoord_V ret = -1;
- MiscTableBorder* const b = [self borderFor:bdr];
- if (b->count() > 0)
- {
- NXRect r; [self getVisibleRect: &r];
- MiscPixels vis_origin = MiscPixels( [self border:bdr rectMinX:&r] );
- ret = b->visualForOffset( vis_origin );
- MiscPixels slot_origin = b->getOffset( ret );
- if (slot_origin < vis_origin)
- ret++;
- }
- return ret;
- }
-
-
- //-----------------------------------------------------------------------------
- // - acceptsFirstMouse
- //-----------------------------------------------------------------------------
- - (BOOL) acceptsFirstMouse
- {
- return YES;
- }
-
-
- //-----------------------------------------------------------------------------
- // - acceptsFirstResponder
- //-----------------------------------------------------------------------------
- - (BOOL) acceptsFirstResponder
- {
- return YES;
- }
-
-
- //-----------------------------------------------------------------------------
- // - setFocusFrame
- //-----------------------------------------------------------------------------
- - (void) setFocusFrame
- {
- NXRect r = {{ 0,0 }, { 0,0 }};
- if (row_border->count() > 0 && col_border->count() > 0)
- {
- MiscTableBorder* const b = [self borderFor: tracker_border];
- MiscCoord_V focusSlot = b->getCursor();
- if (focusSlot < 0 || focusSlot >= b->count())
- focusSlot = (b->hasSelection() ? b->selectedSlot() :
- [self firstVisibleSlot: tracker_border]);
- b->setCursor( focusSlot );
- [self getVisFrame:&r at:focusSlot from:tracker_border];
- }
- [focuser setFrame: &r];
- }
-
-
- //-----------------------------------------------------------------------------
- // - startFocus
- //-----------------------------------------------------------------------------
- - (void) startFocus
- {
- [self setFocusFrame];
- [focuser startFocus];
- }
-
-
- //-----------------------------------------------------------------------------
- // - stopFocus
- //-----------------------------------------------------------------------------
- - (void) stopFocus
- {
- [focuser stopFocus];
- }
-
-
- //-----------------------------------------------------------------------------
- // - becomeFirstResponder
- //-----------------------------------------------------------------------------
- - becomeFirstResponder
- {
- Window* win = [self window];
- if (win && [win isKeyWindow])
- {
- [self startFocus];
- [[FontManager new] setSelFont:[scroll font] isMultiple:NO];
- }
- return self;
- }
-
-
- //-----------------------------------------------------------------------------
- // - resignFirstResponder
- //-----------------------------------------------------------------------------
- - resignFirstResponder
- {
- [self stopFocus];
- return self;
- }
-
-
- //-----------------------------------------------------------------------------
- // - becomeKeyWindow
- //-----------------------------------------------------------------------------
- - becomeKeyWindow
- {
- [self startFocus];
- [[FontManager new] setSelFont:[scroll font] isMultiple:NO];
- return self;
- }
-
-
- //-----------------------------------------------------------------------------
- // - resignKeyWindow
- //-----------------------------------------------------------------------------
- - resignKeyWindow
- {
- [self stopFocus];
- return self;
- }
-
-
- //-----------------------------------------------------------------------------
- // - windowChanged:
- //-----------------------------------------------------------------------------
- - windowChanged: newWindow
- {
- [self stopFocus];
- return self;
- }
-
-
- //-----------------------------------------------------------------------------
- // - resetCursorRects
- //
- // NOTE: This catches srolling. The blinking cursor is always placed
- // within the visibleRect. After scrolling the visibleRect has
- // changed so we need to readjust the cursor frame.
- //-----------------------------------------------------------------------------
- - resetCursorRects
- {
- [self setFocusFrame];
- return self;
- }
-
-
- //-----------------------------------------------------------------------------
- // - sizeTo::
- //-----------------------------------------------------------------------------
- - sizeTo: (NXCoord)width : (NXCoord)height
- {
- [super sizeTo: width : height];
- [self setFocusFrame];
- return self;
- }
-
-
- //-----------------------------------------------------------------------------
- // - setFrame:
- //-----------------------------------------------------------------------------
- - setFrame: (NXRect const*)r
- {
- [super setFrame: r];
- [self setFocusFrame];
- return self;
- }
-
-
- //-----------------------------------------------------------------------------
- // - adjustSize
- //-----------------------------------------------------------------------------
- - (void) adjustSize
- {
- [self sizeTo: col_border->totalSize() : row_border->totalSize()];
- }
-
-
- //-----------------------------------------------------------------------------
- // - scrollCellToVisible:: -- Physical coords
- //-----------------------------------------------------------------------------
- - (void) scrollCellToVisible: (int)row : (int) col
- {
- NXRect r;
- [self getCellFrame: &r at:
- row_border->physicalToVisual(row) :
- col_border->physicalToVisual(col)];
- [self scrollRectToVisible: &r];
- }
-
-
- //-----------------------------------------------------------------------------
- // - border:scrollToVisible: -- Physical coord
- //-----------------------------------------------------------------------------
- - (void) border: (MiscBorderType)bdr scrollToVisible: (MiscCoord_P)slot
- {
- NXRect r;
- MiscTableBorder* const b = [self borderFor:bdr];
- [self getVisFrame:&r at:b->physicalToVisual(slot) from:bdr];
- [self scrollRectToVisible:&r];
- }
-
-
- //-----------------------------------------------------------------------------
- // - scrollRowToVisible: -- Physical coord
- //-----------------------------------------------------------------------------
- - (void) scrollRowToVisible: (int)row
- {
- [self border:MISC_ROW_BORDER scrollToVisible:row];
- }
-
-
- //-----------------------------------------------------------------------------
- // - scrollColToVisible: -- Physical coord
- //-----------------------------------------------------------------------------
- - (void) scrollColToVisible: (int)col
- {
- [self border:MISC_COL_BORDER scrollToVisible:col];
- }
-
-
- //-----------------------------------------------------------------------------
- // - cMin:cMax:rMin:rMax:forRect:
- //-----------------------------------------------------------------------------
- - (void) cMin: (MiscCoord_V*)cmin cMax: (MiscCoord_V*)cmax
- rMin: (MiscCoord_V*)rmin rMax: (MiscCoord_V*)rmax
- forRect: (NXRect const*) nxrect
- {
- *cmin = col_border->visualForOffset( (MiscPixels) nxrect->origin.x );
- *cmax = col_border->visualForOffset(
- (MiscPixels) (nxrect->origin.x + nxrect->size.width) - 1 );
- *rmin = row_border->visualForOffset( (MiscPixels) nxrect->origin.y );
- *rmax = row_border->visualForOffset(
- (MiscPixels) (nxrect->origin.y + nxrect->size.height) - 1 );
- }
-
-
- //-----------------------------------------------------------------------------
- // - drawRect:
- //-----------------------------------------------------------------------------
- - (void) drawRect: (NXRect const*) nxrect
- {
- MiscCoord_V c, cmin, cmax;
- MiscCoord_V r, rmin, rmax;
- [self cMin:&cmin cMax:&cmax rMin:&rmin rMax:&rmax forRect:nxrect];
-
- if (cmin >= 0 && cmax >= 0 && rmin >= 0 && rmax >= 0)
- {
- NXCoord const x0 = floor( (float) col_border->getOffset( cmin ) );
- NXCoord const y0 = floor( (float) row_border->getOffset( rmin ) );
- NXRect rect = { {x0,y0}, {0,0} };
-
- for (r = rmin; r <= rmax; r++)
- {
- rect.size.height = floor( (float) row_border->effectiveSize(r) );
- for (c = cmin; c <= cmax; c++)
- {
- rect.size.width = floor( (float)col_border->effectiveSize(c) );
- id cell = [scroll cellAt: row_border->visualToPhysical(r) :
- col_border->visualToPhysical(c)];
- [cell drawSelf:&rect inView:self];
- [self drewCellAt:r:c];
- rect.origin.x = floor( rect.origin.x + rect.size.width );
- }
- rect.origin.x = x0;
- rect.origin.y = floor( rect.origin.y + rect.size.height );
- }
- }
- }
-
-
- //-----------------------------------------------------------------------------
- // - drawSelf::
- //-----------------------------------------------------------------------------
- - drawSelf: (NXRect const*) rects :(int) nrects
- {
- if (nrects == 1)
- [self drawRect: rects];
- else if (nrects == 3)
- {
- [self drawRect: ++rects];
- [self drawRect: ++rects];
- }
- return self;
- }
-
-
- //-----------------------------------------------------------------------------
- // - drawCellAt::updateSel: -- Physical coords
- //-----------------------------------------------------------------------------
- - (void) drawCellAt: (int)row : (int)col updateSel: (BOOL)updateSel
- {
- if ([self canDraw] &&
- row >= 0 && row < row_border->count() &&
- col >= 0 && col < col_border->count())
- {
- NXRect v; [self getVisibleRect: &v];
- MiscCoord_V const vRow = row_border->physicalToVisual(row);
- MiscCoord_V const vCol = col_border->physicalToVisual(col);
-
- NXRect const r = {
- { col_border->getOffset(vCol), row_border->getOffset(vRow) },
- { col_border->effectiveSize(vCol), row_border->effectiveSize(vRow) }};
-
- if (NXIntersectsRect( &r, &v ))
- {
- id const cell = [scroll cellAt: row : col];
- BOOL const didLock = ![self isFocusView];
- if (didLock) [self lockFocus];
- [cell drawSelf: &r inView: self];
- if (updateSel)
- [self drewCellAt: vRow : vCol];
- if (didLock) [self unlockFocus];
- }
- }
- }
-
-
- //-----------------------------------------------------------------------------
- // - drawCellAt:: -- Physical coords
- //-----------------------------------------------------------------------------
- - drawCellAt: (int)row : (int)col
- {
- [self drawCellAt:row:col updateSel:YES];
- return self;
- }
-
-
- //-----------------------------------------------------------------------------
- // - drawRow: -- Physical coord
- //-----------------------------------------------------------------------------
- - drawRow: (int)row
- {
- if ([self canDraw] && row >= 0 && row < row_border->count())
- {
- MiscCoord_V const vRow = row_border->physicalToVisual(row);
-
- NXRect r;
- [self getVisibleRect: &r];
- r.origin.y = row_border->getOffset(vRow);
- r.size.height = row_border->effectiveSize(vRow);
-
- BOOL const didLock = ![self isFocusView];
- if (didLock) [self lockFocus];
- [self drawRect: &r];
- if (didLock) [self unlockFocus];
- }
- return self;
- }
-
-
- //-----------------------------------------------------------------------------
- // - drawCol: -- Physical coord
- //-----------------------------------------------------------------------------
- - drawCol: (int)col
- {
- if ([self canDraw] && col >= 0 && col < col_border->count())
- {
- MiscCoord_V const vCol = col_border->physicalToVisual(col);
-
- NXRect r;
- [self getVisibleRect: &r];
- r.origin.x = col_border->getOffset(vCol);
- r.size.width = col_border->effectiveSize(vCol);
-
- BOOL const didLock = ![self isFocusView];
- if (didLock) [self lockFocus];
- [self drawRect: &r];
- if (didLock) [self unlockFocus];
- }
- return self;
- }
-
-
- //-----------------------------------------------------------------------------
- // - setSelectionMode:
- //-----------------------------------------------------------------------------
- - (void) setSelectionMode: (MiscSelectionMode) mode
- {
- NXZone* const z = [self zone];
- if (tracker != 0)
- [tracker free];
- switch (mode)
- {
- case MISC_LIST_MODE:
- tracker = [MiscListTracker allocFromZone:z];
- break;
- case MISC_RADIO_MODE:
- tracker = [MiscRadioTracker allocFromZone:z];
- break;
- case MISC_HIGHLIGHT_MODE:
- tracker = [MiscHighlightTracker allocFromZone:z];
- break;
- }
- [tracker initBorder: [self borderFor:tracker_border]];
- }
-
-
- //-----------------------------------------------------------------------------
- // - reflectSelection
- //-----------------------------------------------------------------------------
- - (void) reflectSelection
- {
- if ([self canDraw])
- {
- MiscSparseSet const& newColSel = col_border->selectionSet();
- MiscSparseSet const& newRowSel = row_border->selectionSet();
-
- MiscCoord_V cmin, cmax;
- MiscCoord_V rmin, rmax;
- NXRect vis; [self getVisibleRect: &vis];
- [self cMin:&cmin cMax:&cmax rMin:&rmin rMax:&rmax forRect:&vis];
-
- [window disableFlushWindow];
- BOOL locked = NO;
- for (MiscCoord_V r = rmin; r <= rmax; r++)
- {
- BOOL rowWasOn = oldRowSel->contains(r);
- BOOL rowIsOn = newRowSel.contains(r);
- for (MiscCoord_V c = cmin; c <= cmax; c++)
- {
- BOOL wasOn = rowWasOn || oldColSel->contains(c);
- BOOL isOn = rowIsOn || newColSel.contains(c);
- if (isOn != wasOn)
- {
- if (!locked)
- {
- locked = YES;
- [self lockFocus];
- }
- MiscCoord_P const pCol = col_border->visualToPhysical(c);
- MiscCoord_P const pRow = row_border->visualToPhysical(r);
- [self drawCellAt: pRow : pCol updateSel: NO];
- }
- }
- }
- if (locked)
- [self unlockFocus];
- [[window reenableFlushWindow] flushWindow];
-
- *oldColSel = newColSel;
- *oldRowSel = newRowSel;
- }
- }
-
-
- //-----------------------------------------------------------------------------
- // - trackBy:
- //-----------------------------------------------------------------------------
- - (void) trackBy: (MiscBorderType)b
- {
- tracker_border = b;
- [self setFocusFrame];
- }
-
-
- //-----------------------------------------------------------------------------
- // - trackingBy
- //-----------------------------------------------------------------------------
- - (MiscBorderType) trackingBy
- {
- return tracker_border;
- }
-
-
- //-----------------------------------------------------------------------------
- // - reflectCursor
- //-----------------------------------------------------------------------------
- - (void) reflectCursor
- {
- [self setFocusFrame];
- }
-
-
- //-----------------------------------------------------------------------------
- // constrainSlot:inBorder:
- //-----------------------------------------------------------------------------
- - (MiscCoord_V) constrainSlot:(MiscCoord_V)s inBorder: (MiscTableBorder*)b
- {
- if (s < 0)
- s = 0;
- else if (s >= b->count())
- s = b->count() - 1;
- return s;
- }
-
-
- //-----------------------------------------------------------------------------
- // - mouseDown:
- //-----------------------------------------------------------------------------
- - mouseDown: (NXEvent*) p
- {
- BOOL doubleClicked = (p->data.mouse.click > 1);
- NXPoint evpt = p->location;
- [self convertPoint: &evpt fromView: 0];
- MiscTableBorder* const b = [self borderFor:tracker_border];
- MiscCoord_V slot = b->visualForOffset(
- MiscPixels([self border:tracker_border pointX:&evpt]) );
- int const WANTED = (NX_MOUSEUPMASK | NX_MOUSEDRAGGEDMASK | NX_TIMERMASK);
-
- [focuser stopFocus];
- [tracker mouseDown: p atPos: slot];
- [self borderFor: [self otherBorder:tracker_border]]->selectionSet().empty();
- [scroll reflectSelection];
-
- int old_mask = [window addToEventMask:NX_MOUSEDRAGGEDMASK];
- NXTrackingTimer* timer = 0;
- startTimer( timer );
- NXEvent lastEvent = *p;
-
- for (;;)
- {
- p = [NXApp getNextEvent: WANTED];
- if (p == 0 || p->type == NX_MOUSEUP)
- break;
- else if (p->type == NX_TIMER)
- [self autoscroll: &lastEvent];
- else
- lastEvent = *p;
-
- NXPoint new_loc = lastEvent.location;
- [self convertPoint:&new_loc fromView:0];
- MiscPixels const offset =
- MiscPixels( [self border:tracker_border pointX:&new_loc] );
- MiscCoord_V const new_slot =
- (offset < [self border:tracker_border rectMaxX:&bounds] ?
- b->visualForOffset(offset) : b->count());
- if (new_slot != slot)
- {
- slot = new_slot;
- [tracker mouseDragged: p atPos: slot];
- [scroll reflectSelection];
- }
- }
-
- stopTimer( timer );
- [window setEventMask:old_mask];
-
- [tracker mouseUp: p atPos: slot];
- [scroll reflectSelection];
- [scroll border: tracker_border setCursor:
- b->visualToPhysical([self constrainSlot:slot inBorder:b])];
- [scroll selectText: self];
- [focuser startFocus];
-
- if ([scroll isEnabled])
- {
- if (doubleClicked)
- [scroll sendDoubleAction];
- else
- [scroll sendAction];
- }
- return self;
- }
-
-
- //-----------------------------------------------------------------------------
- // - moveFocusBy:
- //-----------------------------------------------------------------------------
- - (void) moveFocusBy: (int) delta
- {
- MiscTableBorder* const b = [self borderFor: tracker_border];
- int const lim = b->count();
- if ([focuser isShowingFocus] && lim > 0)
- {
- MiscCoord_V focusSlot = b->getCursor() + delta;
- if (focusSlot < 0)
- focusSlot = lim - 1;
- else if (focusSlot >= lim)
- focusSlot = 0;
- b->setCursor( focusSlot );
- [self border:tracker_border scrollToVisible:
- b->visualToPhysical(focusSlot)];
- [self setFocusFrame];
- }
- }
-
-
- //-----------------------------------------------------------------------------
- // - gotoNextText
- //-----------------------------------------------------------------------------
- - (void) gotoNextText
- {
- id targ = [scroll nextText];
- if (targ && [targ respondsTo: @selector(selectText:)])
- [targ selectText: scroll];
- }
-
-
- //-----------------------------------------------------------------------------
- // - gotoPreviousText
- //-----------------------------------------------------------------------------
- - (void) gotoPreviousText
- {
- id targ = [scroll previousText];
- if (targ && [targ respondsTo: @selector(selectText:)])
- [targ selectText: scroll];
- }
-
-
- //-----------------------------------------------------------------------------
- // - keyboardSelect:
- //-----------------------------------------------------------------------------
- - (void) keyboardSelect: (NXEvent const*)p
- {
- [tracker keyDown: p atPos: [self borderFor:tracker_border]->getCursor()];
- [scroll borderClearSelection:[self otherBorder: tracker_border]];
- [scroll reflectSelection];
- if ([scroll isEnabled])
- [scroll sendAction];
- }
-
-
- //-----------------------------------------------------------------------------
- // - keyboardPerform
- //-----------------------------------------------------------------------------
- - (void) keyboardPerform
- {
- if ([scroll isEnabled])
- [scroll sendDoubleAction];
- }
-
-
- //-----------------------------------------------------------------------------
- // - keyDown:
- //-----------------------------------------------------------------------------
- - keyDown: (NXEvent*) p
- {
- enum
- {
- K_TAB = '\t',
- K_BTAB = 0x19,
- K_RETURN= '\r',
- K_SPACE = ' ' ,
- K_LEFT = 0xac,
- K_UP = 0xad,
- K_RIGHT = 0xae,
- K_DOWN = 0xaf,
- };
-
- if ((p->flags & NX_COMMANDMASK) == 0)
- {
- switch (p->data.key.charCode)
- {
- case K_UP : [self moveFocusBy: -1 ]; break;
- case K_DOWN : [self moveFocusBy: 1 ]; break;
- case K_LEFT : [self moveFocusBy: -1 ]; break;
- case K_RIGHT : [self moveFocusBy: 1 ]; break;
- case K_TAB : [self gotoNextText ]; break;
- case K_BTAB : [self gotoPreviousText ]; break;
- case K_SPACE : [self keyboardSelect: p ]; break;
- case K_RETURN : [self keyboardPerform ]; break;
- }
- }
- return self;
- }
-
- @end
-