/* 
   SwitchTableView.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.
*/ 

#include "SwitchTableView.h"

#include "ExtendedTableColumn.h"

//
//
//
@implementation SwitchTableView

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