1 /////////////////////////////////////////////////////////////////////////////
3 // Purpose: wxGrid and related classes
4 // Author: Michael Bedward (based on code by Julian Smart, Robin Dunn)
8 // Copyright: (c) Michael Bedward (mbedward@ozemail.com.au)
9 // Licence: wxWindows licence
10 /////////////////////////////////////////////////////////////////////////////
13 #pragma implementation "grid.h"
16 // For compilers that support precompilation, includes "wx/wx.h".
17 #include "wx/wxprec.h"
25 #if !defined(wxUSE_NEW_GRID) || !(wxUSE_NEW_GRID)
31 #include "wx/dcclient.h"
32 #include "wx/settings.h"
37 #include "wx/generic/grid.h"
40 //////////////////////////////////////////////////////////////////////
42 wxGridCellCoords
wxGridNoCellCoords( -1, -1 );
43 wxRect
wxGridNoCellRect( -1, -1, -1, -1 );
45 // this is a magic incantation which must be done!
46 #include "wx/arrimpl.cpp"
48 WX_DEFINE_OBJARRAY(wxGridCellCoordsArray
)
51 //////////////////////////////////////////////////////////////////////
53 // Abstract base class for grid data (the model)
55 IMPLEMENT_ABSTRACT_CLASS( wxGridTableBase
, wxObject
)
58 wxGridTableBase::wxGridTableBase()
61 m_view
= (wxGrid
*) NULL
;
64 wxGridTableBase::~wxGridTableBase()
69 bool wxGridTableBase::InsertRows( size_t pos
, size_t numRows
)
71 wxLogWarning( wxT("Called grid table class function InsertRows(pos=%d, N=%d)\n"
72 "but your derived table class does not override this function"),
78 bool wxGridTableBase::AppendRows( size_t numRows
)
80 wxLogWarning( wxT("Called grid table class function AppendRows(N=%d)\n"
81 "but your derived table class does not override this function"),
87 bool wxGridTableBase::DeleteRows( size_t pos
, size_t numRows
)
89 wxLogWarning( wxT("Called grid table class function DeleteRows(pos=%d, N=%d)\n"
90 "but your derived table class does not override this function"),
96 bool wxGridTableBase::InsertCols( size_t pos
, size_t numCols
)
98 wxLogWarning( wxT("Called grid table class function InsertCols(pos=%d, N=%d)\n"
99 "but your derived table class does not override this function"),
105 bool wxGridTableBase::AppendCols( size_t numCols
)
107 wxLogWarning( wxT("Called grid table class function AppendCols(N=%d)\n"
108 "but your derived table class does not override this function"),
114 bool wxGridTableBase::DeleteCols( size_t pos
, size_t numCols
)
116 wxLogWarning( wxT("Called grid table class function DeleteCols(pos=%d, N=%d)\n"
117 "but your derived table class does not override this function"),
124 wxString
wxGridTableBase::GetRowLabelValue( int row
)
131 wxString
wxGridTableBase::GetColLabelValue( int col
)
133 // default col labels are:
134 // cols 0 to 25 : A-Z
135 // cols 26 to 675 : AA-ZZ
142 s
+= ('A' + (char)( col%26
));
144 if ( col
< 0 ) break;
147 // reverse the string...
149 for ( i
= 0; i
< n
; i
++ )
159 //////////////////////////////////////////////////////////////////////
161 // Message class for the grid table to send requests and notifications
165 wxGridTableMessage::wxGridTableMessage()
167 m_table
= (wxGridTableBase
*) NULL
;
173 wxGridTableMessage::wxGridTableMessage( wxGridTableBase
*table
, int id
,
174 int commandInt1
, int commandInt2
)
178 m_comInt1
= commandInt1
;
179 m_comInt2
= commandInt2
;
184 //////////////////////////////////////////////////////////////////////
186 // A basic grid table for string data. An object of this class will
187 // created by wxGrid if you don't specify an alternative table class.
190 WX_DEFINE_OBJARRAY(wxGridStringArray
)
192 IMPLEMENT_DYNAMIC_CLASS( wxGridStringTable
, wxGridTableBase
)
194 wxGridStringTable::wxGridStringTable()
199 wxGridStringTable::wxGridStringTable( int numRows
, int numCols
)
204 m_data
.Alloc( numRows
);
208 for ( col
= 0; col
< numCols
; col
++ )
210 sa
.Add( wxEmptyString
);
213 for ( row
= 0; row
< numRows
; row
++ )
219 wxGridStringTable::~wxGridStringTable()
223 long wxGridStringTable::GetNumberRows()
225 return m_data
.GetCount();
228 long wxGridStringTable::GetNumberCols()
230 if ( m_data
.GetCount() > 0 )
231 return m_data
[0].GetCount();
236 wxString
wxGridStringTable::GetValue( int row
, int col
)
238 // TODO: bounds checking
240 return m_data
[row
][col
];
243 void wxGridStringTable::SetValue( int row
, int col
, const wxString
& s
)
245 // TODO: bounds checking
247 m_data
[row
][col
] = s
;
250 bool wxGridStringTable::IsEmptyCell( int row
, int col
)
252 // TODO: bounds checking
254 return (m_data
[row
][col
] == wxEmptyString
);
258 void wxGridStringTable::Clear()
261 int numRows
, numCols
;
263 numRows
= m_data
.GetCount();
266 numCols
= m_data
[0].GetCount();
268 for ( row
= 0; row
< numRows
; row
++ )
270 for ( col
= 0; col
< numCols
; col
++ )
272 m_data
[row
][col
] = wxEmptyString
;
279 bool wxGridStringTable::InsertRows( size_t pos
, size_t numRows
)
283 size_t curNumRows
= m_data
.GetCount();
284 size_t curNumCols
= ( curNumRows
> 0 ? m_data
[0].GetCount() : 0 );
286 if ( pos
>= curNumRows
)
288 return AppendRows( numRows
);
292 sa
.Alloc( curNumCols
);
293 for ( col
= 0; col
< curNumCols
; col
++ )
295 sa
.Add( wxEmptyString
);
298 for ( row
= pos
; row
< pos
+ numRows
; row
++ )
300 m_data
.Insert( sa
, row
);
305 wxGridTableMessage
msg( this,
306 wxGRIDTABLE_NOTIFY_ROWS_INSERTED
,
310 GetView()->ProcessTableMessage( msg
);
316 bool wxGridStringTable::AppendRows( size_t numRows
)
320 size_t curNumRows
= m_data
.GetCount();
321 size_t curNumCols
= ( curNumRows
> 0 ? m_data
[0].GetCount() : 0 );
324 if ( curNumCols
> 0 )
326 sa
.Alloc( curNumCols
);
327 for ( col
= 0; col
< curNumCols
; col
++ )
329 sa
.Add( wxEmptyString
);
333 for ( row
= 0; row
< numRows
; row
++ )
340 wxGridTableMessage
msg( this,
341 wxGRIDTABLE_NOTIFY_ROWS_APPENDED
,
344 GetView()->ProcessTableMessage( msg
);
350 bool wxGridStringTable::DeleteRows( size_t pos
, size_t numRows
)
354 size_t curNumRows
= m_data
.GetCount();
356 if ( pos
>= curNumRows
)
358 wxLogError( wxT("Called wxGridStringTable::DeleteRows(pos=%d, N=%d)...\n"
359 "Pos value is invalid for present table with %d rows"),
360 pos
, numRows
, curNumRows
);
364 if ( numRows
> curNumRows
- pos
)
366 numRows
= curNumRows
- pos
;
369 if ( numRows
>= curNumRows
)
371 m_data
.Empty(); // don't release memory just yet
375 for ( n
= 0; n
< numRows
; n
++ )
377 m_data
.Remove( pos
);
383 wxGridTableMessage
msg( this,
384 wxGRIDTABLE_NOTIFY_ROWS_DELETED
,
388 GetView()->ProcessTableMessage( msg
);
394 bool wxGridStringTable::InsertCols( size_t pos
, size_t numCols
)
398 size_t curNumRows
= m_data
.GetCount();
399 size_t curNumCols
= ( curNumRows
> 0 ? m_data
[0].GetCount() : 0 );
401 if ( pos
>= curNumCols
)
403 return AppendCols( numCols
);
406 for ( row
= 0; row
< curNumRows
; row
++ )
408 for ( col
= pos
; col
< pos
+ numCols
; col
++ )
410 m_data
[row
].Insert( wxEmptyString
, col
);
416 wxGridTableMessage
msg( this,
417 wxGRIDTABLE_NOTIFY_COLS_INSERTED
,
421 GetView()->ProcessTableMessage( msg
);
427 bool wxGridStringTable::AppendCols( size_t numCols
)
431 size_t curNumRows
= m_data
.GetCount();
434 // TODO: something better than this ?
436 wxLogError( wxT("Unable to append cols to a grid table with no rows.\n"
437 "Call AppendRows() first") );
441 for ( row
= 0; row
< curNumRows
; row
++ )
443 for ( n
= 0; n
< numCols
; n
++ )
445 m_data
[row
].Add( wxEmptyString
);
451 wxGridTableMessage
msg( this,
452 wxGRIDTABLE_NOTIFY_COLS_APPENDED
,
455 GetView()->ProcessTableMessage( msg
);
461 bool wxGridStringTable::DeleteCols( size_t pos
, size_t numCols
)
465 size_t curNumRows
= m_data
.GetCount();
466 size_t curNumCols
= ( curNumRows
> 0 ? m_data
[0].GetCount() : 0 );
468 if ( pos
>= curNumCols
)
470 wxLogError( wxT("Called wxGridStringTable::DeleteCols(pos=%d, N=%d)...\n"
471 "Pos value is invalid for present table with %d cols"),
472 pos
, numCols
, curNumCols
);
476 if ( numCols
> curNumCols
- pos
)
478 numCols
= curNumCols
- pos
;
481 for ( row
= 0; row
< curNumRows
; row
++ )
483 if ( numCols
>= curNumCols
)
489 for ( n
= 0; n
< numCols
; n
++ )
491 m_data
[row
].Remove( pos
);
498 wxGridTableMessage
msg( this,
499 wxGRIDTABLE_NOTIFY_COLS_DELETED
,
503 GetView()->ProcessTableMessage( msg
);
509 wxString
wxGridStringTable::GetRowLabelValue( int row
)
511 if ( row
> (int)(m_rowLabels
.GetCount()) - 1 )
513 // using default label
515 return wxGridTableBase::GetRowLabelValue( row
);
519 return m_rowLabels
[ row
];
523 wxString
wxGridStringTable::GetColLabelValue( int col
)
525 if ( col
> (int)(m_colLabels
.GetCount()) - 1 )
527 // using default label
529 return wxGridTableBase::GetColLabelValue( col
);
533 return m_colLabels
[ col
];
537 void wxGridStringTable::SetRowLabelValue( int row
, const wxString
& value
)
539 if ( row
> (int)(m_rowLabels
.GetCount()) - 1 )
541 int n
= m_rowLabels
.GetCount();
543 for ( i
= n
; i
<= row
; i
++ )
545 m_rowLabels
.Add( wxGridTableBase::GetRowLabelValue(i
) );
549 m_rowLabels
[row
] = value
;
552 void wxGridStringTable::SetColLabelValue( int col
, const wxString
& value
)
554 if ( col
> (int)(m_colLabels
.GetCount()) - 1 )
556 int n
= m_colLabels
.GetCount();
558 for ( i
= n
; i
<= col
; i
++ )
560 m_colLabels
.Add( wxGridTableBase::GetColLabelValue(i
) );
564 m_colLabels
[col
] = value
;
570 //////////////////////////////////////////////////////////////////////
572 IMPLEMENT_DYNAMIC_CLASS( wxGridTextCtrl
, wxTextCtrl
)
574 BEGIN_EVENT_TABLE( wxGridTextCtrl
, wxTextCtrl
)
575 EVT_KEY_DOWN( wxGridTextCtrl::OnKeyDown
)
579 wxGridTextCtrl::wxGridTextCtrl( wxWindow
*par
,
583 const wxString
& value
,
587 : wxTextCtrl( par
, id
, value
, pos
, size
, style
)
590 m_isCellControl
= isCellControl
;
594 void wxGridTextCtrl::OnKeyDown( wxKeyEvent
& event
)
596 switch ( event
.KeyCode() )
599 m_grid
->SetEditControlValue( startValue
);
600 SetInsertionPointEnd();
610 if ( m_isCellControl
)
612 // send the event to the parent grid, skipping the
613 // event if nothing happens
615 event
.Skip( m_grid
->ProcessEvent( event
) );
619 // default text control response within the top edit
628 if ( m_isCellControl
)
630 // send the event to the parent grid, skipping the
631 // event if nothing happens
633 event
.Skip( m_grid
->ProcessEvent( event
) );
637 // default text control response within the top edit
649 void wxGridTextCtrl::SetStartValue( const wxString
& s
)
652 wxTextCtrl::SetValue( s
.c_str() );
657 //////////////////////////////////////////////////////////////////////
659 IMPLEMENT_DYNAMIC_CLASS( wxGridRowLabelWindow
, wxWindow
)
661 BEGIN_EVENT_TABLE( wxGridRowLabelWindow
, wxWindow
)
662 EVT_PAINT( wxGridRowLabelWindow::OnPaint
)
663 EVT_MOUSE_EVENTS( wxGridRowLabelWindow::OnMouseEvent
)
664 EVT_KEY_DOWN( wxGridRowLabelWindow::OnKeyDown
)
667 wxGridRowLabelWindow::wxGridRowLabelWindow( wxGrid
*parent
,
669 const wxPoint
&pos
, const wxSize
&size
)
670 : wxWindow( parent
, id
, pos
, size
)
675 void wxGridRowLabelWindow::OnPaint( wxPaintEvent
&event
)
679 // NO - don't do this because it will set both the x and y origin
680 // coords to match the parent scrolled window and we just want to
681 // set the y coord - MB
683 // m_owner->PrepareDC( dc );
686 m_owner
->CalcUnscrolledPosition( 0, 0, &x
, &y
);
687 dc
.SetDeviceOrigin( 0, -y
);
689 m_owner
->CalcRowLabelsExposed( GetUpdateRegion() );
690 m_owner
->DrawRowLabels( dc
);
694 void wxGridRowLabelWindow::OnMouseEvent( wxMouseEvent
& event
)
696 m_owner
->ProcessRowLabelMouseEvent( event
);
700 // This seems to be required for wxMotif otherwise the mouse
701 // cursor must be in the cell edit control to get key events
703 void wxGridRowLabelWindow::OnKeyDown( wxKeyEvent
& event
)
705 if ( !m_owner
->ProcessEvent( event
) ) event
.Skip();
710 //////////////////////////////////////////////////////////////////////
712 IMPLEMENT_DYNAMIC_CLASS( wxGridColLabelWindow
, wxWindow
)
714 BEGIN_EVENT_TABLE( wxGridColLabelWindow
, wxWindow
)
715 EVT_PAINT( wxGridColLabelWindow::OnPaint
)
716 EVT_MOUSE_EVENTS( wxGridColLabelWindow::OnMouseEvent
)
717 EVT_KEY_DOWN( wxGridColLabelWindow::OnKeyDown
)
720 wxGridColLabelWindow::wxGridColLabelWindow( wxGrid
*parent
,
722 const wxPoint
&pos
, const wxSize
&size
)
723 : wxWindow( parent
, id
, pos
, size
)
728 void wxGridColLabelWindow::OnPaint( wxPaintEvent
&event
)
732 // NO - don't do this because it will set both the x and y origin
733 // coords to match the parent scrolled window and we just want to
734 // set the x coord - MB
736 // m_owner->PrepareDC( dc );
739 m_owner
->CalcUnscrolledPosition( 0, 0, &x
, &y
);
740 dc
.SetDeviceOrigin( -x
, 0 );
742 m_owner
->CalcColLabelsExposed( GetUpdateRegion() );
743 m_owner
->DrawColLabels( dc
);
747 void wxGridColLabelWindow::OnMouseEvent( wxMouseEvent
& event
)
749 m_owner
->ProcessColLabelMouseEvent( event
);
753 // This seems to be required for wxMotif otherwise the mouse
754 // cursor must be in the cell edit control to get key events
756 void wxGridColLabelWindow::OnKeyDown( wxKeyEvent
& event
)
758 if ( !m_owner
->ProcessEvent( event
) ) event
.Skip();
763 //////////////////////////////////////////////////////////////////////
765 IMPLEMENT_DYNAMIC_CLASS( wxGridCornerLabelWindow
, wxWindow
)
767 BEGIN_EVENT_TABLE( wxGridCornerLabelWindow
, wxWindow
)
768 EVT_MOUSE_EVENTS( wxGridCornerLabelWindow::OnMouseEvent
)
769 EVT_KEY_DOWN( wxGridCornerLabelWindow::OnKeyDown
)
772 wxGridCornerLabelWindow::wxGridCornerLabelWindow( wxGrid
*parent
,
774 const wxPoint
&pos
, const wxSize
&size
)
775 : wxWindow( parent
, id
, pos
, size
, wxRAISED_BORDER
)
781 void wxGridCornerLabelWindow::OnMouseEvent( wxMouseEvent
& event
)
783 m_owner
->ProcessCornerLabelMouseEvent( event
);
787 // This seems to be required for wxMotif otherwise the mouse
788 // cursor must be in the cell edit control to get key events
790 void wxGridCornerLabelWindow::OnKeyDown( wxKeyEvent
& event
)
792 if ( !m_owner
->ProcessEvent( event
) ) event
.Skip();
797 //////////////////////////////////////////////////////////////////////
799 IMPLEMENT_DYNAMIC_CLASS( wxGridWindow
, wxPanel
)
801 BEGIN_EVENT_TABLE( wxGridWindow
, wxPanel
)
802 EVT_PAINT( wxGridWindow::OnPaint
)
803 EVT_SCROLLWIN( wxGridWindow::ScrollWindow
)
804 EVT_MOUSE_EVENTS( wxGridWindow::OnMouseEvent
)
805 EVT_KEY_DOWN( wxGridWindow::OnKeyDown
)
808 wxGridWindow::wxGridWindow( wxGrid
*parent
,
809 wxGridRowLabelWindow
*rowLblWin
,
810 wxGridColLabelWindow
*colLblWin
,
811 wxWindowID id
, const wxPoint
&pos
, const wxSize
&size
)
812 : wxPanel( parent
, id
, pos
, size
, wxSUNKEN_BORDER
, "grid window" )
815 m_rowLabelWin
= rowLblWin
;
816 m_colLabelWin
= colLblWin
;
818 SetBackgroundColour( "WHITE" );
822 wxGridWindow::~wxGridWindow()
827 void wxGridWindow::OnPaint( wxPaintEvent
&WXUNUSED(event
) )
829 wxPaintDC
dc( this );
830 m_owner
->PrepareDC( dc
);
832 m_owner
->CalcCellsExposed( GetUpdateRegion() );
833 m_owner
->DrawGridCellArea( dc
);
837 void wxGridWindow::ScrollWindow( int dx
, int dy
, const wxRect
*rect
)
839 wxPanel::ScrollWindow( dx
, dy
, rect
);
840 m_rowLabelWin
->ScrollWindow( 0, dy
, rect
);
841 m_colLabelWin
->ScrollWindow( dx
, 0, rect
);
845 void wxGridWindow::OnMouseEvent( wxMouseEvent
& event
)
847 m_owner
->ProcessGridCellMouseEvent( event
);
851 // This seems to be required for wxMotif otherwise the mouse
852 // cursor must be in the cell edit control to get key events
854 void wxGridWindow::OnKeyDown( wxKeyEvent
& event
)
856 if ( !m_owner
->ProcessEvent( event
) ) event
.Skip();
861 //////////////////////////////////////////////////////////////////////
863 IMPLEMENT_DYNAMIC_CLASS( wxGrid
, wxScrolledWindow
)
865 BEGIN_EVENT_TABLE( wxGrid
, wxScrolledWindow
)
866 EVT_PAINT( wxGrid::OnPaint
)
867 EVT_SIZE( wxGrid::OnSize
)
868 EVT_KEY_DOWN( wxGrid::OnKeyDown
)
871 wxGrid::wxGrid( wxWindow
*parent
,
876 const wxString
& name
)
877 : wxScrolledWindow( parent
, id
, pos
, size
, style
, name
)
881 int colLblH
= WXGRID_DEFAULT_COL_LABEL_HEIGHT
;
882 int rowLblW
= WXGRID_DEFAULT_ROW_LABEL_WIDTH
;
884 m_rowLabelWin
= new wxGridRowLabelWindow( this,
887 wxSize(rowLblW
,-1) );
889 m_colLabelWin
= new wxGridColLabelWindow( this,
892 wxSize(-1, colLblH
) );
894 m_cornerLabelWin
= new wxGridCornerLabelWindow( this,
897 wxSize(rowLblW
, colLblH
) );
899 m_gridWin
= new wxGridWindow( this,
906 SetTargetWindow( m_gridWin
);
908 m_mainSizer
= new wxBoxSizer( wxVERTICAL
);
910 m_topSizer
= new wxBoxSizer( wxHORIZONTAL
);
911 m_topSizer
->Add( m_cornerLabelWin
, 0 );
912 m_topSizer
->Add( m_colLabelWin
, 1 );
914 m_mainSizer
->Add( m_topSizer
, 0, wxEXPAND
);
916 m_middleSizer
= new wxBoxSizer( wxHORIZONTAL
);
917 m_middleSizer
->Add( m_rowLabelWin
, 0, wxEXPAND
);
918 m_middleSizer
->Add( m_gridWin
, 1, wxEXPAND
);
920 m_mainSizer
->Add( m_middleSizer
, 1, wxEXPAND
);
922 SetAutoLayout( TRUE
);
923 SetSizer( m_mainSizer
);
933 // ----- internal init and update functions
936 void wxGrid::Create()
938 m_table
= (wxGridTableBase
*) NULL
;
939 m_gridWin
= (wxGridWindow
*) NULL
;
940 m_rowLabelWin
= (wxGridRowLabelWindow
*) NULL
;
941 m_colLabelWin
= (wxGridColLabelWindow
*) NULL
;
942 m_cornerLabelWin
= (wxGridCornerLabelWindow
*) NULL
;
943 m_cellEditCtrl
= (wxWindow
*) NULL
;
947 bool wxGrid::CreateGrid( int numRows
, int numCols
)
951 wxLogError( wxT("wxGrid::CreateGrid(numRows, numCols) called more than once") );
959 m_table
= new wxGridStringTable( m_numRows
, m_numCols
);
960 m_table
->SetView( this );
973 if ( m_numRows
<= 0 )
974 m_numRows
= WXGRID_DEFAULT_NUMBER_ROWS
;
976 if ( m_numCols
<= 0 )
977 m_numCols
= WXGRID_DEFAULT_NUMBER_COLS
;
979 m_rowLabelWidth
= WXGRID_DEFAULT_ROW_LABEL_WIDTH
;
980 m_colLabelHeight
= WXGRID_DEFAULT_COL_LABEL_HEIGHT
;
984 m_labelBackgroundColour
= m_rowLabelWin
->GetBackgroundColour();
988 m_labelBackgroundColour
= wxColour( _T("WHITE") );
991 m_labelTextColour
= wxColour( _T("BLACK") );
993 // TODO: something better than this ?
995 m_labelFont
= this->GetFont();
996 m_labelFont
.SetWeight( m_labelFont
.GetWeight() + 2 );
998 m_rowLabelHorizAlign
= wxLEFT
;
999 m_rowLabelVertAlign
= wxCENTRE
;
1001 m_colLabelHorizAlign
= wxCENTRE
;
1002 m_colLabelVertAlign
= wxTOP
;
1004 m_defaultColWidth
= WXGRID_DEFAULT_COL_WIDTH
;
1005 m_defaultRowHeight
= m_gridWin
->GetCharHeight();
1007 #if defined (__WXMOTIF__) // see also text ctrl sizing in ShowCellEditControl()
1008 m_defaultRowHeight
+= 8;
1010 m_defaultRowHeight
+= 4;
1013 m_rowHeights
.Alloc( m_numRows
);
1014 m_rowBottoms
.Alloc( m_numRows
);
1016 for ( i
= 0; i
< m_numRows
; i
++ )
1018 m_rowHeights
.Add( m_defaultRowHeight
);
1019 rowBottom
+= m_defaultRowHeight
;
1020 m_rowBottoms
.Add( rowBottom
);
1023 m_colWidths
.Alloc( m_numCols
);
1024 m_colRights
.Alloc( m_numCols
);
1026 for ( i
= 0; i
< m_numCols
; i
++ )
1028 m_colWidths
.Add( m_defaultColWidth
);
1029 colRight
+= m_defaultColWidth
;
1030 m_colRights
.Add( colRight
);
1033 // TODO: improve this ?
1035 m_defaultCellFont
= this->GetFont();
1037 m_gridLineColour
= wxColour( 128, 128, 255 );
1038 m_gridLinesEnabled
= TRUE
;
1040 m_cursorMode
= WXGRID_CURSOR_DEFAULT
;
1042 m_dragRowOrCol
= -1;
1043 m_isDragging
= FALSE
;
1045 m_rowResizeCursor
= wxCursor( wxCURSOR_SIZENS
);
1046 m_colResizeCursor
= wxCursor( wxCURSOR_SIZEWE
);
1048 m_currentCellCoords
= wxGridNoCellCoords
;
1050 m_selectedTopLeft
= wxGridNoCellCoords
;
1051 m_selectedBottomRight
= wxGridNoCellCoords
;
1053 m_editable
= TRUE
; // default for whole grid
1055 m_inOnKeyDown
= FALSE
;
1058 // TODO: extend this to other types of controls
1060 m_cellEditCtrl
= new wxGridTextCtrl( m_gridWin
,
1068 , wxTE_MULTILINE
| wxTE_NO_VSCROLL
1072 m_cellEditCtrl
->Show( FALSE
);
1073 m_cellEditCtrlEnabled
= TRUE
;
1074 m_editCtrlType
= wxGRID_TEXTCTRL
;
1078 void wxGrid::CalcDimensions()
1081 GetClientSize( &cw
, &ch
);
1083 if ( m_numRows
> 0 && m_numCols
> 0 )
1085 int right
= m_colRights
[ m_numCols
-1 ] + 20;
1086 int bottom
= m_rowBottoms
[ m_numRows
-1 ] + 20;
1088 // TODO: restore the scroll position that we had before sizing
1091 GetViewStart( &x
, &y
);
1092 SetScrollbars( 10, 10,
1093 right
/10, bottom
/10,
1099 // this is called when the grid table sends a message to say that it
1100 // has been redimensioned
1102 bool wxGrid::Redimension( wxGridTableMessage
& msg
)
1106 switch ( msg
.GetId() )
1108 case wxGRIDTABLE_NOTIFY_ROWS_INSERTED
:
1110 size_t pos
= msg
.GetCommandInt();
1111 int numRows
= msg
.GetCommandInt2();
1112 for ( i
= 0; i
< numRows
; i
++ )
1114 m_rowHeights
.Insert( m_defaultRowHeight
, pos
);
1115 m_rowBottoms
.Insert( 0, pos
);
1117 m_numRows
+= numRows
;
1120 if ( pos
> 0 ) bottom
= m_rowBottoms
[pos
-1];
1122 for ( i
= pos
; i
< m_numRows
; i
++ )
1124 bottom
+= m_rowHeights
[i
];
1125 m_rowBottoms
[i
] = bottom
;
1131 case wxGRIDTABLE_NOTIFY_ROWS_APPENDED
:
1133 int numRows
= msg
.GetCommandInt();
1134 for ( i
= 0; i
< numRows
; i
++ )
1136 m_rowHeights
.Add( m_defaultRowHeight
);
1137 m_rowBottoms
.Add( 0 );
1140 int oldNumRows
= m_numRows
;
1141 m_numRows
+= numRows
;
1144 if ( oldNumRows
> 0 ) bottom
= m_rowBottoms
[oldNumRows
-1];
1146 for ( i
= oldNumRows
; i
< m_numRows
; i
++ )
1148 bottom
+= m_rowHeights
[i
];
1149 m_rowBottoms
[i
] = bottom
;
1155 case wxGRIDTABLE_NOTIFY_ROWS_DELETED
:
1157 size_t pos
= msg
.GetCommandInt();
1158 int numRows
= msg
.GetCommandInt2();
1159 for ( i
= 0; i
< numRows
; i
++ )
1161 m_rowHeights
.Remove( pos
);
1162 m_rowBottoms
.Remove( pos
);
1164 m_numRows
-= numRows
;
1169 m_colWidths
.Clear();
1170 m_colRights
.Clear();
1171 m_currentCellCoords
= wxGridNoCellCoords
;
1175 if ( m_currentCellCoords
.GetRow() >= m_numRows
)
1176 m_currentCellCoords
.Set( 0, 0 );
1179 for ( i
= 0; i
< m_numRows
; i
++ )
1181 h
+= m_rowHeights
[i
];
1182 m_rowBottoms
[i
] = h
;
1190 case wxGRIDTABLE_NOTIFY_COLS_INSERTED
:
1192 size_t pos
= msg
.GetCommandInt();
1193 int numCols
= msg
.GetCommandInt2();
1194 for ( i
= 0; i
< numCols
; i
++ )
1196 m_colWidths
.Insert( m_defaultColWidth
, pos
);
1197 m_colRights
.Insert( 0, pos
);
1199 m_numCols
+= numCols
;
1202 if ( pos
> 0 ) right
= m_colRights
[pos
-1];
1204 for ( i
= pos
; i
< m_numCols
; i
++ )
1206 right
+= m_colWidths
[i
];
1207 m_colRights
[i
] = right
;
1213 case wxGRIDTABLE_NOTIFY_COLS_APPENDED
:
1215 int numCols
= msg
.GetCommandInt();
1216 for ( i
= 0; i
< numCols
; i
++ )
1218 m_colWidths
.Add( m_defaultColWidth
);
1219 m_colRights
.Add( 0 );
1222 int oldNumCols
= m_numCols
;
1223 m_numCols
+= numCols
;
1226 if ( oldNumCols
> 0 ) right
= m_colRights
[oldNumCols
-1];
1228 for ( i
= oldNumCols
; i
< m_numCols
; i
++ )
1230 right
+= m_colWidths
[i
];
1231 m_colRights
[i
] = right
;
1237 case wxGRIDTABLE_NOTIFY_COLS_DELETED
:
1239 size_t pos
= msg
.GetCommandInt();
1240 int numCols
= msg
.GetCommandInt2();
1241 for ( i
= 0; i
< numCols
; i
++ )
1243 m_colWidths
.Remove( pos
);
1244 m_colRights
.Remove( pos
);
1246 m_numCols
-= numCols
;
1250 #if 0 // leave the row alone here so that AppendCols will work subsequently
1252 m_rowHeights
.Clear();
1253 m_rowBottoms
.Clear();
1255 m_currentCellCoords
= wxGridNoCellCoords
;
1259 if ( m_currentCellCoords
.GetCol() >= m_numCols
)
1260 m_currentCellCoords
.Set( 0, 0 );
1263 for ( i
= 0; i
< m_numCols
; i
++ )
1265 w
+= m_colWidths
[i
];
1278 void wxGrid::CalcRowLabelsExposed( wxRegion
& reg
)
1280 wxRegionIterator
iter( reg
);
1283 m_rowLabelsExposed
.Empty();
1290 // TODO: remove this when we can...
1291 // There is a bug in wxMotif that gives garbage update
1292 // rectangles if you jump-scroll a long way by clicking the
1293 // scrollbar with middle button. This is a work-around
1295 #if defined(__WXMOTIF__)
1297 m_gridWin
->GetClientSize( &cw
, &ch
);
1298 if ( r
.GetTop() > ch
) r
.SetTop( 0 );
1299 r
.SetBottom( wxMin( r
.GetBottom(), ch
) );
1302 // logical bounds of update region
1305 CalcUnscrolledPosition( 0, r
.GetTop(), &dummy
, &top
);
1306 CalcUnscrolledPosition( 0, r
.GetBottom(), &dummy
, &bottom
);
1308 // find the row labels within these bounds
1312 for ( row
= 0; row
< m_numRows
; row
++ )
1314 if ( m_rowBottoms
[row
] < top
) continue;
1316 rowTop
= m_rowBottoms
[row
] - m_rowHeights
[row
];
1317 if ( rowTop
> bottom
) break;
1319 m_rowLabelsExposed
.Add( row
);
1327 void wxGrid::CalcColLabelsExposed( wxRegion
& reg
)
1329 wxRegionIterator
iter( reg
);
1332 m_colLabelsExposed
.Empty();
1339 // TODO: remove this when we can...
1340 // There is a bug in wxMotif that gives garbage update
1341 // rectangles if you jump-scroll a long way by clicking the
1342 // scrollbar with middle button. This is a work-around
1344 #if defined(__WXMOTIF__)
1346 m_gridWin
->GetClientSize( &cw
, &ch
);
1347 if ( r
.GetLeft() > cw
) r
.SetLeft( 0 );
1348 r
.SetRight( wxMin( r
.GetRight(), cw
) );
1351 // logical bounds of update region
1354 CalcUnscrolledPosition( r
.GetLeft(), 0, &left
, &dummy
);
1355 CalcUnscrolledPosition( r
.GetRight(), 0, &right
, &dummy
);
1357 // find the cells within these bounds
1361 for ( col
= 0; col
< m_numCols
; col
++ )
1363 if ( m_colRights
[col
] < left
) continue;
1365 colLeft
= m_colRights
[col
] - m_colWidths
[col
];
1366 if ( colLeft
> right
) break;
1368 m_colLabelsExposed
.Add( col
);
1376 void wxGrid::CalcCellsExposed( wxRegion
& reg
)
1378 wxRegionIterator
iter( reg
);
1381 m_cellsExposed
.Empty();
1382 m_rowsExposed
.Empty();
1383 m_colsExposed
.Empty();
1385 int left
, top
, right
, bottom
;
1390 // TODO: remove this when we can...
1391 // There is a bug in wxMotif that gives garbage update
1392 // rectangles if you jump-scroll a long way by clicking the
1393 // scrollbar with middle button. This is a work-around
1395 #if defined(__WXMOTIF__)
1397 m_gridWin
->GetClientSize( &cw
, &ch
);
1398 if ( r
.GetTop() > ch
) r
.SetTop( 0 );
1399 if ( r
.GetLeft() > cw
) r
.SetLeft( 0 );
1400 r
.SetRight( wxMin( r
.GetRight(), cw
) );
1401 r
.SetBottom( wxMin( r
.GetBottom(), ch
) );
1404 // logical bounds of update region
1406 CalcUnscrolledPosition( r
.GetLeft(), r
.GetTop(), &left
, &top
);
1407 CalcUnscrolledPosition( r
.GetRight(), r
.GetBottom(), &right
, &bottom
);
1409 // find the cells within these bounds
1412 int colLeft
, rowTop
;
1413 for ( row
= 0; row
< m_numRows
; row
++ )
1415 if ( m_rowBottoms
[row
] < top
) continue;
1417 rowTop
= m_rowBottoms
[row
] - m_rowHeights
[row
];
1418 if ( rowTop
> bottom
) break;
1420 m_rowsExposed
.Add( row
);
1422 for ( col
= 0; col
< m_numCols
; col
++ )
1424 if ( m_colRights
[col
] < left
) continue;
1426 colLeft
= m_colRights
[col
] - m_colWidths
[col
];
1427 if ( colLeft
> right
) break;
1429 if ( m_colsExposed
.Index( col
) == wxNOT_FOUND
) m_colsExposed
.Add( col
);
1430 m_cellsExposed
.Add( wxGridCellCoords( row
, col
) );
1439 void wxGrid::ProcessRowLabelMouseEvent( wxMouseEvent
& event
)
1442 wxPoint
pos( event
.GetPosition() );
1443 CalcUnscrolledPosition( pos
.x
, pos
.y
, &x
, &y
);
1445 if ( event
.Dragging() )
1447 m_isDragging
= TRUE
;
1449 if ( event
.LeftIsDown() )
1451 switch( m_cursorMode
)
1453 case WXGRID_CURSOR_RESIZE_ROW
:
1455 int cw
, ch
, left
, dummy
;
1456 m_gridWin
->GetClientSize( &cw
, &ch
);
1457 CalcUnscrolledPosition( 0, 0, &left
, &dummy
);
1459 wxClientDC
dc( m_gridWin
);
1461 dc
.SetLogicalFunction(wxXOR
);
1462 if ( m_dragLastPos
>= 0 )
1464 dc
.DrawLine( left
, m_dragLastPos
, left
+cw
, m_dragLastPos
);
1466 dc
.DrawLine( left
, y
, left
+cw
, y
);
1471 case WXGRID_CURSOR_SELECT_ROW
:
1473 if ( (row
= YToRow( y
)) >= 0 &&
1474 !IsInSelection( row
, 0 ) )
1476 SelectRow( row
, TRUE
);
1485 m_isDragging
= FALSE
;
1488 // ------------ Left button pressed
1490 if ( event
.LeftDown() )
1492 // don't send a label click event for a hit on the
1493 // edge of the row label - this is probably the user
1494 // wanting to resize the row
1496 if ( YToEdgeOfRow(y
) < 0 )
1499 if ( !SendEvent( EVT_GRID_LABEL_LEFT_CLICK
, row
, -1, event
) )
1501 SelectRow( row
, event
.ShiftDown() );
1502 m_cursorMode
= WXGRID_CURSOR_SELECT_ROW
;
1507 // starting to drag-resize a row
1509 m_rowLabelWin
->CaptureMouse();
1514 // ------------ Left double click
1516 else if (event
.LeftDClick() )
1518 if ( YToEdgeOfRow(y
) < 0 )
1521 SendEvent( EVT_GRID_LABEL_LEFT_DCLICK
, row
, -1, event
);
1526 // ------------ Left button released
1528 else if ( event
.LeftUp() )
1530 if ( m_cursorMode
== WXGRID_CURSOR_RESIZE_ROW
)
1532 m_rowLabelWin
->ReleaseMouse();
1534 if ( m_dragLastPos
>= 0 )
1536 // erase the last line and resize the row
1538 int cw
, ch
, left
, dummy
;
1539 m_gridWin
->GetClientSize( &cw
, &ch
);
1540 CalcUnscrolledPosition( 0, 0, &left
, &dummy
);
1542 wxClientDC
dc( m_gridWin
);
1544 dc
.SetLogicalFunction( wxINVERT
);
1545 dc
.DrawLine( left
, m_dragLastPos
, left
+cw
, m_dragLastPos
);
1546 HideCellEditControl();
1548 int rowTop
= m_rowBottoms
[m_dragRowOrCol
] - m_rowHeights
[m_dragRowOrCol
];
1549 SetRowSize( m_dragRowOrCol
, wxMax( y
- rowTop
, WXGRID_MIN_ROW_HEIGHT
) );
1550 if ( !GetBatchCount() )
1552 // TODO: optimize this
1553 m_rowLabelWin
->Refresh();
1554 m_gridWin
->Refresh();
1557 ShowCellEditControl();
1559 // Note: we are ending the event *after* doing
1560 // default processing in this case
1562 SendEvent( EVT_GRID_ROW_SIZE
, m_dragRowOrCol
, -1, event
);
1570 // ------------ Right button down
1572 else if ( event
.RightDown() )
1575 if ( !SendEvent( EVT_GRID_LABEL_RIGHT_CLICK
, row
, -1, event
) )
1577 // no default action at the moment
1582 // ------------ Right double click
1584 else if ( event
.RightDClick() )
1587 if ( !SendEvent( EVT_GRID_LABEL_RIGHT_DCLICK
, row
, -1, event
) )
1589 // no default action at the moment
1594 // ------------ No buttons down and mouse moving
1596 else if ( event
.Moving() )
1598 m_dragRowOrCol
= YToEdgeOfRow( y
);
1599 if ( m_dragRowOrCol
>= 0 )
1601 if ( m_cursorMode
== WXGRID_CURSOR_SELECT_CELL
)
1603 m_cursorMode
= WXGRID_CURSOR_RESIZE_ROW
;
1604 m_rowLabelWin
->SetCursor( m_rowResizeCursor
);
1609 if ( m_cursorMode
!= WXGRID_CURSOR_SELECT_CELL
)
1611 m_cursorMode
= WXGRID_CURSOR_SELECT_CELL
;
1612 m_rowLabelWin
->SetCursor( *wxSTANDARD_CURSOR
);
1619 void wxGrid::ProcessColLabelMouseEvent( wxMouseEvent
& event
)
1622 wxPoint
pos( event
.GetPosition() );
1623 CalcUnscrolledPosition( pos
.x
, pos
.y
, &x
, &y
);
1625 if ( event
.Dragging() )
1627 m_isDragging
= TRUE
;
1629 if ( event
.LeftIsDown() )
1631 switch( m_cursorMode
)
1633 case WXGRID_CURSOR_RESIZE_COL
:
1635 int cw
, ch
, dummy
, top
;
1636 m_gridWin
->GetClientSize( &cw
, &ch
);
1637 CalcUnscrolledPosition( 0, 0, &dummy
, &top
);
1639 wxClientDC
dc( m_gridWin
);
1641 dc
.SetLogicalFunction(wxXOR
);
1642 if ( m_dragLastPos
>= 0 )
1644 dc
.DrawLine( m_dragLastPos
, top
, m_dragLastPos
, top
+ch
);
1646 dc
.DrawLine( x
, top
, x
, top
+ch
);
1651 case WXGRID_CURSOR_SELECT_COL
:
1653 if ( (col
= XToCol( x
)) >= 0 &&
1654 !IsInSelection( 0, col
) )
1656 SelectCol( col
, TRUE
);
1665 m_isDragging
= FALSE
;
1668 // ------------ Left button pressed
1670 if ( event
.LeftDown() )
1672 // don't send a label click event for a hit on the
1673 // edge of the col label - this is probably the user
1674 // wanting to resize the col
1676 if ( XToEdgeOfCol(x
) < 0 )
1679 if ( !SendEvent( EVT_GRID_LABEL_LEFT_CLICK
, -1, col
, event
) )
1681 SelectCol( col
, event
.ShiftDown() );
1682 m_cursorMode
= WXGRID_CURSOR_SELECT_COL
;
1687 // starting to drag-resize a col
1689 m_colLabelWin
->CaptureMouse();
1694 // ------------ Left double click
1696 if ( event
.LeftDClick() )
1698 if ( XToEdgeOfCol(x
) < 0 )
1701 SendEvent( EVT_GRID_LABEL_LEFT_DCLICK
, -1, col
, event
);
1706 // ------------ Left button released
1708 else if ( event
.LeftUp() )
1710 if ( m_cursorMode
== WXGRID_CURSOR_RESIZE_COL
)
1712 m_colLabelWin
->ReleaseMouse();
1714 if ( m_dragLastPos
>= 0 )
1716 // erase the last line and resize the col
1718 int cw
, ch
, dummy
, top
;
1719 m_gridWin
->GetClientSize( &cw
, &ch
);
1720 CalcUnscrolledPosition( 0, 0, &dummy
, &top
);
1722 wxClientDC
dc( m_gridWin
);
1724 dc
.SetLogicalFunction( wxINVERT
);
1725 dc
.DrawLine( m_dragLastPos
, top
, m_dragLastPos
, top
+ch
);
1726 HideCellEditControl();
1728 int colLeft
= m_colRights
[m_dragRowOrCol
] - m_colWidths
[m_dragRowOrCol
];
1729 SetColSize( m_dragRowOrCol
, wxMax( x
- colLeft
, WXGRID_MIN_COL_WIDTH
) );
1731 if ( !GetBatchCount() )
1733 // TODO: optimize this
1734 m_colLabelWin
->Refresh();
1735 m_gridWin
->Refresh();
1738 ShowCellEditControl();
1740 // Note: we are ending the event *after* doing
1741 // default processing in this case
1743 SendEvent( EVT_GRID_COL_SIZE
, -1, m_dragRowOrCol
, event
);
1751 // ------------ Right button down
1753 else if ( event
.RightDown() )
1756 if ( !SendEvent( EVT_GRID_LABEL_RIGHT_CLICK
, -1, col
, event
) )
1758 // no default action at the moment
1763 // ------------ Right double click
1765 else if ( event
.RightDClick() )
1768 if ( !SendEvent( EVT_GRID_LABEL_RIGHT_DCLICK
, -1, col
, event
) )
1770 // no default action at the moment
1775 // ------------ No buttons down and mouse moving
1777 else if ( event
.Moving() )
1779 m_dragRowOrCol
= XToEdgeOfCol( x
);
1780 if ( m_dragRowOrCol
>= 0 )
1782 if ( m_cursorMode
== WXGRID_CURSOR_SELECT_CELL
)
1784 m_cursorMode
= WXGRID_CURSOR_RESIZE_COL
;
1785 m_colLabelWin
->SetCursor( m_colResizeCursor
);
1790 if ( m_cursorMode
!= WXGRID_CURSOR_SELECT_CELL
)
1792 m_cursorMode
= WXGRID_CURSOR_SELECT_CELL
;
1793 m_colLabelWin
->SetCursor( *wxSTANDARD_CURSOR
);
1800 void wxGrid::ProcessCornerLabelMouseEvent( wxMouseEvent
& event
)
1802 if ( event
.LeftDown() )
1804 // indicate corner label by having both row and
1807 if ( !SendEvent( EVT_GRID_LABEL_LEFT_CLICK
, -1, -1, event
) )
1813 else if ( event
.LeftDClick() )
1815 SendEvent( EVT_GRID_LABEL_LEFT_DCLICK
, -1, -1, event
);
1818 else if ( event
.RightDown() )
1820 if ( !SendEvent( EVT_GRID_LABEL_RIGHT_CLICK
, -1, -1, event
) )
1822 // no default action at the moment
1826 else if ( event
.RightDClick() )
1828 if ( !SendEvent( EVT_GRID_LABEL_RIGHT_DCLICK
, -1, -1, event
) )
1830 // no default action at the moment
1836 void wxGrid::ProcessGridCellMouseEvent( wxMouseEvent
& event
)
1839 wxPoint
pos( event
.GetPosition() );
1840 CalcUnscrolledPosition( pos
.x
, pos
.y
, &x
, &y
);
1842 wxGridCellCoords coords
;
1843 XYToCell( x
, y
, coords
);
1845 if ( event
.Dragging() )
1847 m_isDragging
= TRUE
;
1848 if ( m_cursorMode
== WXGRID_CURSOR_SELECT_CELL
)
1850 // Hide the edit control, so it
1851 // won't interfer with drag-shrinking.
1852 if ( IsCellEditControlEnabled() )
1853 HideCellEditControl();
1854 if ( coords
!= wxGridNoCellCoords
)
1856 if ( !IsSelection() )
1858 SelectBlock( coords
, coords
);
1862 SelectBlock( m_currentCellCoords
, coords
);
1870 m_isDragging
= FALSE
;
1872 if ( event
.LeftDown() )
1874 if ( !SendEvent( EVT_GRID_CELL_LEFT_CLICK
,
1879 MakeCellVisible( coords
);
1880 SetCurrentCell( coords
);
1885 // ------------ Left double click
1887 else if ( event
.LeftDClick() )
1889 SendEvent( EVT_GRID_CELL_LEFT_DCLICK
,
1896 // ------------ Left button released
1898 else if ( event
.LeftUp() )
1900 if ( m_cursorMode
== WXGRID_CURSOR_SELECT_CELL
)
1902 if ( IsSelection() )
1904 SendEvent( EVT_GRID_RANGE_SELECT
, -1, -1, event
);
1906 // Show the edit control, if it has
1907 // been hidden for drag-shrinking.
1908 if ( IsCellEditControlEnabled() )
1909 ShowCellEditControl();
1916 // ------------ Right button down
1918 else if ( event
.RightDown() )
1920 if ( !SendEvent( EVT_GRID_CELL_RIGHT_CLICK
,
1925 // no default action at the moment
1930 // ------------ Right double click
1932 else if ( event
.RightDClick() )
1934 if ( !SendEvent( EVT_GRID_CELL_RIGHT_DCLICK
,
1939 // no default action at the moment
1946 // ------ interaction with data model
1948 bool wxGrid::ProcessTableMessage( wxGridTableMessage
& msg
)
1950 switch ( msg
.GetId() )
1952 case wxGRIDTABLE_REQUEST_VIEW_GET_VALUES
:
1953 return GetModelValues();
1955 case wxGRIDTABLE_REQUEST_VIEW_SEND_VALUES
:
1956 return SetModelValues();
1958 case wxGRIDTABLE_NOTIFY_ROWS_INSERTED
:
1959 case wxGRIDTABLE_NOTIFY_ROWS_APPENDED
:
1960 case wxGRIDTABLE_NOTIFY_ROWS_DELETED
:
1961 case wxGRIDTABLE_NOTIFY_COLS_INSERTED
:
1962 case wxGRIDTABLE_NOTIFY_COLS_APPENDED
:
1963 case wxGRIDTABLE_NOTIFY_COLS_DELETED
:
1964 return Redimension( msg
);
1973 // The behaviour of this function depends on the grid table class
1974 // Clear() function. For the default wxGridStringTable class the
1975 // behavious is to replace all cell contents with wxEmptyString but
1976 // not to change the number of rows or cols.
1978 void wxGrid::ClearGrid()
1983 SetEditControlValue();
1984 if ( !GetBatchCount() ) m_gridWin
->Refresh();
1989 bool wxGrid::InsertRows( int pos
, int numRows
, bool WXUNUSED(updateLabels
) )
1991 // TODO: something with updateLabels flag
1995 wxLogError( wxT("Called wxGrid::InsertRows() before calling CreateGrid()") );
2001 bool ok
= m_table
->InsertRows( pos
, numRows
);
2003 // the table will have sent the results of the insert row
2004 // operation to this view object as a grid table message
2008 if ( m_numCols
== 0 )
2010 m_table
->AppendCols( WXGRID_DEFAULT_NUMBER_COLS
);
2012 // TODO: perhaps instead of appending the default number of cols
2013 // we should remember what the last non-zero number of cols was ?
2017 if ( m_currentCellCoords
== wxGridNoCellCoords
)
2019 // if we have just inserted cols into an empty grid the current
2020 // cell will be undefined...
2022 SetCurrentCell( 0, 0 );
2026 if ( !GetBatchCount() ) Refresh();
2029 SetEditControlValue();
2039 bool wxGrid::AppendRows( int numRows
, bool WXUNUSED(updateLabels
) )
2041 // TODO: something with updateLabels flag
2045 wxLogError( wxT("Called wxGrid::AppendRows() before calling CreateGrid()") );
2049 if ( m_table
&& m_table
->AppendRows( numRows
) )
2051 if ( m_currentCellCoords
== wxGridNoCellCoords
)
2053 // if we have just inserted cols into an empty grid the current
2054 // cell will be undefined...
2056 SetCurrentCell( 0, 0 );
2059 // the table will have sent the results of the append row
2060 // operation to this view object as a grid table message
2063 if ( !GetBatchCount() ) Refresh();
2073 bool wxGrid::DeleteRows( int pos
, int numRows
, bool WXUNUSED(updateLabels
) )
2075 // TODO: something with updateLabels flag
2079 wxLogError( wxT("Called wxGrid::DeleteRows() before calling CreateGrid()") );
2083 if ( m_table
&& m_table
->DeleteRows( pos
, numRows
) )
2085 // the table will have sent the results of the delete row
2086 // operation to this view object as a grid table message
2088 if ( m_numRows
> 0 )
2089 SetEditControlValue();
2091 HideCellEditControl();
2094 if ( !GetBatchCount() ) Refresh();
2104 bool wxGrid::InsertCols( int pos
, int numCols
, bool WXUNUSED(updateLabels
) )
2106 // TODO: something with updateLabels flag
2110 wxLogError( wxT("Called wxGrid::InsertCols() before calling CreateGrid()") );
2116 HideCellEditControl();
2117 bool ok
= m_table
->InsertCols( pos
, numCols
);
2119 // the table will have sent the results of the insert col
2120 // operation to this view object as a grid table message
2124 if ( m_currentCellCoords
== wxGridNoCellCoords
)
2126 // if we have just inserted cols into an empty grid the current
2127 // cell will be undefined...
2129 SetCurrentCell( 0, 0 );
2133 if ( !GetBatchCount() ) Refresh();
2136 SetEditControlValue();
2146 bool wxGrid::AppendCols( int numCols
, bool WXUNUSED(updateLabels
) )
2148 // TODO: something with updateLabels flag
2152 wxLogError( wxT("Called wxGrid::AppendCols() before calling CreateGrid()") );
2156 if ( m_table
&& m_table
->AppendCols( numCols
) )
2158 // the table will have sent the results of the append col
2159 // operation to this view object as a grid table message
2161 if ( m_currentCellCoords
== wxGridNoCellCoords
)
2163 // if we have just inserted cols into an empty grid the current
2164 // cell will be undefined...
2166 SetCurrentCell( 0, 0 );
2170 if ( !GetBatchCount() ) Refresh();
2180 bool wxGrid::DeleteCols( int pos
, int numCols
, bool WXUNUSED(updateLabels
) )
2182 // TODO: something with updateLabels flag
2186 wxLogError( wxT("Called wxGrid::DeleteCols() before calling CreateGrid()") );
2190 if ( m_table
&& m_table
->DeleteCols( pos
, numCols
) )
2192 // the table will have sent the results of the delete col
2193 // operation to this view object as a grid table message
2195 if ( m_numCols
> 0 )
2196 SetEditControlValue();
2198 HideCellEditControl();
2201 if ( !GetBatchCount() ) Refresh();
2213 // ----- event handlers
2216 // Generate a grid event based on a mouse event and
2217 // return the result of ProcessEvent()
2219 bool wxGrid::SendEvent( const wxEventType type
,
2221 wxMouseEvent
& mouseEv
)
2223 if ( type
== EVT_GRID_ROW_SIZE
||
2224 type
== EVT_GRID_COL_SIZE
)
2226 int rowOrCol
= (row
== -1 ? col
: row
);
2228 wxGridSizeEvent
gridEvt( GetId(),
2232 mouseEv
.GetX(), mouseEv
.GetY(),
2233 mouseEv
.ControlDown(),
2234 mouseEv
.ShiftDown(),
2236 mouseEv
.MetaDown() );
2238 return GetEventHandler()->ProcessEvent(gridEvt
);
2240 else if ( type
== EVT_GRID_RANGE_SELECT
)
2242 wxGridRangeSelectEvent
gridEvt( GetId(),
2246 m_selectedBottomRight
,
2247 mouseEv
.ControlDown(),
2248 mouseEv
.ShiftDown(),
2250 mouseEv
.MetaDown() );
2252 return GetEventHandler()->ProcessEvent(gridEvt
);
2256 wxGridEvent
gridEvt( GetId(),
2260 mouseEv
.GetX(), mouseEv
.GetY(),
2261 mouseEv
.ControlDown(),
2262 mouseEv
.ShiftDown(),
2264 mouseEv
.MetaDown() );
2266 return GetEventHandler()->ProcessEvent(gridEvt
);
2271 // Generate a grid event of specified type and return the result
2272 // of ProcessEvent().
2274 bool wxGrid::SendEvent( const wxEventType type
,
2277 if ( type
== EVT_GRID_ROW_SIZE
||
2278 type
== EVT_GRID_COL_SIZE
)
2280 int rowOrCol
= (row
== -1 ? col
: row
);
2282 wxGridSizeEvent
gridEvt( GetId(),
2287 return GetEventHandler()->ProcessEvent(gridEvt
);
2291 wxGridEvent
gridEvt( GetId(),
2296 return GetEventHandler()->ProcessEvent(gridEvt
);
2301 void wxGrid::OnPaint( wxPaintEvent
& WXUNUSED(event
) )
2303 wxPaintDC
dc( this );
2305 if ( m_currentCellCoords
== wxGridNoCellCoords
&&
2306 m_numRows
&& m_numCols
)
2308 m_currentCellCoords
.Set(0, 0);
2309 SetEditControlValue();
2310 ShowCellEditControl();
2315 // This is just here to make sure that CalcDimensions gets called when
2316 // the grid view is resized... then the size event is skipped to allow
2317 // the box sizers to handle everything
2319 void wxGrid::OnSize( wxSizeEvent
& event
)
2326 void wxGrid::OnKeyDown( wxKeyEvent
& event
)
2328 if ( m_inOnKeyDown
)
2330 // shouldn't be here - we are going round in circles...
2332 wxLogFatalError( wxT("wxGrid::OnKeyDown called while alread active") );
2335 m_inOnKeyDown
= TRUE
;
2337 // propagate the event up and see if it gets processed
2339 wxWindow
*parent
= GetParent();
2340 wxKeyEvent
keyEvt( event
);
2341 keyEvt
.SetEventObject( parent
);
2343 if ( !parent
->GetEventHandler()->ProcessEvent( keyEvt
) )
2345 // try local handlers
2347 switch ( event
.KeyCode() )
2350 if ( event
.ControlDown() )
2352 MoveCursorUpBlock();
2361 if ( event
.ControlDown() )
2363 MoveCursorDownBlock();
2372 if ( event
.ControlDown() )
2374 MoveCursorLeftBlock();
2383 if ( event
.ControlDown() )
2385 MoveCursorRightBlock();
2398 if ( event
.ControlDown() )
2400 MakeCellVisible( 0, 0 );
2401 SetCurrentCell( 0, 0 );
2410 if ( event
.ControlDown() )
2412 MakeCellVisible( m_numRows
-1, m_numCols
-1 );
2413 SetCurrentCell( m_numRows
-1, m_numCols
-1 );
2430 // now try the cell edit control
2432 if ( IsCellEditControlEnabled() )
2434 event
.SetEventObject( m_cellEditCtrl
);
2435 m_cellEditCtrl
->GetEventHandler()->ProcessEvent( event
);
2441 m_inOnKeyDown
= FALSE
;
2445 void wxGrid::SetCurrentCell( const wxGridCellCoords
& coords
)
2447 if ( SendEvent( EVT_GRID_SELECT_CELL
, coords
.GetRow(), coords
.GetCol() ) )
2449 // the event has been intercepted - do nothing
2453 wxClientDC
dc( m_gridWin
);
2456 if ( m_currentCellCoords
!= wxGridNoCellCoords
)
2458 HideCellEditControl();
2459 SaveEditControlValue();
2462 m_currentCellCoords
= coords
;
2464 SetEditControlValue();
2465 ShowCellEditControl();
2467 if ( IsSelection() )
2469 wxRect
r( SelectionToDeviceRect() );
2471 if ( !GetBatchCount() ) m_gridWin
->Refresh( TRUE
, &r
);
2477 // ------ functions to get/send data (see also public functions)
2480 bool wxGrid::GetModelValues()
2484 // all we need to do is repaint the grid
2486 m_gridWin
->Refresh();
2494 bool wxGrid::SetModelValues()
2500 for ( row
= 0; row
< m_numRows
; row
++ )
2502 for ( col
= 0; col
< m_numCols
; col
++ )
2504 m_table
->SetValue( row
, col
, GetCellValue(row
, col
) );
2516 // Note - this function only draws cells that are in the list of
2517 // exposed cells (usually set from the update region by
2518 // CalcExposedCells)
2520 void wxGrid::DrawGridCellArea( wxDC
& dc
)
2522 if ( !m_numRows
|| !m_numCols
) return;
2525 size_t numCells
= m_cellsExposed
.GetCount();
2527 for ( i
= 0; i
< numCells
; i
++ )
2529 DrawCell( dc
, m_cellsExposed
[i
] );
2534 void wxGrid::DrawCell( wxDC
& dc
, const wxGridCellCoords
& coords
)
2536 if ( m_colWidths
[coords
.GetCol()] <=0 ||
2537 m_rowHeights
[coords
.GetRow()] <= 0 ) return;
2539 if ( m_gridLinesEnabled
)
2540 DrawCellBorder( dc
, coords
);
2542 DrawCellBackground( dc
, coords
);
2544 // TODO: separate functions here for different kinds of cells ?
2547 DrawCellValue( dc
, coords
);
2551 void wxGrid::DrawCellBorder( wxDC
& dc
, const wxGridCellCoords
& coords
)
2553 if ( m_colWidths
[coords
.GetCol()] <=0 ||
2554 m_rowHeights
[coords
.GetRow()] <= 0 ) return;
2556 dc
.SetPen( wxPen(GetGridLineColour(), 1, wxSOLID
) );
2557 int row
= coords
.GetRow();
2558 int col
= coords
.GetCol();
2560 // right hand border
2562 dc
.DrawLine( m_colRights
[col
], m_rowBottoms
[row
] - m_rowHeights
[row
],
2563 m_colRights
[col
], m_rowBottoms
[row
] );
2567 dc
.DrawLine( m_colRights
[col
] - m_colWidths
[col
], m_rowBottoms
[row
],
2568 m_colRights
[col
], m_rowBottoms
[row
] );
2572 void wxGrid::DrawCellBackground( wxDC
& dc
, const wxGridCellCoords
& coords
)
2574 if ( m_colWidths
[coords
.GetCol()] <=0 ||
2575 m_rowHeights
[coords
.GetRow()] <= 0 ) return;
2577 int row
= coords
.GetRow();
2578 int col
= coords
.GetCol();
2580 dc
.SetBackgroundMode( wxSOLID
);
2582 if ( IsInSelection( coords
) )
2584 // TODO: improve this
2586 dc
.SetBrush( *wxBLACK_BRUSH
);
2590 dc
.SetBrush( wxBrush(GetCellBackgroundColour(row
, col
), wxSOLID
) );
2593 dc
.SetPen( *wxTRANSPARENT_PEN
);
2595 dc
.DrawRectangle( m_colRights
[col
] - m_colWidths
[col
] + 1,
2596 m_rowBottoms
[row
] - m_rowHeights
[row
] + 1,
2598 m_rowHeights
[row
]-1 );
2602 void wxGrid::DrawCellValue( wxDC
& dc
, const wxGridCellCoords
& coords
)
2604 if ( m_colWidths
[coords
.GetCol()] <=0 ||
2605 m_rowHeights
[coords
.GetRow()] <= 0 ) return;
2607 int row
= coords
.GetRow();
2608 int col
= coords
.GetCol();
2610 dc
.SetBackgroundMode( wxTRANSPARENT
);
2612 if ( IsInSelection( row
, col
) )
2614 // TODO: improve this
2616 dc
.SetTextBackground( wxColour(0, 0, 0) );
2617 dc
.SetTextForeground( wxColour(255, 255, 255) );
2621 dc
.SetTextBackground( GetCellBackgroundColour(row
, col
) );
2622 dc
.SetTextForeground( GetCellTextColour(row
, col
) );
2624 dc
.SetFont( GetCellFont(row
, col
) );
2627 GetCellAlignment( row
, col
, &hAlign
, &vAlign
);
2630 rect
.SetX( m_colRights
[col
] - m_colWidths
[col
] + 2 );
2631 rect
.SetY( m_rowBottoms
[row
] - m_rowHeights
[row
] + 2 );
2632 rect
.SetWidth( m_colWidths
[col
] - 4 );
2633 rect
.SetHeight( m_rowHeights
[row
] - 4 );
2635 DrawTextRectangle( dc
, GetCellValue( row
, col
), rect
, hAlign
, vAlign
);
2640 // TODO: remove this ???
2641 // This is used to redraw all grid lines e.g. when the grid line colour
2644 void wxGrid::DrawAllGridLines( wxDC
& dc
)
2646 if ( !m_gridLinesEnabled
||
2648 !m_numCols
) return;
2651 m_gridWin
->GetClientSize(&cw
, &ch
);
2653 // virtual coords of visible area
2655 int top
, bottom
, left
, right
;
2656 CalcUnscrolledPosition( 0, 0, &left
, &top
);
2657 CalcUnscrolledPosition( cw
, ch
, &right
, &bottom
);
2659 dc
.SetPen( wxPen(GetGridLineColour(), 1, wxSOLID
) );
2661 // horizontal grid lines
2664 for ( i
= 0; i
<= m_numRows
; i
++ )
2666 if ( m_rowBottoms
[i
] > bottom
)
2670 else if ( m_rowBottoms
[i
] >= top
)
2672 dc
.DrawLine( left
, m_rowBottoms
[i
], right
, m_rowBottoms
[i
] );
2677 // vertical grid lines
2679 for ( i
= 0; i
<= m_numCols
; i
++ )
2681 if ( m_colRights
[i
] > right
)
2685 else if ( m_colRights
[i
] >= left
)
2687 dc
.DrawLine( m_colRights
[i
], top
, m_colRights
[i
], bottom
);
2693 void wxGrid::DrawRowLabels( wxDC
& dc
)
2695 if ( !m_numRows
|| !m_numCols
) return;
2698 size_t numLabels
= m_rowLabelsExposed
.GetCount();
2700 for ( i
= 0; i
< numLabels
; i
++ )
2702 DrawRowLabel( dc
, m_rowLabelsExposed
[i
] );
2707 void wxGrid::DrawRowLabel( wxDC
& dc
, int row
)
2709 if ( m_rowHeights
[row
] <= 0 ) return;
2711 // draw the label's horizontal border (the vertical border is
2712 // provided by the cell area window margin)
2714 dc
.SetPen( *wxBLACK_PEN
);
2716 dc
.DrawLine( 0, m_rowBottoms
[row
]+1,
2717 m_rowLabelWidth
, m_rowBottoms
[row
]+1 );
2719 dc
.SetPen( *wxWHITE_PEN
);
2721 dc
.DrawLine( 0, m_rowBottoms
[row
]+2,
2722 m_rowLabelWidth
, m_rowBottoms
[row
]+2 );
2724 dc
.SetBackgroundMode( wxTRANSPARENT
);
2725 dc
.SetTextForeground( GetLabelTextColour() );
2726 dc
.SetFont( GetLabelFont() );
2729 GetRowLabelAlignment( &hAlign
, &vAlign
);
2733 rect
.SetY( m_rowBottoms
[row
] - m_rowHeights
[row
] + 2 );
2734 rect
.SetWidth( m_rowLabelWidth
- 4 );
2735 rect
.SetHeight( m_rowHeights
[row
] - 4 );
2736 DrawTextRectangle( dc
, GetRowLabelValue( row
), rect
, hAlign
, vAlign
);
2740 void wxGrid::DrawColLabels( wxDC
& dc
)
2742 if ( !m_numRows
|| !m_numCols
) return;
2745 size_t numLabels
= m_colLabelsExposed
.GetCount();
2747 for ( i
= 0; i
< numLabels
; i
++ )
2749 DrawColLabel( dc
, m_colLabelsExposed
[i
] );
2754 void wxGrid::DrawColLabel( wxDC
& dc
, int col
)
2756 if ( m_colWidths
[col
] <= 0 ) return;
2758 // draw the label's vertical border (the horizontal border is
2759 // provided by the cell area window margin)
2761 dc
.SetPen( *wxBLACK_PEN
);
2763 dc
.DrawLine( m_colRights
[col
]+1, 0,
2764 m_colRights
[col
]+1, m_colLabelHeight
);
2766 dc
.SetPen( *wxWHITE_PEN
);
2768 dc
.DrawLine( m_colRights
[col
]+2, 0,
2769 m_colRights
[col
]+2, m_colLabelHeight
);
2771 dc
.SetBackgroundMode( wxTRANSPARENT
);
2772 dc
.SetTextForeground( GetLabelTextColour() );
2773 dc
.SetFont( GetLabelFont() );
2776 GetColLabelAlignment( &hAlign
, &vAlign
);
2779 rect
.SetX( m_colRights
[col
] - m_colWidths
[col
] + 2 );
2781 rect
.SetWidth( m_colWidths
[col
] - 4 );
2782 rect
.SetHeight( m_colLabelHeight
- 4 );
2783 DrawTextRectangle( dc
, GetColLabelValue( col
), rect
, hAlign
, vAlign
);
2787 void wxGrid::DrawTextRectangle( wxDC
& dc
,
2788 const wxString
& value
,
2793 long textWidth
, textHeight
;
2794 long lineWidth
, lineHeight
;
2795 wxArrayString lines
;
2797 dc
.SetClippingRegion( rect
);
2798 StringToLines( value
, lines
);
2799 if ( lines
.GetCount() )
2801 GetTextBoxSize( dc
, lines
, &textWidth
, &textHeight
);
2802 dc
.GetTextExtent( lines
[0], &lineWidth
, &lineHeight
);
2805 switch ( horizAlign
)
2808 x
= rect
.x
+ (rect
.width
- textWidth
- 1);
2812 x
= rect
.x
+ ((rect
.width
- textWidth
)/2);
2821 switch ( vertAlign
)
2824 y
= rect
.y
+ (rect
.height
- textHeight
- 1);
2828 y
= rect
.y
+ ((rect
.height
- textHeight
)/2);
2837 for ( size_t i
= 0; i
< lines
.GetCount(); i
++ )
2839 dc
.DrawText( lines
[i
], (long)x
, (long)y
);
2844 dc
.DestroyClippingRegion();
2848 // Split multi line text up into an array of strings. Any existing
2849 // contents of the string array are preserved.
2851 void wxGrid::StringToLines( const wxString
& value
, wxArrayString
& lines
)
2853 // TODO: this won't work for WXMAC ? (lines end with '\r')
2854 // => use wxTextFile functions then (VZ)
2857 while ( startPos
< (int)value
.Length() )
2859 pos
= value
.Mid(startPos
).Find( '\n' );
2864 else if ( pos
== 0 )
2866 lines
.Add( wxEmptyString
);
2870 if ( value
[startPos
+pos
-1] == '\r' )
2872 lines
.Add( value
.Mid(startPos
, pos
-1) );
2876 lines
.Add( value
.Mid(startPos
, pos
) );
2881 if ( startPos
< (int)value
.Length() )
2883 lines
.Add( value
.Mid( startPos
) );
2888 void wxGrid::GetTextBoxSize( wxDC
& dc
,
2889 wxArrayString
& lines
,
2890 long *width
, long *height
)
2897 for ( i
= 0; i
< lines
.GetCount(); i
++ )
2899 dc
.GetTextExtent( lines
[i
], &lineW
, &lineH
);
2900 w
= wxMax( w
, lineW
);
2910 // ------ Edit control functions
2914 void wxGrid::EnableEditing( bool edit
)
2916 // TODO: improve this ?
2918 if ( edit
!= m_editable
)
2922 // TODO: extend this for other edit control types
2924 if ( m_editCtrlType
== wxGRID_TEXTCTRL
)
2926 ((wxTextCtrl
*)m_cellEditCtrl
)->SetEditable( m_editable
);
2932 #if 0 // disabled for the moment - the cell control is always active
2933 void wxGrid::EnableCellEditControl( bool enable
)
2935 if ( m_cellEditCtrl
&&
2936 enable
!= m_cellEditCtrlEnabled
)
2938 m_cellEditCtrlEnabled
= enable
;
2940 if ( m_cellEditCtrlEnabled
)
2942 SetEditControlValue();
2943 ShowCellEditControl();
2947 HideCellEditControl();
2948 SaveEditControlValue();
2955 void wxGrid::ShowCellEditControl()
2959 if ( IsCellEditControlEnabled() )
2961 if ( !IsVisible( m_currentCellCoords
) )
2967 rect
= CellToRect( m_currentCellCoords
);
2969 // convert to scrolled coords
2971 int left
, top
, right
, bottom
;
2972 CalcScrolledPosition( rect
.GetLeft(), rect
.GetTop(), &left
, &top
);
2973 CalcScrolledPosition( rect
.GetRight(), rect
.GetBottom(), &right
, &bottom
);
2976 m_gridWin
->GetClientSize( &cw
, &ch
);
2978 // Make the edit control large enough to allow for internal margins
2979 // TODO: remove this if the text ctrl sizing is improved esp. for unix
2981 #if defined (__WXMOTIF__)
2982 rect
.SetLeft( wxMax(0, left
-4) );
2983 rect
.SetTop( wxMax(0, top
-4) );
2984 rect
.SetRight( rect
.GetRight() + 8 );
2985 rect
.SetBottom( rect
.GetBottom() + 8 );
2987 rect
.SetLeft( wxMax(0, left
-2) );
2988 rect
.SetTop( wxMax(0, top
-2) );
2989 rect
.SetRight( rect
.GetRight() + 4 );
2990 rect
.SetBottom( rect
.GetBottom() + 4 );
2993 m_cellEditCtrl
->SetSize( rect
);
2994 m_cellEditCtrl
->Show( TRUE
);
2996 switch ( m_editCtrlType
)
2998 case wxGRID_TEXTCTRL
:
2999 ((wxTextCtrl
*) m_cellEditCtrl
)->SetInsertionPointEnd();
3002 case wxGRID_CHECKBOX
:
3003 // TODO: anything ???
3008 // TODO: anything ???
3012 case wxGRID_COMBOBOX
:
3013 // TODO: anything ???
3018 m_cellEditCtrl
->SetFocus();
3024 void wxGrid::HideCellEditControl()
3026 if ( IsCellEditControlEnabled() )
3028 m_cellEditCtrl
->Show( FALSE
);
3033 void wxGrid::SetEditControlValue( const wxString
& value
)
3039 s
= GetCellValue(m_currentCellCoords
);
3043 if ( IsCellEditControlEnabled() )
3045 switch ( m_editCtrlType
)
3047 case wxGRID_TEXTCTRL
:
3048 ((wxGridTextCtrl
*)m_cellEditCtrl
)->SetStartValue(s
);
3051 case wxGRID_CHECKBOX
:
3052 // TODO: implement this
3057 // TODO: implement this
3061 case wxGRID_COMBOBOX
:
3062 // TODO: implement this
3071 void wxGrid::SaveEditControlValue()
3075 wxWindow
*ctrl
= (wxWindow
*)NULL
;
3077 if ( IsCellEditControlEnabled() )
3079 ctrl
= m_cellEditCtrl
;
3086 bool valueChanged
= FALSE
;
3088 switch ( m_editCtrlType
)
3090 case wxGRID_TEXTCTRL
:
3091 valueChanged
= (((wxGridTextCtrl
*)ctrl
)->GetValue() !=
3092 ((wxGridTextCtrl
*)ctrl
)->GetStartValue());
3093 SetCellValue( m_currentCellCoords
,
3094 ((wxTextCtrl
*) ctrl
)->GetValue() );
3097 case wxGRID_CHECKBOX
:
3098 // TODO: implement this
3103 // TODO: implement this
3107 case wxGRID_COMBOBOX
:
3108 // TODO: implement this
3115 SendEvent( EVT_GRID_CELL_CHANGE
,
3116 m_currentCellCoords
.GetRow(),
3117 m_currentCellCoords
.GetCol() );
3124 // ------ Grid location functions
3125 // Note that all of these functions work with the logical coordinates of
3126 // grid cells and labels so you will need to convert from device
3127 // coordinates for mouse events etc.
3130 void wxGrid::XYToCell( int x
, int y
, wxGridCellCoords
& coords
)
3132 coords
.SetRow( YToRow(y
) );
3133 coords
.SetCol( XToCol(x
) );
3137 int wxGrid::YToRow( int y
)
3141 for ( i
= 0; i
< m_numRows
; i
++ )
3143 if ( y
< m_rowBottoms
[i
] ) return i
;
3150 int wxGrid::XToCol( int x
)
3154 for ( i
= 0; i
< m_numCols
; i
++ )
3156 if ( x
< m_colRights
[i
] ) return i
;
3163 // return the row number that that the y coord is near the edge of, or
3164 // -1 if not near an edge
3166 int wxGrid::YToEdgeOfRow( int y
)
3170 for ( i
= 0; i
< m_numRows
; i
++ )
3172 if ( m_rowHeights
[i
] > WXGRID_LABEL_EDGE_ZONE
)
3174 d
= abs( y
- m_rowBottoms
[i
] );
3176 if ( d
< WXGRID_LABEL_EDGE_ZONE
) return i
;
3185 // return the col number that that the x coord is near the edge of, or
3186 // -1 if not near an edge
3188 int wxGrid::XToEdgeOfCol( int x
)
3192 for ( i
= 0; i
< m_numCols
; i
++ )
3194 if ( m_colWidths
[i
] > WXGRID_LABEL_EDGE_ZONE
)
3196 d
= abs( x
- m_colRights
[i
] );
3198 if ( d
< WXGRID_LABEL_EDGE_ZONE
) return i
;
3207 wxRect
wxGrid::CellToRect( int row
, int col
)
3209 wxRect
rect( -1, -1, -1, -1 );
3211 if ( row
>= 0 && row
< m_numRows
&&
3212 col
>= 0 && col
< m_numCols
)
3214 rect
.x
= m_colRights
[col
] - m_colWidths
[col
];
3215 rect
.y
= m_rowBottoms
[row
] - m_rowHeights
[row
];
3216 rect
.width
= m_colWidths
[col
];
3217 rect
.height
= m_rowHeights
[ row
];
3224 bool wxGrid::IsVisible( int row
, int col
, bool wholeCellVisible
)
3226 // get the cell rectangle in logical coords
3228 wxRect
r( CellToRect( row
, col
) );
3230 // convert to device coords
3232 int left
, top
, right
, bottom
;
3233 CalcScrolledPosition( r
.GetLeft(), r
.GetTop(), &left
, &top
);
3234 CalcScrolledPosition( r
.GetRight(), r
.GetBottom(), &right
, &bottom
);
3236 // check against the client area of the grid window
3239 m_gridWin
->GetClientSize( &cw
, &ch
);
3241 if ( wholeCellVisible
)
3243 // is the cell wholly visible ?
3245 return ( left
>= 0 && right
<= cw
&&
3246 top
>= 0 && bottom
<= ch
);
3250 // is the cell partly visible ?
3252 return ( ((left
>=0 && left
< cw
) || (right
> 0 && right
<= cw
)) &&
3253 ((top
>=0 && top
< ch
) || (bottom
> 0 && bottom
<= ch
)) );
3258 // make the specified cell location visible by doing a minimal amount
3261 void wxGrid::MakeCellVisible( int row
, int col
)
3264 int xpos
= -1, ypos
= -1;
3266 if ( row
>= 0 && row
< m_numRows
&&
3267 col
>= 0 && col
< m_numCols
)
3269 // get the cell rectangle in logical coords
3271 wxRect
r( CellToRect( row
, col
) );
3273 // convert to device coords
3275 int left
, top
, right
, bottom
;
3276 CalcScrolledPosition( r
.GetLeft(), r
.GetTop(), &left
, &top
);
3277 CalcScrolledPosition( r
.GetRight(), r
.GetBottom(), &right
, &bottom
);
3280 m_gridWin
->GetClientSize( &cw
, &ch
);
3286 else if ( bottom
> ch
)
3288 int h
= r
.GetHeight();
3290 for ( i
= row
-1; i
>= 0; i
-- )
3292 if ( h
+ m_rowHeights
[i
] > ch
) break;
3294 h
+= m_rowHeights
[i
];
3295 ypos
-= m_rowHeights
[i
];
3303 else if ( right
> cw
)
3305 int w
= r
.GetWidth();
3307 for ( i
= col
-1; i
>= 0; i
-- )
3309 if ( w
+ m_colWidths
[i
] > cw
) break;
3311 w
+= m_colWidths
[i
];
3312 xpos
-= m_colWidths
[i
];
3316 if ( xpos
!= -1 || ypos
!= -1 )
3318 if ( xpos
!= -1 ) xpos
= xpos
/10;
3319 if ( ypos
!= -1 ) ypos
= ypos
/10;
3320 Scroll( xpos
, ypos
);
3328 // ------ Grid cursor movement functions
3331 bool wxGrid::MoveCursorUp()
3333 if ( m_currentCellCoords
!= wxGridNoCellCoords
&&
3334 m_currentCellCoords
.GetRow() > 0 )
3336 MakeCellVisible( m_currentCellCoords
.GetRow() - 1,
3337 m_currentCellCoords
.GetCol() );
3339 SetCurrentCell( m_currentCellCoords
.GetRow() - 1,
3340 m_currentCellCoords
.GetCol() );
3349 bool wxGrid::MoveCursorDown()
3351 // TODO: allow for scrolling
3353 if ( m_currentCellCoords
!= wxGridNoCellCoords
&&
3354 m_currentCellCoords
.GetRow() < m_numRows
-1 )
3356 MakeCellVisible( m_currentCellCoords
.GetRow() + 1,
3357 m_currentCellCoords
.GetCol() );
3359 SetCurrentCell( m_currentCellCoords
.GetRow() + 1,
3360 m_currentCellCoords
.GetCol() );
3369 bool wxGrid::MoveCursorLeft()
3371 if ( m_currentCellCoords
!= wxGridNoCellCoords
&&
3372 m_currentCellCoords
.GetCol() > 0 )
3374 MakeCellVisible( m_currentCellCoords
.GetRow(),
3375 m_currentCellCoords
.GetCol() - 1 );
3377 SetCurrentCell( m_currentCellCoords
.GetRow(),
3378 m_currentCellCoords
.GetCol() - 1 );
3387 bool wxGrid::MoveCursorRight()
3389 if ( m_currentCellCoords
!= wxGridNoCellCoords
&&
3390 m_currentCellCoords
.GetCol() < m_numCols
- 1 )
3392 MakeCellVisible( m_currentCellCoords
.GetRow(),
3393 m_currentCellCoords
.GetCol() + 1 );
3395 SetCurrentCell( m_currentCellCoords
.GetRow(),
3396 m_currentCellCoords
.GetCol() + 1 );
3405 bool wxGrid::MovePageUp()
3407 if ( m_currentCellCoords
== wxGridNoCellCoords
) return FALSE
;
3409 int row
= m_currentCellCoords
.GetRow();
3413 m_gridWin
->GetClientSize( &cw
, &ch
);
3415 int y
= m_rowBottoms
[ row
] - m_rowHeights
[ row
];
3416 int newRow
= YToRow( y
- ch
+ 1 );
3421 else if ( newRow
== row
)
3426 MakeCellVisible( newRow
, m_currentCellCoords
.GetCol() );
3427 SetCurrentCell( newRow
, m_currentCellCoords
.GetCol() );
3435 bool wxGrid::MovePageDown()
3437 if ( m_currentCellCoords
== wxGridNoCellCoords
) return FALSE
;
3439 int row
= m_currentCellCoords
.GetRow();
3440 if ( row
< m_numRows
)
3443 m_gridWin
->GetClientSize( &cw
, &ch
);
3445 int y
= m_rowBottoms
[ row
] - m_rowHeights
[ row
];
3446 int newRow
= YToRow( y
+ ch
);
3449 newRow
= m_numRows
- 1;
3451 else if ( newRow
== row
)
3456 MakeCellVisible( newRow
, m_currentCellCoords
.GetCol() );
3457 SetCurrentCell( newRow
, m_currentCellCoords
.GetCol() );
3465 bool wxGrid::MoveCursorUpBlock()
3468 m_currentCellCoords
!= wxGridNoCellCoords
&&
3469 m_currentCellCoords
.GetRow() > 0 )
3471 int row
= m_currentCellCoords
.GetRow();
3472 int col
= m_currentCellCoords
.GetCol();
3474 if ( m_table
->IsEmptyCell(row
, col
) )
3476 // starting in an empty cell: find the next block of
3482 if ( !(m_table
->IsEmptyCell(row
, col
)) ) break;
3485 else if ( m_table
->IsEmptyCell(row
-1, col
) )
3487 // starting at the top of a block: find the next block
3493 if ( !(m_table
->IsEmptyCell(row
, col
)) ) break;
3498 // starting within a block: find the top of the block
3503 if ( m_table
->IsEmptyCell(row
, col
) )
3511 MakeCellVisible( row
, col
);
3512 SetCurrentCell( row
, col
);
3520 bool wxGrid::MoveCursorDownBlock()
3523 m_currentCellCoords
!= wxGridNoCellCoords
&&
3524 m_currentCellCoords
.GetRow() < m_numRows
-1 )
3526 int row
= m_currentCellCoords
.GetRow();
3527 int col
= m_currentCellCoords
.GetCol();
3529 if ( m_table
->IsEmptyCell(row
, col
) )
3531 // starting in an empty cell: find the next block of
3534 while ( row
< m_numRows
-1 )
3537 if ( !(m_table
->IsEmptyCell(row
, col
)) ) break;
3540 else if ( m_table
->IsEmptyCell(row
+1, col
) )
3542 // starting at the bottom of a block: find the next block
3545 while ( row
< m_numRows
-1 )
3548 if ( !(m_table
->IsEmptyCell(row
, col
)) ) break;
3553 // starting within a block: find the bottom of the block
3555 while ( row
< m_numRows
-1 )
3558 if ( m_table
->IsEmptyCell(row
, col
) )
3566 MakeCellVisible( row
, col
);
3567 SetCurrentCell( row
, col
);
3575 bool wxGrid::MoveCursorLeftBlock()
3578 m_currentCellCoords
!= wxGridNoCellCoords
&&
3579 m_currentCellCoords
.GetCol() > 0 )
3581 int row
= m_currentCellCoords
.GetRow();
3582 int col
= m_currentCellCoords
.GetCol();
3584 if ( m_table
->IsEmptyCell(row
, col
) )
3586 // starting in an empty cell: find the next block of
3592 if ( !(m_table
->IsEmptyCell(row
, col
)) ) break;
3595 else if ( m_table
->IsEmptyCell(row
, col
-1) )
3597 // starting at the left of a block: find the next block
3603 if ( !(m_table
->IsEmptyCell(row
, col
)) ) break;
3608 // starting within a block: find the left of the block
3613 if ( m_table
->IsEmptyCell(row
, col
) )
3621 MakeCellVisible( row
, col
);
3622 SetCurrentCell( row
, col
);
3630 bool wxGrid::MoveCursorRightBlock()
3633 m_currentCellCoords
!= wxGridNoCellCoords
&&
3634 m_currentCellCoords
.GetCol() < m_numCols
-1 )
3636 int row
= m_currentCellCoords
.GetRow();
3637 int col
= m_currentCellCoords
.GetCol();
3639 if ( m_table
->IsEmptyCell(row
, col
) )
3641 // starting in an empty cell: find the next block of
3644 while ( col
< m_numCols
-1 )
3647 if ( !(m_table
->IsEmptyCell(row
, col
)) ) break;
3650 else if ( m_table
->IsEmptyCell(row
, col
+1) )
3652 // starting at the right of a block: find the next block
3655 while ( col
< m_numCols
-1 )
3658 if ( !(m_table
->IsEmptyCell(row
, col
)) ) break;
3663 // starting within a block: find the right of the block
3665 while ( col
< m_numCols
-1 )
3668 if ( m_table
->IsEmptyCell(row
, col
) )
3676 MakeCellVisible( row
, col
);
3677 SetCurrentCell( row
, col
);
3688 // ------ Label values and formatting
3691 void wxGrid::GetRowLabelAlignment( int *horiz
, int *vert
)
3693 *horiz
= m_rowLabelHorizAlign
;
3694 *vert
= m_rowLabelVertAlign
;
3697 void wxGrid::GetColLabelAlignment( int *horiz
, int *vert
)
3699 *horiz
= m_colLabelHorizAlign
;
3700 *vert
= m_colLabelVertAlign
;
3703 wxString
wxGrid::GetRowLabelValue( int row
)
3707 return m_table
->GetRowLabelValue( row
);
3717 wxString
wxGrid::GetColLabelValue( int col
)
3721 return m_table
->GetColLabelValue( col
);
3731 void wxGrid::SetRowLabelSize( int width
)
3733 // TODO: how to do this with the box sizers ?
3736 void wxGrid::SetColLabelSize( int height
)
3738 // TODO: how to do this with the box sizers ?
3741 void wxGrid::SetLabelBackgroundColour( const wxColour
& colour
)
3743 if ( m_labelBackgroundColour
!= colour
)
3745 m_labelBackgroundColour
= colour
;
3746 m_rowLabelWin
->SetBackgroundColour( colour
);
3747 m_colLabelWin
->SetBackgroundColour( colour
);
3748 m_cornerLabelWin
->SetBackgroundColour( colour
);
3750 if ( !GetBatchCount() )
3752 m_rowLabelWin
->Refresh();
3753 m_colLabelWin
->Refresh();
3754 m_cornerLabelWin
->Refresh();
3759 void wxGrid::SetLabelTextColour( const wxColour
& colour
)
3761 if ( m_labelTextColour
!= colour
)
3763 m_labelTextColour
= colour
;
3764 if ( !GetBatchCount() )
3766 m_rowLabelWin
->Refresh();
3767 m_colLabelWin
->Refresh();
3772 void wxGrid::SetLabelFont( const wxFont
& font
)
3775 if ( !GetBatchCount() )
3777 m_rowLabelWin
->Refresh();
3778 m_colLabelWin
->Refresh();
3782 void wxGrid::SetRowLabelAlignment( int horiz
, int vert
)
3784 if ( horiz
== wxLEFT
|| horiz
== wxCENTRE
|| horiz
== wxRIGHT
)
3786 m_rowLabelHorizAlign
= horiz
;
3789 if ( vert
== wxTOP
|| vert
== wxCENTRE
|| vert
== wxBOTTOM
)
3791 m_rowLabelVertAlign
= vert
;
3794 if ( !GetBatchCount() )
3796 m_rowLabelWin
->Refresh();
3797 m_colLabelWin
->Refresh();
3801 void wxGrid::SetColLabelAlignment( int horiz
, int vert
)
3803 if ( horiz
== wxLEFT
|| horiz
== wxCENTRE
|| horiz
== wxRIGHT
)
3805 m_colLabelHorizAlign
= horiz
;
3808 if ( vert
== wxTOP
|| vert
== wxCENTRE
|| vert
== wxBOTTOM
)
3810 m_colLabelVertAlign
= vert
;
3813 if ( !GetBatchCount() )
3815 m_rowLabelWin
->Refresh();
3816 m_colLabelWin
->Refresh();
3820 void wxGrid::SetRowLabelValue( int row
, const wxString
& s
)
3824 m_table
->SetRowLabelValue( row
, s
);
3825 if ( !GetBatchCount() )
3827 // TODO: Optimize this
3829 m_rowLabelWin
->Refresh();
3834 void wxGrid::SetColLabelValue( int col
, const wxString
& s
)
3838 m_table
->SetColLabelValue( col
, s
);
3839 if ( !GetBatchCount() )
3841 // TODO: optimize this
3843 m_colLabelWin
->Refresh();
3848 void wxGrid::SetGridLineColour( const wxColour
& colour
)
3850 if ( m_gridLineColour
!= colour
)
3852 m_gridLineColour
= colour
;
3854 wxClientDC
dc( m_gridWin
);
3856 DrawAllGridLines( dc
);
3860 void wxGrid::EnableGridLines( bool enable
)
3862 if ( enable
!= m_gridLinesEnabled
)
3864 m_gridLinesEnabled
= enable
;
3866 if ( !GetBatchCount() )
3870 wxClientDC
dc( m_gridWin
);
3872 DrawAllGridLines( dc
);
3876 m_gridWin
->Refresh();
3883 int wxGrid::GetDefaultRowSize()
3885 return m_defaultRowHeight
;
3888 int wxGrid::GetRowSize( int row
)
3890 if ( row
>= 0 && row
< m_numRows
)
3891 return m_rowHeights
[row
];
3893 return 0; // TODO: log an error here
3896 int wxGrid::GetDefaultColSize()
3898 return m_defaultColWidth
;
3901 int wxGrid::GetColSize( int col
)
3903 if ( col
>= 0 && col
< m_numCols
)
3904 return m_colWidths
[col
];
3906 return 0; // TODO: log an error here
3909 wxColour
wxGrid::GetDefaultCellBackgroundColour()
3911 // TODO: replace this temp test code
3913 return wxColour( 255, 255, 255 );
3916 wxColour
wxGrid::GetCellBackgroundColour( int WXUNUSED(row
), int WXUNUSED(col
) )
3918 // TODO: replace this temp test code
3920 return wxColour( 255, 255, 255 );
3923 wxColour
wxGrid::GetDefaultCellTextColour()
3925 // TODO: replace this temp test code
3927 return wxColour( 0, 0, 0 );
3930 wxColour
wxGrid::GetCellTextColour( int WXUNUSED(row
), int WXUNUSED(col
) )
3932 // TODO: replace this temp test code
3934 return wxColour( 0, 0, 0 );
3938 wxFont
wxGrid::GetDefaultCellFont()
3940 return m_defaultCellFont
;
3943 wxFont
wxGrid::GetCellFont( int WXUNUSED(row
), int WXUNUSED(col
) )
3945 // TODO: replace this temp test code
3947 return m_defaultCellFont
;
3950 void wxGrid::GetDefaultCellAlignment( int *horiz
, int *vert
)
3952 // TODO: replace this temp test code
3958 void wxGrid::GetCellAlignment( int WXUNUSED(row
), int WXUNUSED(col
), int *horiz
, int *vert
)
3960 // TODO: replace this temp test code
3966 void wxGrid::SetDefaultRowSize( int height
, bool resizeExistingRows
)
3968 m_defaultRowHeight
= wxMax( height
, WXGRID_MIN_ROW_HEIGHT
);
3970 if ( resizeExistingRows
)
3974 for ( row
= 0; row
< m_numRows
; row
++ )
3976 m_rowHeights
[row
] = m_defaultRowHeight
;
3977 bottom
+= m_defaultRowHeight
;
3978 m_rowBottoms
[row
] = bottom
;
3984 void wxGrid::SetRowSize( int row
, int height
)
3988 if ( row
>= 0 && row
< m_numRows
)
3990 int h
= wxMax( 0, height
);
3991 int diff
= h
- m_rowHeights
[row
];
3993 m_rowHeights
[row
] = h
;
3994 for ( i
= row
; i
< m_numRows
; i
++ )
3996 m_rowBottoms
[i
] += diff
;
4000 // Note: we are ending the event *after* doing
4001 // default processing in this case
4003 SendEvent( EVT_GRID_ROW_SIZE
,
4008 // TODO: log an error here
4012 void wxGrid::SetDefaultColSize( int width
, bool resizeExistingCols
)
4014 m_defaultColWidth
= wxMax( width
, WXGRID_MIN_COL_WIDTH
);
4016 if ( resizeExistingCols
)
4020 for ( col
= 0; col
< m_numCols
; col
++ )
4022 m_colWidths
[col
] = m_defaultColWidth
;
4023 right
+= m_defaultColWidth
;
4024 m_colRights
[col
] = right
;
4030 void wxGrid::SetColSize( int col
, int width
)
4034 if ( col
>= 0 && col
< m_numCols
)
4036 int w
= wxMax( 0, width
);
4037 int diff
= w
- m_colWidths
[col
];
4038 m_colWidths
[col
] = w
;
4040 for ( i
= col
; i
< m_numCols
; i
++ )
4042 m_colRights
[i
] += diff
;
4046 // Note: we are ending the event *after* doing
4047 // default processing in this case
4049 SendEvent( EVT_GRID_COL_SIZE
,
4054 // TODO: log an error here
4058 void wxGrid::SetDefaultCellBackgroundColour( const wxColour
& )
4060 // TODO: everything !!!
4064 void wxGrid::SetCellBackgroundColour( int WXUNUSED(row
), int WXUNUSED(col
), const wxColour
& )
4066 // TODO: everything !!!
4070 void wxGrid::SetDefaultCellTextColour( const wxColour
& )
4072 // TODO: everything !!!
4076 void wxGrid::SetCellTextColour( int WXUNUSED(row
), int WXUNUSED(col
), const wxColour
& )
4078 // TODO: everything !!!
4082 void wxGrid::SetDefaultCellFont( const wxFont
& )
4084 // TODO: everything !!!
4088 void wxGrid::SetCellFont( int WXUNUSED(row
), int WXUNUSED(col
), const wxFont
& )
4090 // TODO: everything !!!
4094 void wxGrid::SetDefaultCellAlignment( int WXUNUSED(horiz
), int WXUNUSED(vert
) )
4096 // TODO: everything !!!
4100 void wxGrid::SetCellAlignment( int WXUNUSED(row
), int WXUNUSED(col
), int WXUNUSED(horiz
), int WXUNUSED(vert
) )
4102 // TODO: everything !!!
4109 // ------ cell value accessor functions
4112 void wxGrid::SetCellValue( int row
, int col
, const wxString
& s
)
4116 m_table
->SetValue( row
, col
, s
.c_str() );
4117 if ( !GetBatchCount() )
4119 wxClientDC
dc( m_gridWin
);
4121 DrawCell( dc
, wxGridCellCoords(row
, col
) );
4124 #if 0 // TODO: edit in place
4126 if ( m_currentCellCoords
.GetRow() == row
&&
4127 m_currentCellCoords
.GetCol() == col
)
4129 SetEditControlValue( s
);
4138 // ------ Block, row and col selection
4141 void wxGrid::SelectRow( int row
, bool addToSelected
)
4145 if ( IsSelection() && addToSelected
)
4147 if ( m_selectedTopLeft
.GetRow() > row
)
4148 m_selectedTopLeft
.SetRow( row
);
4150 m_selectedTopLeft
.SetCol( 0 );
4152 if ( m_selectedBottomRight
.GetRow() < row
)
4153 m_selectedBottomRight
.SetRow( row
);
4155 m_selectedBottomRight
.SetCol( m_numCols
- 1 );
4157 // TODO: optimize this so that we only refresh the newly
4160 r
= SelectionToDeviceRect();
4161 if ( r
!= wxGridNoCellRect
) m_gridWin
->Refresh( TRUE
, &r
);
4165 r
= SelectionToDeviceRect();
4167 if ( r
!= wxGridNoCellRect
) m_gridWin
->Refresh( TRUE
, &r
);
4169 m_selectedTopLeft
.Set( row
, 0 );
4170 m_selectedBottomRight
.Set( row
, m_numCols
-1 );
4171 r
= SelectionToDeviceRect();
4172 m_gridWin
->Refresh( TRUE
, &r
);
4175 wxGridRangeSelectEvent
gridEvt( GetId(),
4176 EVT_GRID_RANGE_SELECT
,
4179 m_selectedBottomRight
);
4181 GetEventHandler()->ProcessEvent(gridEvt
);
4185 void wxGrid::SelectCol( int col
, bool addToSelected
)
4189 if ( IsSelection() && addToSelected
)
4191 if ( m_selectedTopLeft
.GetCol() > col
)
4192 m_selectedTopLeft
.SetCol( col
);
4194 m_selectedTopLeft
.SetRow( 0 );
4196 if ( m_selectedBottomRight
.GetCol() < col
)
4197 m_selectedBottomRight
.SetCol( col
);
4199 m_selectedBottomRight
.SetRow( m_numRows
- 1 );
4201 // TODO: optimize this so that we only refresh the newly
4204 r
= SelectionToDeviceRect();
4205 if ( r
!= wxGridNoCellRect
) m_gridWin
->Refresh( TRUE
, &r
);
4209 r
= SelectionToDeviceRect();
4211 if ( r
!= wxGridNoCellRect
) m_gridWin
->Refresh( TRUE
, &r
);
4213 m_selectedTopLeft
.Set( 0, col
);
4214 m_selectedBottomRight
.Set( m_numRows
-1, col
);
4215 r
= SelectionToDeviceRect();
4216 m_gridWin
->Refresh( TRUE
, &r
);
4219 wxGridRangeSelectEvent
gridEvt( GetId(),
4220 EVT_GRID_RANGE_SELECT
,
4223 m_selectedBottomRight
);
4225 GetEventHandler()->ProcessEvent(gridEvt
);
4229 void wxGrid::SelectBlock( int topRow
, int leftCol
, int bottomRow
, int rightCol
)
4232 bool changed
= false;
4233 wxGridCellCoords updateTopLeft
, updateBottomRight
;
4235 if ( topRow
> bottomRow
)
4242 if ( leftCol
> rightCol
)
4249 updateTopLeft
= m_selectedTopLeft
;
4250 if (m_selectedTopLeft
!= wxGridCellCoords( topRow
, leftCol
) )
4252 m_selectedTopLeft
= wxGridCellCoords( topRow
, leftCol
);
4253 if (updateTopLeft
== wxGridNoCellCoords
)
4255 updateTopLeft
= m_selectedTopLeft
;
4259 if(updateTopLeft
.GetRow() > topRow
)
4260 updateTopLeft
.SetRow(topRow
);
4261 if (updateTopLeft
.GetCol() > leftCol
)
4262 updateTopLeft
.SetCol(leftCol
);
4267 updateBottomRight
= m_selectedBottomRight
;
4268 if (m_selectedBottomRight
!= wxGridCellCoords( bottomRow
, rightCol
) )
4270 m_selectedBottomRight
= wxGridCellCoords( bottomRow
, rightCol
);
4271 if (updateBottomRight
== wxGridNoCellCoords
)
4273 updateBottomRight
= m_selectedBottomRight
;
4277 if (updateBottomRight
.GetRow() < bottomRow
)
4278 updateBottomRight
.SetRow(bottomRow
);
4279 if (updateBottomRight
.GetCol() < rightCol
)
4280 updateBottomRight
.SetCol(rightCol
);
4287 wxRect
r( BlockToDeviceRect( updateTopLeft
, updateBottomRight
) );
4288 m_gridWin
->Refresh( TRUE
, &r
);
4291 // only generate an event if the block is not being selected by
4292 // dragging the mouse (in which case the event will be generated in
4293 // the mouse event handler)
4294 if ( !m_isDragging
)
4296 wxGridRangeSelectEvent
gridEvt( GetId(),
4297 EVT_GRID_RANGE_SELECT
,
4300 m_selectedBottomRight
);
4302 GetEventHandler()->ProcessEvent(gridEvt
);
4306 void wxGrid::SelectAll()
4308 m_selectedTopLeft
.Set( 0, 0 );
4309 m_selectedBottomRight
.Set( m_numRows
-1, m_numCols
-1 );
4311 m_gridWin
->Refresh();
4315 void wxGrid::ClearSelection()
4317 m_selectedTopLeft
= wxGridNoCellCoords
;
4318 m_selectedBottomRight
= wxGridNoCellCoords
;
4322 // This function returns the rectangle that encloses the given block
4323 // in device coords clipped to the client size of the grid window.
4325 wxRect
wxGrid::BlockToDeviceRect(const wxGridCellCoords
& TopLeft
,
4326 const wxGridCellCoords
& BottomRight
)
4331 if ( IsSelection() )
4333 cellRect
= CellToRect( TopLeft
);
4334 if ( cellRect
!= wxGridNoCellRect
)
4340 rect
= wxRect( 0, 0, 0, 0 );
4343 cellRect
= CellToRect( BottomRight
);
4344 if ( cellRect
!= wxGridNoCellRect
)
4350 return wxGridNoCellRect
;
4353 // convert to scrolled coords
4355 int left
, top
, right
, bottom
;
4356 CalcScrolledPosition( rect
.GetLeft(), rect
.GetTop(), &left
, &top
);
4357 CalcScrolledPosition( rect
.GetRight(), rect
.GetBottom(), &right
, &bottom
);
4360 m_gridWin
->GetClientSize( &cw
, &ch
);
4362 rect
.SetLeft( wxMax(0, left
) );
4363 rect
.SetTop( wxMax(0, top
) );
4364 rect
.SetRight( wxMin(cw
, right
) );
4365 rect
.SetBottom( wxMin(ch
, bottom
) );
4369 return wxGridNoCellRect
;
4377 // ------ Grid event classes
4380 IMPLEMENT_DYNAMIC_CLASS( wxGridEvent
, wxEvent
)
4382 wxGridEvent::wxGridEvent( int id
, wxEventType type
, wxObject
* obj
,
4383 int row
, int col
, int x
, int y
,
4384 bool control
, bool shift
, bool alt
, bool meta
)
4385 : wxNotifyEvent( type
, id
)
4391 m_control
= control
;
4396 SetEventObject(obj
);
4400 IMPLEMENT_DYNAMIC_CLASS( wxGridSizeEvent
, wxEvent
)
4402 wxGridSizeEvent::wxGridSizeEvent( int id
, wxEventType type
, wxObject
* obj
,
4403 int rowOrCol
, int x
, int y
,
4404 bool control
, bool shift
, bool alt
, bool meta
)
4405 : wxNotifyEvent( type
, id
)
4407 m_rowOrCol
= rowOrCol
;
4410 m_control
= control
;
4415 SetEventObject(obj
);
4419 IMPLEMENT_DYNAMIC_CLASS( wxGridRangeSelectEvent
, wxEvent
)
4421 wxGridRangeSelectEvent::wxGridRangeSelectEvent(int id
, wxEventType type
, wxObject
* obj
,
4422 const wxGridCellCoords
& topLeft
,
4423 const wxGridCellCoords
& bottomRight
,
4424 bool control
, bool shift
, bool alt
, bool meta
)
4425 : wxNotifyEvent( type
, id
)
4427 m_topLeft
= topLeft
;
4428 m_bottomRight
= bottomRight
;
4429 m_control
= control
;
4434 SetEventObject(obj
);
4438 #endif // ifndef wxUSE_NEW_GRID