/* ExtendedTableView.m Copyright (C) 2001 Pierre-Yves Rivaille This library is free software; you can redistribute it and/or modify it under the terms of the GNU Library General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This library is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Library General Public License for more details. You should have received a copy of the GNU Library General Public License along with this library; see the file COPYING.LIB. If not, write to the Free Software Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ #import #import "ExtendedTableView.h" #import "ExtendedTableColumn.h" @implementation ExtendedTableView - (void) mouseDown: (NSEvent *)theEvent { NSPoint location = [theEvent locationInWindow]; NSTableColumn *tb; #ifdef MACOSX int _clickedRow; int _clickedColumn; int _numberOfRows = [self frame].size.height / _rowHeight; int _numberOfColumns = [_tableColumns count]; #endif // // Pathological case -- ignore mouse down // if ((_numberOfRows == 0) || (_numberOfColumns == 0)) { [super mouseDown: theEvent]; return; } // Determine row and column which were clicked location = [self convertPoint: location fromView: nil]; _clickedRow = [self rowAtPoint: location]; _clickedColumn = [self columnAtPoint: location]; if (_clickedRow == -1 || _clickedColumn == -1) return; tb = [_tableColumns objectAtIndex: _clickedColumn]; if ([tb shouldUseMouse] == YES) { NSApplication *theApp = [NSApplication sharedApplication]; BOOL mouseUp = NO, done = NO; NSEvent *e; int oldActionMask; NSPoint location; unsigned int event_mask = NSLeftMouseDownMask | NSLeftMouseUpMask | NSMouseMovedMask | NSLeftMouseDraggedMask | NSRightMouseDraggedMask; NSCell *mouseCell; NSRect mouseCellFrame; mouseCell = [[_tableColumns objectAtIndex: _clickedColumn] dataCellForRow: _clickedRow]; mouseCellFrame = [self frameOfCellAtColumn: _clickedColumn row: _clickedRow]; [mouseCell setObjectValue: [_dataSource tableView: self objectValueForTableColumn: tb row: _clickedRow]]; if ([tb shouldUseAndSetState] == YES) [mouseCell setState: [_dataSource tableView: self stateForTableColumn: tb row: _clickedRow]]; if ([tb shouldUseTag] == YES) [mouseCell setTag: [_dataSource tableView: self tagForTableColumn: tb row: _clickedRow]]; #ifdef MACOSX if (_tvFlags.delegateWillDisplayCell) #else if (_del_responds) #endif { [_delegate tableView: self willDisplayCell: mouseCell forTableColumn: tb row: _clickedRow]; } if ([mouseCell isEnabled] == NO) return; if ([mouseCell isContinuous]) oldActionMask = [mouseCell sendActionOn: 0]; else oldActionMask = [mouseCell sendActionOn: NSPeriodicMask]; // [_window _captureMouse: self]; e = theEvent; while (!done) // loop until mouse goes up { location = [e locationInWindow]; location = [self convertPoint: location fromView: nil]; // ask the cell to track the mouse only // if the mouse is within the cell if (NSMouseInRect(location, mouseCellFrame, YES)) { [mouseCell highlight: YES withFrame: mouseCellFrame inView: self]; [_window flushWindow]; if ([mouseCell trackMouse: e inRect: mouseCellFrame ofView: self untilMouseUp: /*[[mouseCell class] prefersTrackingUntilMouseUp]]*/NO]) done = mouseUp = YES; else { [mouseCell highlight: NO withFrame: mouseCellFrame inView: self]; [_window flushWindow]; } } if (done) break; e = [theApp nextEventMatchingMask: event_mask untilDate: nil inMode: NSEventTrackingRunLoopMode dequeue: YES]; if ([e type] == NSLeftMouseUp) done = YES; } // [_window _releaseMouse: self]; if (mouseUp) { #ifdef MACOSX [mouseCell setNextState]; #endif if ([tb shouldUseAndSetState] == YES) [_dataSource tableView: self setState: [mouseCell state] forTableColumn: tb row: _clickedRow]; // [cell setState: ![cell state]]; [mouseCell highlight: NO withFrame: mouseCellFrame inView: self]; [_window flushWindow]; } [mouseCell sendActionOn: oldActionMask]; if (mouseUp) { SEL theAction; theAction = [mouseCell action]; if (theAction) [NSApp sendAction: theAction to: [mouseCell target] from: mouseCell]; } return; } [super mouseDown: theEvent]; } - (void)drawRow: (int)rowIndex clipRect: (NSRect)aRect { int startingColumn; int endingColumn; NSTableColumn *tb; NSRect drawingRect; NSCell *cell; int i; #ifndef MACOSX float x_pos; #endif if (_dataSource == nil) { return; } #ifdef MACOSX startingColumn = [self columnAtPoint: NSMakePoint(NSMinX(aRect), NSMinY(aRect))]; #else /* Using columnAtPoint: here would make it called twice per row per drawn rect - so we avoid it and do it natively */ /* Determine starting column as fast as possible */ x_pos = NSMinX (aRect); i = 0; while ((x_pos > _columnOrigins[i]) && (i < _numberOfColumns)) { i++; } startingColumn = (i - 1); if (startingColumn == -1) startingColumn = 0; #endif #ifdef MACOSX endingColumn = [self columnAtPoint: NSMakePoint(NSMaxX(aRect), NSMinY(aRect))]; #else /* Determine ending column as fast as possible */ x_pos = NSMaxX (aRect); // Nota Bene: we do *not* reset i while ((x_pos > _columnOrigins[i]) && (i < _numberOfColumns)) { i++; } endingColumn = (i - 1); if (endingColumn == -1) endingColumn = _numberOfColumns - 1; #endif /* Draw the row between startingColumn and endingColumn */ for (i = startingColumn; i <= endingColumn; i++) { #ifdef MACOSX if (i != _editingColumn || rowIndex != _editingRow) #else if (i != _editedColumn || rowIndex != _editedRow) #endif { tb = [_tableColumns objectAtIndex: i]; cell = [tb dataCellForRow: rowIndex]; #ifdef MACOSX if (_tvFlags.delegateWillDisplayCell) #else if (_del_responds) #endif { [_delegate tableView: self willDisplayCell: cell forTableColumn: tb row: rowIndex]; } [cell setObjectValue: [_dataSource tableView: self objectValueForTableColumn: tb row: rowIndex]]; if ([tb shouldUseAndSetState] == YES) [cell setState: [_dataSource tableView: self stateForTableColumn: tb row: rowIndex]]; drawingRect = [self frameOfCellAtColumn: i row: rowIndex]; [cell drawWithFrame: drawingRect inView: self]; } } } @end