1/*
2   SwitchTableView.m
3
4   Copyright (c) 2001 Pierre-Yves Rivaille
5
6   This library is free software; you can redistribute it and/or
7   modify it under the terms of the GNU Library General Public
8   License as published by the Free Software Foundation; either
9   version 2 of the License, or (at your option) any later version.
10
11   This library is distributed in the hope that it will be useful,
12   but WITHOUT ANY WARRANTY; without even the implied warranty of
13   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
14   Library General Public License for more details.
15
16   You should have received a copy of the GNU Library General Public
17   License along with this library; see the file COPYING.LIB.
18   If not, write to the Free Software Foundation,
19   59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
20*/
21
22#include "SwitchTableView.h"
23
24#include "ExtendedTableColumn.h"
25
26//
27//
28//
29@implementation SwitchTableView
30
31- (void) mouseDown: (NSEvent *)theEvent
32{
33  NSPoint location = [theEvent locationInWindow];
34  NSTableColumn *tb;
35
36#ifdef MACOSX
37  int _clickedRow;
38  int _clickedColumn;
39  int _numberOfRows = [self frame].size.height / _rowHeight;
40  int _numberOfColumns = [_tableColumns count];
41#endif
42  //
43  // Pathological case -- ignore mouse down
44  //
45  if ((_numberOfRows == 0) || (_numberOfColumns == 0))
46    {
47      [super mouseDown: theEvent];
48      return;
49    }
50
51  // Determine row and column which were clicked
52  location = [self convertPoint: location  fromView: nil];
53  _clickedRow = [self rowAtPoint: location];
54  _clickedColumn = [self columnAtPoint: location];
55
56  if (_clickedRow == -1 || _clickedColumn == -1)
57    return;
58
59  tb = [_tableColumns objectAtIndex: _clickedColumn];
60
61  if ([tb shouldUseMouse] == YES)
62    {
63      NSApplication *theApp = [NSApplication sharedApplication];
64      BOOL mouseUp = NO, done = NO;
65      NSEvent *e;
66      int oldActionMask;
67      NSPoint location;
68      unsigned int event_mask = NSLeftMouseDownMask | NSLeftMouseUpMask
69	| NSMouseMovedMask | NSLeftMouseDraggedMask
70	| NSRightMouseDraggedMask;
71      NSCell *mouseCell;
72      NSRect mouseCellFrame;
73
74      mouseCell = [[_tableColumns objectAtIndex: _clickedColumn]
75		    dataCellForRow: _clickedRow];
76
77      mouseCellFrame = [self frameOfCellAtColumn: _clickedColumn
78			     row: _clickedRow];
79      [mouseCell setObjectValue: [_dataSource tableView: self
80					      objectValueForTableColumn: tb
81					      row: _clickedRow]];
82      if ([tb shouldUseAndSetState] == YES)
83	[mouseCell setState: [_dataSource tableView: self
84					  stateForTableColumn: tb
85					  row: _clickedRow]];
86
87      if ([tb shouldUseTag] == YES)
88	[mouseCell setTag: [_dataSource tableView: self
89					tagForTableColumn: tb
90					row: _clickedRow]];
91
92#ifdef MACOSX
93      if (_tvFlags.delegateWillDisplayCell)
94#else
95      if (_del_responds)
96#endif
97	{
98	  [_delegate tableView: self   willDisplayCell: mouseCell
99		     forTableColumn: tb   row: _clickedRow];
100	}
101
102      if ([mouseCell isEnabled] == NO)
103	return;
104
105
106
107      if ([mouseCell isContinuous])
108	oldActionMask = [mouseCell sendActionOn: 0];
109      else
110	oldActionMask = [mouseCell sendActionOn: NSPeriodicMask];
111
112      //      [_window _captureMouse: self];
113
114      e = theEvent;
115      while (!done)                 // loop until mouse goes up
116	{
117	  location = [e locationInWindow];
118	  location = [self convertPoint: location fromView: nil];
119	  // ask the cell to track the mouse only
120	  // if the mouse is within the cell
121	  if (NSMouseInRect(location, mouseCellFrame, YES))
122	    {
123	      [mouseCell highlight: YES
124			 withFrame: mouseCellFrame
125			 inView: self];
126	      [_window flushWindow];
127	      if ([mouseCell trackMouse: e
128			     inRect: mouseCellFrame
129			     ofView: self
130			     untilMouseUp: /*[[mouseCell class] prefersTrackingUntilMouseUp]]*/NO])
131		done = mouseUp = YES;
132	      else
133		{
134		  [mouseCell highlight: NO
135			     withFrame: mouseCellFrame
136			     inView: self];
137		  [_window flushWindow];
138		}
139	    }
140
141	  if (done)
142	    break;
143
144	  e = [theApp nextEventMatchingMask: event_mask
145		      untilDate: nil
146		      inMode: NSEventTrackingRunLoopMode
147		      dequeue: YES];
148	  if ([e type] == NSLeftMouseUp)
149	    done = YES;
150	}
151
152      //      [_window _releaseMouse: self];
153      if (mouseUp)
154	{
155#ifdef MACOSX
156   [mouseCell setNextState];
157#endif
158	  if ([tb shouldUseAndSetState] == YES)
159	    [_dataSource tableView: self
160			 setState: [mouseCell state]
161			 forTableColumn: tb
162			 row: _clickedRow];
163
164	  //              [cell setState: ![cell state]];
165	  [mouseCell highlight: NO
166		     withFrame: mouseCellFrame
167		     inView: self];
168	  [_window flushWindow];
169	}
170
171      [mouseCell sendActionOn: oldActionMask];
172
173      if (mouseUp)
174	{
175	  SEL theAction;
176	  theAction = [mouseCell action];
177	  if (theAction)
178	    [NSApp sendAction: theAction
179		   to: [mouseCell target]
180		   from: mouseCell];
181	}
182      return;
183    }
184
185  [super mouseDown: theEvent];
186}
187
188
189//
190//
191//
192- (void)drawRow: (int)rowIndex clipRect: (NSRect)aRect
193{
194  int startingColumn;
195  int endingColumn;
196  NSTableColumn *tb;
197  NSRect drawingRect;
198  NSCell *cell;
199  int i;
200#ifndef MACOSX
201  float x_pos;
202#endif
203
204  if (_dataSource == nil)
205    {
206      return;
207    }
208
209#ifdef MACOSX
210  startingColumn = [self columnAtPoint: NSMakePoint(NSMinX(aRect), NSMinY(aRect))];
211#else
212  /* Using columnAtPoint: here would make it called twice per row per drawn
213     rect - so we avoid it and do it natively */
214
215  /* Determine starting column as fast as possible */
216  x_pos = NSMinX (aRect);
217  i = 0;
218  while ((x_pos > _columnOrigins[i]) && (i < _numberOfColumns))
219    {
220      i++;
221    }
222  startingColumn = (i - 1);
223
224  if (startingColumn == -1)
225    startingColumn = 0;
226#endif
227
228
229#ifdef MACOSX
230  endingColumn = [self columnAtPoint: NSMakePoint(NSMaxX(aRect), NSMinY(aRect))];
231#else
232  /* Determine ending column as fast as possible */
233  x_pos = NSMaxX (aRect);
234  // Nota Bene: we do *not* reset i
235  while ((x_pos > _columnOrigins[i]) && (i < _numberOfColumns))
236    {
237      i++;
238    }
239  endingColumn = (i - 1);
240
241  if (endingColumn == -1)
242    endingColumn = _numberOfColumns - 1;
243#endif
244
245
246  /* Draw the row between startingColumn and endingColumn */
247  for (i = startingColumn; i <= endingColumn; i++)
248    {
249#ifdef MACOSX
250      if (i != _editingColumn || rowIndex != _editingRow)
251#else
252      if (i != _editedColumn || rowIndex != _editedRow)
253#endif
254	{
255	  tb = [_tableColumns objectAtIndex: i];
256	  cell = [tb dataCellForRow: rowIndex];
257#ifdef MACOSX
258          if (_tvFlags.delegateWillDisplayCell)
259#else
260	  if (_del_responds)
261#endif
262	    {
263	      [_delegate tableView: self   willDisplayCell: cell
264			 forTableColumn: tb   row: rowIndex];
265	    }
266	  [cell setObjectValue: [_dataSource tableView: self
267					     objectValueForTableColumn: tb
268					     row: rowIndex]];
269	  if ([tb shouldUseAndSetState] == YES)
270	    [cell setState: [_dataSource tableView: self
271					 stateForTableColumn: tb
272					 row: rowIndex]];
273	  drawingRect = [self frameOfCellAtColumn: i
274			      row: rowIndex];
275	  [cell drawWithFrame: drawingRect inView: self];
276	}
277    }
278}
279
280@end
281