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