]> git.saurik.com Git - wxWidgets.git/blame - src/generic/grid.cpp
Added automatic connection of drawn points
[wxWidgets.git] / src / generic / grid.cpp
CommitLineData
5612a518 1/////////////////////////////////////////////////////////////////////////////
f85afd4e
MB
2// Name: grid.cpp
3// Purpose: wxGrid and related classes
4// Author: Michael Bedward (based on code by Julian Smart, Robin Dunn)
5// Modified by:
6// Created: 1/08/1999
7// RCS-ID: $Id$
8// Copyright: (c) Michael Bedward (mbedward@ozemail.com.au)
9// Licence: wxWindows licence
10/////////////////////////////////////////////////////////////////////////////
11
f85afd4e
MB
12#ifdef __GNUG__
13 #pragma implementation "grid.h"
14#endif
15
4d85bcd1
JS
16// For compilers that support precompilation, includes "wx/wx.h".
17#include "wx/wxprec.h"
18
19#include "wx/defs.h"
f85afd4e
MB
20
21#ifdef __BORLANDC__
22 #pragma hdrstop
23#endif
24
8f177c8e 25#if !defined(wxUSE_NEW_GRID) || !(wxUSE_NEW_GRID)
4d85bcd1
JS
26#include "gridg.cpp"
27#else
28
f85afd4e
MB
29#ifndef WX_PRECOMP
30 #include "wx/utils.h"
31 #include "wx/dcclient.h"
32 #include "wx/settings.h"
33 #include "wx/log.h"
18f9565d 34 #include "wx/sizer.h"
7807d81c 35 #include "wx/layout.h"
f85afd4e
MB
36#endif
37
38#include "wx/generic/grid.h"
39
9496deb5
MB
40#ifndef WXGRID_DRAW_LINES
41#define WXGRID_DRAW_LINES 1
796df70a
SN
42#endif
43
f85afd4e
MB
44//////////////////////////////////////////////////////////////////////
45
46wxGridCellCoords wxGridNoCellCoords( -1, -1 );
47wxRect wxGridNoCellRect( -1, -1, -1, -1 );
48
2d66e025
MB
49// this is a magic incantation which must be done!
50#include "wx/arrimpl.cpp"
51
52WX_DEFINE_OBJARRAY(wxGridCellCoordsArray)
f85afd4e 53
f0102d2a
VZ
54// scroll line size
55// TODO: fixed so far - make configurable later (and also different for x/y)
56static const size_t GRID_SCROLL_LINE = 10;
f85afd4e
MB
57
58//////////////////////////////////////////////////////////////////////
59//
60// Abstract base class for grid data (the model)
61//
62IMPLEMENT_ABSTRACT_CLASS( wxGridTableBase, wxObject )
63
64
65wxGridTableBase::wxGridTableBase()
66 : wxObject()
67{
68 m_view = (wxGrid *) NULL;
69}
70
71wxGridTableBase::~wxGridTableBase()
72{
73}
74
75
76bool wxGridTableBase::InsertRows( size_t pos, size_t numRows )
77{
6eec2bee
OK
78 wxLogWarning( wxT("Called grid table class function InsertRows(pos=%d, N=%d)\n"
79 "but your derived table class does not override this function"),
f85afd4e 80 pos, numRows );
8f177c8e 81
f85afd4e
MB
82 return FALSE;
83}
84
85bool wxGridTableBase::AppendRows( size_t numRows )
86{
6eec2bee
OK
87 wxLogWarning( wxT("Called grid table class function AppendRows(N=%d)\n"
88 "but your derived table class does not override this function"),
f85afd4e 89 numRows );
8f177c8e 90
f85afd4e
MB
91 return FALSE;
92}
93
94bool wxGridTableBase::DeleteRows( size_t pos, size_t numRows )
95{
6eec2bee
OK
96 wxLogWarning( wxT("Called grid table class function DeleteRows(pos=%d, N=%d)\n"
97 "but your derived table class does not override this function"),
f85afd4e 98 pos, numRows );
8f177c8e 99
f85afd4e
MB
100 return FALSE;
101}
102
103bool wxGridTableBase::InsertCols( size_t pos, size_t numCols )
104{
6eec2bee
OK
105 wxLogWarning( wxT("Called grid table class function InsertCols(pos=%d, N=%d)\n"
106 "but your derived table class does not override this function"),
f85afd4e 107 pos, numCols );
8f177c8e 108
f85afd4e
MB
109 return FALSE;
110}
111
112bool wxGridTableBase::AppendCols( size_t numCols )
113{
6eec2bee
OK
114 wxLogWarning( wxT("Called grid table class function AppendCols(N=%d)\n"
115 "but your derived table class does not override this function"),
f85afd4e 116 numCols );
8f177c8e 117
f85afd4e
MB
118 return FALSE;
119}
120
121bool wxGridTableBase::DeleteCols( size_t pos, size_t numCols )
122{
6eec2bee
OK
123 wxLogWarning( wxT("Called grid table class function DeleteCols(pos=%d, N=%d)\n"
124 "but your derived table class does not override this function"),
f85afd4e 125 pos, numCols );
8f177c8e 126
f85afd4e
MB
127 return FALSE;
128}
129
130
131wxString wxGridTableBase::GetRowLabelValue( int row )
132{
133 wxString s;
134 s << row;
135 return s;
136}
137
138wxString wxGridTableBase::GetColLabelValue( int col )
139{
140 // default col labels are:
141 // cols 0 to 25 : A-Z
142 // cols 26 to 675 : AA-ZZ
143 // etc.
144
145 wxString s;
146 unsigned int i, n;
147 for ( n = 1; ; n++ )
148 {
f0102d2a 149 s += (_T('A') + (wxChar)( col%26 ));
f85afd4e
MB
150 col = col/26 - 1;
151 if ( col < 0 ) break;
152 }
153
154 // reverse the string...
155 wxString s2;
156 for ( i = 0; i < n; i++ )
157 {
158 s2 += s[n-i-1];
159 }
160
161 return s2;
162}
163
164
165
166//////////////////////////////////////////////////////////////////////
167//
168// Message class for the grid table to send requests and notifications
169// to the grid view
170//
171
172wxGridTableMessage::wxGridTableMessage()
173{
174 m_table = (wxGridTableBase *) NULL;
175 m_id = -1;
176 m_comInt1 = -1;
177 m_comInt2 = -1;
178}
179
180wxGridTableMessage::wxGridTableMessage( wxGridTableBase *table, int id,
181 int commandInt1, int commandInt2 )
182{
183 m_table = table;
184 m_id = id;
185 m_comInt1 = commandInt1;
186 m_comInt2 = commandInt2;
187}
188
189
190
191//////////////////////////////////////////////////////////////////////
192//
193// A basic grid table for string data. An object of this class will
194// created by wxGrid if you don't specify an alternative table class.
195//
196
223d09f6 197WX_DEFINE_OBJARRAY(wxGridStringArray)
f85afd4e
MB
198
199IMPLEMENT_DYNAMIC_CLASS( wxGridStringTable, wxGridTableBase )
200
201wxGridStringTable::wxGridStringTable()
202 : wxGridTableBase()
203{
204}
205
206wxGridStringTable::wxGridStringTable( int numRows, int numCols )
207 : wxGridTableBase()
208{
209 int row, col;
8f177c8e 210
f85afd4e
MB
211 m_data.Alloc( numRows );
212
213 wxArrayString sa;
214 sa.Alloc( numCols );
215 for ( col = 0; col < numCols; col++ )
216 {
217 sa.Add( wxEmptyString );
218 }
8f177c8e 219
f85afd4e
MB
220 for ( row = 0; row < numRows; row++ )
221 {
222 m_data.Add( sa );
223 }
224}
225
226wxGridStringTable::~wxGridStringTable()
227{
228}
229
230long wxGridStringTable::GetNumberRows()
231{
232 return m_data.GetCount();
233}
234
235long wxGridStringTable::GetNumberCols()
236{
237 if ( m_data.GetCount() > 0 )
238 return m_data[0].GetCount();
239 else
240 return 0;
241}
242
243wxString wxGridStringTable::GetValue( int row, int col )
244{
245 // TODO: bounds checking
246 //
247 return m_data[row][col];
248}
249
250void wxGridStringTable::SetValue( int row, int col, const wxString& s )
251{
252 // TODO: bounds checking
253 //
254 m_data[row][col] = s;
255}
256
257bool wxGridStringTable::IsEmptyCell( int row, int col )
258{
259 // TODO: bounds checking
260 //
261 return (m_data[row][col] == wxEmptyString);
262}
263
264
265void wxGridStringTable::Clear()
266{
267 int row, col;
268 int numRows, numCols;
8f177c8e 269
f85afd4e
MB
270 numRows = m_data.GetCount();
271 if ( numRows > 0 )
272 {
273 numCols = m_data[0].GetCount();
274
275 for ( row = 0; row < numRows; row++ )
276 {
277 for ( col = 0; col < numCols; col++ )
278 {
279 m_data[row][col] = wxEmptyString;
280 }
281 }
282 }
283}
284
285
286bool wxGridStringTable::InsertRows( size_t pos, size_t numRows )
287{
288 size_t row, col;
289
290 size_t curNumRows = m_data.GetCount();
291 size_t curNumCols = ( curNumRows > 0 ? m_data[0].GetCount() : 0 );
8f177c8e 292
f85afd4e
MB
293 if ( pos >= curNumRows )
294 {
295 return AppendRows( numRows );
296 }
8f177c8e 297
f85afd4e
MB
298 wxArrayString sa;
299 sa.Alloc( curNumCols );
300 for ( col = 0; col < curNumCols; col++ )
301 {
302 sa.Add( wxEmptyString );
303 }
304
305 for ( row = pos; row < pos + numRows; row++ )
306 {
307 m_data.Insert( sa, row );
308 }
309
310 if ( GetView() )
311 {
312 wxGridTableMessage msg( this,
313 wxGRIDTABLE_NOTIFY_ROWS_INSERTED,
314 pos,
315 numRows );
8f177c8e 316
f85afd4e
MB
317 GetView()->ProcessTableMessage( msg );
318 }
319
320 return TRUE;
321}
322
323bool wxGridStringTable::AppendRows( size_t numRows )
324{
325 size_t row, col;
326
327 size_t curNumRows = m_data.GetCount();
328 size_t curNumCols = ( curNumRows > 0 ? m_data[0].GetCount() : 0 );
8f177c8e 329
f85afd4e
MB
330 wxArrayString sa;
331 if ( curNumCols > 0 )
332 {
333 sa.Alloc( curNumCols );
334 for ( col = 0; col < curNumCols; col++ )
335 {
336 sa.Add( wxEmptyString );
337 }
338 }
8f177c8e 339
f85afd4e
MB
340 for ( row = 0; row < numRows; row++ )
341 {
342 m_data.Add( sa );
343 }
344
345 if ( GetView() )
346 {
347 wxGridTableMessage msg( this,
348 wxGRIDTABLE_NOTIFY_ROWS_APPENDED,
349 numRows );
8f177c8e 350
f85afd4e
MB
351 GetView()->ProcessTableMessage( msg );
352 }
353
8f177c8e 354 return TRUE;
f85afd4e
MB
355}
356
357bool wxGridStringTable::DeleteRows( size_t pos, size_t numRows )
358{
359 size_t n;
360
361 size_t curNumRows = m_data.GetCount();
8f177c8e 362
f85afd4e
MB
363 if ( pos >= curNumRows )
364 {
6eec2bee
OK
365 wxLogError( wxT("Called wxGridStringTable::DeleteRows(pos=%d, N=%d)...\n"
366 "Pos value is invalid for present table with %d rows"),
f85afd4e
MB
367 pos, numRows, curNumRows );
368 return FALSE;
369 }
370
371 if ( numRows > curNumRows - pos )
372 {
373 numRows = curNumRows - pos;
374 }
8f177c8e 375
f85afd4e
MB
376 if ( numRows >= curNumRows )
377 {
378 m_data.Empty(); // don't release memory just yet
379 }
380 else
381 {
382 for ( n = 0; n < numRows; n++ )
383 {
384 m_data.Remove( pos );
385 }
386 }
387
388 if ( GetView() )
389 {
390 wxGridTableMessage msg( this,
391 wxGRIDTABLE_NOTIFY_ROWS_DELETED,
392 pos,
393 numRows );
8f177c8e 394
f85afd4e
MB
395 GetView()->ProcessTableMessage( msg );
396 }
397
8f177c8e 398 return TRUE;
f85afd4e
MB
399}
400
401bool wxGridStringTable::InsertCols( size_t pos, size_t numCols )
402{
403 size_t row, col;
404
405 size_t curNumRows = m_data.GetCount();
406 size_t curNumCols = ( curNumRows > 0 ? m_data[0].GetCount() : 0 );
8f177c8e 407
f85afd4e
MB
408 if ( pos >= curNumCols )
409 {
410 return AppendCols( numCols );
411 }
412
413 for ( row = 0; row < curNumRows; row++ )
414 {
415 for ( col = pos; col < pos + numCols; col++ )
416 {
417 m_data[row].Insert( wxEmptyString, col );
418 }
419 }
420
421 if ( GetView() )
422 {
423 wxGridTableMessage msg( this,
424 wxGRIDTABLE_NOTIFY_COLS_INSERTED,
425 pos,
426 numCols );
8f177c8e 427
f85afd4e
MB
428 GetView()->ProcessTableMessage( msg );
429 }
430
431 return TRUE;
432}
433
434bool wxGridStringTable::AppendCols( size_t numCols )
435{
436 size_t row, n;
437
438 size_t curNumRows = m_data.GetCount();
439 if ( !curNumRows )
440 {
441 // TODO: something better than this ?
442 //
6eec2bee
OK
443 wxLogError( wxT("Unable to append cols to a grid table with no rows.\n"
444 "Call AppendRows() first") );
f85afd4e
MB
445 return FALSE;
446 }
8f177c8e 447
f85afd4e
MB
448 for ( row = 0; row < curNumRows; row++ )
449 {
450 for ( n = 0; n < numCols; n++ )
451 {
452 m_data[row].Add( wxEmptyString );
453 }
454 }
455
456 if ( GetView() )
457 {
458 wxGridTableMessage msg( this,
459 wxGRIDTABLE_NOTIFY_COLS_APPENDED,
460 numCols );
8f177c8e 461
f85afd4e
MB
462 GetView()->ProcessTableMessage( msg );
463 }
464
465 return TRUE;
466}
467
468bool wxGridStringTable::DeleteCols( size_t pos, size_t numCols )
469{
470 size_t row, n;
471
472 size_t curNumRows = m_data.GetCount();
473 size_t curNumCols = ( curNumRows > 0 ? m_data[0].GetCount() : 0 );
8f177c8e 474
f85afd4e
MB
475 if ( pos >= curNumCols )
476 {
8f177c8e
VZ
477 wxLogError( wxT("Called wxGridStringTable::DeleteCols(pos=%d, N=%d)...\n"
478 "Pos value is invalid for present table with %d cols"),
479 pos, numCols, curNumCols );
480 return FALSE;
f85afd4e
MB
481 }
482
483 if ( numCols > curNumCols - pos )
484 {
8f177c8e 485 numCols = curNumCols - pos;
f85afd4e
MB
486 }
487
488 for ( row = 0; row < curNumRows; row++ )
489 {
490 if ( numCols >= curNumCols )
491 {
492 m_data[row].Clear();
493 }
494 else
495 {
496 for ( n = 0; n < numCols; n++ )
497 {
498 m_data[row].Remove( pos );
499 }
500 }
501 }
502
503 if ( GetView() )
504 {
505 wxGridTableMessage msg( this,
506 wxGRIDTABLE_NOTIFY_COLS_DELETED,
507 pos,
508 numCols );
8f177c8e 509
f85afd4e
MB
510 GetView()->ProcessTableMessage( msg );
511 }
512
8f177c8e 513 return TRUE;
f85afd4e
MB
514}
515
516wxString wxGridStringTable::GetRowLabelValue( int row )
517{
518 if ( row > (int)(m_rowLabels.GetCount()) - 1 )
519 {
520 // using default label
521 //
522 return wxGridTableBase::GetRowLabelValue( row );
523 }
524 else
525 {
526 return m_rowLabels[ row ];
527 }
528}
529
530wxString wxGridStringTable::GetColLabelValue( int col )
531{
532 if ( col > (int)(m_colLabels.GetCount()) - 1 )
533 {
534 // using default label
535 //
536 return wxGridTableBase::GetColLabelValue( col );
537 }
538 else
539 {
540 return m_colLabels[ col ];
541 }
542}
543
544void wxGridStringTable::SetRowLabelValue( int row, const wxString& value )
545{
546 if ( row > (int)(m_rowLabels.GetCount()) - 1 )
547 {
548 int n = m_rowLabels.GetCount();
549 int i;
550 for ( i = n; i <= row; i++ )
551 {
552 m_rowLabels.Add( wxGridTableBase::GetRowLabelValue(i) );
553 }
554 }
555
556 m_rowLabels[row] = value;
557}
558
559void wxGridStringTable::SetColLabelValue( int col, const wxString& value )
560{
561 if ( col > (int)(m_colLabels.GetCount()) - 1 )
562 {
563 int n = m_colLabels.GetCount();
564 int i;
565 for ( i = n; i <= col; i++ )
566 {
567 m_colLabels.Add( wxGridTableBase::GetColLabelValue(i) );
568 }
569 }
570
571 m_colLabels[col] = value;
572}
573
574
575
576
577//////////////////////////////////////////////////////////////////////
578
579IMPLEMENT_DYNAMIC_CLASS( wxGridTextCtrl, wxTextCtrl )
8f177c8e 580
f85afd4e
MB
581BEGIN_EVENT_TABLE( wxGridTextCtrl, wxTextCtrl )
582 EVT_KEY_DOWN( wxGridTextCtrl::OnKeyDown )
583END_EVENT_TABLE()
584
585
586wxGridTextCtrl::wxGridTextCtrl( wxWindow *par,
2d66e025 587 wxGrid *grid,
f85afd4e
MB
588 bool isCellControl,
589 wxWindowID id,
590 const wxString& value,
591 const wxPoint& pos,
592 const wxSize& size,
593 long style )
594 : wxTextCtrl( par, id, value, pos, size, style )
595{
2d66e025 596 m_grid = grid;
f85afd4e
MB
597 m_isCellControl = isCellControl;
598}
599
600
2d66e025 601void wxGridTextCtrl::OnKeyDown( wxKeyEvent& event )
f85afd4e 602{
2d66e025 603 switch ( event.KeyCode() )
f85afd4e
MB
604 {
605 case WXK_ESCAPE:
2d66e025 606 m_grid->SetEditControlValue( startValue );
f85afd4e
MB
607 SetInsertionPointEnd();
608 break;
609
610 case WXK_UP:
611 case WXK_DOWN:
612 case WXK_LEFT:
613 case WXK_RIGHT:
edc2c290
MB
614 case WXK_PRIOR:
615 case WXK_NEXT:
f603012f 616 case WXK_SPACE:
f85afd4e
MB
617 if ( m_isCellControl )
618 {
619 // send the event to the parent grid, skipping the
620 // event if nothing happens
621 //
2d66e025 622 event.Skip( m_grid->ProcessEvent( event ) );
f85afd4e
MB
623 }
624 else
625 {
626 // default text control response within the top edit
627 // control
628 //
2d66e025 629 event.Skip();
f85afd4e
MB
630 }
631 break;
632
58dd5b3b
MB
633 case WXK_RETURN:
634 if ( m_isCellControl )
635 {
636 if ( !m_grid->ProcessEvent( event ) )
637 {
8a9a9d58 638#if defined(__WXMOTIF__) || defined(__WXGTK__)
58dd5b3b
MB
639 // wxMotif needs a little extra help...
640 //
641 int pos = GetInsertionPoint();
642 wxString s( GetValue() );
643 s = s.Left(pos) + "\n" + s.Mid(pos);
644 SetValue(s);
645 SetInsertionPoint( pos );
646#else
647 // the other ports can handle a Return key press
648 //
649 event.Skip();
f0102d2a 650#endif
58dd5b3b
MB
651 }
652 }
653 break;
654
f85afd4e
MB
655 case WXK_HOME:
656 case WXK_END:
657 if ( m_isCellControl )
658 {
659 // send the event to the parent grid, skipping the
660 // event if nothing happens
661 //
2d66e025 662 event.Skip( m_grid->ProcessEvent( event ) );
f85afd4e
MB
663 }
664 else
665 {
666 // default text control response within the top edit
667 // control
668 //
2d66e025 669 event.Skip();
f85afd4e
MB
670 }
671 break;
8f177c8e 672
f85afd4e 673 default:
2d66e025 674 event.Skip();
f85afd4e
MB
675 }
676}
677
678void wxGridTextCtrl::SetStartValue( const wxString& s )
679{
680 startValue = s;
f0102d2a 681 wxTextCtrl::SetValue(s);
f85afd4e
MB
682}
683
684
2d66e025
MB
685
686//////////////////////////////////////////////////////////////////////
687
688IMPLEMENT_DYNAMIC_CLASS( wxGridRowLabelWindow, wxWindow )
689
690BEGIN_EVENT_TABLE( wxGridRowLabelWindow, wxWindow )
691 EVT_PAINT( wxGridRowLabelWindow::OnPaint )
692 EVT_MOUSE_EVENTS( wxGridRowLabelWindow::OnMouseEvent )
693 EVT_KEY_DOWN( wxGridRowLabelWindow::OnKeyDown )
694END_EVENT_TABLE()
695
60ff3b99
VZ
696wxGridRowLabelWindow::wxGridRowLabelWindow( wxGrid *parent,
697 wxWindowID id,
2d66e025
MB
698 const wxPoint &pos, const wxSize &size )
699 : wxWindow( parent, id, pos, size )
700{
701 m_owner = parent;
702}
703
704void wxGridRowLabelWindow::OnPaint( wxPaintEvent &event )
705{
706 wxPaintDC dc(this);
707
708 // NO - don't do this because it will set both the x and y origin
709 // coords to match the parent scrolled window and we just want to
710 // set the y coord - MB
711 //
712 // m_owner->PrepareDC( dc );
60ff3b99 713
790ad94f 714 int x, y;
2d66e025
MB
715 m_owner->CalcUnscrolledPosition( 0, 0, &x, &y );
716 dc.SetDeviceOrigin( 0, -y );
60ff3b99 717
2d66e025
MB
718 m_owner->CalcRowLabelsExposed( GetUpdateRegion() );
719 m_owner->DrawRowLabels( dc );
720}
721
722
723void wxGridRowLabelWindow::OnMouseEvent( wxMouseEvent& event )
724{
725 m_owner->ProcessRowLabelMouseEvent( event );
726}
727
728
729// This seems to be required for wxMotif otherwise the mouse
730// cursor must be in the cell edit control to get key events
731//
732void wxGridRowLabelWindow::OnKeyDown( wxKeyEvent& event )
733{
734 if ( !m_owner->ProcessEvent( event ) ) event.Skip();
735}
736
737
738
739//////////////////////////////////////////////////////////////////////
740
741IMPLEMENT_DYNAMIC_CLASS( wxGridColLabelWindow, wxWindow )
742
743BEGIN_EVENT_TABLE( wxGridColLabelWindow, wxWindow )
744 EVT_PAINT( wxGridColLabelWindow::OnPaint )
745 EVT_MOUSE_EVENTS( wxGridColLabelWindow::OnMouseEvent )
746 EVT_KEY_DOWN( wxGridColLabelWindow::OnKeyDown )
747END_EVENT_TABLE()
748
60ff3b99
VZ
749wxGridColLabelWindow::wxGridColLabelWindow( wxGrid *parent,
750 wxWindowID id,
2d66e025
MB
751 const wxPoint &pos, const wxSize &size )
752 : wxWindow( parent, id, pos, size )
753{
754 m_owner = parent;
755}
756
757void wxGridColLabelWindow::OnPaint( wxPaintEvent &event )
758{
759 wxPaintDC dc(this);
760
761 // NO - don't do this because it will set both the x and y origin
762 // coords to match the parent scrolled window and we just want to
763 // set the x coord - MB
764 //
765 // m_owner->PrepareDC( dc );
60ff3b99 766
790ad94f 767 int x, y;
2d66e025
MB
768 m_owner->CalcUnscrolledPosition( 0, 0, &x, &y );
769 dc.SetDeviceOrigin( -x, 0 );
770
60ff3b99
VZ
771 m_owner->CalcColLabelsExposed( GetUpdateRegion() );
772 m_owner->DrawColLabels( dc );
2d66e025
MB
773}
774
775
776void wxGridColLabelWindow::OnMouseEvent( wxMouseEvent& event )
777{
778 m_owner->ProcessColLabelMouseEvent( event );
779}
780
781
782// This seems to be required for wxMotif otherwise the mouse
783// cursor must be in the cell edit control to get key events
784//
785void wxGridColLabelWindow::OnKeyDown( wxKeyEvent& event )
786{
787 if ( !m_owner->ProcessEvent( event ) ) event.Skip();
788}
789
790
791
792//////////////////////////////////////////////////////////////////////
793
794IMPLEMENT_DYNAMIC_CLASS( wxGridCornerLabelWindow, wxWindow )
795
796BEGIN_EVENT_TABLE( wxGridCornerLabelWindow, wxWindow )
797 EVT_MOUSE_EVENTS( wxGridCornerLabelWindow::OnMouseEvent )
d2fdd8d2 798 EVT_PAINT( wxGridCornerLabelWindow::OnPaint)
2d66e025
MB
799 EVT_KEY_DOWN( wxGridCornerLabelWindow::OnKeyDown )
800END_EVENT_TABLE()
801
60ff3b99
VZ
802wxGridCornerLabelWindow::wxGridCornerLabelWindow( wxGrid *parent,
803 wxWindowID id,
2d66e025 804 const wxPoint &pos, const wxSize &size )
d2fdd8d2 805 : wxWindow( parent, id, pos, size )
2d66e025
MB
806{
807 m_owner = parent;
808}
809
d2fdd8d2
RR
810void wxGridCornerLabelWindow::OnPaint( wxPaintEvent& WXUNUSED(event) )
811{
812 wxPaintDC dc(this);
813
814 int client_height = 0;
815 int client_width = 0;
816 GetClientSize( &client_width, &client_height );
817
818 dc.SetPen( *wxBLACK_PEN );
819 dc.DrawLine( client_width-1, client_height-1, client_width-1, 0 );
820 dc.DrawLine( client_width-1, client_height-1, 0, client_height-1 );
821
822 dc.SetPen( *wxWHITE_PEN );
823 dc.DrawLine( 0, 0, client_width, 0 );
824 dc.DrawLine( 0, 0, 0, client_height );
825}
826
2d66e025
MB
827
828void wxGridCornerLabelWindow::OnMouseEvent( wxMouseEvent& event )
829{
830 m_owner->ProcessCornerLabelMouseEvent( event );
831}
832
833
834// This seems to be required for wxMotif otherwise the mouse
835// cursor must be in the cell edit control to get key events
836//
837void wxGridCornerLabelWindow::OnKeyDown( wxKeyEvent& event )
838{
839 if ( !m_owner->ProcessEvent( event ) ) event.Skip();
840}
841
842
843
f85afd4e
MB
844//////////////////////////////////////////////////////////////////////
845
2d66e025
MB
846IMPLEMENT_DYNAMIC_CLASS( wxGridWindow, wxPanel )
847
848BEGIN_EVENT_TABLE( wxGridWindow, wxPanel )
849 EVT_PAINT( wxGridWindow::OnPaint )
2d66e025
MB
850 EVT_MOUSE_EVENTS( wxGridWindow::OnMouseEvent )
851 EVT_KEY_DOWN( wxGridWindow::OnKeyDown )
852END_EVENT_TABLE()
853
60ff3b99
VZ
854wxGridWindow::wxGridWindow( wxGrid *parent,
855 wxGridRowLabelWindow *rowLblWin,
2d66e025
MB
856 wxGridColLabelWindow *colLblWin,
857 wxWindowID id, const wxPoint &pos, const wxSize &size )
b0d6ff2f 858 : wxPanel( parent, id, pos, size, 0, "grid window" )
2d66e025
MB
859{
860 m_owner = parent;
861 m_rowLabelWin = rowLblWin;
862 m_colLabelWin = colLblWin;
60ff3b99 863
2d66e025
MB
864 SetBackgroundColour( "WHITE" );
865}
866
867
868wxGridWindow::~wxGridWindow()
869{
870}
871
872
873void wxGridWindow::OnPaint( wxPaintEvent &WXUNUSED(event) )
874{
875 wxPaintDC dc( this );
876 m_owner->PrepareDC( dc );
796df70a
SN
877 wxRegion reg = GetUpdateRegion();
878 m_owner->CalcCellsExposed( reg );
2d66e025 879 m_owner->DrawGridCellArea( dc );
9496deb5 880#if WXGRID_DRAW_LINES
796df70a
SN
881 m_owner->DrawAllGridLines( dc, reg );
882#endif
2d66e025
MB
883}
884
885
886void wxGridWindow::ScrollWindow( int dx, int dy, const wxRect *rect )
887{
888 wxPanel::ScrollWindow( dx, dy, rect );
889 m_rowLabelWin->ScrollWindow( 0, dy, rect );
890 m_colLabelWin->ScrollWindow( dx, 0, rect );
891}
892
893
894void wxGridWindow::OnMouseEvent( wxMouseEvent& event )
895{
896 m_owner->ProcessGridCellMouseEvent( event );
897}
898
899
900// This seems to be required for wxMotif otherwise the mouse
901// cursor must be in the cell edit control to get key events
902//
903void wxGridWindow::OnKeyDown( wxKeyEvent& event )
904{
905 if ( !m_owner->ProcessEvent( event ) ) event.Skip();
906}
f85afd4e 907
8f177c8e 908
2d66e025
MB
909
910//////////////////////////////////////////////////////////////////////
911
912IMPLEMENT_DYNAMIC_CLASS( wxGrid, wxScrolledWindow )
913
914BEGIN_EVENT_TABLE( wxGrid, wxScrolledWindow )
f85afd4e
MB
915 EVT_PAINT( wxGrid::OnPaint )
916 EVT_SIZE( wxGrid::OnSize )
f85afd4e 917 EVT_KEY_DOWN( wxGrid::OnKeyDown )
f85afd4e 918END_EVENT_TABLE()
8f177c8e 919
2d66e025
MB
920wxGrid::wxGrid( wxWindow *parent,
921 wxWindowID id,
922 const wxPoint& pos,
923 const wxSize& size,
924 long style,
925 const wxString& name )
926 : wxScrolledWindow( parent, id, pos, size, style, name )
927{
928 Create();
58dd5b3b
MB
929}
930
931
932wxGrid::~wxGrid()
933{
934 delete m_table;
935}
936
2d66e025 937
58dd5b3b
MB
938//
939// ----- internal init and update functions
940//
941
942void wxGrid::Create()
f0102d2a 943{
4634a5d6
MB
944 m_created = FALSE; // set to TRUE by CreateGrid
945 m_displayed = FALSE; // set to TRUE by OnPaint
946
947 m_table = (wxGridTableBase *) NULL;
948 m_cellEditCtrl = (wxWindow *) NULL;
949
950 m_numRows = 0;
951 m_numCols = 0;
952 m_currentCellCoords = wxGridNoCellCoords;
953
18f9565d
MB
954 m_rowLabelWidth = WXGRID_DEFAULT_ROW_LABEL_WIDTH;
955 m_colLabelHeight = WXGRID_DEFAULT_COL_LABEL_HEIGHT;
2d66e025 956
7807d81c
MB
957 m_cornerLabelWin = new wxGridCornerLabelWindow( this,
958 -1,
18f9565d
MB
959 wxDefaultPosition,
960 wxDefaultSize );
7807d81c 961
60ff3b99
VZ
962 m_rowLabelWin = new wxGridRowLabelWindow( this,
963 -1,
18f9565d
MB
964 wxDefaultPosition,
965 wxDefaultSize );
2d66e025
MB
966
967 m_colLabelWin = new wxGridColLabelWindow( this,
968 -1,
18f9565d
MB
969 wxDefaultPosition,
970 wxDefaultSize );
60ff3b99 971
60ff3b99
VZ
972 m_gridWin = new wxGridWindow( this,
973 m_rowLabelWin,
974 m_colLabelWin,
975 -1,
18f9565d 976 wxDefaultPosition,
2d66e025
MB
977 wxDefaultSize );
978
979 SetTargetWindow( m_gridWin );
2d66e025 980}
f85afd4e 981
2d66e025
MB
982
983bool wxGrid::CreateGrid( int numRows, int numCols )
984{
985 if ( m_created )
986 {
987 wxLogError( wxT("wxGrid::CreateGrid(numRows, numCols) called more than once") );
988 return FALSE;
989 }
990 else
991 {
992 m_numRows = numRows;
993 m_numCols = numCols;
994
995 m_table = new wxGridStringTable( m_numRows, m_numCols );
996 m_table->SetView( this );
997 Init();
998 m_created = TRUE;
999 }
f85afd4e 1000
2d66e025 1001 return m_created;
f85afd4e
MB
1002}
1003
2d66e025 1004
f85afd4e
MB
1005void wxGrid::Init()
1006{
1007 int i;
1008
f85afd4e
MB
1009 if ( m_numRows <= 0 )
1010 m_numRows = WXGRID_DEFAULT_NUMBER_ROWS;
1011
1012 if ( m_numCols <= 0 )
1013 m_numCols = WXGRID_DEFAULT_NUMBER_COLS;
1014
1015 m_rowLabelWidth = WXGRID_DEFAULT_ROW_LABEL_WIDTH;
1016 m_colLabelHeight = WXGRID_DEFAULT_COL_LABEL_HEIGHT;
1017
60ff3b99
VZ
1018 if ( m_rowLabelWin )
1019 {
1020 m_labelBackgroundColour = m_rowLabelWin->GetBackgroundColour();
1021 }
1022 else
1023 {
1024 m_labelBackgroundColour = wxColour( _T("WHITE") );
1025 }
1026
1027 m_labelTextColour = wxColour( _T("BLACK") );
f85afd4e
MB
1028
1029 // TODO: something better than this ?
1030 //
1031 m_labelFont = this->GetFont();
1032 m_labelFont.SetWeight( m_labelFont.GetWeight() + 2 );
8f177c8e 1033
f85afd4e
MB
1034 m_rowLabelHorizAlign = wxLEFT;
1035 m_rowLabelVertAlign = wxCENTRE;
1036
1037 m_colLabelHorizAlign = wxCENTRE;
1038 m_colLabelVertAlign = wxTOP;
1039
f85afd4e 1040 m_defaultColWidth = WXGRID_DEFAULT_COL_WIDTH;
1f1ce288
MB
1041 m_defaultRowHeight = m_gridWin->GetCharHeight();
1042
d2fdd8d2 1043#if defined(__WXMOTIF__) || defined(__WXGTK__) // see also text ctrl sizing in ShowCellEditControl()
1f1ce288
MB
1044 m_defaultRowHeight += 8;
1045#else
1046 m_defaultRowHeight += 4;
1047#endif
1048
f85afd4e
MB
1049 m_rowHeights.Alloc( m_numRows );
1050 m_rowBottoms.Alloc( m_numRows );
2d66e025 1051 int rowBottom = 0;
f85afd4e
MB
1052 for ( i = 0; i < m_numRows; i++ )
1053 {
1054 m_rowHeights.Add( m_defaultRowHeight );
2d66e025
MB
1055 rowBottom += m_defaultRowHeight;
1056 m_rowBottoms.Add( rowBottom );
f85afd4e 1057 }
8f177c8e 1058
f85afd4e 1059 m_colWidths.Alloc( m_numCols );
2d66e025
MB
1060 m_colRights.Alloc( m_numCols );
1061 int colRight = 0;
f85afd4e
MB
1062 for ( i = 0; i < m_numCols; i++ )
1063 {
1064 m_colWidths.Add( m_defaultColWidth );
2d66e025
MB
1065 colRight += m_defaultColWidth;
1066 m_colRights.Add( colRight );
f85afd4e 1067 }
8f177c8e 1068
f85afd4e
MB
1069 // TODO: improve this ?
1070 //
1071 m_defaultCellFont = this->GetFont();
8f177c8e 1072
2d66e025 1073 m_gridLineColour = wxColour( 128, 128, 255 );
f85afd4e 1074 m_gridLinesEnabled = TRUE;
8f177c8e 1075
58dd5b3b 1076 m_cursorMode = WXGRID_CURSOR_SELECT_CELL;
f85afd4e
MB
1077 m_dragLastPos = -1;
1078 m_dragRowOrCol = -1;
1079 m_isDragging = FALSE;
1080
1081 m_rowResizeCursor = wxCursor( wxCURSOR_SIZENS );
1082 m_colResizeCursor = wxCursor( wxCURSOR_SIZEWE );
1083
1084 m_currentCellCoords = wxGridNoCellCoords;
f85afd4e
MB
1085
1086 m_selectedTopLeft = wxGridNoCellCoords;
1087 m_selectedBottomRight = wxGridNoCellCoords;
8f177c8e 1088
f85afd4e
MB
1089 m_editable = TRUE; // default for whole grid
1090
2d66e025
MB
1091 m_inOnKeyDown = FALSE;
1092 m_batchCount = 0;
1093
f85afd4e
MB
1094 // TODO: extend this to other types of controls
1095 //
2d66e025
MB
1096 m_cellEditCtrl = new wxGridTextCtrl( m_gridWin,
1097 this,
f85afd4e
MB
1098 TRUE,
1099 wxGRID_CELLCTRL,
1100 "",
1101 wxPoint(1,1),
edc2c290 1102 wxSize(1,1)
d2fdd8d2 1103#if defined(__WXMSW__)
edc2c290 1104 , wxTE_MULTILINE | wxTE_NO_VSCROLL
f85afd4e
MB
1105#endif
1106 );
8f177c8e
VZ
1107
1108 m_cellEditCtrl->Show( FALSE );
f85afd4e 1109 m_cellEditCtrlEnabled = TRUE;
8f177c8e 1110 m_editCtrlType = wxGRID_TEXTCTRL;
f85afd4e
MB
1111}
1112
1113
1114void wxGrid::CalcDimensions()
1115{
f85afd4e 1116 int cw, ch;
2d66e025 1117 GetClientSize( &cw, &ch );
f85afd4e 1118
2d66e025 1119 if ( m_numRows > 0 && m_numCols > 0 )
f85afd4e 1120 {
b0d6ff2f
MB
1121 int right = m_colRights[ m_numCols-1 ] + 50;
1122 int bottom = m_rowBottoms[ m_numRows-1 ] + 50;
60ff3b99 1123
2d66e025
MB
1124 // TODO: restore the scroll position that we had before sizing
1125 //
1126 int x, y;
1127 GetViewStart( &x, &y );
f0102d2a
VZ
1128 SetScrollbars( GRID_SCROLL_LINE, GRID_SCROLL_LINE,
1129 right/GRID_SCROLL_LINE, bottom/GRID_SCROLL_LINE,
be46e4a6 1130 x, y );
f85afd4e 1131 }
f85afd4e
MB
1132}
1133
1134
7807d81c
MB
1135void wxGrid::CalcWindowSizes()
1136{
1137 int cw, ch;
1138 GetClientSize( &cw, &ch );
1139
1140 if ( m_cornerLabelWin->IsShown() )
1141 m_cornerLabelWin->SetSize( 0, 0, m_rowLabelWidth, m_colLabelHeight );
1142
1143 if ( m_colLabelWin->IsShown() )
1144 m_colLabelWin->SetSize( m_rowLabelWidth, 0, cw-m_rowLabelWidth, m_colLabelHeight);
1145
1146 if ( m_rowLabelWin->IsShown() )
1147 m_rowLabelWin->SetSize( 0, m_colLabelHeight, m_rowLabelWidth, ch-m_colLabelHeight);
1148
1149 if ( m_gridWin->IsShown() )
1150 m_gridWin->SetSize( m_rowLabelWidth, m_colLabelHeight, cw-m_rowLabelWidth, ch-m_colLabelHeight);
1151}
1152
1153
f85afd4e
MB
1154// this is called when the grid table sends a message to say that it
1155// has been redimensioned
1156//
1157bool wxGrid::Redimension( wxGridTableMessage& msg )
1158{
1159 int i;
8f177c8e 1160
f85afd4e
MB
1161 switch ( msg.GetId() )
1162 {
1163 case wxGRIDTABLE_NOTIFY_ROWS_INSERTED:
1164 {
1165 size_t pos = msg.GetCommandInt();
1166 int numRows = msg.GetCommandInt2();
1167 for ( i = 0; i < numRows; i++ )
1168 {
1169 m_rowHeights.Insert( m_defaultRowHeight, pos );
1170 m_rowBottoms.Insert( 0, pos );
1171 }
1172 m_numRows += numRows;
2d66e025
MB
1173
1174 int bottom = 0;
1175 if ( pos > 0 ) bottom = m_rowBottoms[pos-1];
60ff3b99 1176
2d66e025
MB
1177 for ( i = pos; i < m_numRows; i++ )
1178 {
1179 bottom += m_rowHeights[i];
1180 m_rowBottoms[i] = bottom;
1181 }
f85afd4e
MB
1182 CalcDimensions();
1183 }
1184 return TRUE;
1185
1186 case wxGRIDTABLE_NOTIFY_ROWS_APPENDED:
1187 {
1188 int numRows = msg.GetCommandInt();
1189 for ( i = 0; i < numRows; i++ )
1190 {
1191 m_rowHeights.Add( m_defaultRowHeight );
1192 m_rowBottoms.Add( 0 );
1193 }
2d66e025
MB
1194
1195 int oldNumRows = m_numRows;
f85afd4e 1196 m_numRows += numRows;
2d66e025
MB
1197
1198 int bottom = 0;
1199 if ( oldNumRows > 0 ) bottom = m_rowBottoms[oldNumRows-1];
60ff3b99 1200
2d66e025
MB
1201 for ( i = oldNumRows; i < m_numRows; i++ )
1202 {
1203 bottom += m_rowHeights[i];
1204 m_rowBottoms[i] = bottom;
1205 }
f85afd4e
MB
1206 CalcDimensions();
1207 }
1208 return TRUE;
1209
1210 case wxGRIDTABLE_NOTIFY_ROWS_DELETED:
1211 {
1212 size_t pos = msg.GetCommandInt();
1213 int numRows = msg.GetCommandInt2();
1214 for ( i = 0; i < numRows; i++ )
1215 {
1216 m_rowHeights.Remove( pos );
1217 m_rowBottoms.Remove( pos );
1218 }
1219 m_numRows -= numRows;
1220
f85afd4e
MB
1221 if ( !m_numRows )
1222 {
1223 m_numCols = 0;
1224 m_colWidths.Clear();
1225 m_colRights.Clear();
1226 m_currentCellCoords = wxGridNoCellCoords;
1227 }
2d66e025 1228 else
f85afd4e 1229 {
2d66e025
MB
1230 if ( m_currentCellCoords.GetRow() >= m_numRows )
1231 m_currentCellCoords.Set( 0, 0 );
1232
1233 int h = 0;
1234 for ( i = 0; i < m_numRows; i++ )
1235 {
1236 h += m_rowHeights[i];
1237 m_rowBottoms[i] = h;
1238 }
f85afd4e 1239 }
60ff3b99 1240
f85afd4e
MB
1241 CalcDimensions();
1242 }
1243 return TRUE;
1244
1245 case wxGRIDTABLE_NOTIFY_COLS_INSERTED:
1246 {
1247 size_t pos = msg.GetCommandInt();
1248 int numCols = msg.GetCommandInt2();
1249 for ( i = 0; i < numCols; i++ )
1250 {
1251 m_colWidths.Insert( m_defaultColWidth, pos );
1252 m_colRights.Insert( 0, pos );
1253 }
1254 m_numCols += numCols;
2d66e025
MB
1255
1256 int right = 0;
1257 if ( pos > 0 ) right = m_colRights[pos-1];
60ff3b99 1258
2d66e025
MB
1259 for ( i = pos; i < m_numCols; i++ )
1260 {
1261 right += m_colWidths[i];
1262 m_colRights[i] = right;
1263 }
f85afd4e
MB
1264 CalcDimensions();
1265 }
1266 return TRUE;
1267
1268 case wxGRIDTABLE_NOTIFY_COLS_APPENDED:
1269 {
1270 int numCols = msg.GetCommandInt();
1271 for ( i = 0; i < numCols; i++ )
1272 {
1273 m_colWidths.Add( m_defaultColWidth );
1274 m_colRights.Add( 0 );
1275 }
2d66e025
MB
1276
1277 int oldNumCols = m_numCols;
f85afd4e 1278 m_numCols += numCols;
2d66e025
MB
1279
1280 int right = 0;
1281 if ( oldNumCols > 0 ) right = m_colRights[oldNumCols-1];
60ff3b99 1282
2d66e025
MB
1283 for ( i = oldNumCols; i < m_numCols; i++ )
1284 {
1285 right += m_colWidths[i];
1286 m_colRights[i] = right;
1287 }
f85afd4e
MB
1288 CalcDimensions();
1289 }
1290 return TRUE;
1291
1292 case wxGRIDTABLE_NOTIFY_COLS_DELETED:
1293 {
1294 size_t pos = msg.GetCommandInt();
1295 int numCols = msg.GetCommandInt2();
1296 for ( i = 0; i < numCols; i++ )
1297 {
1298 m_colWidths.Remove( pos );
1299 m_colRights.Remove( pos );
1300 }
1301 m_numCols -= numCols;
f85afd4e
MB
1302
1303 if ( !m_numCols )
1304 {
1305#if 0 // leave the row alone here so that AppendCols will work subsequently
1306 m_numRows = 0;
1307 m_rowHeights.Clear();
1308 m_rowBottoms.Clear();
8f177c8e 1309#endif
f85afd4e
MB
1310 m_currentCellCoords = wxGridNoCellCoords;
1311 }
60ff3b99 1312 else
f85afd4e 1313 {
2d66e025
MB
1314 if ( m_currentCellCoords.GetCol() >= m_numCols )
1315 m_currentCellCoords.Set( 0, 0 );
1316
1317 int w = 0;
1318 for ( i = 0; i < m_numCols; i++ )
1319 {
1320 w += m_colWidths[i];
1321 m_colRights[i] = w;
1322 }
f85afd4e
MB
1323 }
1324 CalcDimensions();
1325 }
1326 return TRUE;
1327 }
1328
1329 return FALSE;
1330}
1331
1332
2d66e025 1333void wxGrid::CalcRowLabelsExposed( wxRegion& reg )
f85afd4e 1334{
2d66e025
MB
1335 wxRegionIterator iter( reg );
1336 wxRect r;
f85afd4e 1337
2d66e025 1338 m_rowLabelsExposed.Empty();
f85afd4e 1339
2d66e025
MB
1340 int top, bottom;
1341 while ( iter )
f85afd4e 1342 {
2d66e025 1343 r = iter.GetRect();
f85afd4e 1344
2d66e025
MB
1345 // TODO: remove this when we can...
1346 // There is a bug in wxMotif that gives garbage update
1347 // rectangles if you jump-scroll a long way by clicking the
1348 // scrollbar with middle button. This is a work-around
1349 //
1350#if defined(__WXMOTIF__)
1351 int cw, ch;
1352 m_gridWin->GetClientSize( &cw, &ch );
1353 if ( r.GetTop() > ch ) r.SetTop( 0 );
1354 r.SetBottom( wxMin( r.GetBottom(), ch ) );
1355#endif
f85afd4e 1356
2d66e025
MB
1357 // logical bounds of update region
1358 //
1359 int dummy;
1360 CalcUnscrolledPosition( 0, r.GetTop(), &dummy, &top );
1361 CalcUnscrolledPosition( 0, r.GetBottom(), &dummy, &bottom );
1362
1363 // find the row labels within these bounds
1364 //
1365 int row;
1366 int rowTop;
1367 for ( row = 0; row < m_numRows; row++ )
1368 {
1369 if ( m_rowBottoms[row] < top ) continue;
1370
1371 rowTop = m_rowBottoms[row] - m_rowHeights[row];
1372 if ( rowTop > bottom ) break;
60ff3b99 1373
2d66e025
MB
1374 m_rowLabelsExposed.Add( row );
1375 }
60ff3b99 1376
2d66e025 1377 iter++ ;
f85afd4e
MB
1378 }
1379}
1380
1381
2d66e025 1382void wxGrid::CalcColLabelsExposed( wxRegion& reg )
f85afd4e 1383{
2d66e025
MB
1384 wxRegionIterator iter( reg );
1385 wxRect r;
f85afd4e 1386
2d66e025 1387 m_colLabelsExposed.Empty();
f85afd4e 1388
2d66e025
MB
1389 int left, right;
1390 while ( iter )
f85afd4e 1391 {
2d66e025 1392 r = iter.GetRect();
f85afd4e 1393
2d66e025
MB
1394 // TODO: remove this when we can...
1395 // There is a bug in wxMotif that gives garbage update
1396 // rectangles if you jump-scroll a long way by clicking the
1397 // scrollbar with middle button. This is a work-around
1398 //
1399#if defined(__WXMOTIF__)
1400 int cw, ch;
1401 m_gridWin->GetClientSize( &cw, &ch );
1402 if ( r.GetLeft() > cw ) r.SetLeft( 0 );
1403 r.SetRight( wxMin( r.GetRight(), cw ) );
1404#endif
1405
1406 // logical bounds of update region
1407 //
1408 int dummy;
1409 CalcUnscrolledPosition( r.GetLeft(), 0, &left, &dummy );
1410 CalcUnscrolledPosition( r.GetRight(), 0, &right, &dummy );
1411
1412 // find the cells within these bounds
1413 //
1414 int col;
1415 int colLeft;
1416 for ( col = 0; col < m_numCols; col++ )
1417 {
1418 if ( m_colRights[col] < left ) continue;
60ff3b99 1419
2d66e025
MB
1420 colLeft = m_colRights[col] - m_colWidths[col];
1421 if ( colLeft > right ) break;
1422
1423 m_colLabelsExposed.Add( col );
1424 }
60ff3b99 1425
2d66e025 1426 iter++ ;
f85afd4e
MB
1427 }
1428}
1429
1430
2d66e025 1431void wxGrid::CalcCellsExposed( wxRegion& reg )
f85afd4e 1432{
2d66e025
MB
1433 wxRegionIterator iter( reg );
1434 wxRect r;
f85afd4e 1435
2d66e025
MB
1436 m_cellsExposed.Empty();
1437 m_rowsExposed.Empty();
1438 m_colsExposed.Empty();
f85afd4e 1439
2d66e025
MB
1440 int left, top, right, bottom;
1441 while ( iter )
1442 {
1443 r = iter.GetRect();
f85afd4e 1444
2d66e025
MB
1445 // TODO: remove this when we can...
1446 // There is a bug in wxMotif that gives garbage update
1447 // rectangles if you jump-scroll a long way by clicking the
1448 // scrollbar with middle button. This is a work-around
1449 //
1450#if defined(__WXMOTIF__)
f85afd4e 1451 int cw, ch;
2d66e025
MB
1452 m_gridWin->GetClientSize( &cw, &ch );
1453 if ( r.GetTop() > ch ) r.SetTop( 0 );
1454 if ( r.GetLeft() > cw ) r.SetLeft( 0 );
1455 r.SetRight( wxMin( r.GetRight(), cw ) );
1456 r.SetBottom( wxMin( r.GetBottom(), ch ) );
1457#endif
8f177c8e 1458
2d66e025
MB
1459 // logical bounds of update region
1460 //
1461 CalcUnscrolledPosition( r.GetLeft(), r.GetTop(), &left, &top );
1462 CalcUnscrolledPosition( r.GetRight(), r.GetBottom(), &right, &bottom );
f85afd4e 1463
c1b2e2b6 1464 left++; top++;
2d66e025 1465 // find the cells within these bounds
f85afd4e 1466 //
2d66e025
MB
1467 int row, col;
1468 int colLeft, rowTop;
1469 for ( row = 0; row < m_numRows; row++ )
f85afd4e 1470 {
2d66e025 1471 if ( m_rowBottoms[row] < top ) continue;
f85afd4e 1472
2d66e025
MB
1473 rowTop = m_rowBottoms[row] - m_rowHeights[row];
1474 if ( rowTop > bottom ) break;
60ff3b99 1475
2d66e025 1476 m_rowsExposed.Add( row );
f85afd4e 1477
2d66e025
MB
1478 for ( col = 0; col < m_numCols; col++ )
1479 {
1480 if ( m_colRights[col] < left ) continue;
60ff3b99 1481
2d66e025
MB
1482 colLeft = m_colRights[col] - m_colWidths[col];
1483 if ( colLeft > right ) break;
60ff3b99 1484
2d66e025
MB
1485 if ( m_colsExposed.Index( col ) == wxNOT_FOUND ) m_colsExposed.Add( col );
1486 m_cellsExposed.Add( wxGridCellCoords( row, col ) );
1487 }
1488 }
60ff3b99 1489
2d66e025 1490 iter++ ;
f85afd4e
MB
1491 }
1492}
1493
1494
2d66e025 1495void wxGrid::ProcessRowLabelMouseEvent( wxMouseEvent& event )
f85afd4e 1496{
2d66e025
MB
1497 int x, y, row;
1498 wxPoint pos( event.GetPosition() );
1499 CalcUnscrolledPosition( pos.x, pos.y, &x, &y );
60ff3b99 1500
2d66e025 1501 if ( event.Dragging() )
f85afd4e
MB
1502 {
1503 m_isDragging = TRUE;
8f177c8e 1504
2d66e025 1505 if ( event.LeftIsDown() )
f85afd4e
MB
1506 {
1507 switch( m_cursorMode )
1508 {
f85afd4e
MB
1509 case WXGRID_CURSOR_RESIZE_ROW:
1510 {
2d66e025
MB
1511 int cw, ch, left, dummy;
1512 m_gridWin->GetClientSize( &cw, &ch );
1513 CalcUnscrolledPosition( 0, 0, &left, &dummy );
60ff3b99 1514
2d66e025
MB
1515 wxClientDC dc( m_gridWin );
1516 PrepareDC( dc );
d2fdd8d2 1517 dc.SetLogicalFunction(wxINVERT);
f85afd4e
MB
1518 if ( m_dragLastPos >= 0 )
1519 {
2d66e025 1520 dc.DrawLine( left, m_dragLastPos, left+cw, m_dragLastPos );
f85afd4e 1521 }
2d66e025
MB
1522 dc.DrawLine( left, y, left+cw, y );
1523 m_dragLastPos = y;
f85afd4e
MB
1524 }
1525 break;
1526
1527 case WXGRID_CURSOR_SELECT_ROW:
1528 {
1529 if ( (row = YToRow( y )) >= 0 &&
1530 !IsInSelection( row, 0 ) )
1531 {
1532 SelectRow( row, TRUE );
1533 }
1534 }
1535 break;
f85afd4e
MB
1536 }
1537 }
1538 return;
1539 }
1540
1541 m_isDragging = FALSE;
8f177c8e 1542
60ff3b99 1543
2d66e025 1544 // ------------ Left button pressed
f85afd4e 1545 //
2d66e025 1546 if ( event.LeftDown() )
f85afd4e 1547 {
2d66e025
MB
1548 // don't send a label click event for a hit on the
1549 // edge of the row label - this is probably the user
1550 // wanting to resize the row
1551 //
1552 if ( YToEdgeOfRow(y) < 0 )
f85afd4e 1553 {
2d66e025 1554 row = YToRow(y);
58dd5b3b
MB
1555 if ( row >= 0 &&
1556 !SendEvent( EVT_GRID_LABEL_LEFT_CLICK, row, -1, event ) )
f85afd4e 1557 {
2d66e025
MB
1558 SelectRow( row, event.ShiftDown() );
1559 m_cursorMode = WXGRID_CURSOR_SELECT_ROW;
f85afd4e 1560 }
2d66e025
MB
1561 }
1562 else
1563 {
1564 // starting to drag-resize a row
1565 //
1566 m_rowLabelWin->CaptureMouse();
1567 }
1568 }
f85afd4e 1569
f85afd4e 1570
2d66e025
MB
1571 // ------------ Left double click
1572 //
1573 else if (event.LeftDClick() )
1574 {
1575 if ( YToEdgeOfRow(y) < 0 )
1576 {
1577 row = YToRow(y);
1578 SendEvent( EVT_GRID_LABEL_LEFT_DCLICK, row, -1, event );
f85afd4e
MB
1579 }
1580 }
60ff3b99
VZ
1581
1582
2d66e025 1583 // ------------ Left button released
f85afd4e 1584 //
2d66e025 1585 else if ( event.LeftUp() )
f85afd4e 1586 {
2d66e025 1587 if ( m_cursorMode == WXGRID_CURSOR_RESIZE_ROW )
f85afd4e 1588 {
2d66e025 1589 m_rowLabelWin->ReleaseMouse();
60ff3b99 1590
2d66e025 1591 if ( m_dragLastPos >= 0 )
f85afd4e 1592 {
2d66e025 1593 // erase the last line and resize the row
f85afd4e 1594 //
2d66e025
MB
1595 int cw, ch, left, dummy;
1596 m_gridWin->GetClientSize( &cw, &ch );
1597 CalcUnscrolledPosition( 0, 0, &left, &dummy );
60ff3b99 1598
2d66e025
MB
1599 wxClientDC dc( m_gridWin );
1600 PrepareDC( dc );
1601 dc.SetLogicalFunction( wxINVERT );
1602 dc.DrawLine( left, m_dragLastPos, left+cw, m_dragLastPos );
1603 HideCellEditControl();
1604
1605 int rowTop = m_rowBottoms[m_dragRowOrCol] - m_rowHeights[m_dragRowOrCol];
60ff3b99 1606 SetRowSize( m_dragRowOrCol, wxMax( y - rowTop, WXGRID_MIN_ROW_HEIGHT ) );
2d66e025 1607 if ( !GetBatchCount() )
f85afd4e 1608 {
70c7a608
SN
1609 // Only needed to get the correct rect.y:
1610 wxRect rect ( CellToRect( m_dragRowOrCol, 0 ) );
1611 rect.x = 0;
cb309039 1612 CalcScrolledPosition(0, rect.y, &dummy, &rect.y);
70c7a608
SN
1613 rect.width = m_rowLabelWidth;
1614 rect.height = ch - rect.y;
1615 m_rowLabelWin->Refresh( TRUE, &rect );
1616 rect.width = cw;
c6a51dcd 1617 m_gridWin->Refresh( FALSE, &rect );
f85afd4e 1618 }
60ff3b99 1619
2d66e025 1620 ShowCellEditControl();
f85afd4e 1621
2d66e025
MB
1622 // Note: we are ending the event *after* doing
1623 // default processing in this case
f85afd4e 1624 //
2d66e025 1625 SendEvent( EVT_GRID_ROW_SIZE, m_dragRowOrCol, -1, event );
f85afd4e 1626 }
2d66e025 1627 }
f85afd4e 1628
790cc417 1629 m_cursorMode = WXGRID_CURSOR_SELECT_CELL;
2d66e025
MB
1630 m_dragLastPos = -1;
1631 }
f85afd4e 1632
f85afd4e 1633
2d66e025
MB
1634 // ------------ Right button down
1635 //
1636 else if ( event.RightDown() )
1637 {
1638 row = YToRow(y);
1639 if ( !SendEvent( EVT_GRID_LABEL_RIGHT_CLICK, row, -1, event ) )
1640 {
1641 // no default action at the moment
f85afd4e
MB
1642 }
1643 }
60ff3b99
VZ
1644
1645
2d66e025 1646 // ------------ Right double click
f85afd4e 1647 //
2d66e025
MB
1648 else if ( event.RightDClick() )
1649 {
1650 row = YToRow(y);
1651 if ( !SendEvent( EVT_GRID_LABEL_RIGHT_DCLICK, row, -1, event ) )
1652 {
1653 // no default action at the moment
1654 }
1655 }
60ff3b99
VZ
1656
1657
2d66e025 1658 // ------------ No buttons down and mouse moving
f85afd4e 1659 //
2d66e025 1660 else if ( event.Moving() )
f85afd4e 1661 {
2d66e025
MB
1662 m_dragRowOrCol = YToEdgeOfRow( y );
1663 if ( m_dragRowOrCol >= 0 )
8f177c8e 1664 {
2d66e025 1665 if ( m_cursorMode == WXGRID_CURSOR_SELECT_CELL )
8f177c8e 1666 {
2d66e025
MB
1667 m_cursorMode = WXGRID_CURSOR_RESIZE_ROW;
1668 m_rowLabelWin->SetCursor( m_rowResizeCursor );
8f177c8e 1669 }
2d66e025
MB
1670 }
1671 else
1672 {
b93a2fe6
MB
1673 m_cursorMode = WXGRID_CURSOR_SELECT_CELL;
1674 if ( m_rowLabelWin->GetCursor() == m_rowResizeCursor )
2d66e025 1675 m_rowLabelWin->SetCursor( *wxSTANDARD_CURSOR );
8f177c8e 1676 }
f85afd4e 1677 }
2d66e025
MB
1678}
1679
1680
1681void wxGrid::ProcessColLabelMouseEvent( wxMouseEvent& event )
1682{
1683 int x, y, col;
1684 wxPoint pos( event.GetPosition() );
1685 CalcUnscrolledPosition( pos.x, pos.y, &x, &y );
60ff3b99 1686
2d66e025 1687 if ( event.Dragging() )
f85afd4e 1688 {
2d66e025 1689 m_isDragging = TRUE;
8f177c8e 1690
2d66e025 1691 if ( event.LeftIsDown() )
8f177c8e 1692 {
2d66e025 1693 switch( m_cursorMode )
8f177c8e 1694 {
2d66e025 1695 case WXGRID_CURSOR_RESIZE_COL:
8f177c8e 1696 {
2d66e025
MB
1697 int cw, ch, dummy, top;
1698 m_gridWin->GetClientSize( &cw, &ch );
1699 CalcUnscrolledPosition( 0, 0, &dummy, &top );
60ff3b99 1700
2d66e025
MB
1701 wxClientDC dc( m_gridWin );
1702 PrepareDC( dc );
d2fdd8d2 1703 dc.SetLogicalFunction(wxINVERT);
2d66e025
MB
1704 if ( m_dragLastPos >= 0 )
1705 {
1706 dc.DrawLine( m_dragLastPos, top, m_dragLastPos, top+ch );
1707 }
1708 dc.DrawLine( x, top, x, top+ch );
1709 m_dragLastPos = x;
f85afd4e 1710 }
2d66e025 1711 break;
f85afd4e 1712
2d66e025 1713 case WXGRID_CURSOR_SELECT_COL:
f85afd4e 1714 {
2d66e025
MB
1715 if ( (col = XToCol( x )) >= 0 &&
1716 !IsInSelection( 0, col ) )
1717 {
1718 SelectCol( col, TRUE );
1719 }
f85afd4e 1720 }
f85afd4e 1721 break;
2d66e025 1722 }
f85afd4e 1723 }
2d66e025 1724 return;
f85afd4e 1725 }
2d66e025
MB
1726
1727 m_isDragging = FALSE;
1728
60ff3b99 1729
2d66e025 1730 // ------------ Left button pressed
f85afd4e 1731 //
2d66e025 1732 if ( event.LeftDown() )
f85afd4e 1733 {
2d66e025
MB
1734 // don't send a label click event for a hit on the
1735 // edge of the col label - this is probably the user
1736 // wanting to resize the col
1737 //
1738 if ( XToEdgeOfCol(x) < 0 )
8f177c8e 1739 {
2d66e025 1740 col = XToCol(x);
58dd5b3b
MB
1741 if ( col >= 0 &&
1742 !SendEvent( EVT_GRID_LABEL_LEFT_CLICK, -1, col, event ) )
8f177c8e 1743 {
2d66e025
MB
1744 SelectCol( col, event.ShiftDown() );
1745 m_cursorMode = WXGRID_CURSOR_SELECT_COL;
f85afd4e 1746 }
2d66e025
MB
1747 }
1748 else
1749 {
1750 // starting to drag-resize a col
1751 //
1752 m_colLabelWin->CaptureMouse();
1753 }
1754 }
f85afd4e 1755
f85afd4e 1756
2d66e025
MB
1757 // ------------ Left double click
1758 //
1759 if ( event.LeftDClick() )
1760 {
1761 if ( XToEdgeOfCol(x) < 0 )
1762 {
1763 col = XToCol(x);
1764 SendEvent( EVT_GRID_LABEL_LEFT_DCLICK, -1, col, event );
1765 }
1766 }
60ff3b99
VZ
1767
1768
2d66e025
MB
1769 // ------------ Left button released
1770 //
1771 else if ( event.LeftUp() )
1772 {
1773 if ( m_cursorMode == WXGRID_CURSOR_RESIZE_COL )
1774 {
1775 m_colLabelWin->ReleaseMouse();
60ff3b99 1776
2d66e025 1777 if ( m_dragLastPos >= 0 )
f85afd4e 1778 {
2d66e025 1779 // erase the last line and resize the col
f85afd4e 1780 //
2d66e025
MB
1781 int cw, ch, dummy, top;
1782 m_gridWin->GetClientSize( &cw, &ch );
1783 CalcUnscrolledPosition( 0, 0, &dummy, &top );
60ff3b99 1784
2d66e025
MB
1785 wxClientDC dc( m_gridWin );
1786 PrepareDC( dc );
1787 dc.SetLogicalFunction( wxINVERT );
1788 dc.DrawLine( m_dragLastPos, top, m_dragLastPos, top+ch );
1789 HideCellEditControl();
1790
1791 int colLeft = m_colRights[m_dragRowOrCol] - m_colWidths[m_dragRowOrCol];
60ff3b99
VZ
1792 SetColSize( m_dragRowOrCol, wxMax( x - colLeft, WXGRID_MIN_COL_WIDTH ) );
1793
2d66e025
MB
1794 if ( !GetBatchCount() )
1795 {
70c7a608
SN
1796 // Only needed to get the correct rect.x:
1797 wxRect rect ( CellToRect( 0, m_dragRowOrCol ) );
1798 rect.y = 0;
cb309039 1799 CalcScrolledPosition(rect.x, 0, &rect.x, &dummy);
70c7a608
SN
1800 rect.width = cw - rect.x;
1801 rect.height = m_colLabelHeight;
1802 m_colLabelWin->Refresh( TRUE, &rect );
1803 rect.height = ch;
c6a51dcd 1804 m_gridWin->Refresh( FALSE, &rect );
2d66e025 1805 }
60ff3b99 1806
2d66e025 1807 ShowCellEditControl();
f85afd4e 1808
2d66e025
MB
1809 // Note: we are ending the event *after* doing
1810 // default processing in this case
1811 //
1812 SendEvent( EVT_GRID_COL_SIZE, -1, m_dragRowOrCol, event );
f85afd4e 1813 }
2d66e025 1814 }
f85afd4e 1815
790cc417 1816 m_cursorMode = WXGRID_CURSOR_SELECT_CELL;
2d66e025 1817 m_dragLastPos = -1;
60ff3b99
VZ
1818 }
1819
1820
2d66e025
MB
1821 // ------------ Right button down
1822 //
1823 else if ( event.RightDown() )
1824 {
1825 col = XToCol(x);
1826 if ( !SendEvent( EVT_GRID_LABEL_RIGHT_CLICK, -1, col, event ) )
1827 {
1828 // no default action at the moment
f85afd4e
MB
1829 }
1830 }
60ff3b99
VZ
1831
1832
2d66e025 1833 // ------------ Right double click
f85afd4e 1834 //
2d66e025
MB
1835 else if ( event.RightDClick() )
1836 {
1837 col = XToCol(x);
1838 if ( !SendEvent( EVT_GRID_LABEL_RIGHT_DCLICK, -1, col, event ) )
1839 {
1840 // no default action at the moment
1841 }
1842 }
60ff3b99
VZ
1843
1844
2d66e025 1845 // ------------ No buttons down and mouse moving
f85afd4e 1846 //
2d66e025 1847 else if ( event.Moving() )
f85afd4e 1848 {
2d66e025
MB
1849 m_dragRowOrCol = XToEdgeOfCol( x );
1850 if ( m_dragRowOrCol >= 0 )
f85afd4e 1851 {
2d66e025 1852 if ( m_cursorMode == WXGRID_CURSOR_SELECT_CELL )
f85afd4e 1853 {
2d66e025
MB
1854 m_cursorMode = WXGRID_CURSOR_RESIZE_COL;
1855 m_colLabelWin->SetCursor( m_colResizeCursor );
f85afd4e 1856 }
2d66e025
MB
1857 }
1858 else
1859 {
b93a2fe6
MB
1860 m_cursorMode = WXGRID_CURSOR_SELECT_CELL;
1861 if ( m_colLabelWin->GetCursor() == m_colResizeCursor )
2d66e025 1862 m_colLabelWin->SetCursor( *wxSTANDARD_CURSOR );
8f177c8e 1863 }
f85afd4e
MB
1864 }
1865}
1866
1867
2d66e025 1868void wxGrid::ProcessCornerLabelMouseEvent( wxMouseEvent& event )
f85afd4e 1869{
2d66e025 1870 if ( event.LeftDown() )
f85afd4e 1871 {
2d66e025
MB
1872 // indicate corner label by having both row and
1873 // col args == -1
f85afd4e 1874 //
2d66e025
MB
1875 if ( !SendEvent( EVT_GRID_LABEL_LEFT_CLICK, -1, -1, event ) )
1876 {
1877 SelectAll();
1878 }
f85afd4e
MB
1879 }
1880
2d66e025
MB
1881 else if ( event.LeftDClick() )
1882 {
1883 SendEvent( EVT_GRID_LABEL_LEFT_DCLICK, -1, -1, event );
1884 }
8f177c8e 1885
2d66e025 1886 else if ( event.RightDown() )
f85afd4e 1887 {
2d66e025 1888 if ( !SendEvent( EVT_GRID_LABEL_RIGHT_CLICK, -1, -1, event ) )
f85afd4e 1889 {
2d66e025
MB
1890 // no default action at the moment
1891 }
1892 }
f85afd4e 1893
2d66e025
MB
1894 else if ( event.RightDClick() )
1895 {
1896 if ( !SendEvent( EVT_GRID_LABEL_RIGHT_DCLICK, -1, -1, event ) )
1897 {
1898 // no default action at the moment
1899 }
1900 }
1901}
f85afd4e 1902
8f177c8e 1903
2d66e025
MB
1904void wxGrid::ProcessGridCellMouseEvent( wxMouseEvent& event )
1905{
1906 int x, y;
1907 wxPoint pos( event.GetPosition() );
1908 CalcUnscrolledPosition( pos.x, pos.y, &x, &y );
60ff3b99 1909
2d66e025
MB
1910 wxGridCellCoords coords;
1911 XYToCell( x, y, coords );
60ff3b99 1912
2d66e025
MB
1913 if ( event.Dragging() )
1914 {
1915 m_isDragging = TRUE;
2d66e025
MB
1916 if ( m_cursorMode == WXGRID_CURSOR_SELECT_CELL )
1917 {
f0102d2a
VZ
1918 // Hide the edit control, so it
1919 // won't interfer with drag-shrinking.
1920 if ( IsCellEditControlEnabled() )
1921 HideCellEditControl();
2d66e025
MB
1922 if ( coords != wxGridNoCellCoords )
1923 {
1924 if ( !IsSelection() )
f85afd4e 1925 {
2d66e025 1926 SelectBlock( coords, coords );
f85afd4e
MB
1927 }
1928 else
1929 {
f0102d2a 1930 SelectBlock( m_currentCellCoords, coords );
f85afd4e 1931 }
2d66e025
MB
1932 }
1933 }
8f177c8e 1934
2d66e025
MB
1935 return;
1936 }
66242c80 1937
2d66e025 1938 m_isDragging = FALSE;
8f177c8e 1939
58dd5b3b 1940 if ( coords != wxGridNoCellCoords )
2d66e025 1941 {
58dd5b3b 1942 if ( event.LeftDown() )
2d66e025 1943 {
58dd5b3b
MB
1944 if ( event.ShiftDown() )
1945 {
1946 SelectBlock( m_currentCellCoords, coords );
1947 }
1948 else
1949 {
1950 if ( !SendEvent( EVT_GRID_CELL_LEFT_CLICK,
1951 coords.GetRow(),
1952 coords.GetCol(),
1953 event ) )
1954 {
1955 MakeCellVisible( coords );
1956 SetCurrentCell( coords );
1957 }
1958 }
f85afd4e 1959 }
f85afd4e 1960
f85afd4e 1961
58dd5b3b
MB
1962 // ------------ Left double click
1963 //
1964 else if ( event.LeftDClick() )
1965 {
1966 SendEvent( EVT_GRID_CELL_LEFT_DCLICK,
1967 coords.GetRow(),
1968 coords.GetCol(),
1969 event );
1970 }
f85afd4e 1971
8f177c8e 1972
58dd5b3b
MB
1973 // ------------ Left button released
1974 //
1975 else if ( event.LeftUp() )
f85afd4e 1976 {
58dd5b3b 1977 if ( m_cursorMode == WXGRID_CURSOR_SELECT_CELL )
52068ea5 1978 {
58dd5b3b
MB
1979 if ( IsSelection() )
1980 {
1981 SendEvent( EVT_GRID_RANGE_SELECT, -1, -1, event );
1982 }
f85afd4e 1983 }
58dd5b3b 1984
f0102d2a
VZ
1985 // Show the edit control, if it has
1986 // been hidden for drag-shrinking.
1987 if ( IsCellEditControlEnabled() )
1988 ShowCellEditControl();
2d66e025 1989
58dd5b3b
MB
1990 m_dragLastPos = -1;
1991 }
f85afd4e 1992
f85afd4e 1993
58dd5b3b
MB
1994 // ------------ Right button down
1995 //
1996 else if ( event.RightDown() )
f85afd4e 1997 {
58dd5b3b
MB
1998 if ( !SendEvent( EVT_GRID_CELL_RIGHT_CLICK,
1999 coords.GetRow(),
2000 coords.GetCol(),
2001 event ) )
2002 {
2003 // no default action at the moment
2004 }
60ff3b99 2005 }
2d66e025 2006
60ff3b99 2007
58dd5b3b
MB
2008 // ------------ Right double click
2009 //
2010 else if ( event.RightDClick() )
f85afd4e 2011 {
58dd5b3b
MB
2012 if ( !SendEvent( EVT_GRID_CELL_RIGHT_DCLICK,
2013 coords.GetRow(),
2014 coords.GetCol(),
2015 event ) )
2016 {
2017 // no default action at the moment
2018 }
60ff3b99 2019 }
790cc417
MB
2020
2021 // ------------ Moving and no button action
2022 //
2023 else if ( event.Moving() && !event.IsButton() )
2024 {
2025 m_cursorMode = WXGRID_CURSOR_SELECT_CELL;
2026 }
f85afd4e 2027 }
f85afd4e
MB
2028}
2029
2030
2d66e025
MB
2031//
2032// ------ interaction with data model
2033//
2034bool wxGrid::ProcessTableMessage( wxGridTableMessage& msg )
f85afd4e 2035{
2d66e025 2036 switch ( msg.GetId() )
17732cec 2037 {
2d66e025
MB
2038 case wxGRIDTABLE_REQUEST_VIEW_GET_VALUES:
2039 return GetModelValues();
17732cec 2040
2d66e025
MB
2041 case wxGRIDTABLE_REQUEST_VIEW_SEND_VALUES:
2042 return SetModelValues();
f85afd4e 2043
2d66e025
MB
2044 case wxGRIDTABLE_NOTIFY_ROWS_INSERTED:
2045 case wxGRIDTABLE_NOTIFY_ROWS_APPENDED:
2046 case wxGRIDTABLE_NOTIFY_ROWS_DELETED:
2047 case wxGRIDTABLE_NOTIFY_COLS_INSERTED:
2048 case wxGRIDTABLE_NOTIFY_COLS_APPENDED:
2049 case wxGRIDTABLE_NOTIFY_COLS_DELETED:
2050 return Redimension( msg );
2051
2052 default:
2053 return FALSE;
f85afd4e 2054 }
2d66e025 2055}
f85afd4e 2056
f85afd4e 2057
f85afd4e 2058
2d66e025
MB
2059// The behaviour of this function depends on the grid table class
2060// Clear() function. For the default wxGridStringTable class the
2061// behavious is to replace all cell contents with wxEmptyString but
2062// not to change the number of rows or cols.
2063//
2064void wxGrid::ClearGrid()
2065{
2066 if ( m_table )
f85afd4e 2067 {
2d66e025
MB
2068 m_table->Clear();
2069 SetEditControlValue();
1f1ce288 2070 if ( !GetBatchCount() ) m_gridWin->Refresh();
f85afd4e
MB
2071 }
2072}
2073
2074
2d66e025 2075bool wxGrid::InsertRows( int pos, int numRows, bool WXUNUSED(updateLabels) )
f85afd4e 2076{
2d66e025 2077 // TODO: something with updateLabels flag
8f177c8e 2078
2d66e025 2079 if ( !m_created )
f85afd4e 2080 {
2d66e025
MB
2081 wxLogError( wxT("Called wxGrid::InsertRows() before calling CreateGrid()") );
2082 return FALSE;
2083 }
8f177c8e 2084
2d66e025
MB
2085 if ( m_table )
2086 {
2087 bool ok = m_table->InsertRows( pos, numRows );
f85afd4e 2088
2d66e025
MB
2089 // the table will have sent the results of the insert row
2090 // operation to this view object as a grid table message
2091 //
2092 if ( ok )
2093 {
2094 if ( m_numCols == 0 )
f85afd4e 2095 {
2d66e025
MB
2096 m_table->AppendCols( WXGRID_DEFAULT_NUMBER_COLS );
2097 //
2098 // TODO: perhaps instead of appending the default number of cols
2099 // we should remember what the last non-zero number of cols was ?
2100 //
2101 }
8f177c8e 2102
2d66e025
MB
2103 if ( m_currentCellCoords == wxGridNoCellCoords )
2104 {
2105 // if we have just inserted cols into an empty grid the current
2106 // cell will be undefined...
2107 //
2108 SetCurrentCell( 0, 0 );
f85afd4e
MB
2109 }
2110
2d66e025
MB
2111 ClearSelection();
2112 if ( !GetBatchCount() ) Refresh();
f85afd4e 2113 }
2d66e025
MB
2114
2115 SetEditControlValue();
2116 return ok;
2117 }
2118 else
2119 {
2120 return FALSE;
f85afd4e
MB
2121 }
2122}
2123
2124
2d66e025 2125bool wxGrid::AppendRows( int numRows, bool WXUNUSED(updateLabels) )
f85afd4e 2126{
2d66e025
MB
2127 // TODO: something with updateLabels flag
2128
2129 if ( !m_created )
f85afd4e 2130 {
2d66e025
MB
2131 wxLogError( wxT("Called wxGrid::AppendRows() before calling CreateGrid()") );
2132 return FALSE;
2133 }
2134
2135 if ( m_table && m_table->AppendRows( numRows ) )
2136 {
2137 if ( m_currentCellCoords == wxGridNoCellCoords )
2138 {
2139 // if we have just inserted cols into an empty grid the current
2140 // cell will be undefined...
2141 //
2142 SetCurrentCell( 0, 0 );
2143 }
2144
2145 // the table will have sent the results of the append row
2146 // operation to this view object as a grid table message
2147 //
2148 ClearSelection();
2149 if ( !GetBatchCount() ) Refresh();
2150 return TRUE;
2151 }
2152 else
2153 {
2154 return FALSE;
f85afd4e
MB
2155 }
2156}
2157
2d66e025
MB
2158
2159bool wxGrid::DeleteRows( int pos, int numRows, bool WXUNUSED(updateLabels) )
f85afd4e 2160{
2d66e025
MB
2161 // TODO: something with updateLabels flag
2162
2163 if ( !m_created )
f85afd4e 2164 {
2d66e025
MB
2165 wxLogError( wxT("Called wxGrid::DeleteRows() before calling CreateGrid()") );
2166 return FALSE;
2167 }
2168
2169 if ( m_table && m_table->DeleteRows( pos, numRows ) )
2170 {
2171 // the table will have sent the results of the delete row
2172 // operation to this view object as a grid table message
2173 //
2174 if ( m_numRows > 0 )
2175 SetEditControlValue();
2b37dc19 2176 else
2d66e025 2177 HideCellEditControl();
f85afd4e 2178
2d66e025
MB
2179 ClearSelection();
2180 if ( !GetBatchCount() ) Refresh();
2181 return TRUE;
2182 }
2183 else
2184 {
2185 return FALSE;
2186 }
2187}
f85afd4e 2188
f85afd4e 2189
2d66e025
MB
2190bool wxGrid::InsertCols( int pos, int numCols, bool WXUNUSED(updateLabels) )
2191{
2192 // TODO: something with updateLabels flag
8f177c8e 2193
2d66e025
MB
2194 if ( !m_created )
2195 {
2196 wxLogError( wxT("Called wxGrid::InsertCols() before calling CreateGrid()") );
2197 return FALSE;
2198 }
f85afd4e 2199
2d66e025
MB
2200 if ( m_table )
2201 {
2202 HideCellEditControl();
2203 bool ok = m_table->InsertCols( pos, numCols );
2204
2205 // the table will have sent the results of the insert col
2206 // operation to this view object as a grid table message
2207 //
2208 if ( ok )
f85afd4e 2209 {
2d66e025 2210 if ( m_currentCellCoords == wxGridNoCellCoords )
f85afd4e 2211 {
2d66e025
MB
2212 // if we have just inserted cols into an empty grid the current
2213 // cell will be undefined...
2214 //
2215 SetCurrentCell( 0, 0 );
f85afd4e 2216 }
2d66e025
MB
2217
2218 ClearSelection();
2219 if ( !GetBatchCount() ) Refresh();
f85afd4e 2220 }
2d66e025
MB
2221
2222 SetEditControlValue();
2223 return ok;
2224 }
2225 else
2226 {
2227 return FALSE;
f85afd4e
MB
2228 }
2229}
2230
2d66e025
MB
2231
2232bool wxGrid::AppendCols( int numCols, bool WXUNUSED(updateLabels) )
f85afd4e 2233{
2d66e025
MB
2234 // TODO: something with updateLabels flag
2235
2236 if ( !m_created )
f85afd4e 2237 {
2d66e025
MB
2238 wxLogError( wxT("Called wxGrid::AppendCols() before calling CreateGrid()") );
2239 return FALSE;
2240 }
f85afd4e 2241
2d66e025
MB
2242 if ( m_table && m_table->AppendCols( numCols ) )
2243 {
2244 // the table will have sent the results of the append col
2245 // operation to this view object as a grid table message
2246 //
2247 if ( m_currentCellCoords == wxGridNoCellCoords )
f85afd4e 2248 {
2d66e025
MB
2249 // if we have just inserted cols into an empty grid the current
2250 // cell will be undefined...
2251 //
2252 SetCurrentCell( 0, 0 );
f85afd4e 2253 }
8f177c8e 2254
2d66e025
MB
2255 ClearSelection();
2256 if ( !GetBatchCount() ) Refresh();
2257 return TRUE;
f85afd4e 2258 }
2d66e025 2259 else
f85afd4e 2260 {
2d66e025 2261 return FALSE;
f85afd4e 2262 }
f85afd4e
MB
2263}
2264
2265
2d66e025 2266bool wxGrid::DeleteCols( int pos, int numCols, bool WXUNUSED(updateLabels) )
f85afd4e 2267{
2d66e025 2268 // TODO: something with updateLabels flag
8f177c8e 2269
2d66e025 2270 if ( !m_created )
f85afd4e 2271 {
2d66e025
MB
2272 wxLogError( wxT("Called wxGrid::DeleteCols() before calling CreateGrid()") );
2273 return FALSE;
f85afd4e
MB
2274 }
2275
2d66e025
MB
2276 if ( m_table && m_table->DeleteCols( pos, numCols ) )
2277 {
2278 // the table will have sent the results of the delete col
2279 // operation to this view object as a grid table message
2280 //
2281 if ( m_numCols > 0 )
2282 SetEditControlValue();
2283 else
2284 HideCellEditControl();
8f177c8e 2285
2d66e025
MB
2286 ClearSelection();
2287 if ( !GetBatchCount() ) Refresh();
2288 return TRUE;
2289 }
2290 else
f85afd4e 2291 {
2d66e025 2292 return FALSE;
f85afd4e 2293 }
f85afd4e
MB
2294}
2295
2296
2d66e025
MB
2297
2298//
2299// ----- event handlers
f85afd4e 2300//
8f177c8e 2301
2d66e025
MB
2302// Generate a grid event based on a mouse event and
2303// return the result of ProcessEvent()
2304//
2305bool wxGrid::SendEvent( const wxEventType type,
2306 int row, int col,
2307 wxMouseEvent& mouseEv )
2308{
2309 if ( type == EVT_GRID_ROW_SIZE ||
2310 type == EVT_GRID_COL_SIZE )
f85afd4e 2311 {
2d66e025
MB
2312 int rowOrCol = (row == -1 ? col : row);
2313
2314 wxGridSizeEvent gridEvt( GetId(),
2315 type,
2316 this,
2317 rowOrCol,
2318 mouseEv.GetX(), mouseEv.GetY(),
2319 mouseEv.ControlDown(),
2320 mouseEv.ShiftDown(),
2321 mouseEv.AltDown(),
2322 mouseEv.MetaDown() );
2323
2324 return GetEventHandler()->ProcessEvent(gridEvt);
f85afd4e 2325 }
2d66e025
MB
2326 else if ( type == EVT_GRID_RANGE_SELECT )
2327 {
2328 wxGridRangeSelectEvent gridEvt( GetId(),
2329 type,
2330 this,
2331 m_selectedTopLeft,
2332 m_selectedBottomRight,
2333 mouseEv.ControlDown(),
2334 mouseEv.ShiftDown(),
2335 mouseEv.AltDown(),
2336 mouseEv.MetaDown() );
f85afd4e 2337
2d66e025
MB
2338 return GetEventHandler()->ProcessEvent(gridEvt);
2339 }
2340 else
2341 {
2342 wxGridEvent gridEvt( GetId(),
2343 type,
2344 this,
2345 row, col,
2346 mouseEv.GetX(), mouseEv.GetY(),
2347 mouseEv.ControlDown(),
2348 mouseEv.ShiftDown(),
2349 mouseEv.AltDown(),
2350 mouseEv.MetaDown() );
8f177c8e 2351
2d66e025
MB
2352 return GetEventHandler()->ProcessEvent(gridEvt);
2353 }
f85afd4e
MB
2354}
2355
2356
2d66e025
MB
2357// Generate a grid event of specified type and return the result
2358// of ProcessEvent().
f85afd4e 2359//
2d66e025
MB
2360bool wxGrid::SendEvent( const wxEventType type,
2361 int row, int col )
f85afd4e 2362{
2d66e025
MB
2363 if ( type == EVT_GRID_ROW_SIZE ||
2364 type == EVT_GRID_COL_SIZE )
f85afd4e 2365 {
2d66e025 2366 int rowOrCol = (row == -1 ? col : row);
f85afd4e 2367
2d66e025
MB
2368 wxGridSizeEvent gridEvt( GetId(),
2369 type,
2370 this,
2371 rowOrCol );
2372
2373 return GetEventHandler()->ProcessEvent(gridEvt);
2374 }
2375 else
2376 {
2377 wxGridEvent gridEvt( GetId(),
2378 type,
2379 this,
2380 row, col );
8f177c8e 2381
2d66e025
MB
2382 return GetEventHandler()->ProcessEvent(gridEvt);
2383 }
f85afd4e
MB
2384}
2385
2386
2d66e025 2387void wxGrid::OnPaint( wxPaintEvent& WXUNUSED(event) )
f85afd4e 2388{
2d66e025 2389 wxPaintDC dc( this );
f85afd4e 2390
2d66e025
MB
2391 if ( m_currentCellCoords == wxGridNoCellCoords &&
2392 m_numRows && m_numCols )
f85afd4e 2393 {
2d66e025
MB
2394 m_currentCellCoords.Set(0, 0);
2395 SetEditControlValue();
2396 ShowCellEditControl();
f85afd4e 2397 }
4634a5d6
MB
2398
2399 m_displayed = TRUE;
8f177c8e 2400}
f85afd4e
MB
2401
2402
18f9565d
MB
2403// This is just here to make sure that CalcDimensions gets called when
2404// the grid view is resized... then the size event is skipped to allow
2405// the box sizers to handle everything
2406//
2d66e025 2407void wxGrid::OnSize( wxSizeEvent& event )
f85afd4e 2408{
7807d81c 2409 CalcWindowSizes();
2d66e025 2410 CalcDimensions();
f85afd4e
MB
2411}
2412
f85afd4e 2413
2d66e025 2414void wxGrid::OnKeyDown( wxKeyEvent& event )
f85afd4e 2415{
2d66e025 2416 if ( m_inOnKeyDown )
f85afd4e 2417 {
2d66e025
MB
2418 // shouldn't be here - we are going round in circles...
2419 //
2420 wxLogFatalError( wxT("wxGrid::OnKeyDown called while alread active") );
f85afd4e
MB
2421 }
2422
2d66e025 2423 m_inOnKeyDown = TRUE;
f85afd4e 2424
2d66e025
MB
2425 // propagate the event up and see if it gets processed
2426 //
2427 wxWindow *parent = GetParent();
2428 wxKeyEvent keyEvt( event );
2429 keyEvt.SetEventObject( parent );
2430
2431 if ( !parent->GetEventHandler()->ProcessEvent( keyEvt ) )
f85afd4e 2432 {
2d66e025
MB
2433 // try local handlers
2434 //
2435 switch ( event.KeyCode() )
2436 {
2437 case WXK_UP:
2438 if ( event.ControlDown() )
2439 {
2440 MoveCursorUpBlock();
2441 }
2442 else
2443 {
2444 MoveCursorUp();
2445 }
2446 break;
f85afd4e 2447
2d66e025
MB
2448 case WXK_DOWN:
2449 if ( event.ControlDown() )
2450 {
2451 MoveCursorDownBlock();
2452 }
2453 else
2454 {
2455 MoveCursorDown();
2456 }
2457 break;
8f177c8e 2458
2d66e025
MB
2459 case WXK_LEFT:
2460 if ( event.ControlDown() )
2461 {
2462 MoveCursorLeftBlock();
2463 }
2464 else
2465 {
2466 MoveCursorLeft();
2467 }
2468 break;
2469
2470 case WXK_RIGHT:
2471 if ( event.ControlDown() )
2472 {
2473 MoveCursorRightBlock();
2474 }
2475 else
2476 {
2477 MoveCursorRight();
2478 }
2479 break;
f603012f
MB
2480
2481 case WXK_SPACE:
2482 if ( !IsEditable() )
2483 {
2484 MoveCursorRight();
2485 }
2486 else
2487 {
8a9a9d58 2488 event.Skip();
f603012f 2489 }
8febdd39 2490 break;
2d66e025
MB
2491
2492 case WXK_RETURN:
58dd5b3b
MB
2493 if ( event.ControlDown() )
2494 {
2495 event.Skip(); // to let the edit control have the return
2496 }
2497 else
2498 {
2499 MoveCursorDown();
2500 }
2d66e025
MB
2501 break;
2502
2503 case WXK_HOME:
2504 if ( event.ControlDown() )
2505 {
2506 MakeCellVisible( 0, 0 );
2507 SetCurrentCell( 0, 0 );
2508 }
2509 else
2510 {
2511 event.Skip();
2512 }
2513 break;
2514
2515 case WXK_END:
2516 if ( event.ControlDown() )
2517 {
2518 MakeCellVisible( m_numRows-1, m_numCols-1 );
2519 SetCurrentCell( m_numRows-1, m_numCols-1 );
2520 }
2521 else
2522 {
2523 event.Skip();
2524 }
2525 break;
2526
2527 case WXK_PRIOR:
2528 MovePageUp();
2529 break;
2530
2531 case WXK_NEXT:
2532 MovePageDown();
2533 break;
2534
2535 default:
2536 // now try the cell edit control
2537 //
2538 if ( IsCellEditControlEnabled() )
2539 {
2540 event.SetEventObject( m_cellEditCtrl );
2541 m_cellEditCtrl->GetEventHandler()->ProcessEvent( event );
2542 }
2543 break;
2544 }
f85afd4e
MB
2545 }
2546
2d66e025 2547 m_inOnKeyDown = FALSE;
f85afd4e
MB
2548}
2549
2d66e025
MB
2550
2551void wxGrid::SetCurrentCell( const wxGridCellCoords& coords )
66242c80 2552{
2d66e025 2553 if ( SendEvent( EVT_GRID_SELECT_CELL, coords.GetRow(), coords.GetCol() ) )
66242c80 2554 {
2d66e025
MB
2555 // the event has been intercepted - do nothing
2556 return;
2557 }
66242c80 2558
4634a5d6
MB
2559 if ( m_displayed &&
2560 m_currentCellCoords != wxGridNoCellCoords )
2d66e025 2561 {
2d66e025
MB
2562 HideCellEditControl();
2563 SaveEditControlValue();
66242c80 2564 }
8f177c8e 2565
2d66e025
MB
2566 m_currentCellCoords = coords;
2567
2568 SetEditControlValue();
2d66e025 2569
4634a5d6 2570 if ( m_displayed )
2d66e025 2571 {
4634a5d6
MB
2572 ShowCellEditControl();
2573
2574 if ( IsSelection() )
2575 {
2576 wxRect r( SelectionToDeviceRect() );
2577 ClearSelection();
2578 if ( !GetBatchCount() ) m_gridWin->Refresh( FALSE, &r );
2579 }
2d66e025 2580 }
66242c80
MB
2581}
2582
2d66e025
MB
2583
2584//
2585// ------ functions to get/send data (see also public functions)
2586//
2587
2588bool wxGrid::GetModelValues()
66242c80 2589{
2d66e025 2590 if ( m_table )
66242c80 2591 {
2d66e025 2592 // all we need to do is repaint the grid
66242c80 2593 //
2d66e025 2594 m_gridWin->Refresh();
66242c80
MB
2595 return TRUE;
2596 }
8f177c8e 2597
66242c80
MB
2598 return FALSE;
2599}
2600
2d66e025
MB
2601
2602bool wxGrid::SetModelValues()
f85afd4e 2603{
2d66e025 2604 int row, col;
8f177c8e 2605
2d66e025
MB
2606 if ( m_table )
2607 {
2608 for ( row = 0; row < m_numRows; row++ )
f85afd4e 2609 {
2d66e025 2610 for ( col = 0; col < m_numCols; col++ )
f85afd4e 2611 {
2d66e025 2612 m_table->SetValue( row, col, GetCellValue(row, col) );
f85afd4e
MB
2613 }
2614 }
8f177c8e 2615
f85afd4e
MB
2616 return TRUE;
2617 }
2618
2619 return FALSE;
2620}
2621
2d66e025
MB
2622
2623
2624// Note - this function only draws cells that are in the list of
2625// exposed cells (usually set from the update region by
2626// CalcExposedCells)
2627//
2628void wxGrid::DrawGridCellArea( wxDC& dc )
f85afd4e 2629{
2d66e025 2630 if ( !m_numRows || !m_numCols ) return;
60ff3b99 2631
2d66e025
MB
2632 size_t i;
2633 size_t numCells = m_cellsExposed.GetCount();
60ff3b99 2634
2d66e025 2635 for ( i = 0; i < numCells; i++ )
f85afd4e 2636 {
2d66e025
MB
2637 DrawCell( dc, m_cellsExposed[i] );
2638 }
2639}
8f177c8e 2640
8f177c8e 2641
2d66e025
MB
2642void wxGrid::DrawCell( wxDC& dc, const wxGridCellCoords& coords )
2643{
2644 if ( m_colWidths[coords.GetCol()] <=0 ||
2645 m_rowHeights[coords.GetRow()] <= 0 ) return;
60ff3b99 2646
9496deb5 2647#if !WXGRID_DRAW_LINES
2d66e025
MB
2648 if ( m_gridLinesEnabled )
2649 DrawCellBorder( dc, coords );
796df70a 2650#endif
f85afd4e 2651
2d66e025 2652 DrawCellBackground( dc, coords );
f85afd4e 2653
2d66e025
MB
2654 // TODO: separate functions here for different kinds of cells ?
2655 // e.g. text, image
2656 //
2657 DrawCellValue( dc, coords );
2658}
f85afd4e 2659
2d66e025
MB
2660
2661void wxGrid::DrawCellBorder( wxDC& dc, const wxGridCellCoords& coords )
2662{
2663 if ( m_colWidths[coords.GetCol()] <=0 ||
2664 m_rowHeights[coords.GetRow()] <= 0 ) return;
60ff3b99 2665
2d66e025
MB
2666 dc.SetPen( wxPen(GetGridLineColour(), 1, wxSOLID) );
2667 int row = coords.GetRow();
2668 int col = coords.GetCol();
60ff3b99 2669
2d66e025
MB
2670 // right hand border
2671 //
27fa3246
MB
2672 dc.DrawLine( m_colRights[col]-1, m_rowBottoms[row] - m_rowHeights[row],
2673 m_colRights[col]-1, m_rowBottoms[row]-1 );
2d66e025
MB
2674
2675 // bottom border
2676 //
27fa3246
MB
2677 dc.DrawLine( m_colRights[col] - m_colWidths[col], m_rowBottoms[row]-1,
2678 m_colRights[col]-1, m_rowBottoms[row]-1 );
f85afd4e
MB
2679}
2680
2d66e025
MB
2681
2682void wxGrid::DrawCellBackground( wxDC& dc, const wxGridCellCoords& coords )
f85afd4e 2683{
2d66e025
MB
2684 if ( m_colWidths[coords.GetCol()] <=0 ||
2685 m_rowHeights[coords.GetRow()] <= 0 ) return;
60ff3b99 2686
2d66e025
MB
2687 int row = coords.GetRow();
2688 int col = coords.GetCol();
8f177c8e 2689
2d66e025 2690 dc.SetBackgroundMode( wxSOLID );
f85afd4e 2691
2d66e025
MB
2692 if ( IsInSelection( coords ) )
2693 {
2694 // TODO: improve this
2695 //
2696 dc.SetBrush( *wxBLACK_BRUSH );
f85afd4e 2697 }
2d66e025 2698 else
f85afd4e 2699 {
2d66e025 2700 dc.SetBrush( wxBrush(GetCellBackgroundColour(row, col), wxSOLID) );
f85afd4e
MB
2701 }
2702
2d66e025 2703 dc.SetPen( *wxTRANSPARENT_PEN );
8f177c8e 2704
2d66e025
MB
2705 dc.DrawRectangle( m_colRights[col] - m_colWidths[col] + 1,
2706 m_rowBottoms[row] - m_rowHeights[row] + 1,
2707 m_colWidths[col]-1,
2708 m_rowHeights[row]-1 );
f85afd4e
MB
2709}
2710
2711
2d66e025 2712void wxGrid::DrawCellValue( wxDC& dc, const wxGridCellCoords& coords )
f85afd4e 2713{
2d66e025
MB
2714 if ( m_colWidths[coords.GetCol()] <=0 ||
2715 m_rowHeights[coords.GetRow()] <= 0 ) return;
60ff3b99 2716
2d66e025
MB
2717 int row = coords.GetRow();
2718 int col = coords.GetCol();
f85afd4e 2719
2d66e025 2720 dc.SetBackgroundMode( wxTRANSPARENT );
8f177c8e 2721
2d66e025
MB
2722 if ( IsInSelection( row, col ) )
2723 {
2724 // TODO: improve this
2725 //
2726 dc.SetTextBackground( wxColour(0, 0, 0) );
2727 dc.SetTextForeground( wxColour(255, 255, 255) );
2728 }
2729 else
f85afd4e 2730 {
2d66e025
MB
2731 dc.SetTextBackground( GetCellBackgroundColour(row, col) );
2732 dc.SetTextForeground( GetCellTextColour(row, col) );
2733 }
2734 dc.SetFont( GetCellFont(row, col) );
f85afd4e 2735
2d66e025
MB
2736 int hAlign, vAlign;
2737 GetCellAlignment( row, col, &hAlign, &vAlign );
8f177c8e 2738
2d66e025
MB
2739 wxRect rect;
2740 rect.SetX( m_colRights[col] - m_colWidths[col] + 2 );
2741 rect.SetY( m_rowBottoms[row] - m_rowHeights[row] + 2 );
2742 rect.SetWidth( m_colWidths[col] - 4 );
2743 rect.SetHeight( m_rowHeights[row] - 4 );
60ff3b99 2744
2d66e025 2745 DrawTextRectangle( dc, GetCellValue( row, col ), rect, hAlign, vAlign );
f85afd4e
MB
2746}
2747
2748
2d66e025
MB
2749
2750// TODO: remove this ???
2751// This is used to redraw all grid lines e.g. when the grid line colour
2752// has been changed
2753//
796df70a 2754void wxGrid::DrawAllGridLines( wxDC& dc, const wxRegion & reg )
f85afd4e 2755{
60ff3b99
VZ
2756 if ( !m_gridLinesEnabled ||
2757 !m_numRows ||
2d66e025 2758 !m_numCols ) return;
f85afd4e 2759
2d66e025 2760 int top, bottom, left, right;
796df70a
SN
2761
2762 if (reg.IsEmpty()){
2763 int cw, ch;
2764 m_gridWin->GetClientSize(&cw, &ch);
2765
2766 // virtual coords of visible area
2767 //
2768 CalcUnscrolledPosition( 0, 0, &left, &top );
2769 CalcUnscrolledPosition( cw, ch, &right, &bottom );
2770 }
2771 else{
2772 wxCoord x, y, w, h;
2773 reg.GetBox(x, y, w, h);
2774 CalcUnscrolledPosition( x, y, &left, &top );
2775 CalcUnscrolledPosition( x + w, y + h, &right, &bottom );
2776 }
f85afd4e 2777
9496deb5
MB
2778 // avoid drawing grid lines past the last row and col
2779 //
2780 right = wxMin( right, m_colRights[m_numCols-1] );
2781 bottom = wxMin( bottom, m_rowBottoms[m_numRows-1] );
2782
2d66e025 2783 dc.SetPen( wxPen(GetGridLineColour(), 1, wxSOLID) );
f85afd4e 2784
2d66e025 2785 // horizontal grid lines
f85afd4e 2786 //
60ff3b99 2787 int i;
9496deb5 2788 for ( i = 0; i < m_numRows; i++ )
f85afd4e 2789 {
27fa3246 2790 if ( m_rowBottoms[i]-1 > bottom )
2d66e025
MB
2791 {
2792 break;
2793 }
27fa3246 2794 else if ( m_rowBottoms[i]-1 >= top )
2d66e025 2795 {
27fa3246 2796 dc.DrawLine( left, m_rowBottoms[i]-1, right, m_rowBottoms[i]-1 );
2d66e025 2797 }
f85afd4e
MB
2798 }
2799
f85afd4e 2800
2d66e025
MB
2801 // vertical grid lines
2802 //
9496deb5 2803 for ( i = 0; i < m_numCols; i++ )
f85afd4e 2804 {
27fa3246 2805 if ( m_colRights[i]-1 > right )
2d66e025
MB
2806 {
2807 break;
2808 }
27fa3246 2809 else if ( m_colRights[i]-1 >= left )
2d66e025 2810 {
27fa3246 2811 dc.DrawLine( m_colRights[i]-1, top, m_colRights[i]-1, bottom );
2d66e025
MB
2812 }
2813 }
2814}
f85afd4e 2815
8f177c8e 2816
2d66e025
MB
2817void wxGrid::DrawRowLabels( wxDC& dc )
2818{
2819 if ( !m_numRows || !m_numCols ) return;
60ff3b99 2820
2d66e025
MB
2821 size_t i;
2822 size_t numLabels = m_rowLabelsExposed.GetCount();
60ff3b99 2823
2d66e025
MB
2824 for ( i = 0; i < numLabels; i++ )
2825 {
2826 DrawRowLabel( dc, m_rowLabelsExposed[i] );
60ff3b99 2827 }
f85afd4e
MB
2828}
2829
2830
2d66e025 2831void wxGrid::DrawRowLabel( wxDC& dc, int row )
f85afd4e 2832{
2d66e025 2833 if ( m_rowHeights[row] <= 0 ) return;
60ff3b99 2834
b0d6ff2f
MB
2835 int rowTop = m_rowBottoms[row] - m_rowHeights[row];
2836
2d66e025 2837 dc.SetPen( *wxBLACK_PEN );
b0d6ff2f
MB
2838 dc.DrawLine( m_rowLabelWidth-1, rowTop,
2839 m_rowLabelWidth-1, m_rowBottoms[row]-1 );
2840
2841 dc.DrawLine( 0, m_rowBottoms[row]-1,
2842 m_rowLabelWidth-1, m_rowBottoms[row]-1 );
2843
2d66e025 2844 dc.SetPen( *wxWHITE_PEN );
b0d6ff2f
MB
2845 dc.DrawLine( 0, rowTop, 0, m_rowBottoms[row]-1 );
2846 dc.DrawLine( 0, rowTop, m_rowLabelWidth-1, rowTop );
60ff3b99 2847
f85afd4e 2848 dc.SetBackgroundMode( wxTRANSPARENT );
f85afd4e
MB
2849 dc.SetTextForeground( GetLabelTextColour() );
2850 dc.SetFont( GetLabelFont() );
8f177c8e 2851
f85afd4e 2852 int hAlign, vAlign;
2d66e025 2853 GetRowLabelAlignment( &hAlign, &vAlign );
60ff3b99 2854
2d66e025
MB
2855 wxRect rect;
2856 rect.SetX( 2 );
2857 rect.SetY( m_rowBottoms[row] - m_rowHeights[row] + 2 );
2858 rect.SetWidth( m_rowLabelWidth - 4 );
2859 rect.SetHeight( m_rowHeights[row] - 4 );
60ff3b99 2860 DrawTextRectangle( dc, GetRowLabelValue( row ), rect, hAlign, vAlign );
f85afd4e
MB
2861}
2862
2863
2d66e025 2864void wxGrid::DrawColLabels( wxDC& dc )
f85afd4e 2865{
2d66e025 2866 if ( !m_numRows || !m_numCols ) return;
60ff3b99 2867
2d66e025
MB
2868 size_t i;
2869 size_t numLabels = m_colLabelsExposed.GetCount();
60ff3b99 2870
2d66e025 2871 for ( i = 0; i < numLabels; i++ )
f85afd4e 2872 {
2d66e025 2873 DrawColLabel( dc, m_colLabelsExposed[i] );
60ff3b99 2874 }
f85afd4e
MB
2875}
2876
2877
2d66e025 2878void wxGrid::DrawColLabel( wxDC& dc, int col )
f85afd4e 2879{
2d66e025 2880 if ( m_colWidths[col] <= 0 ) return;
60ff3b99 2881
b0d6ff2f
MB
2882 int colLeft = m_colRights[col] - m_colWidths[col];
2883
2d66e025 2884 dc.SetPen( *wxBLACK_PEN );
b0d6ff2f
MB
2885 dc.DrawLine( m_colRights[col]-1, 0,
2886 m_colRights[col]-1, m_colLabelHeight-1 );
2887
2888 dc.DrawLine( colLeft, m_colLabelHeight-1,
2889 m_colRights[col]-1, m_colLabelHeight-1 );
2890
f85afd4e 2891 dc.SetPen( *wxWHITE_PEN );
b0d6ff2f
MB
2892 dc.DrawLine( colLeft, 0, colLeft, m_colLabelHeight-1 );
2893 dc.DrawLine( colLeft, 0, m_colRights[col]-1, 0 );
f85afd4e 2894
b0d6ff2f
MB
2895 dc.SetBackgroundMode( wxTRANSPARENT );
2896 dc.SetTextForeground( GetLabelTextColour() );
2897 dc.SetFont( GetLabelFont() );
8f177c8e 2898
f85afd4e 2899 dc.SetBackgroundMode( wxTRANSPARENT );
f85afd4e
MB
2900 dc.SetTextForeground( GetLabelTextColour() );
2901 dc.SetFont( GetLabelFont() );
8f177c8e 2902
f85afd4e 2903 int hAlign, vAlign;
2d66e025 2904 GetColLabelAlignment( &hAlign, &vAlign );
60ff3b99 2905
2d66e025
MB
2906 wxRect rect;
2907 rect.SetX( m_colRights[col] - m_colWidths[col] + 2 );
2908 rect.SetY( 2 );
2909 rect.SetWidth( m_colWidths[col] - 4 );
2910 rect.SetHeight( m_colLabelHeight - 4 );
60ff3b99 2911 DrawTextRectangle( dc, GetColLabelValue( col ), rect, hAlign, vAlign );
f85afd4e
MB
2912}
2913
2914
2d66e025
MB
2915void wxGrid::DrawTextRectangle( wxDC& dc,
2916 const wxString& value,
2917 const wxRect& rect,
2918 int horizAlign,
2919 int vertAlign )
f85afd4e 2920{
2d66e025
MB
2921 long textWidth, textHeight;
2922 long lineWidth, lineHeight;
2923 wxArrayString lines;
f85afd4e 2924
2d66e025
MB
2925 dc.SetClippingRegion( rect );
2926 StringToLines( value, lines );
2927 if ( lines.GetCount() )
2928 {
2929 GetTextBoxSize( dc, lines, &textWidth, &textHeight );
2930 dc.GetTextExtent( lines[0], &lineWidth, &lineHeight );
f85afd4e 2931
2d66e025
MB
2932 float x, y;
2933 switch ( horizAlign )
2934 {
2935 case wxRIGHT:
2936 x = rect.x + (rect.width - textWidth - 1);
2937 break;
f85afd4e 2938
2d66e025
MB
2939 case wxCENTRE:
2940 x = rect.x + ((rect.width - textWidth)/2);
2941 break;
f85afd4e 2942
2d66e025
MB
2943 case wxLEFT:
2944 default:
2945 x = rect.x + 1;
2946 break;
2947 }
f85afd4e 2948
2d66e025
MB
2949 switch ( vertAlign )
2950 {
2951 case wxBOTTOM:
2952 y = rect.y + (rect.height - textHeight - 1);
2953 break;
f85afd4e
MB
2954
2955 case wxCENTRE:
8f177c8e 2956 y = rect.y + ((rect.height - textHeight)/2);
f85afd4e
MB
2957 break;
2958
2959 case wxTOP:
2960 default:
8f177c8e 2961 y = rect.y + 1;
f85afd4e
MB
2962 break;
2963 }
2964
b540eb2b 2965 for ( size_t i = 0; i < lines.GetCount(); i++ )
f85afd4e
MB
2966 {
2967 dc.DrawText( lines[i], (long)x, (long)y );
2968 y += lineHeight;
2969 }
2970 }
8f177c8e 2971
f85afd4e 2972 dc.DestroyClippingRegion();
f85afd4e
MB
2973}
2974
2975
2976// Split multi line text up into an array of strings. Any existing
2977// contents of the string array are preserved.
2978//
2979void wxGrid::StringToLines( const wxString& value, wxArrayString& lines )
2980{
2981 // TODO: this won't work for WXMAC ? (lines end with '\r')
b540eb2b 2982 // => use wxTextFile functions then (VZ)
f85afd4e
MB
2983 int startPos = 0;
2984 int pos;
b540eb2b 2985 while ( startPos < (int)value.Length() )
f85afd4e
MB
2986 {
2987 pos = value.Mid(startPos).Find( '\n' );
2988 if ( pos < 0 )
2989 {
2990 break;
2991 }
2992 else if ( pos == 0 )
2993 {
2994 lines.Add( wxEmptyString );
2995 }
2996 else
2997 {
2998 if ( value[startPos+pos-1] == '\r' )
2999 {
3000 lines.Add( value.Mid(startPos, pos-1) );
3001 }
3002 else
3003 {
3004 lines.Add( value.Mid(startPos, pos) );
3005 }
3006 }
3007 startPos += pos+1;
3008 }
b540eb2b 3009 if ( startPos < (int)value.Length() )
f85afd4e
MB
3010 {
3011 lines.Add( value.Mid( startPos ) );
3012 }
3013}
3014
3015
3016void wxGrid::GetTextBoxSize( wxDC& dc,
3017 wxArrayString& lines,
3018 long *width, long *height )
3019{
3020 long w = 0;
3021 long h = 0;
3022 long lineW, lineH;
3023
b540eb2b 3024 size_t i;
f85afd4e
MB
3025 for ( i = 0; i < lines.GetCount(); i++ )
3026 {
3027 dc.GetTextExtent( lines[i], &lineW, &lineH );
3028 w = wxMax( w, lineW );
3029 h += lineH;
3030 }
3031
3032 *width = w;
3033 *height = h;
3034}
3035
3036
3037//
2d66e025 3038// ------ Edit control functions
f85afd4e
MB
3039//
3040
2d66e025
MB
3041
3042void wxGrid::EnableEditing( bool edit )
f85afd4e 3043{
2d66e025
MB
3044 // TODO: improve this ?
3045 //
3046 if ( edit != m_editable )
f85afd4e 3047 {
2d66e025 3048 m_editable = edit;
1f1ce288
MB
3049
3050 // TODO: extend this for other edit control types
3051 //
3052 if ( m_editCtrlType == wxGRID_TEXTCTRL )
3053 {
3054 ((wxTextCtrl *)m_cellEditCtrl)->SetEditable( m_editable );
3055 }
f85afd4e 3056 }
f85afd4e
MB
3057}
3058
3059
1f1ce288 3060#if 0 // disabled for the moment - the cell control is always active
2d66e025 3061void wxGrid::EnableCellEditControl( bool enable )
f85afd4e 3062{
2d66e025
MB
3063 if ( m_cellEditCtrl &&
3064 enable != m_cellEditCtrlEnabled )
f85afd4e 3065 {
2d66e025 3066 m_cellEditCtrlEnabled = enable;
60ff3b99 3067
2d66e025 3068 if ( m_cellEditCtrlEnabled )
f85afd4e 3069 {
2d66e025
MB
3070 SetEditControlValue();
3071 ShowCellEditControl();
2d66e025
MB
3072 }
3073 else
3074 {
2d66e025
MB
3075 HideCellEditControl();
3076 SaveEditControlValue();
f85afd4e 3077 }
f85afd4e 3078 }
f85afd4e 3079}
1f1ce288 3080#endif
f85afd4e
MB
3081
3082
2d66e025 3083void wxGrid::ShowCellEditControl()
f85afd4e 3084{
2d66e025
MB
3085 wxRect rect;
3086
3087 if ( IsCellEditControlEnabled() )
f85afd4e 3088 {
2d66e025
MB
3089 if ( !IsVisible( m_currentCellCoords ) )
3090 {
3091 return;
3092 }
3093 else
3094 {
3095 rect = CellToRect( m_currentCellCoords );
3096
3097 // convert to scrolled coords
3098 //
3099 int left, top, right, bottom;
3100 CalcScrolledPosition( rect.GetLeft(), rect.GetTop(), &left, &top );
3101 CalcScrolledPosition( rect.GetRight(), rect.GetBottom(), &right, &bottom );
60ff3b99 3102
2d66e025
MB
3103 int cw, ch;
3104 m_gridWin->GetClientSize( &cw, &ch );
1f1ce288
MB
3105
3106 // Make the edit control large enough to allow for internal margins
3107 // TODO: remove this if the text ctrl sizing is improved esp. for unix
3108 //
58dd5b3b 3109 int extra;
d2fdd8d2 3110#if defined(__WXMOTIF__)
58dd5b3b
MB
3111 if ( m_currentCellCoords.GetRow() == 0 ||
3112 m_currentCellCoords.GetCol() == 0 )
3113 {
3114 extra = 2;
3115 }
3116 else
3117 {
3118 extra = 4;
3119 }
1f1ce288 3120#else
58dd5b3b
MB
3121 if ( m_currentCellCoords.GetRow() == 0 ||
3122 m_currentCellCoords.GetCol() == 0 )
3123 {
3124 extra = 1;
3125 }
3126 else
3127 {
3128 extra = 2;
3129 }
1f1ce288 3130#endif
d2fdd8d2
RR
3131
3132#if defined(__WXGTK__)
3133 int top_diff = 0;
3134 int left_diff = 0;
3135 if (left != 0) left_diff++;
3136 if (top != 0) top_diff++;
3137 rect.SetLeft( left + left_diff );
3138 rect.SetTop( top + top_diff );
3139 rect.SetRight( rect.GetRight() - left_diff );
3140 rect.SetBottom( rect.GetBottom() - top_diff );
3141#else
58dd5b3b
MB
3142 rect.SetLeft( wxMax(0, left - extra) );
3143 rect.SetTop( wxMax(0, top - extra) );
3144 rect.SetRight( rect.GetRight() + 2*extra );
3145 rect.SetBottom( rect.GetBottom() + 2*extra );
d2fdd8d2 3146#endif
f0102d2a 3147
2d66e025
MB
3148 m_cellEditCtrl->SetSize( rect );
3149 m_cellEditCtrl->Show( TRUE );
3150
3151 switch ( m_editCtrlType )
3152 {
3153 case wxGRID_TEXTCTRL:
3154 ((wxTextCtrl *) m_cellEditCtrl)->SetInsertionPointEnd();
3155 break;
3156
3157 case wxGRID_CHECKBOX:
3158 // TODO: anything ???
3159 //
3160 break;
3161
3162 case wxGRID_CHOICE:
3163 // TODO: anything ???
3164 //
3165 break;
3166
3167 case wxGRID_COMBOBOX:
3168 // TODO: anything ???
3169 //
3170 break;
3171 }
3172
3173 m_cellEditCtrl->SetFocus();
3174 }
f85afd4e
MB
3175 }
3176}
3177
3178
2d66e025 3179void wxGrid::HideCellEditControl()
f85afd4e 3180{
2d66e025 3181 if ( IsCellEditControlEnabled() )
f85afd4e 3182 {
2d66e025 3183 m_cellEditCtrl->Show( FALSE );
f85afd4e 3184 }
2d66e025 3185}
8f177c8e 3186
2d66e025
MB
3187
3188void wxGrid::SetEditControlValue( const wxString& value )
3189{
f85afd4e
MB
3190 if ( m_table )
3191 {
2d66e025
MB
3192 wxString s;
3193 if ( !value )
3194 s = GetCellValue(m_currentCellCoords);
3195 else
3196 s = value;
f85afd4e 3197
2d66e025
MB
3198 if ( IsCellEditControlEnabled() )
3199 {
3200 switch ( m_editCtrlType )
3f296516 3201 {
2d66e025
MB
3202 case wxGRID_TEXTCTRL:
3203 ((wxGridTextCtrl *)m_cellEditCtrl)->SetStartValue(s);
3204 break;
8f177c8e 3205
2d66e025
MB
3206 case wxGRID_CHECKBOX:
3207 // TODO: implement this
3208 //
3209 break;
3f296516 3210
2d66e025
MB
3211 case wxGRID_CHOICE:
3212 // TODO: implement this
3213 //
3214 break;
3215
3216 case wxGRID_COMBOBOX:
3217 // TODO: implement this
3218 //
3219 break;
3220 }
3221 }
f85afd4e
MB
3222 }
3223}
3224
8f177c8e 3225
2d66e025
MB
3226void wxGrid::SaveEditControlValue()
3227{
3228 if ( m_table )
f85afd4e 3229 {
2d66e025 3230 wxWindow *ctrl = (wxWindow *)NULL;
8f177c8e 3231
2d66e025 3232 if ( IsCellEditControlEnabled() )
3f296516 3233 {
2d66e025
MB
3234 ctrl = m_cellEditCtrl;
3235 }
2d66e025
MB
3236 else
3237 {
3238 return;
3f296516 3239 }
8f177c8e 3240
2d66e025
MB
3241 bool valueChanged = FALSE;
3242
3243 switch ( m_editCtrlType )
3244 {
3245 case wxGRID_TEXTCTRL:
3246 valueChanged = (((wxGridTextCtrl *)ctrl)->GetValue() !=
3247 ((wxGridTextCtrl *)ctrl)->GetStartValue());
3248 SetCellValue( m_currentCellCoords,
3249 ((wxTextCtrl *) ctrl)->GetValue() );
3250 break;
3251
3252 case wxGRID_CHECKBOX:
3253 // TODO: implement this
3254 //
3255 break;
3256
3257 case wxGRID_CHOICE:
3258 // TODO: implement this
3259 //
3260 break;
3261
3262 case wxGRID_COMBOBOX:
3263 // TODO: implement this
3264 //
3265 break;
3266 }
3267
3268 if ( valueChanged )
3269 {
3270 SendEvent( EVT_GRID_CELL_CHANGE,
3271 m_currentCellCoords.GetRow(),
3272 m_currentCellCoords.GetCol() );
3273 }
f85afd4e
MB
3274 }
3275}
3276
2d66e025
MB
3277
3278//
60ff3b99
VZ
3279// ------ Grid location functions
3280// Note that all of these functions work with the logical coordinates of
2d66e025
MB
3281// grid cells and labels so you will need to convert from device
3282// coordinates for mouse events etc.
3283//
3284
3285void wxGrid::XYToCell( int x, int y, wxGridCellCoords& coords )
f85afd4e 3286{
58dd5b3b
MB
3287 int row = YToRow(y);
3288 int col = XToCol(x);
3289
3290 if ( row == -1 || col == -1 )
3291 {
3292 coords = wxGridNoCellCoords;
3293 }
3294 else
3295 {
3296 coords.Set( row, col );
3297 }
2d66e025 3298}
f85afd4e 3299
8f177c8e 3300
2d66e025
MB
3301int wxGrid::YToRow( int y )
3302{
3303 int i;
8f177c8e 3304
2d66e025 3305 for ( i = 0; i < m_numRows; i++ )
f85afd4e 3306 {
2d66e025 3307 if ( y < m_rowBottoms[i] ) return i;
f85afd4e 3308 }
2d66e025
MB
3309
3310 return -1;
f85afd4e
MB
3311}
3312
2d66e025
MB
3313
3314int wxGrid::XToCol( int x )
f85afd4e 3315{
2d66e025 3316 int i;
8f177c8e 3317
2d66e025 3318 for ( i = 0; i < m_numCols; i++ )
f85afd4e 3319 {
2d66e025 3320 if ( x < m_colRights[i] ) return i;
f85afd4e
MB
3321 }
3322
2d66e025
MB
3323 return -1;
3324}
8f177c8e 3325
2d66e025
MB
3326
3327// return the row number that that the y coord is near the edge of, or
3328// -1 if not near an edge
3329//
3330int wxGrid::YToEdgeOfRow( int y )
3331{
3332 int i, d;
3333
3334 for ( i = 0; i < m_numRows; i++ )
3335 {
3336 if ( m_rowHeights[i] > WXGRID_LABEL_EDGE_ZONE )
f85afd4e 3337 {
2d66e025 3338 d = abs( y - m_rowBottoms[i] );
3f296516 3339 {
2d66e025 3340 if ( d < WXGRID_LABEL_EDGE_ZONE ) return i;
3f296516 3341 }
f85afd4e 3342 }
f85afd4e 3343 }
2d66e025
MB
3344
3345 return -1;
3346}
3347
3348
3349// return the col number that that the x coord is near the edge of, or
3350// -1 if not near an edge
3351//
3352int wxGrid::XToEdgeOfCol( int x )
3353{
3354 int i, d;
3355
3356 for ( i = 0; i < m_numCols; i++ )
f85afd4e 3357 {
2d66e025
MB
3358 if ( m_colWidths[i] > WXGRID_LABEL_EDGE_ZONE )
3359 {
3360 d = abs( x - m_colRights[i] );
3361 {
3362 if ( d < WXGRID_LABEL_EDGE_ZONE ) return i;
3363 }
3364 }
f85afd4e 3365 }
2d66e025
MB
3366
3367 return -1;
f85afd4e
MB
3368}
3369
2d66e025
MB
3370
3371wxRect wxGrid::CellToRect( int row, int col )
f85afd4e 3372{
2d66e025 3373 wxRect rect( -1, -1, -1, -1 );
f85afd4e 3374
2d66e025
MB
3375 if ( row >= 0 && row < m_numRows &&
3376 col >= 0 && col < m_numCols )
f85afd4e 3377 {
2d66e025
MB
3378 rect.x = m_colRights[col] - m_colWidths[col];
3379 rect.y = m_rowBottoms[row] - m_rowHeights[row];
3380 rect.width = m_colWidths[col];
3381 rect.height = m_rowHeights[ row ];
f85afd4e
MB
3382 }
3383
2d66e025
MB
3384 return rect;
3385}
3386
3387
3388bool wxGrid::IsVisible( int row, int col, bool wholeCellVisible )
3389{
3390 // get the cell rectangle in logical coords
3391 //
3392 wxRect r( CellToRect( row, col ) );
60ff3b99 3393
2d66e025
MB
3394 // convert to device coords
3395 //
3396 int left, top, right, bottom;
3397 CalcScrolledPosition( r.GetLeft(), r.GetTop(), &left, &top );
3398 CalcScrolledPosition( r.GetRight(), r.GetBottom(), &right, &bottom );
60ff3b99 3399
2d66e025
MB
3400 // check against the client area of the grid window
3401 //
3402 int cw, ch;
3403 m_gridWin->GetClientSize( &cw, &ch );
60ff3b99 3404
2d66e025 3405 if ( wholeCellVisible )
f85afd4e 3406 {
2d66e025 3407 // is the cell wholly visible ?
8f177c8e 3408 //
2d66e025
MB
3409 return ( left >= 0 && right <= cw &&
3410 top >= 0 && bottom <= ch );
3411 }
3412 else
3413 {
3414 // is the cell partly visible ?
3415 //
3416 return ( ((left >=0 && left < cw) || (right > 0 && right <= cw)) &&
3417 ((top >=0 && top < ch) || (bottom > 0 && bottom <= ch)) );
3418 }
3419}
3420
3421
3422// make the specified cell location visible by doing a minimal amount
3423// of scrolling
3424//
3425void wxGrid::MakeCellVisible( int row, int col )
3426{
3427 int i;
60ff3b99 3428 int xpos = -1, ypos = -1;
2d66e025
MB
3429
3430 if ( row >= 0 && row < m_numRows &&
3431 col >= 0 && col < m_numCols )
3432 {
3433 // get the cell rectangle in logical coords
3434 //
3435 wxRect r( CellToRect( row, col ) );
60ff3b99 3436
2d66e025
MB
3437 // convert to device coords
3438 //
3439 int left, top, right, bottom;
3440 CalcScrolledPosition( r.GetLeft(), r.GetTop(), &left, &top );
3441 CalcScrolledPosition( r.GetRight(), r.GetBottom(), &right, &bottom );
60ff3b99 3442
2d66e025
MB
3443 int cw, ch;
3444 m_gridWin->GetClientSize( &cw, &ch );
60ff3b99 3445
2d66e025 3446 if ( top < 0 )
3f296516 3447 {
2d66e025 3448 ypos = r.GetTop();
3f296516 3449 }
2d66e025
MB
3450 else if ( bottom > ch )
3451 {
3452 int h = r.GetHeight();
3453 ypos = r.GetTop();
3454 for ( i = row-1; i >= 0; i-- )
3455 {
3456 if ( h + m_rowHeights[i] > ch ) break;
3457
3458 h += m_rowHeights[i];
3459 ypos -= m_rowHeights[i];
3460 }
f0102d2a
VZ
3461
3462 // we divide it later by GRID_SCROLL_LINE, make sure that we don't
3463 // have rounding errors (this is important, because if we do, we
3464 // might not scroll at all and some cells won't be redrawn)
3465 ypos += GRID_SCROLL_LINE / 2;
2d66e025
MB
3466 }
3467
3468 if ( left < 0 )
3469 {
3470 xpos = r.GetLeft();
3471 }
3472 else if ( right > cw )
3473 {
3474 int w = r.GetWidth();
3475 xpos = r.GetLeft();
3476 for ( i = col-1; i >= 0; i-- )
3477 {
3478 if ( w + m_colWidths[i] > cw ) break;
3479
3480 w += m_colWidths[i];
3481 xpos -= m_colWidths[i];
3482 }
f0102d2a
VZ
3483
3484 // see comment for ypos above
3485 xpos += GRID_SCROLL_LINE / 2;
2d66e025
MB
3486 }
3487
3488 if ( xpos != -1 || ypos != -1 )
3489 {
f0102d2a
VZ
3490 if ( xpos != -1 ) xpos /= GRID_SCROLL_LINE;
3491 if ( ypos != -1 ) ypos /= GRID_SCROLL_LINE;
2d66e025
MB
3492 Scroll( xpos, ypos );
3493 AdjustScrollbars();
3494 }
3495 }
3496}
3497
3498
3499//
3500// ------ Grid cursor movement functions
3501//
3502
3503bool wxGrid::MoveCursorUp()
3504{
3505 if ( m_currentCellCoords != wxGridNoCellCoords &&
3506 m_currentCellCoords.GetRow() > 0 )
3507 {
3508 MakeCellVisible( m_currentCellCoords.GetRow() - 1,
3509 m_currentCellCoords.GetCol() );
60ff3b99 3510
2d66e025
MB
3511 SetCurrentCell( m_currentCellCoords.GetRow() - 1,
3512 m_currentCellCoords.GetCol() );
3513
8f177c8e 3514 return TRUE;
f85afd4e 3515 }
2d66e025
MB
3516
3517 return FALSE;
3518}
3519
3520
3521bool wxGrid::MoveCursorDown()
3522{
3523 // TODO: allow for scrolling
3524 //
3525 if ( m_currentCellCoords != wxGridNoCellCoords &&
3526 m_currentCellCoords.GetRow() < m_numRows-1 )
f85afd4e 3527 {
2d66e025
MB
3528 MakeCellVisible( m_currentCellCoords.GetRow() + 1,
3529 m_currentCellCoords.GetCol() );
60ff3b99 3530
2d66e025
MB
3531 SetCurrentCell( m_currentCellCoords.GetRow() + 1,
3532 m_currentCellCoords.GetCol() );
3533
3534 return TRUE;
f85afd4e 3535 }
2d66e025
MB
3536
3537 return FALSE;
f85afd4e
MB
3538}
3539
2d66e025
MB
3540
3541bool wxGrid::MoveCursorLeft()
f85afd4e 3542{
2d66e025
MB
3543 if ( m_currentCellCoords != wxGridNoCellCoords &&
3544 m_currentCellCoords.GetCol() > 0 )
3545 {
3546 MakeCellVisible( m_currentCellCoords.GetRow(),
3547 m_currentCellCoords.GetCol() - 1 );
60ff3b99 3548
2d66e025
MB
3549 SetCurrentCell( m_currentCellCoords.GetRow(),
3550 m_currentCellCoords.GetCol() - 1 );
8f177c8e 3551
2d66e025
MB
3552 return TRUE;
3553 }
3554
3555 return FALSE;
3556}
3557
3558
3559bool wxGrid::MoveCursorRight()
3560{
3561 if ( m_currentCellCoords != wxGridNoCellCoords &&
3562 m_currentCellCoords.GetCol() < m_numCols - 1 )
f85afd4e 3563 {
2d66e025
MB
3564 MakeCellVisible( m_currentCellCoords.GetRow(),
3565 m_currentCellCoords.GetCol() + 1 );
60ff3b99 3566
2d66e025
MB
3567 SetCurrentCell( m_currentCellCoords.GetRow(),
3568 m_currentCellCoords.GetCol() + 1 );
3569
3570 return TRUE;
f85afd4e 3571 }
8f177c8e 3572
2d66e025
MB
3573 return FALSE;
3574}
3575
3576
3577bool wxGrid::MovePageUp()
3578{
3579 if ( m_currentCellCoords == wxGridNoCellCoords ) return FALSE;
60ff3b99 3580
2d66e025
MB
3581 int row = m_currentCellCoords.GetRow();
3582 if ( row > 0 )
f85afd4e 3583 {
2d66e025
MB
3584 int cw, ch;
3585 m_gridWin->GetClientSize( &cw, &ch );
60ff3b99 3586
2d66e025
MB
3587 int y = m_rowBottoms[ row ] - m_rowHeights[ row ];
3588 int newRow = YToRow( y - ch + 1 );
3589 if ( newRow == -1 )
3590 {
3591 newRow = 0;
3592 }
60ff3b99 3593 else if ( newRow == row )
2d66e025
MB
3594 {
3595 newRow = row - 1;
3596 }
8f177c8e 3597
2d66e025
MB
3598 MakeCellVisible( newRow, m_currentCellCoords.GetCol() );
3599 SetCurrentCell( newRow, m_currentCellCoords.GetCol() );
60ff3b99 3600
f85afd4e
MB
3601 return TRUE;
3602 }
2d66e025
MB
3603
3604 return FALSE;
3605}
3606
3607bool wxGrid::MovePageDown()
3608{
3609 if ( m_currentCellCoords == wxGridNoCellCoords ) return FALSE;
60ff3b99 3610
2d66e025
MB
3611 int row = m_currentCellCoords.GetRow();
3612 if ( row < m_numRows )
f85afd4e 3613 {
2d66e025
MB
3614 int cw, ch;
3615 m_gridWin->GetClientSize( &cw, &ch );
60ff3b99 3616
2d66e025
MB
3617 int y = m_rowBottoms[ row ] - m_rowHeights[ row ];
3618 int newRow = YToRow( y + ch );
3619 if ( newRow == -1 )
3620 {
3621 newRow = m_numRows - 1;
3622 }
60ff3b99 3623 else if ( newRow == row )
2d66e025
MB
3624 {
3625 newRow = row + 1;
3626 }
3627
3628 MakeCellVisible( newRow, m_currentCellCoords.GetCol() );
3629 SetCurrentCell( newRow, m_currentCellCoords.GetCol() );
60ff3b99 3630
2d66e025 3631 return TRUE;
f85afd4e 3632 }
2d66e025
MB
3633
3634 return FALSE;
f85afd4e 3635}
8f177c8e 3636
2d66e025
MB
3637bool wxGrid::MoveCursorUpBlock()
3638{
3639 if ( m_table &&
3640 m_currentCellCoords != wxGridNoCellCoords &&
3641 m_currentCellCoords.GetRow() > 0 )
3642 {
3643 int row = m_currentCellCoords.GetRow();
3644 int col = m_currentCellCoords.GetCol();
3645
3646 if ( m_table->IsEmptyCell(row, col) )
3647 {
3648 // starting in an empty cell: find the next block of
3649 // non-empty cells
3650 //
3651 while ( row > 0 )
3652 {
3653 row-- ;
3654 if ( !(m_table->IsEmptyCell(row, col)) ) break;
3655 }
3656 }
3657 else if ( m_table->IsEmptyCell(row-1, col) )
3658 {
3659 // starting at the top of a block: find the next block
3660 //
3661 row--;
3662 while ( row > 0 )
3663 {
3664 row-- ;
3665 if ( !(m_table->IsEmptyCell(row, col)) ) break;
3666 }
3667 }
3668 else
3669 {
3670 // starting within a block: find the top of the block
3671 //
3672 while ( row > 0 )
3673 {
3674 row-- ;
3675 if ( m_table->IsEmptyCell(row, col) )
3676 {
3677 row++ ;
3678 break;
3679 }
3680 }
3681 }
f85afd4e 3682
2d66e025
MB
3683 MakeCellVisible( row, col );
3684 SetCurrentCell( row, col );
f85afd4e 3685
2d66e025
MB
3686 return TRUE;
3687 }
f85afd4e 3688
2d66e025
MB
3689 return FALSE;
3690}
f85afd4e 3691
2d66e025 3692bool wxGrid::MoveCursorDownBlock()
f85afd4e 3693{
2d66e025
MB
3694 if ( m_table &&
3695 m_currentCellCoords != wxGridNoCellCoords &&
3696 m_currentCellCoords.GetRow() < m_numRows-1 )
f85afd4e 3697 {
2d66e025
MB
3698 int row = m_currentCellCoords.GetRow();
3699 int col = m_currentCellCoords.GetCol();
3700
3701 if ( m_table->IsEmptyCell(row, col) )
3702 {
3703 // starting in an empty cell: find the next block of
3704 // non-empty cells
3705 //
3706 while ( row < m_numRows-1 )
3707 {
3708 row++ ;
3709 if ( !(m_table->IsEmptyCell(row, col)) ) break;
3710 }
3711 }
3712 else if ( m_table->IsEmptyCell(row+1, col) )
3713 {
3714 // starting at the bottom of a block: find the next block
3715 //
3716 row++;
3717 while ( row < m_numRows-1 )
3718 {
3719 row++ ;
3720 if ( !(m_table->IsEmptyCell(row, col)) ) break;
3721 }
3722 }
3723 else
3724 {
3725 // starting within a block: find the bottom of the block
3726 //
3727 while ( row < m_numRows-1 )
3728 {
3729 row++ ;
3730 if ( m_table->IsEmptyCell(row, col) )
3731 {
3732 row-- ;
3733 break;
3734 }
3735 }
3736 }
3737
3738 MakeCellVisible( row, col );
3739 SetCurrentCell( row, col );
3740
3741 return TRUE;
f85afd4e 3742 }
f85afd4e 3743
2d66e025
MB
3744 return FALSE;
3745}
f85afd4e 3746
2d66e025 3747bool wxGrid::MoveCursorLeftBlock()
f85afd4e 3748{
2d66e025
MB
3749 if ( m_table &&
3750 m_currentCellCoords != wxGridNoCellCoords &&
3751 m_currentCellCoords.GetCol() > 0 )
f85afd4e 3752 {
2d66e025
MB
3753 int row = m_currentCellCoords.GetRow();
3754 int col = m_currentCellCoords.GetCol();
3755
3756 if ( m_table->IsEmptyCell(row, col) )
3757 {
3758 // starting in an empty cell: find the next block of
3759 // non-empty cells
3760 //
3761 while ( col > 0 )
3762 {
3763 col-- ;
3764 if ( !(m_table->IsEmptyCell(row, col)) ) break;
3765 }
3766 }
3767 else if ( m_table->IsEmptyCell(row, col-1) )
3768 {
3769 // starting at the left of a block: find the next block
3770 //
3771 col--;
3772 while ( col > 0 )
3773 {
3774 col-- ;
3775 if ( !(m_table->IsEmptyCell(row, col)) ) break;
3776 }
3777 }
3778 else
3779 {
3780 // starting within a block: find the left of the block
3781 //
3782 while ( col > 0 )
3783 {
3784 col-- ;
3785 if ( m_table->IsEmptyCell(row, col) )
3786 {
3787 col++ ;
3788 break;
3789 }
3790 }
3791 }
f85afd4e 3792
2d66e025
MB
3793 MakeCellVisible( row, col );
3794 SetCurrentCell( row, col );
8f177c8e 3795
2d66e025 3796 return TRUE;
f85afd4e 3797 }
2d66e025
MB
3798
3799 return FALSE;
f85afd4e
MB
3800}
3801
2d66e025 3802bool wxGrid::MoveCursorRightBlock()
f85afd4e 3803{
2d66e025
MB
3804 if ( m_table &&
3805 m_currentCellCoords != wxGridNoCellCoords &&
3806 m_currentCellCoords.GetCol() < m_numCols-1 )
f85afd4e 3807 {
2d66e025
MB
3808 int row = m_currentCellCoords.GetRow();
3809 int col = m_currentCellCoords.GetCol();
8f177c8e 3810
2d66e025
MB
3811 if ( m_table->IsEmptyCell(row, col) )
3812 {
3813 // starting in an empty cell: find the next block of
3814 // non-empty cells
3815 //
3816 while ( col < m_numCols-1 )
3817 {
3818 col++ ;
3819 if ( !(m_table->IsEmptyCell(row, col)) ) break;
3820 }
3821 }
3822 else if ( m_table->IsEmptyCell(row, col+1) )
3823 {
3824 // starting at the right of a block: find the next block
3825 //
3826 col++;
3827 while ( col < m_numCols-1 )
3828 {
3829 col++ ;
3830 if ( !(m_table->IsEmptyCell(row, col)) ) break;
3831 }
3832 }
3833 else
3834 {
3835 // starting within a block: find the right of the block
3836 //
3837 while ( col < m_numCols-1 )
3838 {
3839 col++ ;
3840 if ( m_table->IsEmptyCell(row, col) )
3841 {
3842 col-- ;
3843 break;
3844 }
3845 }
3846 }
8f177c8e 3847
2d66e025
MB
3848 MakeCellVisible( row, col );
3849 SetCurrentCell( row, col );
f85afd4e 3850
2d66e025 3851 return TRUE;
f85afd4e 3852 }
2d66e025
MB
3853
3854 return FALSE;
f85afd4e
MB
3855}
3856
3857
2d66e025 3858
f85afd4e 3859//
2d66e025 3860// ------ Label values and formatting
f85afd4e
MB
3861//
3862
3863void wxGrid::GetRowLabelAlignment( int *horiz, int *vert )
3864{
3865 *horiz = m_rowLabelHorizAlign;
3866 *vert = m_rowLabelVertAlign;
3867}
3868
3869void wxGrid::GetColLabelAlignment( int *horiz, int *vert )
3870{
3871 *horiz = m_colLabelHorizAlign;
3872 *vert = m_colLabelVertAlign;
3873}
3874
3875wxString wxGrid::GetRowLabelValue( int row )
3876{
3877 if ( m_table )
3878 {
3879 return m_table->GetRowLabelValue( row );
3880 }
3881 else
3882 {
3883 wxString s;
3884 s << row;
3885 return s;
3886 }
3887}
3888
3889wxString wxGrid::GetColLabelValue( int col )
3890{
3891 if ( m_table )
3892 {
3893 return m_table->GetColLabelValue( col );
3894 }
3895 else
3896 {
3897 wxString s;
3898 s << col;
3899 return s;
3900 }
3901}
3902
2e8cd977 3903
f85afd4e
MB
3904void wxGrid::SetRowLabelSize( int width )
3905{
2e8cd977
MB
3906 width = wxMax( width, 0 );
3907 if ( width != m_rowLabelWidth )
3908 {
2e8cd977
MB
3909 if ( width == 0 )
3910 {
3911 m_rowLabelWin->Show( FALSE );
7807d81c 3912 m_cornerLabelWin->Show( FALSE );
2e8cd977 3913 }
7807d81c 3914 else if ( m_rowLabelWidth == 0 )
2e8cd977 3915 {
7807d81c
MB
3916 m_rowLabelWin->Show( TRUE );
3917 if ( m_colLabelHeight > 0 ) m_cornerLabelWin->Show( TRUE );
2e8cd977 3918 }
7807d81c 3919
2e8cd977 3920 m_rowLabelWidth = width;
7807d81c
MB
3921 CalcWindowSizes();
3922 Refresh( TRUE );
2e8cd977 3923 }
f85afd4e
MB
3924}
3925
2e8cd977 3926
f85afd4e
MB
3927void wxGrid::SetColLabelSize( int height )
3928{
7807d81c 3929 height = wxMax( height, 0 );
2e8cd977
MB
3930 if ( height != m_colLabelHeight )
3931 {
2e8cd977
MB
3932 if ( height == 0 )
3933 {
2e8cd977 3934 m_colLabelWin->Show( FALSE );
7807d81c 3935 m_cornerLabelWin->Show( FALSE );
2e8cd977 3936 }
7807d81c 3937 else if ( m_colLabelHeight == 0 )
2e8cd977 3938 {
7807d81c
MB
3939 m_colLabelWin->Show( TRUE );
3940 if ( m_rowLabelWidth > 0 ) m_cornerLabelWin->Show( TRUE );
2e8cd977 3941 }
7807d81c 3942
2e8cd977 3943 m_colLabelHeight = height;
7807d81c
MB
3944 CalcWindowSizes();
3945 Refresh( TRUE );
2e8cd977 3946 }
f85afd4e
MB
3947}
3948
2e8cd977 3949
f85afd4e
MB
3950void wxGrid::SetLabelBackgroundColour( const wxColour& colour )
3951{
2d66e025
MB
3952 if ( m_labelBackgroundColour != colour )
3953 {
3954 m_labelBackgroundColour = colour;
3955 m_rowLabelWin->SetBackgroundColour( colour );
3956 m_colLabelWin->SetBackgroundColour( colour );
3957 m_cornerLabelWin->SetBackgroundColour( colour );
3958
3959 if ( !GetBatchCount() )
3960 {
3961 m_rowLabelWin->Refresh();
3962 m_colLabelWin->Refresh();
3963 m_cornerLabelWin->Refresh();
3964 }
3965 }
f85afd4e
MB
3966}
3967
3968void wxGrid::SetLabelTextColour( const wxColour& colour )
3969{
2d66e025
MB
3970 if ( m_labelTextColour != colour )
3971 {
3972 m_labelTextColour = colour;
3973 if ( !GetBatchCount() )
3974 {
3975 m_rowLabelWin->Refresh();
3976 m_colLabelWin->Refresh();
3977 }
3978 }
f85afd4e
MB
3979}
3980
3981void wxGrid::SetLabelFont( const wxFont& font )
3982{
3983 m_labelFont = font;
2d66e025
MB
3984 if ( !GetBatchCount() )
3985 {
3986 m_rowLabelWin->Refresh();
3987 m_colLabelWin->Refresh();
3988 }
f85afd4e
MB
3989}
3990
3991void wxGrid::SetRowLabelAlignment( int horiz, int vert )
3992{
3993 if ( horiz == wxLEFT || horiz == wxCENTRE || horiz == wxRIGHT )
3994 {
3995 m_rowLabelHorizAlign = horiz;
3996 }
8f177c8e 3997
f85afd4e
MB
3998 if ( vert == wxTOP || vert == wxCENTRE || vert == wxBOTTOM )
3999 {
4000 m_rowLabelVertAlign = vert;
4001 }
4002
2d66e025
MB
4003 if ( !GetBatchCount() )
4004 {
4005 m_rowLabelWin->Refresh();
60ff3b99 4006 }
f85afd4e
MB
4007}
4008
4009void wxGrid::SetColLabelAlignment( int horiz, int vert )
4010{
4011 if ( horiz == wxLEFT || horiz == wxCENTRE || horiz == wxRIGHT )
4012 {
4013 m_colLabelHorizAlign = horiz;
4014 }
8f177c8e 4015
f85afd4e
MB
4016 if ( vert == wxTOP || vert == wxCENTRE || vert == wxBOTTOM )
4017 {
4018 m_colLabelVertAlign = vert;
4019 }
4020
2d66e025
MB
4021 if ( !GetBatchCount() )
4022 {
2d66e025 4023 m_colLabelWin->Refresh();
60ff3b99 4024 }
f85afd4e
MB
4025}
4026
4027void wxGrid::SetRowLabelValue( int row, const wxString& s )
4028{
4029 if ( m_table )
4030 {
4031 m_table->SetRowLabelValue( row, s );
2d66e025
MB
4032 if ( !GetBatchCount() )
4033 {
70c7a608
SN
4034 wxRect rect = CellToRect( row, 0);
4035 if ( rect.height > 0 )
4036 {
cb309039 4037 CalcScrolledPosition(0, rect.y, &rect.x, &rect.y);
70c7a608
SN
4038 rect.x = m_left;
4039 rect.width = m_rowLabelWidth;
4040 m_rowLabelWin->Refresh( TRUE, &rect );
4041 }
2d66e025 4042 }
f85afd4e
MB
4043 }
4044}
4045
4046void wxGrid::SetColLabelValue( int col, const wxString& s )
4047{
4048 if ( m_table )
4049 {
4050 m_table->SetColLabelValue( col, s );
2d66e025
MB
4051 if ( !GetBatchCount() )
4052 {
70c7a608
SN
4053 wxRect rect = CellToRect( 0, col );
4054 if ( rect.width > 0 )
4055 {
cb309039 4056 CalcScrolledPosition(rect.x, 0, &rect.x, &rect.y);
70c7a608
SN
4057 rect.y = m_top;
4058 rect.height = m_colLabelHeight;
4059 m_colLabelWin->Refresh( TRUE, &rect );
4060 }
2d66e025 4061 }
f85afd4e
MB
4062 }
4063}
4064
4065void wxGrid::SetGridLineColour( const wxColour& colour )
4066{
2d66e025
MB
4067 if ( m_gridLineColour != colour )
4068 {
4069 m_gridLineColour = colour;
60ff3b99 4070
2d66e025
MB
4071 wxClientDC dc( m_gridWin );
4072 PrepareDC( dc );
c6a51dcd 4073 DrawAllGridLines( dc, wxRegion() );
2d66e025 4074 }
f85afd4e
MB
4075}
4076
4077void wxGrid::EnableGridLines( bool enable )
4078{
4079 if ( enable != m_gridLinesEnabled )
4080 {
4081 m_gridLinesEnabled = enable;
2d66e025
MB
4082
4083 if ( !GetBatchCount() )
4084 {
4085 if ( enable )
4086 {
4087 wxClientDC dc( m_gridWin );
4088 PrepareDC( dc );
c6a51dcd 4089 DrawAllGridLines( dc, wxRegion() );
2d66e025
MB
4090 }
4091 else
4092 {
4093 m_gridWin->Refresh();
4094 }
4095 }
f85afd4e
MB
4096 }
4097}
4098
4099
4100int wxGrid::GetDefaultRowSize()
4101{
4102 return m_defaultRowHeight;
4103}
4104
4105int wxGrid::GetRowSize( int row )
4106{
4107 if ( row >= 0 && row < m_numRows )
4108 return m_rowHeights[row];
4109 else
4110 return 0; // TODO: log an error here
4111}
4112
4113int wxGrid::GetDefaultColSize()
4114{
4115 return m_defaultColWidth;
4116}
4117
4118int wxGrid::GetColSize( int col )
4119{
4120 if ( col >= 0 && col < m_numCols )
4121 return m_colWidths[col];
4122 else
4123 return 0; // TODO: log an error here
4124}
4125
4126wxColour wxGrid::GetDefaultCellBackgroundColour()
4127{
4128 // TODO: replace this temp test code
4129 //
4130 return wxColour( 255, 255, 255 );
4131}
4132
af111fc3 4133wxColour wxGrid::GetCellBackgroundColour( int WXUNUSED(row), int WXUNUSED(col) )
f85afd4e
MB
4134{
4135 // TODO: replace this temp test code
4136 //
8f177c8e 4137 return wxColour( 255, 255, 255 );
f85afd4e
MB
4138}
4139
4140wxColour wxGrid::GetDefaultCellTextColour()
4141{
4142 // TODO: replace this temp test code
4143 //
8f177c8e 4144 return wxColour( 0, 0, 0 );
f85afd4e
MB
4145}
4146
af111fc3 4147wxColour wxGrid::GetCellTextColour( int WXUNUSED(row), int WXUNUSED(col) )
f85afd4e
MB
4148{
4149 // TODO: replace this temp test code
4150 //
8f177c8e 4151 return wxColour( 0, 0, 0 );
f85afd4e
MB
4152}
4153
4154
f85afd4e
MB
4155wxFont wxGrid::GetDefaultCellFont()
4156{
4157 return m_defaultCellFont;
4158}
4159
af111fc3 4160wxFont wxGrid::GetCellFont( int WXUNUSED(row), int WXUNUSED(col) )
f85afd4e
MB
4161{
4162 // TODO: replace this temp test code
4163 //
4164 return m_defaultCellFont;
4165}
4166
4167void wxGrid::GetDefaultCellAlignment( int *horiz, int *vert )
4168{
4169 // TODO: replace this temp test code
4170 //
4171 *horiz = wxLEFT;
4172 *vert = wxTOP;
4173}
4174
af111fc3 4175void wxGrid::GetCellAlignment( int WXUNUSED(row), int WXUNUSED(col), int *horiz, int *vert )
f85afd4e
MB
4176{
4177 // TODO: replace this temp test code
4178 //
4179 *horiz = wxLEFT;
4180 *vert = wxTOP;
4181}
4182
4183void wxGrid::SetDefaultRowSize( int height, bool resizeExistingRows )
4184{
4185 m_defaultRowHeight = wxMax( height, WXGRID_MIN_ROW_HEIGHT );
4186
4187 if ( resizeExistingRows )
4188 {
f85afd4e 4189 int row;
2d66e025 4190 int bottom = 0;
f85afd4e
MB
4191 for ( row = 0; row < m_numRows; row++ )
4192 {
4193 m_rowHeights[row] = m_defaultRowHeight;
2d66e025
MB
4194 bottom += m_defaultRowHeight;
4195 m_rowBottoms[row] = bottom;
f85afd4e
MB
4196 }
4197 CalcDimensions();
f85afd4e
MB
4198 }
4199}
4200
4201void wxGrid::SetRowSize( int row, int height )
4202{
2d66e025 4203 int i;
60ff3b99 4204
f85afd4e
MB
4205 if ( row >= 0 && row < m_numRows )
4206 {
2d66e025
MB
4207 int h = wxMax( 0, height );
4208 int diff = h - m_rowHeights[row];
60ff3b99 4209
2d66e025
MB
4210 m_rowHeights[row] = h;
4211 for ( i = row; i < m_numRows; i++ )
4212 {
4213 m_rowBottoms[i] += diff;
4214 }
f85afd4e 4215 CalcDimensions();
60ff3b99 4216
f85afd4e
MB
4217 // Note: we are ending the event *after* doing
4218 // default processing in this case
4219 //
b5f788a5 4220 SendEvent( EVT_GRID_ROW_SIZE,
f85afd4e
MB
4221 row, -1 );
4222 }
4223 else
4224 {
4225 // TODO: log an error here
4226 }
4227}
4228
4229void wxGrid::SetDefaultColSize( int width, bool resizeExistingCols )
4230{
4231 m_defaultColWidth = wxMax( width, WXGRID_MIN_COL_WIDTH );
4232
4233 if ( resizeExistingCols )
4234 {
f85afd4e 4235 int col;
2d66e025 4236 int right = 0;
f85afd4e
MB
4237 for ( col = 0; col < m_numCols; col++ )
4238 {
4239 m_colWidths[col] = m_defaultColWidth;
2d66e025
MB
4240 right += m_defaultColWidth;
4241 m_colRights[col] = right;
f85afd4e
MB
4242 }
4243 CalcDimensions();
f85afd4e
MB
4244 }
4245}
4246
4247void wxGrid::SetColSize( int col, int width )
4248{
2d66e025 4249 int i;
60ff3b99 4250
f85afd4e
MB
4251 if ( col >= 0 && col < m_numCols )
4252 {
2d66e025
MB
4253 int w = wxMax( 0, width );
4254 int diff = w - m_colWidths[col];
4255 m_colWidths[col] = w;
f85afd4e 4256
2d66e025
MB
4257 for ( i = col; i < m_numCols; i++ )
4258 {
4259 m_colRights[i] += diff;
4260 }
4261 CalcDimensions();
60ff3b99 4262
f85afd4e
MB
4263 // Note: we are ending the event *after* doing
4264 // default processing in this case
4265 //
b5f788a5 4266 SendEvent( EVT_GRID_COL_SIZE,
f85afd4e
MB
4267 -1, col );
4268 }
4269 else
4270 {
4271 // TODO: log an error here
4272 }
4273}
4274
4275void wxGrid::SetDefaultCellBackgroundColour( const wxColour& )
4276{
4277 // TODO: everything !!!
4278 //
4279}
4280
af111fc3 4281void wxGrid::SetCellBackgroundColour( int WXUNUSED(row), int WXUNUSED(col), const wxColour& )
f85afd4e
MB
4282{
4283 // TODO: everything !!!
4284 //
4285}
4286
4287void wxGrid::SetDefaultCellTextColour( const wxColour& )
4288{
4289 // TODO: everything !!!
4290 //
4291}
4292
af111fc3 4293void wxGrid::SetCellTextColour( int WXUNUSED(row), int WXUNUSED(col), const wxColour& )
f85afd4e
MB
4294{
4295 // TODO: everything !!!
4296 //
4297}
4298
f85afd4e
MB
4299void wxGrid::SetDefaultCellFont( const wxFont& )
4300{
4301 // TODO: everything !!!
4302 //
4303}
4304
af111fc3 4305void wxGrid::SetCellFont( int WXUNUSED(row), int WXUNUSED(col), const wxFont& )
f85afd4e
MB
4306{
4307 // TODO: everything !!!
4308 //
4309}
4310
af111fc3 4311void wxGrid::SetDefaultCellAlignment( int WXUNUSED(horiz), int WXUNUSED(vert) )
f85afd4e
MB
4312{
4313 // TODO: everything !!!
4314 //
4315}
4316
af111fc3 4317void wxGrid::SetCellAlignment( int WXUNUSED(row), int WXUNUSED(col), int WXUNUSED(horiz), int WXUNUSED(vert) )
f85afd4e
MB
4318{
4319 // TODO: everything !!!
4320 //
4321}
4322
4323
2d66e025 4324
f85afd4e
MB
4325//
4326// ------ cell value accessor functions
4327//
4328
4329void wxGrid::SetCellValue( int row, int col, const wxString& s )
4330{
4331 if ( m_table )
4332 {
4333 m_table->SetValue( row, col, s.c_str() );
2d66e025
MB
4334 if ( !GetBatchCount() )
4335 {
4336 wxClientDC dc( m_gridWin );
4337 PrepareDC( dc );
4338 DrawCell( dc, wxGridCellCoords(row, col) );
4339 }
60ff3b99 4340
2d66e025 4341#if 0 // TODO: edit in place
60ff3b99 4342
f85afd4e
MB
4343 if ( m_currentCellCoords.GetRow() == row &&
4344 m_currentCellCoords.GetCol() == col )
4345 {
4346 SetEditControlValue( s );
4347 }
2d66e025 4348#endif
f85afd4e 4349
f85afd4e
MB
4350 }
4351}
4352
4353
4354//
2d66e025 4355// ------ Block, row and col selection
f85afd4e
MB
4356//
4357
4358void wxGrid::SelectRow( int row, bool addToSelected )
4359{
2d66e025 4360 wxRect r;
60ff3b99 4361
f85afd4e
MB
4362 if ( IsSelection() && addToSelected )
4363 {
70c7a608
SN
4364 wxRect rect[4];
4365 bool need_refresh[4] = { FALSE, FALSE, FALSE, FALSE };
4366 int i;
4367
4368 wxCoord oldLeft = m_selectedTopLeft.GetCol();
4369 wxCoord oldTop = m_selectedTopLeft.GetRow();
4370 wxCoord oldRight = m_selectedBottomRight.GetCol();
4371 wxCoord oldBottom = m_selectedBottomRight.GetRow();
4372
4373 if ( oldTop > row )
4374 {
4375 need_refresh[0] = TRUE;
4376 rect[0] = BlockToDeviceRect( wxGridCellCoords ( row, 0 ),
4377 wxGridCellCoords ( oldTop - 1,
4378 m_numCols - 1 ) );
f85afd4e 4379 m_selectedTopLeft.SetRow( row );
70c7a608 4380 }
8f177c8e 4381
70c7a608
SN
4382 if ( oldLeft > 0 )
4383 {
4384 need_refresh[1] = TRUE;
4385 rect[1] = BlockToDeviceRect( wxGridCellCoords ( oldTop, 0 ),
4386 wxGridCellCoords ( oldBottom,
4387 oldLeft - 1 ) );
8f177c8e 4388
70c7a608
SN
4389 m_selectedTopLeft.SetCol( 0 );
4390 }
4391
4392 if ( oldBottom < row )
4393 {
4394 need_refresh[2] = TRUE;
4395 rect[2] = BlockToDeviceRect( wxGridCellCoords ( oldBottom + 1, 0 ),
4396 wxGridCellCoords ( row,
4397 m_numCols - 1 ) );
f85afd4e 4398 m_selectedBottomRight.SetRow( row );
70c7a608 4399 }
8f177c8e 4400
70c7a608
SN
4401 if ( oldRight < m_numCols - 1 )
4402 {
4403 need_refresh[3] = TRUE;
4404 rect[3] = BlockToDeviceRect( wxGridCellCoords ( oldTop ,
4405 oldRight + 1 ),
4406 wxGridCellCoords ( oldBottom,
4407 m_numCols - 1 ) );
4408 m_selectedBottomRight.SetCol( m_numCols - 1 );
4409 }
2d66e025 4410
70c7a608
SN
4411 for (i = 0; i < 4; i++ )
4412 if ( need_refresh[i] && rect[i] != wxGridNoCellRect )
c6a51dcd 4413 m_gridWin->Refresh( FALSE, &(rect[i]) );
f85afd4e
MB
4414 }
4415 else
4416 {
2d66e025 4417 r = SelectionToDeviceRect();
f85afd4e 4418 ClearSelection();
c6a51dcd 4419 if ( r != wxGridNoCellRect ) m_gridWin->Refresh( FALSE, &r );
60ff3b99 4420
f85afd4e
MB
4421 m_selectedTopLeft.Set( row, 0 );
4422 m_selectedBottomRight.Set( row, m_numCols-1 );
2d66e025 4423 r = SelectionToDeviceRect();
c6a51dcd 4424 m_gridWin->Refresh( FALSE, &r );
f85afd4e 4425 }
8f177c8e 4426
f85afd4e 4427 wxGridRangeSelectEvent gridEvt( GetId(),
b5f788a5 4428 EVT_GRID_RANGE_SELECT,
f85afd4e
MB
4429 this,
4430 m_selectedTopLeft,
4431 m_selectedBottomRight );
4432
4433 GetEventHandler()->ProcessEvent(gridEvt);
4434}
4435
4436
4437void wxGrid::SelectCol( int col, bool addToSelected )
4438{
2d66e025 4439 if ( IsSelection() && addToSelected )
f85afd4e 4440 {
70c7a608
SN
4441 wxRect rect[4];
4442 bool need_refresh[4] = { FALSE, FALSE, FALSE, FALSE };
4443 int i;
4444
4445 wxCoord oldLeft = m_selectedTopLeft.GetCol();
4446 wxCoord oldTop = m_selectedTopLeft.GetRow();
4447 wxCoord oldRight = m_selectedBottomRight.GetCol();
4448 wxCoord oldBottom = m_selectedBottomRight.GetRow();
4449
4450 if ( oldLeft > col )
4451 {
4452 need_refresh[0] = TRUE;
4453 rect[0] = BlockToDeviceRect( wxGridCellCoords ( 0, col ),
4454 wxGridCellCoords ( m_numRows - 1,
4455 oldLeft - 1 ) );
f85afd4e 4456 m_selectedTopLeft.SetCol( col );
70c7a608 4457 }
f85afd4e 4458
70c7a608
SN
4459 if ( oldTop > 0 )
4460 {
4461 need_refresh[1] = TRUE;
4462 rect[1] = BlockToDeviceRect( wxGridCellCoords ( 0, oldLeft ),
4463 wxGridCellCoords ( oldTop - 1,
4464 oldRight ) );
4465 m_selectedTopLeft.SetRow( 0 );
4466 }
f85afd4e 4467
70c7a608
SN
4468 if ( oldRight < col )
4469 {
4470 need_refresh[2] = TRUE;
4471 rect[2] = BlockToDeviceRect( wxGridCellCoords ( 0, oldRight + 1 ),
4472 wxGridCellCoords ( m_numRows - 1,
4473 col ) );
f85afd4e 4474 m_selectedBottomRight.SetCol( col );
70c7a608 4475 }
f85afd4e 4476
70c7a608
SN
4477 if ( oldBottom < m_numRows - 1 )
4478 {
4479 need_refresh[3] = TRUE;
4480 rect[3] = BlockToDeviceRect( wxGridCellCoords ( oldBottom + 1,
4481 oldLeft ),
4482 wxGridCellCoords ( m_numRows - 1,
4483 oldRight ) );
4484 m_selectedBottomRight.SetRow( m_numRows - 1 );
4485 }
2d66e025 4486
70c7a608
SN
4487 for (i = 0; i < 4; i++ )
4488 if ( need_refresh[i] && rect[i] != wxGridNoCellRect )
c6a51dcd 4489 m_gridWin->Refresh( FALSE, &(rect[i]) );
f85afd4e
MB
4490 }
4491 else
4492 {
70c7a608
SN
4493 wxRect r;
4494
2d66e025 4495 r = SelectionToDeviceRect();
f85afd4e 4496 ClearSelection();
c6a51dcd 4497 if ( r != wxGridNoCellRect ) m_gridWin->Refresh( FALSE, &r );
60ff3b99 4498
f85afd4e
MB
4499 m_selectedTopLeft.Set( 0, col );
4500 m_selectedBottomRight.Set( m_numRows-1, col );
2d66e025 4501 r = SelectionToDeviceRect();
c6a51dcd 4502 m_gridWin->Refresh( FALSE, &r );
f85afd4e
MB
4503 }
4504
4505 wxGridRangeSelectEvent gridEvt( GetId(),
b5f788a5 4506 EVT_GRID_RANGE_SELECT,
f85afd4e
MB
4507 this,
4508 m_selectedTopLeft,
4509 m_selectedBottomRight );
4510
4511 GetEventHandler()->ProcessEvent(gridEvt);
4512}
4513
4514
4515void wxGrid::SelectBlock( int topRow, int leftCol, int bottomRow, int rightCol )
4516{
4517 int temp;
da6af900 4518 wxGridCellCoords updateTopLeft, updateBottomRight;
8f177c8e 4519
f85afd4e
MB
4520 if ( topRow > bottomRow )
4521 {
4522 temp = topRow;
4523 topRow = bottomRow;
4524 bottomRow = temp;
4525 }
4526
4527 if ( leftCol > rightCol )
4528 {
4529 temp = leftCol;
4530 leftCol = rightCol;
4531 rightCol = temp;
4532 }
f0102d2a 4533
70c7a608
SN
4534 updateTopLeft = wxGridCellCoords( topRow, leftCol );
4535 updateBottomRight = wxGridCellCoords( bottomRow, rightCol );
da6af900 4536
70c7a608
SN
4537 if ( m_selectedTopLeft != updateTopLeft ||
4538 m_selectedBottomRight != updateBottomRight )
da6af900 4539 {
70c7a608
SN
4540 // Compute two optimal update rectangles:
4541 // Either one rectangle is a real subset of the
4542 // other, or they are (almost) disjoint!
4543 wxRect rect[4];
4544 bool need_refresh[4] = { FALSE, FALSE, FALSE, FALSE };
4545 int i;
4546
4547 // Store intermediate values
4548 wxCoord oldLeft = m_selectedTopLeft.GetCol();
4549 wxCoord oldTop = m_selectedTopLeft.GetRow();
4550 wxCoord oldRight = m_selectedBottomRight.GetCol();
4551 wxCoord oldBottom = m_selectedBottomRight.GetRow();
4552
4553 // Determine the outer/inner coordinates.
4554 if (oldLeft > leftCol)
f0102d2a 4555 {
70c7a608
SN
4556 temp = oldLeft;
4557 oldLeft = leftCol;
4558 leftCol = temp;
cb309039 4559 }
70c7a608 4560 if (oldTop > topRow )
f0102d2a 4561 {
70c7a608
SN
4562 temp = oldTop;
4563 oldTop = topRow;
4564 topRow = temp;
cb309039
SN
4565 }
4566 if (oldRight < rightCol )
70c7a608
SN
4567 {
4568 temp = oldRight;
4569 oldRight = rightCol;
4570 rightCol = temp;
cb309039
SN
4571 }
4572 if (oldBottom < bottomRow)
4573 {
70c7a608
SN
4574 temp = oldBottom;
4575 oldBottom = bottomRow;
4576 bottomRow = temp;
cb309039 4577 }
70c7a608
SN
4578
4579 // Now, either the stuff marked old is the outer
4580 // rectangle or we don't have a situation where one
4581 // is contained in the other.
4582
cb309039
SN
4583 if ( oldLeft < leftCol )
4584 {
4585 need_refresh[0] = TRUE;
4586 rect[0] = BlockToDeviceRect( wxGridCellCoords ( oldTop,
4587 oldLeft ),
4588 wxGridCellCoords ( oldBottom,
4589 leftCol - 1 ) );
4590 }
4591
4592 if ( oldTop < topRow )
4593 {
4594 need_refresh[1] = TRUE;
4595 rect[1] = BlockToDeviceRect( wxGridCellCoords ( oldTop,
4596 leftCol ),
4597 wxGridCellCoords ( topRow - 1,
4598 rightCol ) );
4599 }
4600
4601 if ( oldRight > rightCol )
4602 {
4603 need_refresh[2] = TRUE;
4604 rect[2] = BlockToDeviceRect( wxGridCellCoords ( oldTop,
4605 rightCol + 1 ),
4606 wxGridCellCoords ( oldBottom,
4607 oldRight ) );
4608 }
4609
4610 if ( oldBottom > bottomRow )
4611 {
4612 need_refresh[3] = TRUE;
4613 rect[3] = BlockToDeviceRect( wxGridCellCoords ( bottomRow + 1,
4614 leftCol ),
4615 wxGridCellCoords ( oldBottom,
4616 rightCol ) );
4617 }
70c7a608
SN
4618
4619
4620 // Change Selection
4621 m_selectedTopLeft = updateTopLeft;
4622 m_selectedBottomRight = updateBottomRight;
4623
4624 // various Refresh() calls
4625 for (i = 0; i < 4; i++ )
4626 if ( need_refresh[i] && rect[i] != wxGridNoCellRect )
c6a51dcd 4627 m_gridWin->Refresh( FALSE, &(rect[i]) );
da6af900 4628 }
f85afd4e
MB
4629
4630 // only generate an event if the block is not being selected by
4631 // dragging the mouse (in which case the event will be generated in
2d66e025 4632 // the mouse event handler)
f85afd4e
MB
4633 if ( !m_isDragging )
4634 {
4635 wxGridRangeSelectEvent gridEvt( GetId(),
b5f788a5 4636 EVT_GRID_RANGE_SELECT,
f85afd4e
MB
4637 this,
4638 m_selectedTopLeft,
4639 m_selectedBottomRight );
8f177c8e 4640
f85afd4e
MB
4641 GetEventHandler()->ProcessEvent(gridEvt);
4642 }
4643}
4644
4645void wxGrid::SelectAll()
4646{
4647 m_selectedTopLeft.Set( 0, 0 );
4648 m_selectedBottomRight.Set( m_numRows-1, m_numCols-1 );
4649
2d66e025 4650 m_gridWin->Refresh();
f85afd4e
MB
4651}
4652
4653
4654void wxGrid::ClearSelection()
4655{
2d66e025
MB
4656 m_selectedTopLeft = wxGridNoCellCoords;
4657 m_selectedBottomRight = wxGridNoCellCoords;
8f177c8e 4658}
f85afd4e
MB
4659
4660
da6af900 4661// This function returns the rectangle that encloses the given block
2d66e025
MB
4662// in device coords clipped to the client size of the grid window.
4663//
58dd5b3b
MB
4664wxRect wxGrid::BlockToDeviceRect( const wxGridCellCoords &topLeft,
4665 const wxGridCellCoords &bottomRight )
f85afd4e 4666{
58dd5b3b 4667 wxRect rect( wxGridNoCellRect );
f85afd4e
MB
4668 wxRect cellRect;
4669
58dd5b3b
MB
4670 cellRect = CellToRect( topLeft );
4671 if ( cellRect != wxGridNoCellRect )
f85afd4e 4672 {
58dd5b3b
MB
4673 rect = cellRect;
4674 }
4675 else
4676 {
4677 rect = wxRect( 0, 0, 0, 0 );
4678 }
60ff3b99 4679
58dd5b3b
MB
4680 cellRect = CellToRect( bottomRight );
4681 if ( cellRect != wxGridNoCellRect )
4682 {
4683 rect += cellRect;
2d66e025
MB
4684 }
4685 else
4686 {
4687 return wxGridNoCellRect;
f85afd4e
MB
4688 }
4689
58dd5b3b
MB
4690 // convert to scrolled coords
4691 //
4692 int left, top, right, bottom;
4693 CalcScrolledPosition( rect.GetLeft(), rect.GetTop(), &left, &top );
4694 CalcScrolledPosition( rect.GetRight(), rect.GetBottom(), &right, &bottom );
4695
4696 int cw, ch;
4697 m_gridWin->GetClientSize( &cw, &ch );
4698
4699 rect.SetLeft( wxMax(0, left) );
4700 rect.SetTop( wxMax(0, top) );
4701 rect.SetRight( wxMin(cw, right) );
4702 rect.SetBottom( wxMin(ch, bottom) );
4703
f85afd4e
MB
4704 return rect;
4705}
4706
4707
58dd5b3b 4708
f85afd4e
MB
4709//
4710// ------ Grid event classes
4711//
4712
4713IMPLEMENT_DYNAMIC_CLASS( wxGridEvent, wxEvent )
4714
4715wxGridEvent::wxGridEvent( int id, wxEventType type, wxObject* obj,
4716 int row, int col, int x, int y,
4717 bool control, bool shift, bool alt, bool meta )
4718 : wxNotifyEvent( type, id )
4719{
4720 m_row = row;
4721 m_col = col;
4722 m_x = x;
4723 m_y = y;
4724 m_control = control;
4725 m_shift = shift;
4726 m_alt = alt;
4727 m_meta = meta;
8f177c8e 4728
f85afd4e
MB
4729 SetEventObject(obj);
4730}
4731
4732
4733IMPLEMENT_DYNAMIC_CLASS( wxGridSizeEvent, wxEvent )
4734
4735wxGridSizeEvent::wxGridSizeEvent( int id, wxEventType type, wxObject* obj,
4736 int rowOrCol, int x, int y,
4737 bool control, bool shift, bool alt, bool meta )
4738 : wxNotifyEvent( type, id )
4739{
4740 m_rowOrCol = rowOrCol;
4741 m_x = x;
4742 m_y = y;
4743 m_control = control;
4744 m_shift = shift;
4745 m_alt = alt;
4746 m_meta = meta;
8f177c8e 4747
f85afd4e
MB
4748 SetEventObject(obj);
4749}
4750
4751
4752IMPLEMENT_DYNAMIC_CLASS( wxGridRangeSelectEvent, wxEvent )
4753
4754wxGridRangeSelectEvent::wxGridRangeSelectEvent(int id, wxEventType type, wxObject* obj,
8f177c8e
VZ
4755 const wxGridCellCoords& topLeft,
4756 const wxGridCellCoords& bottomRight,
4757 bool control, bool shift, bool alt, bool meta )
4758 : wxNotifyEvent( type, id )
f85afd4e
MB
4759{
4760 m_topLeft = topLeft;
4761 m_bottomRight = bottomRight;
4762 m_control = control;
4763 m_shift = shift;
4764 m_alt = alt;
4765 m_meta = meta;
4766
4767 SetEventObject(obj);
4768}
4769
4770
4771#endif // ifndef wxUSE_NEW_GRID
4772