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
;
945 // TODO: do we need this or should the top edit control be an add-on ?
947 m_topEditCtrl
= (wxWindow
*) NULL
;
951 bool wxGrid::CreateGrid( int numRows
, int numCols
)
955 wxLogError( wxT("wxGrid::CreateGrid(numRows, numCols) called more than once") );
963 m_table
= new wxGridStringTable( m_numRows
, m_numCols
);
964 m_table
->SetView( this );
977 if ( m_numRows
<= 0 )
978 m_numRows
= WXGRID_DEFAULT_NUMBER_ROWS
;
980 if ( m_numCols
<= 0 )
981 m_numCols
= WXGRID_DEFAULT_NUMBER_COLS
;
983 m_rowLabelWidth
= WXGRID_DEFAULT_ROW_LABEL_WIDTH
;
984 m_colLabelHeight
= WXGRID_DEFAULT_COL_LABEL_HEIGHT
;
986 m_labelBackgroundColour
= m_rowLabelWin
->GetBackgroundColour();
987 m_labelTextColour
= wxColour( "BLACK" );
989 // TODO: something better than this ?
991 m_labelFont
= this->GetFont();
992 m_labelFont
.SetWeight( m_labelFont
.GetWeight() + 2 );
994 m_rowLabelHorizAlign
= wxLEFT
;
995 m_rowLabelVertAlign
= wxCENTRE
;
997 m_colLabelHorizAlign
= wxCENTRE
;
998 m_colLabelVertAlign
= wxTOP
;
1000 m_defaultColWidth
= WXGRID_DEFAULT_COL_WIDTH
;
1001 m_defaultRowHeight
= m_gridWin
->GetCharHeight() + 8;
1003 m_rowHeights
.Alloc( m_numRows
);
1004 m_rowBottoms
.Alloc( m_numRows
);
1006 for ( i
= 0; i
< m_numRows
; i
++ )
1008 m_rowHeights
.Add( m_defaultRowHeight
);
1009 rowBottom
+= m_defaultRowHeight
;
1010 m_rowBottoms
.Add( rowBottom
);
1013 m_colWidths
.Alloc( m_numCols
);
1014 m_colRights
.Alloc( m_numCols
);
1016 for ( i
= 0; i
< m_numCols
; i
++ )
1018 m_colWidths
.Add( m_defaultColWidth
);
1019 colRight
+= m_defaultColWidth
;
1020 m_colRights
.Add( colRight
);
1023 // TODO: improve this ?
1025 m_defaultCellFont
= this->GetFont();
1027 m_gridLineColour
= wxColour( 128, 128, 255 );
1028 m_gridLinesEnabled
= TRUE
;
1030 m_cursorMode
= WXGRID_CURSOR_DEFAULT
;
1032 m_dragRowOrCol
= -1;
1033 m_isDragging
= FALSE
;
1035 m_rowResizeCursor
= wxCursor( wxCURSOR_SIZENS
);
1036 m_colResizeCursor
= wxCursor( wxCURSOR_SIZEWE
);
1038 m_currentCellCoords
= wxGridNoCellCoords
;
1039 m_currentCellHighlighted
= FALSE
;
1041 m_selectedTopLeft
= wxGridNoCellCoords
;
1042 m_selectedBottomRight
= wxGridNoCellCoords
;
1044 m_editable
= TRUE
; // default for whole grid
1046 m_inOnKeyDown
= FALSE
;
1049 // TODO: extend this to other types of controls
1051 m_cellEditCtrl
= new wxGridTextCtrl( m_gridWin
,
1059 , wxTE_MULTILINE
| wxTE_NO_VSCROLL
1063 m_cellEditCtrl
->Show( FALSE
);
1064 m_cellEditCtrlEnabled
= TRUE
;
1065 m_editCtrlType
= wxGRID_TEXTCTRL
;
1067 // TODO: do we need this or should the top edit control be an add-on ?
1069 m_topEditCtrlEnabled
= FALSE
;
1073 void wxGrid::CalcDimensions()
1076 GetClientSize( &cw
, &ch
);
1078 if ( m_numRows
> 0 && m_numCols
> 0 )
1080 int right
= m_colRights
[ m_numCols
-1 ] + 20;
1081 int bottom
= m_rowBottoms
[ m_numRows
-1 ] + 20;
1083 // TODO: restore the scroll position that we had before sizing
1086 GetViewStart( &x
, &y
);
1087 SetScrollbars( 10, 10,
1088 right
/10, bottom
/10,
1094 // this is called when the grid table sends a message to say that it
1095 // has been redimensioned
1097 bool wxGrid::Redimension( wxGridTableMessage
& msg
)
1101 switch ( msg
.GetId() )
1103 case wxGRIDTABLE_NOTIFY_ROWS_INSERTED
:
1105 size_t pos
= msg
.GetCommandInt();
1106 int numRows
= msg
.GetCommandInt2();
1107 for ( i
= 0; i
< numRows
; i
++ )
1109 m_rowHeights
.Insert( m_defaultRowHeight
, pos
);
1110 m_rowBottoms
.Insert( 0, pos
);
1112 m_numRows
+= numRows
;
1115 if ( pos
> 0 ) bottom
= m_rowBottoms
[pos
-1];
1117 for ( i
= pos
; i
< m_numRows
; i
++ )
1119 bottom
+= m_rowHeights
[i
];
1120 m_rowBottoms
[i
] = bottom
;
1126 case wxGRIDTABLE_NOTIFY_ROWS_APPENDED
:
1128 int numRows
= msg
.GetCommandInt();
1129 for ( i
= 0; i
< numRows
; i
++ )
1131 m_rowHeights
.Add( m_defaultRowHeight
);
1132 m_rowBottoms
.Add( 0 );
1135 int oldNumRows
= m_numRows
;
1136 m_numRows
+= numRows
;
1139 if ( oldNumRows
> 0 ) bottom
= m_rowBottoms
[oldNumRows
-1];
1141 for ( i
= oldNumRows
; i
< m_numRows
; i
++ )
1143 bottom
+= m_rowHeights
[i
];
1144 m_rowBottoms
[i
] = bottom
;
1150 case wxGRIDTABLE_NOTIFY_ROWS_DELETED
:
1152 size_t pos
= msg
.GetCommandInt();
1153 int numRows
= msg
.GetCommandInt2();
1154 for ( i
= 0; i
< numRows
; i
++ )
1156 m_rowHeights
.Remove( pos
);
1157 m_rowBottoms
.Remove( pos
);
1159 m_numRows
-= numRows
;
1164 m_colWidths
.Clear();
1165 m_colRights
.Clear();
1166 m_currentCellCoords
= wxGridNoCellCoords
;
1170 if ( m_currentCellCoords
.GetRow() >= m_numRows
)
1171 m_currentCellCoords
.Set( 0, 0 );
1174 for ( i
= 0; i
< m_numRows
; i
++ )
1176 h
+= m_rowHeights
[i
];
1177 m_rowBottoms
[i
] = h
;
1185 case wxGRIDTABLE_NOTIFY_COLS_INSERTED
:
1187 size_t pos
= msg
.GetCommandInt();
1188 int numCols
= msg
.GetCommandInt2();
1189 for ( i
= 0; i
< numCols
; i
++ )
1191 m_colWidths
.Insert( m_defaultColWidth
, pos
);
1192 m_colRights
.Insert( 0, pos
);
1194 m_numCols
+= numCols
;
1197 if ( pos
> 0 ) right
= m_colRights
[pos
-1];
1199 for ( i
= pos
; i
< m_numCols
; i
++ )
1201 right
+= m_colWidths
[i
];
1202 m_colRights
[i
] = right
;
1208 case wxGRIDTABLE_NOTIFY_COLS_APPENDED
:
1210 int numCols
= msg
.GetCommandInt();
1211 for ( i
= 0; i
< numCols
; i
++ )
1213 m_colWidths
.Add( m_defaultColWidth
);
1214 m_colRights
.Add( 0 );
1217 int oldNumCols
= m_numCols
;
1218 m_numCols
+= numCols
;
1221 if ( oldNumCols
> 0 ) right
= m_colRights
[oldNumCols
-1];
1223 for ( i
= oldNumCols
; i
< m_numCols
; i
++ )
1225 right
+= m_colWidths
[i
];
1226 m_colRights
[i
] = right
;
1232 case wxGRIDTABLE_NOTIFY_COLS_DELETED
:
1234 size_t pos
= msg
.GetCommandInt();
1235 int numCols
= msg
.GetCommandInt2();
1236 for ( i
= 0; i
< numCols
; i
++ )
1238 m_colWidths
.Remove( pos
);
1239 m_colRights
.Remove( pos
);
1241 m_numCols
-= numCols
;
1245 #if 0 // leave the row alone here so that AppendCols will work subsequently
1247 m_rowHeights
.Clear();
1248 m_rowBottoms
.Clear();
1250 m_currentCellCoords
= wxGridNoCellCoords
;
1254 if ( m_currentCellCoords
.GetCol() >= m_numCols
)
1255 m_currentCellCoords
.Set( 0, 0 );
1258 for ( i
= 0; i
< m_numCols
; i
++ )
1260 w
+= m_colWidths
[i
];
1273 void wxGrid::CalcRowLabelsExposed( wxRegion
& reg
)
1275 wxRegionIterator
iter( reg
);
1278 m_rowLabelsExposed
.Empty();
1285 // TODO: remove this when we can...
1286 // There is a bug in wxMotif that gives garbage update
1287 // rectangles if you jump-scroll a long way by clicking the
1288 // scrollbar with middle button. This is a work-around
1290 #if defined(__WXMOTIF__)
1292 m_gridWin
->GetClientSize( &cw
, &ch
);
1293 if ( r
.GetTop() > ch
) r
.SetTop( 0 );
1294 r
.SetBottom( wxMin( r
.GetBottom(), ch
) );
1297 // logical bounds of update region
1300 CalcUnscrolledPosition( 0, r
.GetTop(), &dummy
, &top
);
1301 CalcUnscrolledPosition( 0, r
.GetBottom(), &dummy
, &bottom
);
1303 // find the row labels within these bounds
1307 for ( row
= 0; row
< m_numRows
; row
++ )
1309 if ( m_rowBottoms
[row
] < top
) continue;
1311 rowTop
= m_rowBottoms
[row
] - m_rowHeights
[row
];
1312 if ( rowTop
> bottom
) break;
1314 m_rowLabelsExposed
.Add( row
);
1322 void wxGrid::CalcColLabelsExposed( wxRegion
& reg
)
1324 wxRegionIterator
iter( reg
);
1327 m_colLabelsExposed
.Empty();
1334 // TODO: remove this when we can...
1335 // There is a bug in wxMotif that gives garbage update
1336 // rectangles if you jump-scroll a long way by clicking the
1337 // scrollbar with middle button. This is a work-around
1339 #if defined(__WXMOTIF__)
1341 m_gridWin
->GetClientSize( &cw
, &ch
);
1342 if ( r
.GetLeft() > cw
) r
.SetLeft( 0 );
1343 r
.SetRight( wxMin( r
.GetRight(), cw
) );
1346 // logical bounds of update region
1349 CalcUnscrolledPosition( r
.GetLeft(), 0, &left
, &dummy
);
1350 CalcUnscrolledPosition( r
.GetRight(), 0, &right
, &dummy
);
1352 // find the cells within these bounds
1356 for ( col
= 0; col
< m_numCols
; col
++ )
1358 if ( m_colRights
[col
] < left
) continue;
1360 colLeft
= m_colRights
[col
] - m_colWidths
[col
];
1361 if ( colLeft
> right
) break;
1363 m_colLabelsExposed
.Add( col
);
1371 void wxGrid::CalcCellsExposed( wxRegion
& reg
)
1373 wxRegionIterator
iter( reg
);
1376 m_cellsExposed
.Empty();
1377 m_rowsExposed
.Empty();
1378 m_colsExposed
.Empty();
1380 int left
, top
, right
, bottom
;
1385 // TODO: remove this when we can...
1386 // There is a bug in wxMotif that gives garbage update
1387 // rectangles if you jump-scroll a long way by clicking the
1388 // scrollbar with middle button. This is a work-around
1390 #if defined(__WXMOTIF__)
1392 m_gridWin
->GetClientSize( &cw
, &ch
);
1393 if ( r
.GetTop() > ch
) r
.SetTop( 0 );
1394 if ( r
.GetLeft() > cw
) r
.SetLeft( 0 );
1395 r
.SetRight( wxMin( r
.GetRight(), cw
) );
1396 r
.SetBottom( wxMin( r
.GetBottom(), ch
) );
1399 // logical bounds of update region
1401 CalcUnscrolledPosition( r
.GetLeft(), r
.GetTop(), &left
, &top
);
1402 CalcUnscrolledPosition( r
.GetRight(), r
.GetBottom(), &right
, &bottom
);
1404 // find the cells within these bounds
1407 int colLeft
, rowTop
;
1408 for ( row
= 0; row
< m_numRows
; row
++ )
1410 if ( m_rowBottoms
[row
] < top
) continue;
1412 rowTop
= m_rowBottoms
[row
] - m_rowHeights
[row
];
1413 if ( rowTop
> bottom
) break;
1415 m_rowsExposed
.Add( row
);
1417 for ( col
= 0; col
< m_numCols
; col
++ )
1419 if ( m_colRights
[col
] < left
) continue;
1421 colLeft
= m_colRights
[col
] - m_colWidths
[col
];
1422 if ( colLeft
> right
) break;
1424 if ( m_colsExposed
.Index( col
) == wxNOT_FOUND
) m_colsExposed
.Add( col
);
1425 m_cellsExposed
.Add( wxGridCellCoords( row
, col
) );
1434 void wxGrid::ProcessRowLabelMouseEvent( wxMouseEvent
& event
)
1437 wxPoint
pos( event
.GetPosition() );
1438 CalcUnscrolledPosition( pos
.x
, pos
.y
, &x
, &y
);
1440 if ( event
.Dragging() )
1442 m_isDragging
= TRUE
;
1444 if ( event
.LeftIsDown() )
1446 switch( m_cursorMode
)
1448 case WXGRID_CURSOR_RESIZE_ROW
:
1450 int cw
, ch
, left
, dummy
;
1451 m_gridWin
->GetClientSize( &cw
, &ch
);
1452 CalcUnscrolledPosition( 0, 0, &left
, &dummy
);
1454 wxClientDC
dc( m_gridWin
);
1456 dc
.SetLogicalFunction(wxXOR
);
1457 if ( m_dragLastPos
>= 0 )
1459 dc
.DrawLine( left
, m_dragLastPos
, left
+cw
, m_dragLastPos
);
1461 dc
.DrawLine( left
, y
, left
+cw
, y
);
1466 case WXGRID_CURSOR_SELECT_ROW
:
1468 if ( (row
= YToRow( y
)) >= 0 &&
1469 !IsInSelection( row
, 0 ) )
1471 SelectRow( row
, TRUE
);
1480 m_isDragging
= FALSE
;
1483 // ------------ Left button pressed
1485 if ( event
.LeftDown() )
1487 // don't send a label click event for a hit on the
1488 // edge of the row label - this is probably the user
1489 // wanting to resize the row
1491 if ( YToEdgeOfRow(y
) < 0 )
1494 if ( !SendEvent( EVT_GRID_LABEL_LEFT_CLICK
, row
, -1, event
) )
1496 SelectRow( row
, event
.ShiftDown() );
1497 m_cursorMode
= WXGRID_CURSOR_SELECT_ROW
;
1502 // starting to drag-resize a row
1504 m_rowLabelWin
->CaptureMouse();
1509 // ------------ Left double click
1511 else if (event
.LeftDClick() )
1513 if ( YToEdgeOfRow(y
) < 0 )
1516 SendEvent( EVT_GRID_LABEL_LEFT_DCLICK
, row
, -1, event
);
1521 // ------------ Left button released
1523 else if ( event
.LeftUp() )
1525 if ( m_cursorMode
== WXGRID_CURSOR_RESIZE_ROW
)
1527 m_rowLabelWin
->ReleaseMouse();
1529 if ( m_dragLastPos
>= 0 )
1531 // erase the last line and resize the row
1533 int cw
, ch
, left
, dummy
;
1534 m_gridWin
->GetClientSize( &cw
, &ch
);
1535 CalcUnscrolledPosition( 0, 0, &left
, &dummy
);
1537 wxClientDC
dc( m_gridWin
);
1539 dc
.SetLogicalFunction( wxINVERT
);
1540 dc
.DrawLine( left
, m_dragLastPos
, left
+cw
, m_dragLastPos
);
1541 HideCellEditControl();
1543 int rowTop
= m_rowBottoms
[m_dragRowOrCol
] - m_rowHeights
[m_dragRowOrCol
];
1544 SetRowSize( m_dragRowOrCol
, wxMax( y
- rowTop
, WXGRID_MIN_ROW_HEIGHT
) );
1545 if ( !GetBatchCount() )
1547 // TODO: optimize this
1548 m_rowLabelWin
->Refresh();
1549 m_gridWin
->Refresh();
1552 ShowCellEditControl();
1554 // Note: we are ending the event *after* doing
1555 // default processing in this case
1557 SendEvent( EVT_GRID_ROW_SIZE
, m_dragRowOrCol
, -1, event
);
1565 // ------------ Right button down
1567 else if ( event
.RightDown() )
1570 if ( !SendEvent( EVT_GRID_LABEL_RIGHT_CLICK
, row
, -1, event
) )
1572 // no default action at the moment
1577 // ------------ Right double click
1579 else if ( event
.RightDClick() )
1582 if ( !SendEvent( EVT_GRID_LABEL_RIGHT_DCLICK
, row
, -1, event
) )
1584 // no default action at the moment
1589 // ------------ No buttons down and mouse moving
1591 else if ( event
.Moving() )
1593 m_dragRowOrCol
= YToEdgeOfRow( y
);
1594 if ( m_dragRowOrCol
>= 0 )
1596 if ( m_cursorMode
== WXGRID_CURSOR_SELECT_CELL
)
1598 m_cursorMode
= WXGRID_CURSOR_RESIZE_ROW
;
1599 m_rowLabelWin
->SetCursor( m_rowResizeCursor
);
1604 if ( m_cursorMode
!= WXGRID_CURSOR_SELECT_CELL
)
1606 m_cursorMode
= WXGRID_CURSOR_SELECT_CELL
;
1607 m_rowLabelWin
->SetCursor( *wxSTANDARD_CURSOR
);
1614 void wxGrid::ProcessColLabelMouseEvent( wxMouseEvent
& event
)
1617 wxPoint
pos( event
.GetPosition() );
1618 CalcUnscrolledPosition( pos
.x
, pos
.y
, &x
, &y
);
1620 if ( event
.Dragging() )
1622 m_isDragging
= TRUE
;
1624 if ( event
.LeftIsDown() )
1626 switch( m_cursorMode
)
1628 case WXGRID_CURSOR_RESIZE_COL
:
1630 int cw
, ch
, dummy
, top
;
1631 m_gridWin
->GetClientSize( &cw
, &ch
);
1632 CalcUnscrolledPosition( 0, 0, &dummy
, &top
);
1634 wxClientDC
dc( m_gridWin
);
1636 dc
.SetLogicalFunction(wxXOR
);
1637 if ( m_dragLastPos
>= 0 )
1639 dc
.DrawLine( m_dragLastPos
, top
, m_dragLastPos
, top
+ch
);
1641 dc
.DrawLine( x
, top
, x
, top
+ch
);
1646 case WXGRID_CURSOR_SELECT_COL
:
1648 if ( (col
= XToCol( x
)) >= 0 &&
1649 !IsInSelection( 0, col
) )
1651 SelectCol( col
, TRUE
);
1660 m_isDragging
= FALSE
;
1663 // ------------ Left button pressed
1665 if ( event
.LeftDown() )
1667 // don't send a label click event for a hit on the
1668 // edge of the col label - this is probably the user
1669 // wanting to resize the col
1671 if ( XToEdgeOfCol(x
) < 0 )
1674 if ( !SendEvent( EVT_GRID_LABEL_LEFT_CLICK
, -1, col
, event
) )
1676 SelectCol( col
, event
.ShiftDown() );
1677 m_cursorMode
= WXGRID_CURSOR_SELECT_COL
;
1682 // starting to drag-resize a col
1684 m_colLabelWin
->CaptureMouse();
1689 // ------------ Left double click
1691 if ( event
.LeftDClick() )
1693 if ( XToEdgeOfCol(x
) < 0 )
1696 SendEvent( EVT_GRID_LABEL_LEFT_DCLICK
, -1, col
, event
);
1701 // ------------ Left button released
1703 else if ( event
.LeftUp() )
1705 if ( m_cursorMode
== WXGRID_CURSOR_RESIZE_COL
)
1707 m_colLabelWin
->ReleaseMouse();
1709 if ( m_dragLastPos
>= 0 )
1711 // erase the last line and resize the col
1713 int cw
, ch
, dummy
, top
;
1714 m_gridWin
->GetClientSize( &cw
, &ch
);
1715 CalcUnscrolledPosition( 0, 0, &dummy
, &top
);
1717 wxClientDC
dc( m_gridWin
);
1719 dc
.SetLogicalFunction( wxINVERT
);
1720 dc
.DrawLine( m_dragLastPos
, top
, m_dragLastPos
, top
+ch
);
1721 HideCellEditControl();
1723 int colLeft
= m_colRights
[m_dragRowOrCol
] - m_colWidths
[m_dragRowOrCol
];
1724 SetColSize( m_dragRowOrCol
, wxMax( x
- colLeft
, WXGRID_MIN_COL_WIDTH
) );
1726 if ( !GetBatchCount() )
1728 // TODO: optimize this
1729 m_colLabelWin
->Refresh();
1730 m_gridWin
->Refresh();
1733 ShowCellEditControl();
1735 // Note: we are ending the event *after* doing
1736 // default processing in this case
1738 SendEvent( EVT_GRID_COL_SIZE
, -1, m_dragRowOrCol
, event
);
1746 // ------------ Right button down
1748 else if ( event
.RightDown() )
1751 if ( !SendEvent( EVT_GRID_LABEL_RIGHT_CLICK
, -1, col
, event
) )
1753 // no default action at the moment
1758 // ------------ Right double click
1760 else if ( event
.RightDClick() )
1763 if ( !SendEvent( EVT_GRID_LABEL_RIGHT_DCLICK
, -1, col
, event
) )
1765 // no default action at the moment
1770 // ------------ No buttons down and mouse moving
1772 else if ( event
.Moving() )
1774 m_dragRowOrCol
= XToEdgeOfCol( x
);
1775 if ( m_dragRowOrCol
>= 0 )
1777 if ( m_cursorMode
== WXGRID_CURSOR_SELECT_CELL
)
1779 m_cursorMode
= WXGRID_CURSOR_RESIZE_COL
;
1780 m_colLabelWin
->SetCursor( m_colResizeCursor
);
1785 if ( m_cursorMode
!= WXGRID_CURSOR_SELECT_CELL
)
1787 m_cursorMode
= WXGRID_CURSOR_SELECT_CELL
;
1788 m_colLabelWin
->SetCursor( *wxSTANDARD_CURSOR
);
1795 void wxGrid::ProcessCornerLabelMouseEvent( wxMouseEvent
& event
)
1797 if ( event
.LeftDown() )
1799 // indicate corner label by having both row and
1802 if ( !SendEvent( EVT_GRID_LABEL_LEFT_CLICK
, -1, -1, event
) )
1808 else if ( event
.LeftDClick() )
1810 SendEvent( EVT_GRID_LABEL_LEFT_DCLICK
, -1, -1, event
);
1813 else if ( event
.RightDown() )
1815 if ( !SendEvent( EVT_GRID_LABEL_RIGHT_CLICK
, -1, -1, event
) )
1817 // no default action at the moment
1821 else if ( event
.RightDClick() )
1823 if ( !SendEvent( EVT_GRID_LABEL_RIGHT_DCLICK
, -1, -1, event
) )
1825 // no default action at the moment
1831 void wxGrid::ProcessGridCellMouseEvent( wxMouseEvent
& event
)
1834 wxPoint
pos( event
.GetPosition() );
1835 CalcUnscrolledPosition( pos
.x
, pos
.y
, &x
, &y
);
1837 wxGridCellCoords coords
;
1838 XYToCell( x
, y
, coords
);
1840 if ( event
.Dragging() )
1842 m_isDragging
= TRUE
;
1844 if ( m_cursorMode
== WXGRID_CURSOR_SELECT_CELL
)
1846 if ( coords
!= wxGridNoCellCoords
)
1848 if ( !IsSelection() )
1850 SelectBlock( coords
, coords
);
1854 if ( !IsInSelection( coords
) )
1855 SelectBlock( m_currentCellCoords
, coords
);
1863 m_isDragging
= FALSE
;
1865 if ( event
.LeftDown() )
1867 if ( !SendEvent( EVT_GRID_CELL_LEFT_CLICK
,
1872 MakeCellVisible( coords
);
1873 SetCurrentCell( coords
);
1878 // ------------ Left double click
1880 else if ( event
.LeftDClick() )
1882 SendEvent( EVT_GRID_CELL_LEFT_DCLICK
,
1889 // ------------ Left button released
1891 else if ( event
.LeftUp() )
1893 if ( m_cursorMode
== WXGRID_CURSOR_SELECT_CELL
)
1895 if ( IsSelection() )
1897 SendEvent( EVT_GRID_RANGE_SELECT
, -1, -1, event
);
1905 // ------------ Right button down
1907 else if ( event
.RightDown() )
1909 if ( !SendEvent( EVT_GRID_CELL_RIGHT_CLICK
,
1914 // no default action at the moment
1919 // ------------ Right double click
1921 else if ( event
.RightDClick() )
1923 if ( !SendEvent( EVT_GRID_CELL_RIGHT_DCLICK
,
1928 // no default action at the moment
1935 // ------ interaction with data model
1937 bool wxGrid::ProcessTableMessage( wxGridTableMessage
& msg
)
1939 switch ( msg
.GetId() )
1941 case wxGRIDTABLE_REQUEST_VIEW_GET_VALUES
:
1942 return GetModelValues();
1944 case wxGRIDTABLE_REQUEST_VIEW_SEND_VALUES
:
1945 return SetModelValues();
1947 case wxGRIDTABLE_NOTIFY_ROWS_INSERTED
:
1948 case wxGRIDTABLE_NOTIFY_ROWS_APPENDED
:
1949 case wxGRIDTABLE_NOTIFY_ROWS_DELETED
:
1950 case wxGRIDTABLE_NOTIFY_COLS_INSERTED
:
1951 case wxGRIDTABLE_NOTIFY_COLS_APPENDED
:
1952 case wxGRIDTABLE_NOTIFY_COLS_DELETED
:
1953 return Redimension( msg
);
1962 // The behaviour of this function depends on the grid table class
1963 // Clear() function. For the default wxGridStringTable class the
1964 // behavious is to replace all cell contents with wxEmptyString but
1965 // not to change the number of rows or cols.
1967 void wxGrid::ClearGrid()
1972 SetEditControlValue();
1973 if ( !GetBatchCount() ) Refresh();
1978 bool wxGrid::InsertRows( int pos
, int numRows
, bool WXUNUSED(updateLabels
) )
1980 // TODO: something with updateLabels flag
1984 wxLogError( wxT("Called wxGrid::InsertRows() before calling CreateGrid()") );
1990 bool ok
= m_table
->InsertRows( pos
, numRows
);
1992 // the table will have sent the results of the insert row
1993 // operation to this view object as a grid table message
1997 if ( m_numCols
== 0 )
1999 m_table
->AppendCols( WXGRID_DEFAULT_NUMBER_COLS
);
2001 // TODO: perhaps instead of appending the default number of cols
2002 // we should remember what the last non-zero number of cols was ?
2006 if ( m_currentCellCoords
== wxGridNoCellCoords
)
2008 // if we have just inserted cols into an empty grid the current
2009 // cell will be undefined...
2011 SetCurrentCell( 0, 0 );
2015 if ( !GetBatchCount() ) Refresh();
2018 SetEditControlValue();
2028 bool wxGrid::AppendRows( int numRows
, bool WXUNUSED(updateLabels
) )
2030 // TODO: something with updateLabels flag
2034 wxLogError( wxT("Called wxGrid::AppendRows() before calling CreateGrid()") );
2038 if ( m_table
&& m_table
->AppendRows( numRows
) )
2040 if ( m_currentCellCoords
== wxGridNoCellCoords
)
2042 // if we have just inserted cols into an empty grid the current
2043 // cell will be undefined...
2045 SetCurrentCell( 0, 0 );
2048 // the table will have sent the results of the append row
2049 // operation to this view object as a grid table message
2052 if ( !GetBatchCount() ) Refresh();
2062 bool wxGrid::DeleteRows( int pos
, int numRows
, bool WXUNUSED(updateLabels
) )
2064 // TODO: something with updateLabels flag
2068 wxLogError( wxT("Called wxGrid::DeleteRows() before calling CreateGrid()") );
2072 if ( m_table
&& m_table
->DeleteRows( pos
, numRows
) )
2074 // the table will have sent the results of the delete row
2075 // operation to this view object as a grid table message
2077 if ( m_numRows
> 0 )
2078 SetEditControlValue();
2080 HideCellEditControl();
2083 if ( !GetBatchCount() ) Refresh();
2093 bool wxGrid::InsertCols( int pos
, int numCols
, bool WXUNUSED(updateLabels
) )
2095 // TODO: something with updateLabels flag
2099 wxLogError( wxT("Called wxGrid::InsertCols() before calling CreateGrid()") );
2105 HideCellEditControl();
2106 bool ok
= m_table
->InsertCols( pos
, numCols
);
2108 // the table will have sent the results of the insert col
2109 // operation to this view object as a grid table message
2113 if ( m_currentCellCoords
== wxGridNoCellCoords
)
2115 // if we have just inserted cols into an empty grid the current
2116 // cell will be undefined...
2118 SetCurrentCell( 0, 0 );
2122 if ( !GetBatchCount() ) Refresh();
2125 SetEditControlValue();
2135 bool wxGrid::AppendCols( int numCols
, bool WXUNUSED(updateLabels
) )
2137 // TODO: something with updateLabels flag
2141 wxLogError( wxT("Called wxGrid::AppendCols() before calling CreateGrid()") );
2145 if ( m_table
&& m_table
->AppendCols( numCols
) )
2147 // the table will have sent the results of the append col
2148 // operation to this view object as a grid table message
2150 if ( m_currentCellCoords
== wxGridNoCellCoords
)
2152 // if we have just inserted cols into an empty grid the current
2153 // cell will be undefined...
2155 SetCurrentCell( 0, 0 );
2159 if ( !GetBatchCount() ) Refresh();
2169 bool wxGrid::DeleteCols( int pos
, int numCols
, bool WXUNUSED(updateLabels
) )
2171 // TODO: something with updateLabels flag
2175 wxLogError( wxT("Called wxGrid::DeleteCols() before calling CreateGrid()") );
2179 if ( m_table
&& m_table
->DeleteCols( pos
, numCols
) )
2181 // the table will have sent the results of the delete col
2182 // operation to this view object as a grid table message
2184 if ( m_numCols
> 0 )
2185 SetEditControlValue();
2187 HideCellEditControl();
2190 if ( !GetBatchCount() ) Refresh();
2202 // ----- event handlers
2205 // Generate a grid event based on a mouse event and
2206 // return the result of ProcessEvent()
2208 bool wxGrid::SendEvent( const wxEventType type
,
2210 wxMouseEvent
& mouseEv
)
2212 if ( type
== EVT_GRID_ROW_SIZE
||
2213 type
== EVT_GRID_COL_SIZE
)
2215 int rowOrCol
= (row
== -1 ? col
: row
);
2217 wxGridSizeEvent
gridEvt( GetId(),
2221 mouseEv
.GetX(), mouseEv
.GetY(),
2222 mouseEv
.ControlDown(),
2223 mouseEv
.ShiftDown(),
2225 mouseEv
.MetaDown() );
2227 return GetEventHandler()->ProcessEvent(gridEvt
);
2229 else if ( type
== EVT_GRID_RANGE_SELECT
)
2231 wxGridRangeSelectEvent
gridEvt( GetId(),
2235 m_selectedBottomRight
,
2236 mouseEv
.ControlDown(),
2237 mouseEv
.ShiftDown(),
2239 mouseEv
.MetaDown() );
2241 return GetEventHandler()->ProcessEvent(gridEvt
);
2245 wxGridEvent
gridEvt( GetId(),
2249 mouseEv
.GetX(), mouseEv
.GetY(),
2250 mouseEv
.ControlDown(),
2251 mouseEv
.ShiftDown(),
2253 mouseEv
.MetaDown() );
2255 return GetEventHandler()->ProcessEvent(gridEvt
);
2260 // Generate a grid event of specified type and return the result
2261 // of ProcessEvent().
2263 bool wxGrid::SendEvent( const wxEventType type
,
2266 if ( type
== EVT_GRID_ROW_SIZE
||
2267 type
== EVT_GRID_COL_SIZE
)
2269 int rowOrCol
= (row
== -1 ? col
: row
);
2271 wxGridSizeEvent
gridEvt( GetId(),
2276 return GetEventHandler()->ProcessEvent(gridEvt
);
2280 wxGridEvent
gridEvt( GetId(),
2285 return GetEventHandler()->ProcessEvent(gridEvt
);
2290 void wxGrid::OnPaint( wxPaintEvent
& WXUNUSED(event
) )
2292 wxPaintDC
dc( this );
2294 if ( m_currentCellCoords
== wxGridNoCellCoords
&&
2295 m_numRows
&& m_numCols
)
2297 m_currentCellCoords
.Set(0, 0);
2298 SetEditControlValue();
2299 ShowCellEditControl();
2304 // This is just here to make sure that CalcDimensions gets called when
2305 // the grid view is resized... then the size event is skipped to allow
2306 // the box sizers to handle everything
2308 void wxGrid::OnSize( wxSizeEvent
& event
)
2315 void wxGrid::OnKeyDown( wxKeyEvent
& event
)
2317 if ( m_inOnKeyDown
)
2319 // shouldn't be here - we are going round in circles...
2321 wxLogFatalError( wxT("wxGrid::OnKeyDown called while alread active") );
2324 m_inOnKeyDown
= TRUE
;
2326 // propagate the event up and see if it gets processed
2328 wxWindow
*parent
= GetParent();
2329 wxKeyEvent
keyEvt( event
);
2330 keyEvt
.SetEventObject( parent
);
2332 if ( !parent
->GetEventHandler()->ProcessEvent( keyEvt
) )
2334 // try local handlers
2336 switch ( event
.KeyCode() )
2339 if ( event
.ControlDown() )
2341 MoveCursorUpBlock();
2350 if ( event
.ControlDown() )
2352 MoveCursorDownBlock();
2361 if ( event
.ControlDown() )
2363 MoveCursorLeftBlock();
2372 if ( event
.ControlDown() )
2374 MoveCursorRightBlock();
2387 if ( event
.ControlDown() )
2389 MakeCellVisible( 0, 0 );
2390 SetCurrentCell( 0, 0 );
2399 if ( event
.ControlDown() )
2401 MakeCellVisible( m_numRows
-1, m_numCols
-1 );
2402 SetCurrentCell( m_numRows
-1, m_numCols
-1 );
2419 // now try the cell edit control
2421 if ( IsCellEditControlEnabled() )
2423 event
.SetEventObject( m_cellEditCtrl
);
2424 m_cellEditCtrl
->GetEventHandler()->ProcessEvent( event
);
2430 m_inOnKeyDown
= FALSE
;
2434 void wxGrid::SetCurrentCell( const wxGridCellCoords
& coords
)
2436 if ( SendEvent( EVT_GRID_SELECT_CELL
, coords
.GetRow(), coords
.GetCol() ) )
2438 // the event has been intercepted - do nothing
2442 wxClientDC
dc( m_gridWin
);
2445 if ( m_currentCellCoords
!= wxGridNoCellCoords
)
2447 // HideCurrentCellHighlight( dc );
2448 HideCellEditControl();
2449 SaveEditControlValue();
2452 m_currentCellCoords
= coords
;
2454 SetEditControlValue();
2455 ShowCellEditControl();
2456 // ShowCurrentCellHighlight( dc );
2458 if ( IsSelection() )
2460 wxRect
r( SelectionToDeviceRect() );
2462 if ( !GetBatchCount() ) m_gridWin
->Refresh( TRUE
, &r
);
2468 // ------ functions to get/send data (see also public functions)
2471 bool wxGrid::GetModelValues()
2475 // all we need to do is repaint the grid
2477 m_gridWin
->Refresh();
2485 bool wxGrid::SetModelValues()
2491 for ( row
= 0; row
< m_numRows
; row
++ )
2493 for ( col
= 0; col
< m_numCols
; col
++ )
2495 m_table
->SetValue( row
, col
, GetCellValue(row
, col
) );
2507 // Note - this function only draws cells that are in the list of
2508 // exposed cells (usually set from the update region by
2509 // CalcExposedCells)
2511 void wxGrid::DrawGridCellArea( wxDC
& dc
)
2513 if ( !m_numRows
|| !m_numCols
) return;
2516 size_t numCells
= m_cellsExposed
.GetCount();
2518 for ( i
= 0; i
< numCells
; i
++ )
2520 DrawCell( dc
, m_cellsExposed
[i
] );
2525 void wxGrid::DrawCell( wxDC
& dc
, const wxGridCellCoords
& coords
)
2527 if ( m_colWidths
[coords
.GetCol()] <=0 ||
2528 m_rowHeights
[coords
.GetRow()] <= 0 ) return;
2530 if ( m_gridLinesEnabled
)
2531 DrawCellBorder( dc
, coords
);
2533 DrawCellBackground( dc
, coords
);
2535 // TODO: separate functions here for different kinds of cells ?
2538 DrawCellValue( dc
, coords
);
2542 void wxGrid::DrawCellBorder( wxDC
& dc
, const wxGridCellCoords
& coords
)
2544 if ( m_colWidths
[coords
.GetCol()] <=0 ||
2545 m_rowHeights
[coords
.GetRow()] <= 0 ) return;
2547 dc
.SetPen( wxPen(GetGridLineColour(), 1, wxSOLID
) );
2548 int row
= coords
.GetRow();
2549 int col
= coords
.GetCol();
2551 // right hand border
2553 dc
.DrawLine( m_colRights
[col
], m_rowBottoms
[row
] - m_rowHeights
[row
],
2554 m_colRights
[col
], m_rowBottoms
[row
] );
2558 dc
.DrawLine( m_colRights
[col
] - m_colWidths
[col
], m_rowBottoms
[row
],
2559 m_colRights
[col
], m_rowBottoms
[row
] );
2563 void wxGrid::DrawCellBackground( wxDC
& dc
, const wxGridCellCoords
& coords
)
2565 if ( m_colWidths
[coords
.GetCol()] <=0 ||
2566 m_rowHeights
[coords
.GetRow()] <= 0 ) return;
2568 int row
= coords
.GetRow();
2569 int col
= coords
.GetCol();
2571 dc
.SetBackgroundMode( wxSOLID
);
2573 if ( IsInSelection( coords
) )
2575 // TODO: improve this
2577 dc
.SetBrush( *wxBLACK_BRUSH
);
2581 dc
.SetBrush( wxBrush(GetCellBackgroundColour(row
, col
), wxSOLID
) );
2584 dc
.SetPen( *wxTRANSPARENT_PEN
);
2586 dc
.DrawRectangle( m_colRights
[col
] - m_colWidths
[col
] + 1,
2587 m_rowBottoms
[row
] - m_rowHeights
[row
] + 1,
2589 m_rowHeights
[row
]-1 );
2593 void wxGrid::DrawCellValue( wxDC
& dc
, const wxGridCellCoords
& coords
)
2595 if ( m_colWidths
[coords
.GetCol()] <=0 ||
2596 m_rowHeights
[coords
.GetRow()] <= 0 ) return;
2598 int row
= coords
.GetRow();
2599 int col
= coords
.GetCol();
2601 dc
.SetBackgroundMode( wxTRANSPARENT
);
2603 if ( IsInSelection( row
, col
) )
2605 // TODO: improve this
2607 dc
.SetTextBackground( wxColour(0, 0, 0) );
2608 dc
.SetTextForeground( wxColour(255, 255, 255) );
2612 dc
.SetTextBackground( GetCellBackgroundColour(row
, col
) );
2613 dc
.SetTextForeground( GetCellTextColour(row
, col
) );
2615 dc
.SetFont( GetCellFont(row
, col
) );
2618 GetCellAlignment( row
, col
, &hAlign
, &vAlign
);
2621 rect
.SetX( m_colRights
[col
] - m_colWidths
[col
] + 2 );
2622 rect
.SetY( m_rowBottoms
[row
] - m_rowHeights
[row
] + 2 );
2623 rect
.SetWidth( m_colWidths
[col
] - 4 );
2624 rect
.SetHeight( m_rowHeights
[row
] - 4 );
2626 DrawTextRectangle( dc
, GetCellValue( row
, col
), rect
, hAlign
, vAlign
);
2631 // TODO: remove this ???
2632 // This is used to redraw all grid lines e.g. when the grid line colour
2635 void wxGrid::DrawAllGridLines( wxDC
& dc
)
2637 if ( !m_gridLinesEnabled
||
2639 !m_numCols
) return;
2642 m_gridWin
->GetClientSize(&cw
, &ch
);
2644 // virtual coords of visible area
2646 int top
, bottom
, left
, right
;
2647 CalcUnscrolledPosition( 0, 0, &left
, &top
);
2648 CalcUnscrolledPosition( cw
, ch
, &right
, &bottom
);
2650 dc
.SetPen( wxPen(GetGridLineColour(), 1, wxSOLID
) );
2652 // horizontal grid lines
2655 for ( i
= 0; i
<= m_numRows
; i
++ )
2657 if ( m_rowBottoms
[i
] > bottom
)
2661 else if ( m_rowBottoms
[i
] >= top
)
2663 dc
.DrawLine( left
, m_rowBottoms
[i
], right
, m_rowBottoms
[i
] );
2668 // vertical grid lines
2670 for ( i
= 0; i
<= m_numCols
; i
++ )
2672 if ( m_colRights
[i
] > right
)
2676 else if ( m_colRights
[i
] >= left
)
2678 dc
.DrawLine( m_colRights
[i
], top
, m_colRights
[i
], bottom
);
2684 void wxGrid::DrawRowLabels( wxDC
& dc
)
2686 if ( !m_numRows
|| !m_numCols
) return;
2689 size_t numLabels
= m_rowLabelsExposed
.GetCount();
2691 for ( i
= 0; i
< numLabels
; i
++ )
2693 DrawRowLabel( dc
, m_rowLabelsExposed
[i
] );
2698 void wxGrid::DrawRowLabel( wxDC
& dc
, int row
)
2700 if ( m_rowHeights
[row
] <= 0 ) return;
2702 // draw the label's horizontal border (the vertical border is
2703 // provided by the cell area window margin)
2705 dc
.SetPen( *wxBLACK_PEN
);
2707 dc
.DrawLine( 0, m_rowBottoms
[row
]+1,
2708 m_rowLabelWidth
, m_rowBottoms
[row
]+1 );
2710 dc
.SetPen( *wxWHITE_PEN
);
2712 dc
.DrawLine( 0, m_rowBottoms
[row
]+2,
2713 m_rowLabelWidth
, m_rowBottoms
[row
]+2 );
2715 dc
.SetBackgroundMode( wxTRANSPARENT
);
2716 dc
.SetTextForeground( GetLabelTextColour() );
2717 dc
.SetFont( GetLabelFont() );
2720 GetRowLabelAlignment( &hAlign
, &vAlign
);
2724 rect
.SetY( m_rowBottoms
[row
] - m_rowHeights
[row
] + 2 );
2725 rect
.SetWidth( m_rowLabelWidth
- 4 );
2726 rect
.SetHeight( m_rowHeights
[row
] - 4 );
2727 DrawTextRectangle( dc
, GetRowLabelValue( row
), rect
, hAlign
, vAlign
);
2731 void wxGrid::DrawColLabels( wxDC
& dc
)
2733 if ( !m_numRows
|| !m_numCols
) return;
2736 size_t numLabels
= m_colLabelsExposed
.GetCount();
2738 for ( i
= 0; i
< numLabels
; i
++ )
2740 DrawColLabel( dc
, m_colLabelsExposed
[i
] );
2745 void wxGrid::DrawColLabel( wxDC
& dc
, int col
)
2747 if ( m_colWidths
[col
] <= 0 ) return;
2749 // draw the label's vertical border (the horizontal border is
2750 // provided by the cell area window margin)
2752 dc
.SetPen( *wxBLACK_PEN
);
2754 dc
.DrawLine( m_colRights
[col
]+1, 0,
2755 m_colRights
[col
]+1, m_colLabelHeight
);
2757 dc
.SetPen( *wxWHITE_PEN
);
2759 dc
.DrawLine( m_colRights
[col
]+2, 0,
2760 m_colRights
[col
]+2, m_colLabelHeight
);
2762 dc
.SetBackgroundMode( wxTRANSPARENT
);
2763 dc
.SetTextForeground( GetLabelTextColour() );
2764 dc
.SetFont( GetLabelFont() );
2767 GetColLabelAlignment( &hAlign
, &vAlign
);
2770 rect
.SetX( m_colRights
[col
] - m_colWidths
[col
] + 2 );
2772 rect
.SetWidth( m_colWidths
[col
] - 4 );
2773 rect
.SetHeight( m_colLabelHeight
- 4 );
2774 DrawTextRectangle( dc
, GetColLabelValue( col
), rect
, hAlign
, vAlign
);
2778 void wxGrid::DrawTextRectangle( wxDC
& dc
,
2779 const wxString
& value
,
2784 long textWidth
, textHeight
;
2785 long lineWidth
, lineHeight
;
2786 wxArrayString lines
;
2788 dc
.SetClippingRegion( rect
);
2789 StringToLines( value
, lines
);
2790 if ( lines
.GetCount() )
2792 GetTextBoxSize( dc
, lines
, &textWidth
, &textHeight
);
2793 dc
.GetTextExtent( lines
[0], &lineWidth
, &lineHeight
);
2796 switch ( horizAlign
)
2799 x
= rect
.x
+ (rect
.width
- textWidth
- 1);
2803 x
= rect
.x
+ ((rect
.width
- textWidth
)/2);
2812 switch ( vertAlign
)
2815 y
= rect
.y
+ (rect
.height
- textHeight
- 1);
2819 y
= rect
.y
+ ((rect
.height
- textHeight
)/2);
2828 for ( size_t i
= 0; i
< lines
.GetCount(); i
++ )
2830 dc
.DrawText( lines
[i
], (long)x
, (long)y
);
2835 dc
.DestroyClippingRegion();
2839 // Split multi line text up into an array of strings. Any existing
2840 // contents of the string array are preserved.
2842 void wxGrid::StringToLines( const wxString
& value
, wxArrayString
& lines
)
2844 // TODO: this won't work for WXMAC ? (lines end with '\r')
2845 // => use wxTextFile functions then (VZ)
2848 while ( startPos
< (int)value
.Length() )
2850 pos
= value
.Mid(startPos
).Find( '\n' );
2855 else if ( pos
== 0 )
2857 lines
.Add( wxEmptyString
);
2861 if ( value
[startPos
+pos
-1] == '\r' )
2863 lines
.Add( value
.Mid(startPos
, pos
-1) );
2867 lines
.Add( value
.Mid(startPos
, pos
) );
2872 if ( startPos
< (int)value
.Length() )
2874 lines
.Add( value
.Mid( startPos
) );
2879 void wxGrid::GetTextBoxSize( wxDC
& dc
,
2880 wxArrayString
& lines
,
2881 long *width
, long *height
)
2888 for ( i
= 0; i
< lines
.GetCount(); i
++ )
2890 dc
.GetTextExtent( lines
[i
], &lineW
, &lineH
);
2891 w
= wxMax( w
, lineW
);
2901 // ------ Edit control functions
2905 void wxGrid::EnableEditing( bool edit
)
2907 // TODO: improve this ?
2909 if ( edit
!= m_editable
)
2912 if ( !m_editable
) HideCellEditControl();
2913 m_cellEditCtrlEnabled
= m_editable
;
2914 if ( m_editable
) ShowCellEditControl();
2919 void wxGrid::EnableCellEditControl( bool enable
)
2921 if ( m_cellEditCtrl
&&
2922 enable
!= m_cellEditCtrlEnabled
)
2924 m_cellEditCtrlEnabled
= enable
;
2926 if ( m_cellEditCtrlEnabled
)
2928 SetEditControlValue();
2929 ShowCellEditControl();
2930 // ShowCurrentCellHighlight( dc );
2934 // HideCurrentCellHighlight( dc );
2935 HideCellEditControl();
2936 SaveEditControlValue();
2942 // TODO: not implemented at the moment
2945 void wxGrid::EnableTopEditControl( bool enable
)
2947 // TODO: do we want this here or should the top edit
2948 // control be an add-on class ?
2952 void wxGrid::ShowCellEditControl()
2956 if ( IsCellEditControlEnabled() )
2958 if ( !IsVisible( m_currentCellCoords
) )
2964 rect
= CellToRect( m_currentCellCoords
);
2966 // convert to scrolled coords
2968 int left
, top
, right
, bottom
;
2969 CalcScrolledPosition( rect
.GetLeft(), rect
.GetTop(), &left
, &top
);
2970 CalcScrolledPosition( rect
.GetRight(), rect
.GetBottom(), &right
, &bottom
);
2973 m_gridWin
->GetClientSize( &cw
, &ch
);
2975 rect
.SetLeft( wxMax(0, left
) );
2976 rect
.SetTop( wxMax(0, top
) );
2978 m_cellEditCtrl
->SetSize( rect
);
2979 m_cellEditCtrl
->Show( TRUE
);
2981 switch ( m_editCtrlType
)
2983 case wxGRID_TEXTCTRL
:
2984 ((wxTextCtrl
*) m_cellEditCtrl
)->SetInsertionPointEnd();
2987 case wxGRID_CHECKBOX
:
2988 // TODO: anything ???
2993 // TODO: anything ???
2997 case wxGRID_COMBOBOX
:
2998 // TODO: anything ???
3003 m_cellEditCtrl
->SetFocus();
3009 void wxGrid::HideCellEditControl()
3011 if ( IsCellEditControlEnabled() )
3013 m_cellEditCtrl
->Show( FALSE
);
3018 void wxGrid::SetEditControlValue( const wxString
& value
)
3024 s
= GetCellValue(m_currentCellCoords
);
3028 // TODO: no top edit control implemented at the moment...
3029 // Do we want it in this class ?
3031 if ( IsTopEditControlEnabled() )
3033 switch ( m_editCtrlType
)
3035 case wxGRID_TEXTCTRL
:
3036 ((wxGridTextCtrl
*)m_topEditCtrl
)->SetStartValue(s
);
3039 case wxGRID_CHECKBOX
:
3040 // TODO: implement this
3045 // TODO: implement this
3049 case wxGRID_COMBOBOX
:
3050 // TODO: implement this
3056 if ( IsCellEditControlEnabled() )
3058 switch ( m_editCtrlType
)
3060 case wxGRID_TEXTCTRL
:
3061 ((wxGridTextCtrl
*)m_cellEditCtrl
)->SetStartValue(s
);
3064 case wxGRID_CHECKBOX
:
3065 // TODO: implement this
3070 // TODO: implement this
3074 case wxGRID_COMBOBOX
:
3075 // TODO: implement this
3084 void wxGrid::SaveEditControlValue()
3088 wxWindow
*ctrl
= (wxWindow
*)NULL
;
3090 if ( IsCellEditControlEnabled() )
3092 ctrl
= m_cellEditCtrl
;
3094 else if ( IsTopEditControlEnabled() )
3096 ctrl
= m_topEditCtrl
;
3103 bool valueChanged
= FALSE
;
3105 switch ( m_editCtrlType
)
3107 case wxGRID_TEXTCTRL
:
3108 valueChanged
= (((wxGridTextCtrl
*)ctrl
)->GetValue() !=
3109 ((wxGridTextCtrl
*)ctrl
)->GetStartValue());
3110 SetCellValue( m_currentCellCoords
,
3111 ((wxTextCtrl
*) ctrl
)->GetValue() );
3114 case wxGRID_CHECKBOX
:
3115 // TODO: implement this
3120 // TODO: implement this
3124 case wxGRID_COMBOBOX
:
3125 // TODO: implement this
3132 SendEvent( EVT_GRID_CELL_CHANGE
,
3133 m_currentCellCoords
.GetRow(),
3134 m_currentCellCoords
.GetCol() );
3141 // ------ Grid location functions
3142 // Note that all of these functions work with the logical coordinates of
3143 // grid cells and labels so you will need to convert from device
3144 // coordinates for mouse events etc.
3147 void wxGrid::XYToCell( int x
, int y
, wxGridCellCoords
& coords
)
3149 coords
.SetRow( YToRow(y
) );
3150 coords
.SetCol( XToCol(x
) );
3154 int wxGrid::YToRow( int y
)
3158 for ( i
= 0; i
< m_numRows
; i
++ )
3160 if ( y
< m_rowBottoms
[i
] ) return i
;
3167 int wxGrid::XToCol( int x
)
3171 for ( i
= 0; i
< m_numCols
; i
++ )
3173 if ( x
< m_colRights
[i
] ) return i
;
3180 // return the row number that that the y coord is near the edge of, or
3181 // -1 if not near an edge
3183 int wxGrid::YToEdgeOfRow( int y
)
3187 for ( i
= 0; i
< m_numRows
; i
++ )
3189 if ( m_rowHeights
[i
] > WXGRID_LABEL_EDGE_ZONE
)
3191 d
= abs( y
- m_rowBottoms
[i
] );
3193 if ( d
< WXGRID_LABEL_EDGE_ZONE
) return i
;
3202 // return the col number that that the x coord is near the edge of, or
3203 // -1 if not near an edge
3205 int wxGrid::XToEdgeOfCol( int x
)
3209 for ( i
= 0; i
< m_numCols
; i
++ )
3211 if ( m_colWidths
[i
] > WXGRID_LABEL_EDGE_ZONE
)
3213 d
= abs( x
- m_colRights
[i
] );
3215 if ( d
< WXGRID_LABEL_EDGE_ZONE
) return i
;
3224 wxRect
wxGrid::CellToRect( int row
, int col
)
3226 wxRect
rect( -1, -1, -1, -1 );
3228 if ( row
>= 0 && row
< m_numRows
&&
3229 col
>= 0 && col
< m_numCols
)
3231 rect
.x
= m_colRights
[col
] - m_colWidths
[col
];
3232 rect
.y
= m_rowBottoms
[row
] - m_rowHeights
[row
];
3233 rect
.width
= m_colWidths
[col
];
3234 rect
.height
= m_rowHeights
[ row
];
3241 bool wxGrid::IsVisible( int row
, int col
, bool wholeCellVisible
)
3243 // get the cell rectangle in logical coords
3245 wxRect
r( CellToRect( row
, col
) );
3247 // convert to device coords
3249 int left
, top
, right
, bottom
;
3250 CalcScrolledPosition( r
.GetLeft(), r
.GetTop(), &left
, &top
);
3251 CalcScrolledPosition( r
.GetRight(), r
.GetBottom(), &right
, &bottom
);
3253 // check against the client area of the grid window
3256 m_gridWin
->GetClientSize( &cw
, &ch
);
3258 if ( wholeCellVisible
)
3260 // is the cell wholly visible ?
3262 return ( left
>= 0 && right
<= cw
&&
3263 top
>= 0 && bottom
<= ch
);
3267 // is the cell partly visible ?
3269 return ( ((left
>=0 && left
< cw
) || (right
> 0 && right
<= cw
)) &&
3270 ((top
>=0 && top
< ch
) || (bottom
> 0 && bottom
<= ch
)) );
3275 // make the specified cell location visible by doing a minimal amount
3278 void wxGrid::MakeCellVisible( int row
, int col
)
3281 int xpos
= -1, ypos
= -1;
3283 if ( row
>= 0 && row
< m_numRows
&&
3284 col
>= 0 && col
< m_numCols
)
3286 // get the cell rectangle in logical coords
3288 wxRect
r( CellToRect( row
, col
) );
3290 // convert to device coords
3292 int left
, top
, right
, bottom
;
3293 CalcScrolledPosition( r
.GetLeft(), r
.GetTop(), &left
, &top
);
3294 CalcScrolledPosition( r
.GetRight(), r
.GetBottom(), &right
, &bottom
);
3297 m_gridWin
->GetClientSize( &cw
, &ch
);
3303 else if ( bottom
> ch
)
3305 int h
= r
.GetHeight();
3307 for ( i
= row
-1; i
>= 0; i
-- )
3309 if ( h
+ m_rowHeights
[i
] > ch
) break;
3311 h
+= m_rowHeights
[i
];
3312 ypos
-= m_rowHeights
[i
];
3320 else if ( right
> cw
)
3322 int w
= r
.GetWidth();
3324 for ( i
= col
-1; i
>= 0; i
-- )
3326 if ( w
+ m_colWidths
[i
] > cw
) break;
3328 w
+= m_colWidths
[i
];
3329 xpos
-= m_colWidths
[i
];
3333 if ( xpos
!= -1 || ypos
!= -1 )
3335 if ( xpos
!= -1 ) xpos
= xpos
/10;
3336 if ( ypos
!= -1 ) ypos
= ypos
/10;
3337 Scroll( xpos
, ypos
);
3345 // ------ Grid cursor movement functions
3348 bool wxGrid::MoveCursorUp()
3350 if ( m_currentCellCoords
!= wxGridNoCellCoords
&&
3351 m_currentCellCoords
.GetRow() > 0 )
3353 MakeCellVisible( m_currentCellCoords
.GetRow() - 1,
3354 m_currentCellCoords
.GetCol() );
3356 SetCurrentCell( m_currentCellCoords
.GetRow() - 1,
3357 m_currentCellCoords
.GetCol() );
3366 bool wxGrid::MoveCursorDown()
3368 // TODO: allow for scrolling
3370 if ( m_currentCellCoords
!= wxGridNoCellCoords
&&
3371 m_currentCellCoords
.GetRow() < m_numRows
-1 )
3373 MakeCellVisible( m_currentCellCoords
.GetRow() + 1,
3374 m_currentCellCoords
.GetCol() );
3376 SetCurrentCell( m_currentCellCoords
.GetRow() + 1,
3377 m_currentCellCoords
.GetCol() );
3386 bool wxGrid::MoveCursorLeft()
3388 if ( m_currentCellCoords
!= wxGridNoCellCoords
&&
3389 m_currentCellCoords
.GetCol() > 0 )
3391 MakeCellVisible( m_currentCellCoords
.GetRow(),
3392 m_currentCellCoords
.GetCol() - 1 );
3394 SetCurrentCell( m_currentCellCoords
.GetRow(),
3395 m_currentCellCoords
.GetCol() - 1 );
3404 bool wxGrid::MoveCursorRight()
3406 if ( m_currentCellCoords
!= wxGridNoCellCoords
&&
3407 m_currentCellCoords
.GetCol() < m_numCols
- 1 )
3409 MakeCellVisible( m_currentCellCoords
.GetRow(),
3410 m_currentCellCoords
.GetCol() + 1 );
3412 SetCurrentCell( m_currentCellCoords
.GetRow(),
3413 m_currentCellCoords
.GetCol() + 1 );
3422 bool wxGrid::MovePageUp()
3424 if ( m_currentCellCoords
== wxGridNoCellCoords
) return FALSE
;
3426 int row
= m_currentCellCoords
.GetRow();
3430 m_gridWin
->GetClientSize( &cw
, &ch
);
3432 int y
= m_rowBottoms
[ row
] - m_rowHeights
[ row
];
3433 int newRow
= YToRow( y
- ch
+ 1 );
3438 else if ( newRow
== row
)
3443 MakeCellVisible( newRow
, m_currentCellCoords
.GetCol() );
3444 SetCurrentCell( newRow
, m_currentCellCoords
.GetCol() );
3452 bool wxGrid::MovePageDown()
3454 if ( m_currentCellCoords
== wxGridNoCellCoords
) return FALSE
;
3456 int row
= m_currentCellCoords
.GetRow();
3457 if ( row
< m_numRows
)
3460 m_gridWin
->GetClientSize( &cw
, &ch
);
3462 int y
= m_rowBottoms
[ row
] - m_rowHeights
[ row
];
3463 int newRow
= YToRow( y
+ ch
);
3466 newRow
= m_numRows
- 1;
3468 else if ( newRow
== row
)
3473 MakeCellVisible( newRow
, m_currentCellCoords
.GetCol() );
3474 SetCurrentCell( newRow
, m_currentCellCoords
.GetCol() );
3482 bool wxGrid::MoveCursorUpBlock()
3485 m_currentCellCoords
!= wxGridNoCellCoords
&&
3486 m_currentCellCoords
.GetRow() > 0 )
3488 int row
= m_currentCellCoords
.GetRow();
3489 int col
= m_currentCellCoords
.GetCol();
3491 if ( m_table
->IsEmptyCell(row
, col
) )
3493 // starting in an empty cell: find the next block of
3499 if ( !(m_table
->IsEmptyCell(row
, col
)) ) break;
3502 else if ( m_table
->IsEmptyCell(row
-1, col
) )
3504 // starting at the top of a block: find the next block
3510 if ( !(m_table
->IsEmptyCell(row
, col
)) ) break;
3515 // starting within a block: find the top of the block
3520 if ( m_table
->IsEmptyCell(row
, col
) )
3528 MakeCellVisible( row
, col
);
3529 SetCurrentCell( row
, col
);
3537 bool wxGrid::MoveCursorDownBlock()
3540 m_currentCellCoords
!= wxGridNoCellCoords
&&
3541 m_currentCellCoords
.GetRow() < m_numRows
-1 )
3543 int row
= m_currentCellCoords
.GetRow();
3544 int col
= m_currentCellCoords
.GetCol();
3546 if ( m_table
->IsEmptyCell(row
, col
) )
3548 // starting in an empty cell: find the next block of
3551 while ( row
< m_numRows
-1 )
3554 if ( !(m_table
->IsEmptyCell(row
, col
)) ) break;
3557 else if ( m_table
->IsEmptyCell(row
+1, col
) )
3559 // starting at the bottom of a block: find the next block
3562 while ( row
< m_numRows
-1 )
3565 if ( !(m_table
->IsEmptyCell(row
, col
)) ) break;
3570 // starting within a block: find the bottom of the block
3572 while ( row
< m_numRows
-1 )
3575 if ( m_table
->IsEmptyCell(row
, col
) )
3583 MakeCellVisible( row
, col
);
3584 SetCurrentCell( row
, col
);
3592 bool wxGrid::MoveCursorLeftBlock()
3595 m_currentCellCoords
!= wxGridNoCellCoords
&&
3596 m_currentCellCoords
.GetCol() > 0 )
3598 int row
= m_currentCellCoords
.GetRow();
3599 int col
= m_currentCellCoords
.GetCol();
3601 if ( m_table
->IsEmptyCell(row
, col
) )
3603 // starting in an empty cell: find the next block of
3609 if ( !(m_table
->IsEmptyCell(row
, col
)) ) break;
3612 else if ( m_table
->IsEmptyCell(row
, col
-1) )
3614 // starting at the left of a block: find the next block
3620 if ( !(m_table
->IsEmptyCell(row
, col
)) ) break;
3625 // starting within a block: find the left of the block
3630 if ( m_table
->IsEmptyCell(row
, col
) )
3638 MakeCellVisible( row
, col
);
3639 SetCurrentCell( row
, col
);
3647 bool wxGrid::MoveCursorRightBlock()
3650 m_currentCellCoords
!= wxGridNoCellCoords
&&
3651 m_currentCellCoords
.GetCol() < m_numCols
-1 )
3653 int row
= m_currentCellCoords
.GetRow();
3654 int col
= m_currentCellCoords
.GetCol();
3656 if ( m_table
->IsEmptyCell(row
, col
) )
3658 // starting in an empty cell: find the next block of
3661 while ( col
< m_numCols
-1 )
3664 if ( !(m_table
->IsEmptyCell(row
, col
)) ) break;
3667 else if ( m_table
->IsEmptyCell(row
, col
+1) )
3669 // starting at the right of a block: find the next block
3672 while ( col
< m_numCols
-1 )
3675 if ( !(m_table
->IsEmptyCell(row
, col
)) ) break;
3680 // starting within a block: find the right of the block
3682 while ( col
< m_numCols
-1 )
3685 if ( m_table
->IsEmptyCell(row
, col
) )
3693 MakeCellVisible( row
, col
);
3694 SetCurrentCell( row
, col
);
3705 // ------ Label values and formatting
3708 void wxGrid::GetRowLabelAlignment( int *horiz
, int *vert
)
3710 *horiz
= m_rowLabelHorizAlign
;
3711 *vert
= m_rowLabelVertAlign
;
3714 void wxGrid::GetColLabelAlignment( int *horiz
, int *vert
)
3716 *horiz
= m_colLabelHorizAlign
;
3717 *vert
= m_colLabelVertAlign
;
3720 wxString
wxGrid::GetRowLabelValue( int row
)
3724 return m_table
->GetRowLabelValue( row
);
3734 wxString
wxGrid::GetColLabelValue( int col
)
3738 return m_table
->GetColLabelValue( col
);
3748 void wxGrid::SetRowLabelSize( int width
)
3750 // TODO: how to do this with the box sizers ?
3753 void wxGrid::SetColLabelSize( int height
)
3755 // TODO: how to do this with the box sizers ?
3758 void wxGrid::SetLabelBackgroundColour( const wxColour
& colour
)
3760 if ( m_labelBackgroundColour
!= colour
)
3762 m_labelBackgroundColour
= colour
;
3763 m_rowLabelWin
->SetBackgroundColour( colour
);
3764 m_colLabelWin
->SetBackgroundColour( colour
);
3765 m_cornerLabelWin
->SetBackgroundColour( colour
);
3767 if ( !GetBatchCount() )
3769 m_rowLabelWin
->Refresh();
3770 m_colLabelWin
->Refresh();
3771 m_cornerLabelWin
->Refresh();
3776 void wxGrid::SetLabelTextColour( const wxColour
& colour
)
3778 if ( m_labelTextColour
!= colour
)
3780 m_labelTextColour
= colour
;
3781 if ( !GetBatchCount() )
3783 m_rowLabelWin
->Refresh();
3784 m_colLabelWin
->Refresh();
3789 void wxGrid::SetLabelFont( const wxFont
& font
)
3792 if ( !GetBatchCount() )
3794 m_rowLabelWin
->Refresh();
3795 m_colLabelWin
->Refresh();
3799 void wxGrid::SetRowLabelAlignment( int horiz
, int vert
)
3801 if ( horiz
== wxLEFT
|| horiz
== wxCENTRE
|| horiz
== wxRIGHT
)
3803 m_rowLabelHorizAlign
= horiz
;
3806 if ( vert
== wxTOP
|| vert
== wxCENTRE
|| vert
== wxBOTTOM
)
3808 m_rowLabelVertAlign
= vert
;
3811 if ( !GetBatchCount() )
3813 m_rowLabelWin
->Refresh();
3814 m_colLabelWin
->Refresh();
3818 void wxGrid::SetColLabelAlignment( int horiz
, int vert
)
3820 if ( horiz
== wxLEFT
|| horiz
== wxCENTRE
|| horiz
== wxRIGHT
)
3822 m_colLabelHorizAlign
= horiz
;
3825 if ( vert
== wxTOP
|| vert
== wxCENTRE
|| vert
== wxBOTTOM
)
3827 m_colLabelVertAlign
= vert
;
3830 if ( !GetBatchCount() )
3832 m_rowLabelWin
->Refresh();
3833 m_colLabelWin
->Refresh();
3837 void wxGrid::SetRowLabelValue( int row
, const wxString
& s
)
3841 m_table
->SetRowLabelValue( row
, s
);
3842 if ( !GetBatchCount() )
3844 // TODO: Optimize this
3846 m_rowLabelWin
->Refresh();
3851 void wxGrid::SetColLabelValue( int col
, const wxString
& s
)
3855 m_table
->SetColLabelValue( col
, s
);
3856 if ( !GetBatchCount() )
3858 // TODO: optimize this
3860 m_colLabelWin
->Refresh();
3865 void wxGrid::SetGridLineColour( const wxColour
& colour
)
3867 if ( m_gridLineColour
!= colour
)
3869 m_gridLineColour
= colour
;
3871 wxClientDC
dc( m_gridWin
);
3873 DrawAllGridLines( dc
);
3877 void wxGrid::EnableGridLines( bool enable
)
3879 if ( enable
!= m_gridLinesEnabled
)
3881 m_gridLinesEnabled
= enable
;
3883 if ( !GetBatchCount() )
3887 wxClientDC
dc( m_gridWin
);
3889 DrawAllGridLines( dc
);
3893 m_gridWin
->Refresh();
3900 int wxGrid::GetDefaultRowSize()
3902 return m_defaultRowHeight
;
3905 int wxGrid::GetRowSize( int row
)
3907 if ( row
>= 0 && row
< m_numRows
)
3908 return m_rowHeights
[row
];
3910 return 0; // TODO: log an error here
3913 int wxGrid::GetDefaultColSize()
3915 return m_defaultColWidth
;
3918 int wxGrid::GetColSize( int col
)
3920 if ( col
>= 0 && col
< m_numCols
)
3921 return m_colWidths
[col
];
3923 return 0; // TODO: log an error here
3926 wxColour
wxGrid::GetDefaultCellBackgroundColour()
3928 // TODO: replace this temp test code
3930 return wxColour( 255, 255, 255 );
3933 wxColour
wxGrid::GetCellBackgroundColour( int WXUNUSED(row
), int WXUNUSED(col
) )
3935 // TODO: replace this temp test code
3937 return wxColour( 255, 255, 255 );
3940 wxColour
wxGrid::GetDefaultCellTextColour()
3942 // TODO: replace this temp test code
3944 return wxColour( 0, 0, 0 );
3947 wxColour
wxGrid::GetCellTextColour( int WXUNUSED(row
), int WXUNUSED(col
) )
3949 // TODO: replace this temp test code
3951 return wxColour( 0, 0, 0 );
3955 wxColour
wxGrid::GetCellHighlightColour()
3957 // TODO: replace this temp test code
3959 return wxColour( 0, 0, 0 );
3963 wxFont
wxGrid::GetDefaultCellFont()
3965 return m_defaultCellFont
;
3968 wxFont
wxGrid::GetCellFont( int WXUNUSED(row
), int WXUNUSED(col
) )
3970 // TODO: replace this temp test code
3972 return m_defaultCellFont
;
3975 void wxGrid::GetDefaultCellAlignment( int *horiz
, int *vert
)
3977 // TODO: replace this temp test code
3983 void wxGrid::GetCellAlignment( int WXUNUSED(row
), int WXUNUSED(col
), int *horiz
, int *vert
)
3985 // TODO: replace this temp test code
3991 void wxGrid::SetDefaultRowSize( int height
, bool resizeExistingRows
)
3993 m_defaultRowHeight
= wxMax( height
, WXGRID_MIN_ROW_HEIGHT
);
3995 if ( resizeExistingRows
)
3999 for ( row
= 0; row
< m_numRows
; row
++ )
4001 m_rowHeights
[row
] = m_defaultRowHeight
;
4002 bottom
+= m_defaultRowHeight
;
4003 m_rowBottoms
[row
] = bottom
;
4009 void wxGrid::SetRowSize( int row
, int height
)
4013 if ( row
>= 0 && row
< m_numRows
)
4015 int h
= wxMax( 0, height
);
4016 int diff
= h
- m_rowHeights
[row
];
4018 m_rowHeights
[row
] = h
;
4019 for ( i
= row
; i
< m_numRows
; i
++ )
4021 m_rowBottoms
[i
] += diff
;
4025 // Note: we are ending the event *after* doing
4026 // default processing in this case
4028 SendEvent( EVT_GRID_ROW_SIZE
,
4033 // TODO: log an error here
4037 void wxGrid::SetDefaultColSize( int width
, bool resizeExistingCols
)
4039 m_defaultColWidth
= wxMax( width
, WXGRID_MIN_COL_WIDTH
);
4041 if ( resizeExistingCols
)
4045 for ( col
= 0; col
< m_numCols
; col
++ )
4047 m_colWidths
[col
] = m_defaultColWidth
;
4048 right
+= m_defaultColWidth
;
4049 m_colRights
[col
] = right
;
4055 void wxGrid::SetColSize( int col
, int width
)
4059 if ( col
>= 0 && col
< m_numCols
)
4061 int w
= wxMax( 0, width
);
4062 int diff
= w
- m_colWidths
[col
];
4063 m_colWidths
[col
] = w
;
4065 for ( i
= col
; i
< m_numCols
; i
++ )
4067 m_colRights
[i
] += diff
;
4071 // Note: we are ending the event *after* doing
4072 // default processing in this case
4074 SendEvent( EVT_GRID_COL_SIZE
,
4079 // TODO: log an error here
4083 void wxGrid::SetDefaultCellBackgroundColour( const wxColour
& )
4085 // TODO: everything !!!
4089 void wxGrid::SetCellBackgroundColour( int WXUNUSED(row
), int WXUNUSED(col
), const wxColour
& )
4091 // TODO: everything !!!
4095 void wxGrid::SetDefaultCellTextColour( const wxColour
& )
4097 // TODO: everything !!!
4101 void wxGrid::SetCellTextColour( int WXUNUSED(row
), int WXUNUSED(col
), const wxColour
& )
4103 // TODO: everything !!!
4107 void wxGrid::SetCellHighlightColour( const wxColour
& )
4109 // TODO: everything !!!
4113 void wxGrid::SetDefaultCellFont( const wxFont
& )
4115 // TODO: everything !!!
4119 void wxGrid::SetCellFont( int WXUNUSED(row
), int WXUNUSED(col
), const wxFont
& )
4121 // TODO: everything !!!
4125 void wxGrid::SetDefaultCellAlignment( int WXUNUSED(horiz
), int WXUNUSED(vert
) )
4127 // TODO: everything !!!
4131 void wxGrid::SetCellAlignment( int WXUNUSED(row
), int WXUNUSED(col
), int WXUNUSED(horiz
), int WXUNUSED(vert
) )
4133 // TODO: everything !!!
4140 // ------ cell value accessor functions
4143 void wxGrid::SetCellValue( int row
, int col
, const wxString
& s
)
4147 m_table
->SetValue( row
, col
, s
.c_str() );
4148 if ( !GetBatchCount() )
4150 wxClientDC
dc( m_gridWin
);
4152 DrawCell( dc
, wxGridCellCoords(row
, col
) );
4155 #if 0 // TODO: edit in place
4157 if ( m_currentCellCoords
.GetRow() == row
&&
4158 m_currentCellCoords
.GetCol() == col
)
4160 SetEditControlValue( s
);
4169 // ------ Block, row and col selection
4172 void wxGrid::SelectRow( int row
, bool addToSelected
)
4176 if ( IsSelection() && addToSelected
)
4178 if ( m_selectedTopLeft
.GetRow() > row
)
4179 m_selectedTopLeft
.SetRow( row
);
4181 m_selectedTopLeft
.SetCol( 0 );
4183 if ( m_selectedBottomRight
.GetRow() < row
)
4184 m_selectedBottomRight
.SetRow( row
);
4186 m_selectedBottomRight
.SetCol( m_numCols
- 1 );
4188 // TODO: optimize this so that we only refresh the newly
4191 r
= SelectionToDeviceRect();
4192 if ( r
!= wxGridNoCellRect
) m_gridWin
->Refresh( TRUE
, &r
);
4196 r
= SelectionToDeviceRect();
4198 if ( r
!= wxGridNoCellRect
) m_gridWin
->Refresh( TRUE
, &r
);
4200 m_selectedTopLeft
.Set( row
, 0 );
4201 m_selectedBottomRight
.Set( row
, m_numCols
-1 );
4202 r
= SelectionToDeviceRect();
4203 m_gridWin
->Refresh( TRUE
, &r
);
4206 wxGridRangeSelectEvent
gridEvt( GetId(),
4207 EVT_GRID_RANGE_SELECT
,
4210 m_selectedBottomRight
);
4212 GetEventHandler()->ProcessEvent(gridEvt
);
4216 void wxGrid::SelectCol( int col
, bool addToSelected
)
4220 if ( IsSelection() && addToSelected
)
4222 if ( m_selectedTopLeft
.GetCol() > col
)
4223 m_selectedTopLeft
.SetCol( col
);
4225 m_selectedTopLeft
.SetRow( 0 );
4227 if ( m_selectedBottomRight
.GetCol() < col
)
4228 m_selectedBottomRight
.SetCol( col
);
4230 m_selectedBottomRight
.SetRow( m_numRows
- 1 );
4232 // TODO: optimize this so that we only refresh the newly
4235 r
= SelectionToDeviceRect();
4236 if ( r
!= wxGridNoCellRect
) m_gridWin
->Refresh( TRUE
, &r
);
4240 r
= SelectionToDeviceRect();
4242 if ( r
!= wxGridNoCellRect
) m_gridWin
->Refresh( TRUE
, &r
);
4244 m_selectedTopLeft
.Set( 0, col
);
4245 m_selectedBottomRight
.Set( m_numRows
-1, col
);
4246 r
= SelectionToDeviceRect();
4247 m_gridWin
->Refresh( TRUE
, &r
);
4250 wxGridRangeSelectEvent
gridEvt( GetId(),
4251 EVT_GRID_RANGE_SELECT
,
4254 m_selectedBottomRight
);
4256 GetEventHandler()->ProcessEvent(gridEvt
);
4260 void wxGrid::SelectBlock( int topRow
, int leftCol
, int bottomRow
, int rightCol
)
4264 if ( topRow
> bottomRow
)
4271 if ( leftCol
> rightCol
)
4278 m_selectedTopLeft
.Set( topRow
, leftCol
);
4279 m_selectedBottomRight
.Set( bottomRow
, rightCol
);
4282 r
= SelectionToDeviceRect();
4283 m_gridWin
->Refresh( TRUE
, &r
);
4285 // only generate an event if the block is not being selected by
4286 // dragging the mouse (in which case the event will be generated in
4287 // the mouse event handler)
4288 if ( !m_isDragging
)
4290 wxGridRangeSelectEvent
gridEvt( GetId(),
4291 EVT_GRID_RANGE_SELECT
,
4294 m_selectedBottomRight
);
4296 GetEventHandler()->ProcessEvent(gridEvt
);
4300 void wxGrid::SelectAll()
4302 m_selectedTopLeft
.Set( 0, 0 );
4303 m_selectedBottomRight
.Set( m_numRows
-1, m_numCols
-1 );
4305 m_gridWin
->Refresh();
4309 void wxGrid::ClearSelection()
4311 m_selectedTopLeft
= wxGridNoCellCoords
;
4312 m_selectedBottomRight
= wxGridNoCellCoords
;
4316 // This function returns the rectangle that encloses the selected cells
4317 // in device coords clipped to the client size of the grid window.
4319 wxRect
wxGrid::SelectionToDeviceRect()
4324 if ( IsSelection() )
4326 cellRect
= CellToRect( m_selectedTopLeft
);
4327 if ( cellRect
!= wxGridNoCellRect
)
4333 rect
= wxRect( 0, 0, 0, 0 );
4336 cellRect
= CellToRect( m_selectedBottomRight
);
4337 if ( cellRect
!= wxGridNoCellRect
)
4343 return wxGridNoCellRect
;
4346 // convert to scrolled coords
4348 int left
, top
, right
, bottom
;
4349 CalcScrolledPosition( rect
.GetLeft(), rect
.GetTop(), &left
, &top
);
4350 CalcScrolledPosition( rect
.GetRight(), rect
.GetBottom(), &right
, &bottom
);
4353 m_gridWin
->GetClientSize( &cw
, &ch
);
4355 rect
.SetLeft( wxMax(0, left
) );
4356 rect
.SetTop( wxMax(0, top
) );
4357 rect
.SetRight( wxMin(cw
, right
) );
4358 rect
.SetBottom( wxMin(ch
, bottom
) );
4362 return wxGridNoCellRect
;
4370 // ------ Grid event classes
4373 IMPLEMENT_DYNAMIC_CLASS( wxGridEvent
, wxEvent
)
4375 wxGridEvent::wxGridEvent( int id
, wxEventType type
, wxObject
* obj
,
4376 int row
, int col
, int x
, int y
,
4377 bool control
, bool shift
, bool alt
, bool meta
)
4378 : wxNotifyEvent( type
, id
)
4384 m_control
= control
;
4389 SetEventObject(obj
);
4393 IMPLEMENT_DYNAMIC_CLASS( wxGridSizeEvent
, wxEvent
)
4395 wxGridSizeEvent::wxGridSizeEvent( int id
, wxEventType type
, wxObject
* obj
,
4396 int rowOrCol
, int x
, int y
,
4397 bool control
, bool shift
, bool alt
, bool meta
)
4398 : wxNotifyEvent( type
, id
)
4400 m_rowOrCol
= rowOrCol
;
4403 m_control
= control
;
4408 SetEventObject(obj
);
4412 IMPLEMENT_DYNAMIC_CLASS( wxGridRangeSelectEvent
, wxEvent
)
4414 wxGridRangeSelectEvent::wxGridRangeSelectEvent(int id
, wxEventType type
, wxObject
* obj
,
4415 const wxGridCellCoords
& topLeft
,
4416 const wxGridCellCoords
& bottomRight
,
4417 bool control
, bool shift
, bool alt
, bool meta
)
4418 : wxNotifyEvent( type
, id
)
4420 m_topLeft
= topLeft
;
4421 m_bottomRight
= bottomRight
;
4422 m_control
= control
;
4427 SetEventObject(obj
);
4431 #endif // ifndef wxUSE_NEW_GRID