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"
39 //////////////////////////////////////////////////////////////////////
41 wxGridCellCoords
wxGridNoCellCoords( -1, -1 );
42 wxRect
wxGridNoCellRect( -1, -1, -1, -1 );
44 // this is a magic incantation which must be done!
45 #include "wx/arrimpl.cpp"
47 WX_DEFINE_OBJARRAY(wxGridCellCoordsArray
)
50 // TODO: fixed so far - make configurable later (and also different for x/y)
51 static const size_t GRID_SCROLL_LINE
= 10;
53 //////////////////////////////////////////////////////////////////////
55 // Abstract base class for grid data (the model)
57 IMPLEMENT_ABSTRACT_CLASS( wxGridTableBase
, wxObject
)
60 wxGridTableBase::wxGridTableBase()
63 m_view
= (wxGrid
*) NULL
;
66 wxGridTableBase::~wxGridTableBase()
71 bool wxGridTableBase::InsertRows( size_t pos
, size_t numRows
)
73 wxLogWarning( wxT("Called grid table class function InsertRows(pos=%d, N=%d)\n"
74 "but your derived table class does not override this function"),
80 bool wxGridTableBase::AppendRows( size_t numRows
)
82 wxLogWarning( wxT("Called grid table class function AppendRows(N=%d)\n"
83 "but your derived table class does not override this function"),
89 bool wxGridTableBase::DeleteRows( size_t pos
, size_t numRows
)
91 wxLogWarning( wxT("Called grid table class function DeleteRows(pos=%d, N=%d)\n"
92 "but your derived table class does not override this function"),
98 bool wxGridTableBase::InsertCols( size_t pos
, size_t numCols
)
100 wxLogWarning( wxT("Called grid table class function InsertCols(pos=%d, N=%d)\n"
101 "but your derived table class does not override this function"),
107 bool wxGridTableBase::AppendCols( size_t numCols
)
109 wxLogWarning( wxT("Called grid table class function AppendCols(N=%d)\n"
110 "but your derived table class does not override this function"),
116 bool wxGridTableBase::DeleteCols( size_t pos
, size_t numCols
)
118 wxLogWarning( wxT("Called grid table class function DeleteCols(pos=%d, N=%d)\n"
119 "but your derived table class does not override this function"),
126 wxString
wxGridTableBase::GetRowLabelValue( int row
)
133 wxString
wxGridTableBase::GetColLabelValue( int col
)
135 // default col labels are:
136 // cols 0 to 25 : A-Z
137 // cols 26 to 675 : AA-ZZ
144 s
+= (_T('A') + (wxChar
)( col%26
));
146 if ( col
< 0 ) break;
149 // reverse the string...
151 for ( i
= 0; i
< n
; i
++ )
161 //////////////////////////////////////////////////////////////////////
163 // Message class for the grid table to send requests and notifications
167 wxGridTableMessage::wxGridTableMessage()
169 m_table
= (wxGridTableBase
*) NULL
;
175 wxGridTableMessage::wxGridTableMessage( wxGridTableBase
*table
, int id
,
176 int commandInt1
, int commandInt2
)
180 m_comInt1
= commandInt1
;
181 m_comInt2
= commandInt2
;
186 //////////////////////////////////////////////////////////////////////
188 // A basic grid table for string data. An object of this class will
189 // created by wxGrid if you don't specify an alternative table class.
192 WX_DEFINE_OBJARRAY(wxGridStringArray
)
194 IMPLEMENT_DYNAMIC_CLASS( wxGridStringTable
, wxGridTableBase
)
196 wxGridStringTable::wxGridStringTable()
201 wxGridStringTable::wxGridStringTable( int numRows
, int numCols
)
206 m_data
.Alloc( numRows
);
210 for ( col
= 0; col
< numCols
; col
++ )
212 sa
.Add( wxEmptyString
);
215 for ( row
= 0; row
< numRows
; row
++ )
221 wxGridStringTable::~wxGridStringTable()
225 long wxGridStringTable::GetNumberRows()
227 return m_data
.GetCount();
230 long wxGridStringTable::GetNumberCols()
232 if ( m_data
.GetCount() > 0 )
233 return m_data
[0].GetCount();
238 wxString
wxGridStringTable::GetValue( int row
, int col
)
240 // TODO: bounds checking
242 return m_data
[row
][col
];
245 void wxGridStringTable::SetValue( int row
, int col
, const wxString
& s
)
247 // TODO: bounds checking
249 m_data
[row
][col
] = s
;
252 bool wxGridStringTable::IsEmptyCell( int row
, int col
)
254 // TODO: bounds checking
256 return (m_data
[row
][col
] == wxEmptyString
);
260 void wxGridStringTable::Clear()
263 int numRows
, numCols
;
265 numRows
= m_data
.GetCount();
268 numCols
= m_data
[0].GetCount();
270 for ( row
= 0; row
< numRows
; row
++ )
272 for ( col
= 0; col
< numCols
; col
++ )
274 m_data
[row
][col
] = wxEmptyString
;
281 bool wxGridStringTable::InsertRows( size_t pos
, size_t numRows
)
285 size_t curNumRows
= m_data
.GetCount();
286 size_t curNumCols
= ( curNumRows
> 0 ? m_data
[0].GetCount() : 0 );
288 if ( pos
>= curNumRows
)
290 return AppendRows( numRows
);
294 sa
.Alloc( curNumCols
);
295 for ( col
= 0; col
< curNumCols
; col
++ )
297 sa
.Add( wxEmptyString
);
300 for ( row
= pos
; row
< pos
+ numRows
; row
++ )
302 m_data
.Insert( sa
, row
);
307 wxGridTableMessage
msg( this,
308 wxGRIDTABLE_NOTIFY_ROWS_INSERTED
,
312 GetView()->ProcessTableMessage( msg
);
318 bool wxGridStringTable::AppendRows( size_t numRows
)
322 size_t curNumRows
= m_data
.GetCount();
323 size_t curNumCols
= ( curNumRows
> 0 ? m_data
[0].GetCount() : 0 );
326 if ( curNumCols
> 0 )
328 sa
.Alloc( curNumCols
);
329 for ( col
= 0; col
< curNumCols
; col
++ )
331 sa
.Add( wxEmptyString
);
335 for ( row
= 0; row
< numRows
; row
++ )
342 wxGridTableMessage
msg( this,
343 wxGRIDTABLE_NOTIFY_ROWS_APPENDED
,
346 GetView()->ProcessTableMessage( msg
);
352 bool wxGridStringTable::DeleteRows( size_t pos
, size_t numRows
)
356 size_t curNumRows
= m_data
.GetCount();
358 if ( pos
>= curNumRows
)
360 wxLogError( wxT("Called wxGridStringTable::DeleteRows(pos=%d, N=%d)...\n"
361 "Pos value is invalid for present table with %d rows"),
362 pos
, numRows
, curNumRows
);
366 if ( numRows
> curNumRows
- pos
)
368 numRows
= curNumRows
- pos
;
371 if ( numRows
>= curNumRows
)
373 m_data
.Empty(); // don't release memory just yet
377 for ( n
= 0; n
< numRows
; n
++ )
379 m_data
.Remove( pos
);
385 wxGridTableMessage
msg( this,
386 wxGRIDTABLE_NOTIFY_ROWS_DELETED
,
390 GetView()->ProcessTableMessage( msg
);
396 bool wxGridStringTable::InsertCols( size_t pos
, size_t numCols
)
400 size_t curNumRows
= m_data
.GetCount();
401 size_t curNumCols
= ( curNumRows
> 0 ? m_data
[0].GetCount() : 0 );
403 if ( pos
>= curNumCols
)
405 return AppendCols( numCols
);
408 for ( row
= 0; row
< curNumRows
; row
++ )
410 for ( col
= pos
; col
< pos
+ numCols
; col
++ )
412 m_data
[row
].Insert( wxEmptyString
, col
);
418 wxGridTableMessage
msg( this,
419 wxGRIDTABLE_NOTIFY_COLS_INSERTED
,
423 GetView()->ProcessTableMessage( msg
);
429 bool wxGridStringTable::AppendCols( size_t numCols
)
433 size_t curNumRows
= m_data
.GetCount();
436 // TODO: something better than this ?
438 wxLogError( wxT("Unable to append cols to a grid table with no rows.\n"
439 "Call AppendRows() first") );
443 for ( row
= 0; row
< curNumRows
; row
++ )
445 for ( n
= 0; n
< numCols
; n
++ )
447 m_data
[row
].Add( wxEmptyString
);
453 wxGridTableMessage
msg( this,
454 wxGRIDTABLE_NOTIFY_COLS_APPENDED
,
457 GetView()->ProcessTableMessage( msg
);
463 bool wxGridStringTable::DeleteCols( size_t pos
, size_t numCols
)
467 size_t curNumRows
= m_data
.GetCount();
468 size_t curNumCols
= ( curNumRows
> 0 ? m_data
[0].GetCount() : 0 );
470 if ( pos
>= curNumCols
)
472 wxLogError( wxT("Called wxGridStringTable::DeleteCols(pos=%d, N=%d)...\n"
473 "Pos value is invalid for present table with %d cols"),
474 pos
, numCols
, curNumCols
);
478 if ( numCols
> curNumCols
- pos
)
480 numCols
= curNumCols
- pos
;
483 for ( row
= 0; row
< curNumRows
; row
++ )
485 if ( numCols
>= curNumCols
)
491 for ( n
= 0; n
< numCols
; n
++ )
493 m_data
[row
].Remove( pos
);
500 wxGridTableMessage
msg( this,
501 wxGRIDTABLE_NOTIFY_COLS_DELETED
,
505 GetView()->ProcessTableMessage( msg
);
511 wxString
wxGridStringTable::GetRowLabelValue( int row
)
513 if ( row
> (int)(m_rowLabels
.GetCount()) - 1 )
515 // using default label
517 return wxGridTableBase::GetRowLabelValue( row
);
521 return m_rowLabels
[ row
];
525 wxString
wxGridStringTable::GetColLabelValue( int col
)
527 if ( col
> (int)(m_colLabels
.GetCount()) - 1 )
529 // using default label
531 return wxGridTableBase::GetColLabelValue( col
);
535 return m_colLabels
[ col
];
539 void wxGridStringTable::SetRowLabelValue( int row
, const wxString
& value
)
541 if ( row
> (int)(m_rowLabels
.GetCount()) - 1 )
543 int n
= m_rowLabels
.GetCount();
545 for ( i
= n
; i
<= row
; i
++ )
547 m_rowLabels
.Add( wxGridTableBase::GetRowLabelValue(i
) );
551 m_rowLabels
[row
] = value
;
554 void wxGridStringTable::SetColLabelValue( int col
, const wxString
& value
)
556 if ( col
> (int)(m_colLabels
.GetCount()) - 1 )
558 int n
= m_colLabels
.GetCount();
560 for ( i
= n
; i
<= col
; i
++ )
562 m_colLabels
.Add( wxGridTableBase::GetColLabelValue(i
) );
566 m_colLabels
[col
] = value
;
572 //////////////////////////////////////////////////////////////////////
574 IMPLEMENT_DYNAMIC_CLASS( wxGridTextCtrl
, wxTextCtrl
)
576 BEGIN_EVENT_TABLE( wxGridTextCtrl
, wxTextCtrl
)
577 EVT_KEY_DOWN( wxGridTextCtrl::OnKeyDown
)
581 wxGridTextCtrl::wxGridTextCtrl( wxWindow
*par
,
585 const wxString
& value
,
589 : wxTextCtrl( par
, id
, value
, pos
, size
, style
)
592 m_isCellControl
= isCellControl
;
596 void wxGridTextCtrl::OnKeyDown( wxKeyEvent
& event
)
598 switch ( event
.KeyCode() )
601 m_grid
->SetEditControlValue( startValue
);
602 SetInsertionPointEnd();
612 if ( m_isCellControl
)
614 // send the event to the parent grid, skipping the
615 // event if nothing happens
617 event
.Skip( m_grid
->ProcessEvent( event
) );
621 // default text control response within the top edit
629 if ( m_isCellControl
)
631 if ( !m_grid
->ProcessEvent( event
) )
633 #if defined(__WXMOTIF__) || defined(__WXGTK__)
634 // wxMotif needs a little extra help...
636 int pos
= GetInsertionPoint();
637 wxString
s( GetValue() );
638 s
= s
.Left(pos
) + "\n" + s
.Mid(pos
);
640 SetInsertionPoint( pos
);
642 // the other ports can handle a Return key press
652 if ( m_isCellControl
)
654 // send the event to the parent grid, skipping the
655 // event if nothing happens
657 event
.Skip( m_grid
->ProcessEvent( event
) );
661 // default text control response within the top edit
673 void wxGridTextCtrl::SetStartValue( const wxString
& s
)
676 wxTextCtrl::SetValue(s
);
681 //////////////////////////////////////////////////////////////////////
683 IMPLEMENT_DYNAMIC_CLASS( wxGridRowLabelWindow
, wxWindow
)
685 BEGIN_EVENT_TABLE( wxGridRowLabelWindow
, wxWindow
)
686 EVT_PAINT( wxGridRowLabelWindow::OnPaint
)
687 EVT_MOUSE_EVENTS( wxGridRowLabelWindow::OnMouseEvent
)
688 EVT_KEY_DOWN( wxGridRowLabelWindow::OnKeyDown
)
691 wxGridRowLabelWindow::wxGridRowLabelWindow( wxGrid
*parent
,
693 const wxPoint
&pos
, const wxSize
&size
)
694 : wxWindow( parent
, id
, pos
, size
)
699 void wxGridRowLabelWindow::OnPaint( wxPaintEvent
&event
)
703 // NO - don't do this because it will set both the x and y origin
704 // coords to match the parent scrolled window and we just want to
705 // set the y coord - MB
707 // m_owner->PrepareDC( dc );
710 m_owner
->CalcUnscrolledPosition( 0, 0, &x
, &y
);
711 dc
.SetDeviceOrigin( 0, -y
);
713 m_owner
->CalcRowLabelsExposed( GetUpdateRegion() );
714 m_owner
->DrawRowLabels( dc
);
718 void wxGridRowLabelWindow::OnMouseEvent( wxMouseEvent
& event
)
720 m_owner
->ProcessRowLabelMouseEvent( event
);
724 // This seems to be required for wxMotif otherwise the mouse
725 // cursor must be in the cell edit control to get key events
727 void wxGridRowLabelWindow::OnKeyDown( wxKeyEvent
& event
)
729 if ( !m_owner
->ProcessEvent( event
) ) event
.Skip();
734 //////////////////////////////////////////////////////////////////////
736 IMPLEMENT_DYNAMIC_CLASS( wxGridColLabelWindow
, wxWindow
)
738 BEGIN_EVENT_TABLE( wxGridColLabelWindow
, wxWindow
)
739 EVT_PAINT( wxGridColLabelWindow::OnPaint
)
740 EVT_MOUSE_EVENTS( wxGridColLabelWindow::OnMouseEvent
)
741 EVT_KEY_DOWN( wxGridColLabelWindow::OnKeyDown
)
744 wxGridColLabelWindow::wxGridColLabelWindow( wxGrid
*parent
,
746 const wxPoint
&pos
, const wxSize
&size
)
747 : wxWindow( parent
, id
, pos
, size
)
752 void wxGridColLabelWindow::OnPaint( wxPaintEvent
&event
)
756 // NO - don't do this because it will set both the x and y origin
757 // coords to match the parent scrolled window and we just want to
758 // set the x coord - MB
760 // m_owner->PrepareDC( dc );
763 m_owner
->CalcUnscrolledPosition( 0, 0, &x
, &y
);
764 dc
.SetDeviceOrigin( -x
, 0 );
766 m_owner
->CalcColLabelsExposed( GetUpdateRegion() );
767 m_owner
->DrawColLabels( dc
);
771 void wxGridColLabelWindow::OnMouseEvent( wxMouseEvent
& event
)
773 m_owner
->ProcessColLabelMouseEvent( event
);
777 // This seems to be required for wxMotif otherwise the mouse
778 // cursor must be in the cell edit control to get key events
780 void wxGridColLabelWindow::OnKeyDown( wxKeyEvent
& event
)
782 if ( !m_owner
->ProcessEvent( event
) ) event
.Skip();
787 //////////////////////////////////////////////////////////////////////
789 IMPLEMENT_DYNAMIC_CLASS( wxGridCornerLabelWindow
, wxWindow
)
791 BEGIN_EVENT_TABLE( wxGridCornerLabelWindow
, wxWindow
)
792 EVT_MOUSE_EVENTS( wxGridCornerLabelWindow::OnMouseEvent
)
793 EVT_PAINT( wxGridCornerLabelWindow::OnPaint
)
794 EVT_KEY_DOWN( wxGridCornerLabelWindow::OnKeyDown
)
797 wxGridCornerLabelWindow::wxGridCornerLabelWindow( wxGrid
*parent
,
799 const wxPoint
&pos
, const wxSize
&size
)
800 : wxWindow( parent
, id
, pos
, size
)
805 void wxGridCornerLabelWindow::OnPaint( wxPaintEvent
& WXUNUSED(event
) )
809 int client_height
= 0;
810 int client_width
= 0;
811 GetClientSize( &client_width
, &client_height
);
813 dc
.SetPen( *wxBLACK_PEN
);
814 dc
.DrawLine( client_width
-1, client_height
-1, client_width
-1, 0 );
815 dc
.DrawLine( client_width
-1, client_height
-1, 0, client_height
-1 );
817 dc
.SetPen( *wxWHITE_PEN
);
818 dc
.DrawLine( 0, 0, client_width
, 0 );
819 dc
.DrawLine( 0, 0, 0, client_height
);
823 void wxGridCornerLabelWindow::OnMouseEvent( wxMouseEvent
& event
)
825 m_owner
->ProcessCornerLabelMouseEvent( event
);
829 // This seems to be required for wxMotif otherwise the mouse
830 // cursor must be in the cell edit control to get key events
832 void wxGridCornerLabelWindow::OnKeyDown( wxKeyEvent
& event
)
834 if ( !m_owner
->ProcessEvent( event
) ) event
.Skip();
839 //////////////////////////////////////////////////////////////////////
841 IMPLEMENT_DYNAMIC_CLASS( wxGridWindow
, wxPanel
)
843 BEGIN_EVENT_TABLE( wxGridWindow
, wxPanel
)
844 EVT_PAINT( wxGridWindow::OnPaint
)
845 EVT_MOUSE_EVENTS( wxGridWindow::OnMouseEvent
)
846 EVT_KEY_DOWN( wxGridWindow::OnKeyDown
)
849 wxGridWindow::wxGridWindow( wxGrid
*parent
,
850 wxGridRowLabelWindow
*rowLblWin
,
851 wxGridColLabelWindow
*colLblWin
,
852 wxWindowID id
, const wxPoint
&pos
, const wxSize
&size
)
853 : wxPanel( parent
, id
, pos
, size
, wxSUNKEN_BORDER
, "grid window" )
856 m_rowLabelWin
= rowLblWin
;
857 m_colLabelWin
= colLblWin
;
859 SetBackgroundColour( "WHITE" );
863 wxGridWindow::~wxGridWindow()
868 void wxGridWindow::OnPaint( wxPaintEvent
&WXUNUSED(event
) )
870 wxPaintDC
dc( this );
871 m_owner
->PrepareDC( dc
);
873 m_owner
->CalcCellsExposed( GetUpdateRegion() );
874 m_owner
->DrawGridCellArea( dc
);
878 void wxGridWindow::ScrollWindow( int dx
, int dy
, const wxRect
*rect
)
880 wxPanel::ScrollWindow( dx
, dy
, rect
);
881 m_rowLabelWin
->ScrollWindow( 0, dy
, rect
);
882 m_colLabelWin
->ScrollWindow( dx
, 0, rect
);
886 void wxGridWindow::OnMouseEvent( wxMouseEvent
& event
)
888 m_owner
->ProcessGridCellMouseEvent( event
);
892 // This seems to be required for wxMotif otherwise the mouse
893 // cursor must be in the cell edit control to get key events
895 void wxGridWindow::OnKeyDown( wxKeyEvent
& event
)
897 if ( !m_owner
->ProcessEvent( event
) ) event
.Skip();
902 //////////////////////////////////////////////////////////////////////
904 IMPLEMENT_DYNAMIC_CLASS( wxGrid
, wxScrolledWindow
)
906 BEGIN_EVENT_TABLE( wxGrid
, wxScrolledWindow
)
907 EVT_PAINT( wxGrid::OnPaint
)
908 EVT_SIZE( wxGrid::OnSize
)
909 EVT_KEY_DOWN( wxGrid::OnKeyDown
)
912 wxGrid::wxGrid( wxWindow
*parent
,
917 const wxString
& name
)
918 : wxScrolledWindow( parent
, id
, pos
, size
, style
, name
)
931 // ----- internal init and update functions
934 void wxGrid::Create()
936 int colLblH
= WXGRID_DEFAULT_COL_LABEL_HEIGHT
;
937 int rowLblW
= WXGRID_DEFAULT_ROW_LABEL_WIDTH
;
939 m_rowLabelWin
= new wxGridRowLabelWindow( this,
942 wxSize(rowLblW
,-1) );
944 m_colLabelWin
= new wxGridColLabelWindow( this,
947 wxSize(-1, colLblH
) );
949 m_cornerLabelWin
= new wxGridCornerLabelWindow( this,
952 wxSize(rowLblW
, colLblH
) );
954 m_gridWin
= new wxGridWindow( this,
961 SetTargetWindow( m_gridWin
);
963 m_mainSizer
= new wxBoxSizer( wxVERTICAL
);
965 m_topSizer
= new wxBoxSizer( wxHORIZONTAL
);
966 m_topSizer
->Add( m_cornerLabelWin
, 0 );
967 m_topSizer
->Add( m_colLabelWin
, 1 );
969 m_mainSizer
->Add( m_topSizer
, 0, wxEXPAND
);
971 m_middleSizer
= new wxBoxSizer( wxHORIZONTAL
);
972 m_middleSizer
->Add( m_rowLabelWin
, 0, wxEXPAND
);
973 m_middleSizer
->Add( m_gridWin
, 1, wxEXPAND
);
975 m_mainSizer
->Add( m_middleSizer
, 1, wxEXPAND
);
977 SetAutoLayout( TRUE
);
978 SetSizer( m_mainSizer
);
982 bool wxGrid::CreateGrid( int numRows
, int numCols
)
986 wxLogError( wxT("wxGrid::CreateGrid(numRows, numCols) called more than once") );
994 m_table
= new wxGridStringTable( m_numRows
, m_numCols
);
995 m_table
->SetView( this );
1008 if ( m_numRows
<= 0 )
1009 m_numRows
= WXGRID_DEFAULT_NUMBER_ROWS
;
1011 if ( m_numCols
<= 0 )
1012 m_numCols
= WXGRID_DEFAULT_NUMBER_COLS
;
1014 m_rowLabelWidth
= WXGRID_DEFAULT_ROW_LABEL_WIDTH
;
1015 m_colLabelHeight
= WXGRID_DEFAULT_COL_LABEL_HEIGHT
;
1017 if ( m_rowLabelWin
)
1019 m_labelBackgroundColour
= m_rowLabelWin
->GetBackgroundColour();
1023 m_labelBackgroundColour
= wxColour( _T("WHITE") );
1026 m_labelTextColour
= wxColour( _T("BLACK") );
1028 // TODO: something better than this ?
1030 m_labelFont
= this->GetFont();
1031 m_labelFont
.SetWeight( m_labelFont
.GetWeight() + 2 );
1033 m_rowLabelHorizAlign
= wxLEFT
;
1034 m_rowLabelVertAlign
= wxCENTRE
;
1036 m_colLabelHorizAlign
= wxCENTRE
;
1037 m_colLabelVertAlign
= wxTOP
;
1039 m_defaultColWidth
= WXGRID_DEFAULT_COL_WIDTH
;
1040 m_defaultRowHeight
= m_gridWin
->GetCharHeight();
1042 #if defined(__WXMOTIF__) || defined(__WXGTK__) // see also text ctrl sizing in ShowCellEditControl()
1043 m_defaultRowHeight
+= 8;
1045 m_defaultRowHeight
+= 4;
1048 m_rowHeights
.Alloc( m_numRows
);
1049 m_rowBottoms
.Alloc( m_numRows
);
1051 for ( i
= 0; i
< m_numRows
; i
++ )
1053 m_rowHeights
.Add( m_defaultRowHeight
);
1054 rowBottom
+= m_defaultRowHeight
;
1055 m_rowBottoms
.Add( rowBottom
);
1058 m_colWidths
.Alloc( m_numCols
);
1059 m_colRights
.Alloc( m_numCols
);
1061 for ( i
= 0; i
< m_numCols
; i
++ )
1063 m_colWidths
.Add( m_defaultColWidth
);
1064 colRight
+= m_defaultColWidth
;
1065 m_colRights
.Add( colRight
);
1068 // TODO: improve this ?
1070 m_defaultCellFont
= this->GetFont();
1072 m_gridLineColour
= wxColour( 128, 128, 255 );
1073 m_gridLinesEnabled
= TRUE
;
1075 m_cursorMode
= WXGRID_CURSOR_SELECT_CELL
;
1077 m_dragRowOrCol
= -1;
1078 m_isDragging
= FALSE
;
1080 m_rowResizeCursor
= wxCursor( wxCURSOR_SIZENS
);
1081 m_colResizeCursor
= wxCursor( wxCURSOR_SIZEWE
);
1083 m_currentCellCoords
= wxGridNoCellCoords
;
1085 m_selectedTopLeft
= wxGridNoCellCoords
;
1086 m_selectedBottomRight
= wxGridNoCellCoords
;
1088 m_editable
= TRUE
; // default for whole grid
1090 m_inOnKeyDown
= FALSE
;
1093 // TODO: extend this to other types of controls
1095 m_cellEditCtrl
= new wxGridTextCtrl( m_gridWin
,
1102 #if defined(__WXMSW__)
1103 , wxTE_MULTILINE
| wxTE_NO_VSCROLL
1107 m_cellEditCtrl
->Show( FALSE
);
1108 m_cellEditCtrlEnabled
= TRUE
;
1109 m_editCtrlType
= wxGRID_TEXTCTRL
;
1113 void wxGrid::CalcDimensions()
1116 GetClientSize( &cw
, &ch
);
1118 if ( m_numRows
> 0 && m_numCols
> 0 )
1120 int right
= m_colRights
[ m_numCols
-1 ] + 20;
1121 int bottom
= m_rowBottoms
[ m_numRows
-1 ] + 20;
1123 // TODO: restore the scroll position that we had before sizing
1126 GetViewStart( &x
, &y
);
1127 SetScrollbars( GRID_SCROLL_LINE
, GRID_SCROLL_LINE
,
1128 right
/GRID_SCROLL_LINE
, bottom
/GRID_SCROLL_LINE
,
1134 // this is called when the grid table sends a message to say that it
1135 // has been redimensioned
1137 bool wxGrid::Redimension( wxGridTableMessage
& msg
)
1141 switch ( msg
.GetId() )
1143 case wxGRIDTABLE_NOTIFY_ROWS_INSERTED
:
1145 size_t pos
= msg
.GetCommandInt();
1146 int numRows
= msg
.GetCommandInt2();
1147 for ( i
= 0; i
< numRows
; i
++ )
1149 m_rowHeights
.Insert( m_defaultRowHeight
, pos
);
1150 m_rowBottoms
.Insert( 0, pos
);
1152 m_numRows
+= numRows
;
1155 if ( pos
> 0 ) bottom
= m_rowBottoms
[pos
-1];
1157 for ( i
= pos
; i
< m_numRows
; i
++ )
1159 bottom
+= m_rowHeights
[i
];
1160 m_rowBottoms
[i
] = bottom
;
1166 case wxGRIDTABLE_NOTIFY_ROWS_APPENDED
:
1168 int numRows
= msg
.GetCommandInt();
1169 for ( i
= 0; i
< numRows
; i
++ )
1171 m_rowHeights
.Add( m_defaultRowHeight
);
1172 m_rowBottoms
.Add( 0 );
1175 int oldNumRows
= m_numRows
;
1176 m_numRows
+= numRows
;
1179 if ( oldNumRows
> 0 ) bottom
= m_rowBottoms
[oldNumRows
-1];
1181 for ( i
= oldNumRows
; i
< m_numRows
; i
++ )
1183 bottom
+= m_rowHeights
[i
];
1184 m_rowBottoms
[i
] = bottom
;
1190 case wxGRIDTABLE_NOTIFY_ROWS_DELETED
:
1192 size_t pos
= msg
.GetCommandInt();
1193 int numRows
= msg
.GetCommandInt2();
1194 for ( i
= 0; i
< numRows
; i
++ )
1196 m_rowHeights
.Remove( pos
);
1197 m_rowBottoms
.Remove( pos
);
1199 m_numRows
-= numRows
;
1204 m_colWidths
.Clear();
1205 m_colRights
.Clear();
1206 m_currentCellCoords
= wxGridNoCellCoords
;
1210 if ( m_currentCellCoords
.GetRow() >= m_numRows
)
1211 m_currentCellCoords
.Set( 0, 0 );
1214 for ( i
= 0; i
< m_numRows
; i
++ )
1216 h
+= m_rowHeights
[i
];
1217 m_rowBottoms
[i
] = h
;
1225 case wxGRIDTABLE_NOTIFY_COLS_INSERTED
:
1227 size_t pos
= msg
.GetCommandInt();
1228 int numCols
= msg
.GetCommandInt2();
1229 for ( i
= 0; i
< numCols
; i
++ )
1231 m_colWidths
.Insert( m_defaultColWidth
, pos
);
1232 m_colRights
.Insert( 0, pos
);
1234 m_numCols
+= numCols
;
1237 if ( pos
> 0 ) right
= m_colRights
[pos
-1];
1239 for ( i
= pos
; i
< m_numCols
; i
++ )
1241 right
+= m_colWidths
[i
];
1242 m_colRights
[i
] = right
;
1248 case wxGRIDTABLE_NOTIFY_COLS_APPENDED
:
1250 int numCols
= msg
.GetCommandInt();
1251 for ( i
= 0; i
< numCols
; i
++ )
1253 m_colWidths
.Add( m_defaultColWidth
);
1254 m_colRights
.Add( 0 );
1257 int oldNumCols
= m_numCols
;
1258 m_numCols
+= numCols
;
1261 if ( oldNumCols
> 0 ) right
= m_colRights
[oldNumCols
-1];
1263 for ( i
= oldNumCols
; i
< m_numCols
; i
++ )
1265 right
+= m_colWidths
[i
];
1266 m_colRights
[i
] = right
;
1272 case wxGRIDTABLE_NOTIFY_COLS_DELETED
:
1274 size_t pos
= msg
.GetCommandInt();
1275 int numCols
= msg
.GetCommandInt2();
1276 for ( i
= 0; i
< numCols
; i
++ )
1278 m_colWidths
.Remove( pos
);
1279 m_colRights
.Remove( pos
);
1281 m_numCols
-= numCols
;
1285 #if 0 // leave the row alone here so that AppendCols will work subsequently
1287 m_rowHeights
.Clear();
1288 m_rowBottoms
.Clear();
1290 m_currentCellCoords
= wxGridNoCellCoords
;
1294 if ( m_currentCellCoords
.GetCol() >= m_numCols
)
1295 m_currentCellCoords
.Set( 0, 0 );
1298 for ( i
= 0; i
< m_numCols
; i
++ )
1300 w
+= m_colWidths
[i
];
1313 void wxGrid::CalcRowLabelsExposed( wxRegion
& reg
)
1315 wxRegionIterator
iter( reg
);
1318 m_rowLabelsExposed
.Empty();
1325 // TODO: remove this when we can...
1326 // There is a bug in wxMotif that gives garbage update
1327 // rectangles if you jump-scroll a long way by clicking the
1328 // scrollbar with middle button. This is a work-around
1330 #if defined(__WXMOTIF__)
1332 m_gridWin
->GetClientSize( &cw
, &ch
);
1333 if ( r
.GetTop() > ch
) r
.SetTop( 0 );
1334 r
.SetBottom( wxMin( r
.GetBottom(), ch
) );
1337 // logical bounds of update region
1340 CalcUnscrolledPosition( 0, r
.GetTop(), &dummy
, &top
);
1341 CalcUnscrolledPosition( 0, r
.GetBottom(), &dummy
, &bottom
);
1343 // find the row labels within these bounds
1347 for ( row
= 0; row
< m_numRows
; row
++ )
1349 if ( m_rowBottoms
[row
] < top
) continue;
1351 rowTop
= m_rowBottoms
[row
] - m_rowHeights
[row
];
1352 if ( rowTop
> bottom
) break;
1354 m_rowLabelsExposed
.Add( row
);
1362 void wxGrid::CalcColLabelsExposed( wxRegion
& reg
)
1364 wxRegionIterator
iter( reg
);
1367 m_colLabelsExposed
.Empty();
1374 // TODO: remove this when we can...
1375 // There is a bug in wxMotif that gives garbage update
1376 // rectangles if you jump-scroll a long way by clicking the
1377 // scrollbar with middle button. This is a work-around
1379 #if defined(__WXMOTIF__)
1381 m_gridWin
->GetClientSize( &cw
, &ch
);
1382 if ( r
.GetLeft() > cw
) r
.SetLeft( 0 );
1383 r
.SetRight( wxMin( r
.GetRight(), cw
) );
1386 // logical bounds of update region
1389 CalcUnscrolledPosition( r
.GetLeft(), 0, &left
, &dummy
);
1390 CalcUnscrolledPosition( r
.GetRight(), 0, &right
, &dummy
);
1392 // find the cells within these bounds
1396 for ( col
= 0; col
< m_numCols
; col
++ )
1398 if ( m_colRights
[col
] < left
) continue;
1400 colLeft
= m_colRights
[col
] - m_colWidths
[col
];
1401 if ( colLeft
> right
) break;
1403 m_colLabelsExposed
.Add( col
);
1411 void wxGrid::CalcCellsExposed( wxRegion
& reg
)
1413 wxRegionIterator
iter( reg
);
1416 m_cellsExposed
.Empty();
1417 m_rowsExposed
.Empty();
1418 m_colsExposed
.Empty();
1420 int left
, top
, right
, bottom
;
1425 // TODO: remove this when we can...
1426 // There is a bug in wxMotif that gives garbage update
1427 // rectangles if you jump-scroll a long way by clicking the
1428 // scrollbar with middle button. This is a work-around
1430 #if defined(__WXMOTIF__)
1432 m_gridWin
->GetClientSize( &cw
, &ch
);
1433 if ( r
.GetTop() > ch
) r
.SetTop( 0 );
1434 if ( r
.GetLeft() > cw
) r
.SetLeft( 0 );
1435 r
.SetRight( wxMin( r
.GetRight(), cw
) );
1436 r
.SetBottom( wxMin( r
.GetBottom(), ch
) );
1439 // logical bounds of update region
1441 CalcUnscrolledPosition( r
.GetLeft(), r
.GetTop(), &left
, &top
);
1442 CalcUnscrolledPosition( r
.GetRight(), r
.GetBottom(), &right
, &bottom
);
1444 // find the cells within these bounds
1447 int colLeft
, rowTop
;
1448 for ( row
= 0; row
< m_numRows
; row
++ )
1450 if ( m_rowBottoms
[row
] < top
) continue;
1452 rowTop
= m_rowBottoms
[row
] - m_rowHeights
[row
];
1453 if ( rowTop
> bottom
) break;
1455 m_rowsExposed
.Add( row
);
1457 for ( col
= 0; col
< m_numCols
; col
++ )
1459 if ( m_colRights
[col
] < left
) continue;
1461 colLeft
= m_colRights
[col
] - m_colWidths
[col
];
1462 if ( colLeft
> right
) break;
1464 if ( m_colsExposed
.Index( col
) == wxNOT_FOUND
) m_colsExposed
.Add( col
);
1465 m_cellsExposed
.Add( wxGridCellCoords( row
, col
) );
1474 void wxGrid::ProcessRowLabelMouseEvent( wxMouseEvent
& event
)
1477 wxPoint
pos( event
.GetPosition() );
1478 CalcUnscrolledPosition( pos
.x
, pos
.y
, &x
, &y
);
1480 if ( event
.Dragging() )
1482 m_isDragging
= TRUE
;
1484 if ( event
.LeftIsDown() )
1486 switch( m_cursorMode
)
1488 case WXGRID_CURSOR_RESIZE_ROW
:
1490 int cw
, ch
, left
, dummy
;
1491 m_gridWin
->GetClientSize( &cw
, &ch
);
1492 CalcUnscrolledPosition( 0, 0, &left
, &dummy
);
1494 wxClientDC
dc( m_gridWin
);
1496 dc
.SetLogicalFunction(wxINVERT
);
1497 if ( m_dragLastPos
>= 0 )
1499 dc
.DrawLine( left
, m_dragLastPos
, left
+cw
, m_dragLastPos
);
1501 dc
.DrawLine( left
, y
, left
+cw
, y
);
1506 case WXGRID_CURSOR_SELECT_ROW
:
1508 if ( (row
= YToRow( y
)) >= 0 &&
1509 !IsInSelection( row
, 0 ) )
1511 SelectRow( row
, TRUE
);
1520 m_isDragging
= FALSE
;
1523 // ------------ Left button pressed
1525 if ( event
.LeftDown() )
1527 // don't send a label click event for a hit on the
1528 // edge of the row label - this is probably the user
1529 // wanting to resize the row
1531 if ( YToEdgeOfRow(y
) < 0 )
1535 !SendEvent( EVT_GRID_LABEL_LEFT_CLICK
, row
, -1, event
) )
1537 SelectRow( row
, event
.ShiftDown() );
1538 m_cursorMode
= WXGRID_CURSOR_SELECT_ROW
;
1543 // starting to drag-resize a row
1545 m_rowLabelWin
->CaptureMouse();
1550 // ------------ Left double click
1552 else if (event
.LeftDClick() )
1554 if ( YToEdgeOfRow(y
) < 0 )
1557 SendEvent( EVT_GRID_LABEL_LEFT_DCLICK
, row
, -1, event
);
1562 // ------------ Left button released
1564 else if ( event
.LeftUp() )
1566 if ( m_cursorMode
== WXGRID_CURSOR_RESIZE_ROW
)
1568 m_rowLabelWin
->ReleaseMouse();
1570 if ( m_dragLastPos
>= 0 )
1572 // erase the last line and resize the row
1574 int cw
, ch
, left
, dummy
;
1575 m_gridWin
->GetClientSize( &cw
, &ch
);
1576 CalcUnscrolledPosition( 0, 0, &left
, &dummy
);
1578 wxClientDC
dc( m_gridWin
);
1580 dc
.SetLogicalFunction( wxINVERT
);
1581 dc
.DrawLine( left
, m_dragLastPos
, left
+cw
, m_dragLastPos
);
1582 HideCellEditControl();
1584 int rowTop
= m_rowBottoms
[m_dragRowOrCol
] - m_rowHeights
[m_dragRowOrCol
];
1585 SetRowSize( m_dragRowOrCol
, wxMax( y
- rowTop
, WXGRID_MIN_ROW_HEIGHT
) );
1586 if ( !GetBatchCount() )
1588 // TODO: optimize this
1589 m_rowLabelWin
->Refresh();
1590 m_gridWin
->Refresh();
1593 ShowCellEditControl();
1595 // Note: we are ending the event *after* doing
1596 // default processing in this case
1598 SendEvent( EVT_GRID_ROW_SIZE
, m_dragRowOrCol
, -1, event
);
1606 // ------------ Right button down
1608 else if ( event
.RightDown() )
1611 if ( !SendEvent( EVT_GRID_LABEL_RIGHT_CLICK
, row
, -1, event
) )
1613 // no default action at the moment
1618 // ------------ Right double click
1620 else if ( event
.RightDClick() )
1623 if ( !SendEvent( EVT_GRID_LABEL_RIGHT_DCLICK
, row
, -1, event
) )
1625 // no default action at the moment
1630 // ------------ No buttons down and mouse moving
1632 else if ( event
.Moving() )
1634 m_dragRowOrCol
= YToEdgeOfRow( y
);
1635 if ( m_dragRowOrCol
>= 0 )
1637 if ( m_cursorMode
== WXGRID_CURSOR_SELECT_CELL
)
1639 m_cursorMode
= WXGRID_CURSOR_RESIZE_ROW
;
1640 m_rowLabelWin
->SetCursor( m_rowResizeCursor
);
1645 if ( m_cursorMode
!= WXGRID_CURSOR_SELECT_CELL
)
1647 m_cursorMode
= WXGRID_CURSOR_SELECT_CELL
;
1648 m_rowLabelWin
->SetCursor( *wxSTANDARD_CURSOR
);
1655 void wxGrid::ProcessColLabelMouseEvent( wxMouseEvent
& event
)
1658 wxPoint
pos( event
.GetPosition() );
1659 CalcUnscrolledPosition( pos
.x
, pos
.y
, &x
, &y
);
1661 if ( event
.Dragging() )
1663 m_isDragging
= TRUE
;
1665 if ( event
.LeftIsDown() )
1667 switch( m_cursorMode
)
1669 case WXGRID_CURSOR_RESIZE_COL
:
1671 int cw
, ch
, dummy
, top
;
1672 m_gridWin
->GetClientSize( &cw
, &ch
);
1673 CalcUnscrolledPosition( 0, 0, &dummy
, &top
);
1675 wxClientDC
dc( m_gridWin
);
1677 dc
.SetLogicalFunction(wxINVERT
);
1678 if ( m_dragLastPos
>= 0 )
1680 dc
.DrawLine( m_dragLastPos
, top
, m_dragLastPos
, top
+ch
);
1682 dc
.DrawLine( x
, top
, x
, top
+ch
);
1687 case WXGRID_CURSOR_SELECT_COL
:
1689 if ( (col
= XToCol( x
)) >= 0 &&
1690 !IsInSelection( 0, col
) )
1692 SelectCol( col
, TRUE
);
1701 m_isDragging
= FALSE
;
1704 // ------------ Left button pressed
1706 if ( event
.LeftDown() )
1708 // don't send a label click event for a hit on the
1709 // edge of the col label - this is probably the user
1710 // wanting to resize the col
1712 if ( XToEdgeOfCol(x
) < 0 )
1716 !SendEvent( EVT_GRID_LABEL_LEFT_CLICK
, -1, col
, event
) )
1718 SelectCol( col
, event
.ShiftDown() );
1719 m_cursorMode
= WXGRID_CURSOR_SELECT_COL
;
1724 // starting to drag-resize a col
1726 m_colLabelWin
->CaptureMouse();
1731 // ------------ Left double click
1733 if ( event
.LeftDClick() )
1735 if ( XToEdgeOfCol(x
) < 0 )
1738 SendEvent( EVT_GRID_LABEL_LEFT_DCLICK
, -1, col
, event
);
1743 // ------------ Left button released
1745 else if ( event
.LeftUp() )
1747 if ( m_cursorMode
== WXGRID_CURSOR_RESIZE_COL
)
1749 m_colLabelWin
->ReleaseMouse();
1751 if ( m_dragLastPos
>= 0 )
1753 // erase the last line and resize the col
1755 int cw
, ch
, dummy
, top
;
1756 m_gridWin
->GetClientSize( &cw
, &ch
);
1757 CalcUnscrolledPosition( 0, 0, &dummy
, &top
);
1759 wxClientDC
dc( m_gridWin
);
1761 dc
.SetLogicalFunction( wxINVERT
);
1762 dc
.DrawLine( m_dragLastPos
, top
, m_dragLastPos
, top
+ch
);
1763 HideCellEditControl();
1765 int colLeft
= m_colRights
[m_dragRowOrCol
] - m_colWidths
[m_dragRowOrCol
];
1766 SetColSize( m_dragRowOrCol
, wxMax( x
- colLeft
, WXGRID_MIN_COL_WIDTH
) );
1768 if ( !GetBatchCount() )
1770 // TODO: optimize this
1771 m_colLabelWin
->Refresh();
1772 m_gridWin
->Refresh();
1775 ShowCellEditControl();
1777 // Note: we are ending the event *after* doing
1778 // default processing in this case
1780 SendEvent( EVT_GRID_COL_SIZE
, -1, m_dragRowOrCol
, event
);
1788 // ------------ Right button down
1790 else if ( event
.RightDown() )
1793 if ( !SendEvent( EVT_GRID_LABEL_RIGHT_CLICK
, -1, col
, event
) )
1795 // no default action at the moment
1800 // ------------ Right double click
1802 else if ( event
.RightDClick() )
1805 if ( !SendEvent( EVT_GRID_LABEL_RIGHT_DCLICK
, -1, col
, event
) )
1807 // no default action at the moment
1812 // ------------ No buttons down and mouse moving
1814 else if ( event
.Moving() )
1816 m_dragRowOrCol
= XToEdgeOfCol( x
);
1817 if ( m_dragRowOrCol
>= 0 )
1819 if ( m_cursorMode
== WXGRID_CURSOR_SELECT_CELL
)
1821 m_cursorMode
= WXGRID_CURSOR_RESIZE_COL
;
1822 m_colLabelWin
->SetCursor( m_colResizeCursor
);
1827 if ( m_cursorMode
!= WXGRID_CURSOR_SELECT_CELL
)
1829 m_cursorMode
= WXGRID_CURSOR_SELECT_CELL
;
1830 m_colLabelWin
->SetCursor( *wxSTANDARD_CURSOR
);
1837 void wxGrid::ProcessCornerLabelMouseEvent( wxMouseEvent
& event
)
1839 if ( event
.LeftDown() )
1841 // indicate corner label by having both row and
1844 if ( !SendEvent( EVT_GRID_LABEL_LEFT_CLICK
, -1, -1, event
) )
1850 else if ( event
.LeftDClick() )
1852 SendEvent( EVT_GRID_LABEL_LEFT_DCLICK
, -1, -1, event
);
1855 else if ( event
.RightDown() )
1857 if ( !SendEvent( EVT_GRID_LABEL_RIGHT_CLICK
, -1, -1, event
) )
1859 // no default action at the moment
1863 else if ( event
.RightDClick() )
1865 if ( !SendEvent( EVT_GRID_LABEL_RIGHT_DCLICK
, -1, -1, event
) )
1867 // no default action at the moment
1873 void wxGrid::ProcessGridCellMouseEvent( wxMouseEvent
& event
)
1876 wxPoint
pos( event
.GetPosition() );
1877 CalcUnscrolledPosition( pos
.x
, pos
.y
, &x
, &y
);
1879 wxGridCellCoords coords
;
1880 XYToCell( x
, y
, coords
);
1882 if ( event
.Dragging() )
1884 m_isDragging
= TRUE
;
1885 if ( m_cursorMode
== WXGRID_CURSOR_SELECT_CELL
)
1887 // Hide the edit control, so it
1888 // won't interfer with drag-shrinking.
1889 if ( IsCellEditControlEnabled() )
1890 HideCellEditControl();
1891 if ( coords
!= wxGridNoCellCoords
)
1893 if ( !IsSelection() )
1895 SelectBlock( coords
, coords
);
1899 SelectBlock( m_currentCellCoords
, coords
);
1907 m_isDragging
= FALSE
;
1909 if ( coords
!= wxGridNoCellCoords
)
1911 if ( event
.LeftDown() )
1913 if ( event
.ShiftDown() )
1915 SelectBlock( m_currentCellCoords
, coords
);
1919 if ( !SendEvent( EVT_GRID_CELL_LEFT_CLICK
,
1924 MakeCellVisible( coords
);
1925 SetCurrentCell( coords
);
1931 // ------------ Left double click
1933 else if ( event
.LeftDClick() )
1935 SendEvent( EVT_GRID_CELL_LEFT_DCLICK
,
1942 // ------------ Left button released
1944 else if ( event
.LeftUp() )
1946 if ( m_cursorMode
== WXGRID_CURSOR_SELECT_CELL
)
1948 if ( IsSelection() )
1950 SendEvent( EVT_GRID_RANGE_SELECT
, -1, -1, event
);
1954 // Show the edit control, if it has
1955 // been hidden for drag-shrinking.
1956 if ( IsCellEditControlEnabled() )
1957 ShowCellEditControl();
1963 // ------------ Right button down
1965 else if ( event
.RightDown() )
1967 if ( !SendEvent( EVT_GRID_CELL_RIGHT_CLICK
,
1972 // no default action at the moment
1977 // ------------ Right double click
1979 else if ( event
.RightDClick() )
1981 if ( !SendEvent( EVT_GRID_CELL_RIGHT_DCLICK
,
1986 // no default action at the moment
1994 // ------ interaction with data model
1996 bool wxGrid::ProcessTableMessage( wxGridTableMessage
& msg
)
1998 switch ( msg
.GetId() )
2000 case wxGRIDTABLE_REQUEST_VIEW_GET_VALUES
:
2001 return GetModelValues();
2003 case wxGRIDTABLE_REQUEST_VIEW_SEND_VALUES
:
2004 return SetModelValues();
2006 case wxGRIDTABLE_NOTIFY_ROWS_INSERTED
:
2007 case wxGRIDTABLE_NOTIFY_ROWS_APPENDED
:
2008 case wxGRIDTABLE_NOTIFY_ROWS_DELETED
:
2009 case wxGRIDTABLE_NOTIFY_COLS_INSERTED
:
2010 case wxGRIDTABLE_NOTIFY_COLS_APPENDED
:
2011 case wxGRIDTABLE_NOTIFY_COLS_DELETED
:
2012 return Redimension( msg
);
2021 // The behaviour of this function depends on the grid table class
2022 // Clear() function. For the default wxGridStringTable class the
2023 // behavious is to replace all cell contents with wxEmptyString but
2024 // not to change the number of rows or cols.
2026 void wxGrid::ClearGrid()
2031 SetEditControlValue();
2032 if ( !GetBatchCount() ) m_gridWin
->Refresh();
2037 bool wxGrid::InsertRows( int pos
, int numRows
, bool WXUNUSED(updateLabels
) )
2039 // TODO: something with updateLabels flag
2043 wxLogError( wxT("Called wxGrid::InsertRows() before calling CreateGrid()") );
2049 bool ok
= m_table
->InsertRows( pos
, numRows
);
2051 // the table will have sent the results of the insert row
2052 // operation to this view object as a grid table message
2056 if ( m_numCols
== 0 )
2058 m_table
->AppendCols( WXGRID_DEFAULT_NUMBER_COLS
);
2060 // TODO: perhaps instead of appending the default number of cols
2061 // we should remember what the last non-zero number of cols was ?
2065 if ( m_currentCellCoords
== wxGridNoCellCoords
)
2067 // if we have just inserted cols into an empty grid the current
2068 // cell will be undefined...
2070 SetCurrentCell( 0, 0 );
2074 if ( !GetBatchCount() ) Refresh();
2077 SetEditControlValue();
2087 bool wxGrid::AppendRows( int numRows
, bool WXUNUSED(updateLabels
) )
2089 // TODO: something with updateLabels flag
2093 wxLogError( wxT("Called wxGrid::AppendRows() before calling CreateGrid()") );
2097 if ( m_table
&& m_table
->AppendRows( numRows
) )
2099 if ( m_currentCellCoords
== wxGridNoCellCoords
)
2101 // if we have just inserted cols into an empty grid the current
2102 // cell will be undefined...
2104 SetCurrentCell( 0, 0 );
2107 // the table will have sent the results of the append row
2108 // operation to this view object as a grid table message
2111 if ( !GetBatchCount() ) Refresh();
2121 bool wxGrid::DeleteRows( int pos
, int numRows
, bool WXUNUSED(updateLabels
) )
2123 // TODO: something with updateLabels flag
2127 wxLogError( wxT("Called wxGrid::DeleteRows() before calling CreateGrid()") );
2131 if ( m_table
&& m_table
->DeleteRows( pos
, numRows
) )
2133 // the table will have sent the results of the delete row
2134 // operation to this view object as a grid table message
2136 if ( m_numRows
> 0 )
2137 SetEditControlValue();
2139 HideCellEditControl();
2142 if ( !GetBatchCount() ) Refresh();
2152 bool wxGrid::InsertCols( int pos
, int numCols
, bool WXUNUSED(updateLabels
) )
2154 // TODO: something with updateLabels flag
2158 wxLogError( wxT("Called wxGrid::InsertCols() before calling CreateGrid()") );
2164 HideCellEditControl();
2165 bool ok
= m_table
->InsertCols( pos
, numCols
);
2167 // the table will have sent the results of the insert col
2168 // operation to this view object as a grid table message
2172 if ( m_currentCellCoords
== wxGridNoCellCoords
)
2174 // if we have just inserted cols into an empty grid the current
2175 // cell will be undefined...
2177 SetCurrentCell( 0, 0 );
2181 if ( !GetBatchCount() ) Refresh();
2184 SetEditControlValue();
2194 bool wxGrid::AppendCols( int numCols
, bool WXUNUSED(updateLabels
) )
2196 // TODO: something with updateLabels flag
2200 wxLogError( wxT("Called wxGrid::AppendCols() before calling CreateGrid()") );
2204 if ( m_table
&& m_table
->AppendCols( numCols
) )
2206 // the table will have sent the results of the append col
2207 // operation to this view object as a grid table message
2209 if ( m_currentCellCoords
== wxGridNoCellCoords
)
2211 // if we have just inserted cols into an empty grid the current
2212 // cell will be undefined...
2214 SetCurrentCell( 0, 0 );
2218 if ( !GetBatchCount() ) Refresh();
2228 bool wxGrid::DeleteCols( int pos
, int numCols
, bool WXUNUSED(updateLabels
) )
2230 // TODO: something with updateLabels flag
2234 wxLogError( wxT("Called wxGrid::DeleteCols() before calling CreateGrid()") );
2238 if ( m_table
&& m_table
->DeleteCols( pos
, numCols
) )
2240 // the table will have sent the results of the delete col
2241 // operation to this view object as a grid table message
2243 if ( m_numCols
> 0 )
2244 SetEditControlValue();
2246 HideCellEditControl();
2249 if ( !GetBatchCount() ) Refresh();
2261 // ----- event handlers
2264 // Generate a grid event based on a mouse event and
2265 // return the result of ProcessEvent()
2267 bool wxGrid::SendEvent( const wxEventType type
,
2269 wxMouseEvent
& mouseEv
)
2271 if ( type
== EVT_GRID_ROW_SIZE
||
2272 type
== EVT_GRID_COL_SIZE
)
2274 int rowOrCol
= (row
== -1 ? col
: row
);
2276 wxGridSizeEvent
gridEvt( GetId(),
2280 mouseEv
.GetX(), mouseEv
.GetY(),
2281 mouseEv
.ControlDown(),
2282 mouseEv
.ShiftDown(),
2284 mouseEv
.MetaDown() );
2286 return GetEventHandler()->ProcessEvent(gridEvt
);
2288 else if ( type
== EVT_GRID_RANGE_SELECT
)
2290 wxGridRangeSelectEvent
gridEvt( GetId(),
2294 m_selectedBottomRight
,
2295 mouseEv
.ControlDown(),
2296 mouseEv
.ShiftDown(),
2298 mouseEv
.MetaDown() );
2300 return GetEventHandler()->ProcessEvent(gridEvt
);
2304 wxGridEvent
gridEvt( GetId(),
2308 mouseEv
.GetX(), mouseEv
.GetY(),
2309 mouseEv
.ControlDown(),
2310 mouseEv
.ShiftDown(),
2312 mouseEv
.MetaDown() );
2314 return GetEventHandler()->ProcessEvent(gridEvt
);
2319 // Generate a grid event of specified type and return the result
2320 // of ProcessEvent().
2322 bool wxGrid::SendEvent( const wxEventType type
,
2325 if ( type
== EVT_GRID_ROW_SIZE
||
2326 type
== EVT_GRID_COL_SIZE
)
2328 int rowOrCol
= (row
== -1 ? col
: row
);
2330 wxGridSizeEvent
gridEvt( GetId(),
2335 return GetEventHandler()->ProcessEvent(gridEvt
);
2339 wxGridEvent
gridEvt( GetId(),
2344 return GetEventHandler()->ProcessEvent(gridEvt
);
2349 void wxGrid::OnPaint( wxPaintEvent
& WXUNUSED(event
) )
2351 wxPaintDC
dc( this );
2353 if ( m_currentCellCoords
== wxGridNoCellCoords
&&
2354 m_numRows
&& m_numCols
)
2356 m_currentCellCoords
.Set(0, 0);
2357 SetEditControlValue();
2358 ShowCellEditControl();
2363 // This is just here to make sure that CalcDimensions gets called when
2364 // the grid view is resized... then the size event is skipped to allow
2365 // the box sizers to handle everything
2367 void wxGrid::OnSize( wxSizeEvent
& event
)
2374 void wxGrid::OnKeyDown( wxKeyEvent
& event
)
2376 if ( m_inOnKeyDown
)
2378 // shouldn't be here - we are going round in circles...
2380 wxLogFatalError( wxT("wxGrid::OnKeyDown called while alread active") );
2383 m_inOnKeyDown
= TRUE
;
2385 // propagate the event up and see if it gets processed
2387 wxWindow
*parent
= GetParent();
2388 wxKeyEvent
keyEvt( event
);
2389 keyEvt
.SetEventObject( parent
);
2391 if ( !parent
->GetEventHandler()->ProcessEvent( keyEvt
) )
2393 // try local handlers
2395 switch ( event
.KeyCode() )
2398 if ( event
.ControlDown() )
2400 MoveCursorUpBlock();
2409 if ( event
.ControlDown() )
2411 MoveCursorDownBlock();
2420 if ( event
.ControlDown() )
2422 MoveCursorLeftBlock();
2431 if ( event
.ControlDown() )
2433 MoveCursorRightBlock();
2442 if ( !IsEditable() )
2453 if ( event
.ControlDown() )
2455 event
.Skip(); // to let the edit control have the return
2464 if ( event
.ControlDown() )
2466 MakeCellVisible( 0, 0 );
2467 SetCurrentCell( 0, 0 );
2476 if ( event
.ControlDown() )
2478 MakeCellVisible( m_numRows
-1, m_numCols
-1 );
2479 SetCurrentCell( m_numRows
-1, m_numCols
-1 );
2496 // now try the cell edit control
2498 if ( IsCellEditControlEnabled() )
2500 event
.SetEventObject( m_cellEditCtrl
);
2501 m_cellEditCtrl
->GetEventHandler()->ProcessEvent( event
);
2507 m_inOnKeyDown
= FALSE
;
2511 void wxGrid::SetCurrentCell( const wxGridCellCoords
& coords
)
2513 if ( SendEvent( EVT_GRID_SELECT_CELL
, coords
.GetRow(), coords
.GetCol() ) )
2515 // the event has been intercepted - do nothing
2519 wxClientDC
dc( m_gridWin
);
2522 if ( m_currentCellCoords
!= wxGridNoCellCoords
)
2524 HideCellEditControl();
2525 SaveEditControlValue();
2528 m_currentCellCoords
= coords
;
2530 SetEditControlValue();
2531 ShowCellEditControl();
2533 if ( IsSelection() )
2535 wxRect
r( SelectionToDeviceRect() );
2537 if ( !GetBatchCount() ) m_gridWin
->Refresh( TRUE
, &r
);
2543 // ------ functions to get/send data (see also public functions)
2546 bool wxGrid::GetModelValues()
2550 // all we need to do is repaint the grid
2552 m_gridWin
->Refresh();
2560 bool wxGrid::SetModelValues()
2566 for ( row
= 0; row
< m_numRows
; row
++ )
2568 for ( col
= 0; col
< m_numCols
; col
++ )
2570 m_table
->SetValue( row
, col
, GetCellValue(row
, col
) );
2582 // Note - this function only draws cells that are in the list of
2583 // exposed cells (usually set from the update region by
2584 // CalcExposedCells)
2586 void wxGrid::DrawGridCellArea( wxDC
& dc
)
2588 if ( !m_numRows
|| !m_numCols
) return;
2591 size_t numCells
= m_cellsExposed
.GetCount();
2593 for ( i
= 0; i
< numCells
; i
++ )
2595 DrawCell( dc
, m_cellsExposed
[i
] );
2600 void wxGrid::DrawCell( wxDC
& dc
, const wxGridCellCoords
& coords
)
2602 if ( m_colWidths
[coords
.GetCol()] <=0 ||
2603 m_rowHeights
[coords
.GetRow()] <= 0 ) return;
2605 if ( m_gridLinesEnabled
)
2606 DrawCellBorder( dc
, coords
);
2608 DrawCellBackground( dc
, coords
);
2610 // TODO: separate functions here for different kinds of cells ?
2613 DrawCellValue( dc
, coords
);
2617 void wxGrid::DrawCellBorder( wxDC
& dc
, const wxGridCellCoords
& coords
)
2619 if ( m_colWidths
[coords
.GetCol()] <=0 ||
2620 m_rowHeights
[coords
.GetRow()] <= 0 ) return;
2622 dc
.SetPen( wxPen(GetGridLineColour(), 1, wxSOLID
) );
2623 int row
= coords
.GetRow();
2624 int col
= coords
.GetCol();
2626 // right hand border
2628 dc
.DrawLine( m_colRights
[col
], m_rowBottoms
[row
] - m_rowHeights
[row
],
2629 m_colRights
[col
], m_rowBottoms
[row
] );
2633 dc
.DrawLine( m_colRights
[col
] - m_colWidths
[col
], m_rowBottoms
[row
],
2634 m_colRights
[col
], m_rowBottoms
[row
] );
2638 void wxGrid::DrawCellBackground( wxDC
& dc
, const wxGridCellCoords
& coords
)
2640 if ( m_colWidths
[coords
.GetCol()] <=0 ||
2641 m_rowHeights
[coords
.GetRow()] <= 0 ) return;
2643 int row
= coords
.GetRow();
2644 int col
= coords
.GetCol();
2646 dc
.SetBackgroundMode( wxSOLID
);
2648 if ( IsInSelection( coords
) )
2650 // TODO: improve this
2652 dc
.SetBrush( *wxBLACK_BRUSH
);
2656 dc
.SetBrush( wxBrush(GetCellBackgroundColour(row
, col
), wxSOLID
) );
2659 dc
.SetPen( *wxTRANSPARENT_PEN
);
2661 dc
.DrawRectangle( m_colRights
[col
] - m_colWidths
[col
] + 1,
2662 m_rowBottoms
[row
] - m_rowHeights
[row
] + 1,
2664 m_rowHeights
[row
]-1 );
2668 void wxGrid::DrawCellValue( wxDC
& dc
, const wxGridCellCoords
& coords
)
2670 if ( m_colWidths
[coords
.GetCol()] <=0 ||
2671 m_rowHeights
[coords
.GetRow()] <= 0 ) return;
2673 int row
= coords
.GetRow();
2674 int col
= coords
.GetCol();
2676 dc
.SetBackgroundMode( wxTRANSPARENT
);
2678 if ( IsInSelection( row
, col
) )
2680 // TODO: improve this
2682 dc
.SetTextBackground( wxColour(0, 0, 0) );
2683 dc
.SetTextForeground( wxColour(255, 255, 255) );
2687 dc
.SetTextBackground( GetCellBackgroundColour(row
, col
) );
2688 dc
.SetTextForeground( GetCellTextColour(row
, col
) );
2690 dc
.SetFont( GetCellFont(row
, col
) );
2693 GetCellAlignment( row
, col
, &hAlign
, &vAlign
);
2696 rect
.SetX( m_colRights
[col
] - m_colWidths
[col
] + 2 );
2697 rect
.SetY( m_rowBottoms
[row
] - m_rowHeights
[row
] + 2 );
2698 rect
.SetWidth( m_colWidths
[col
] - 4 );
2699 rect
.SetHeight( m_rowHeights
[row
] - 4 );
2701 DrawTextRectangle( dc
, GetCellValue( row
, col
), rect
, hAlign
, vAlign
);
2706 // TODO: remove this ???
2707 // This is used to redraw all grid lines e.g. when the grid line colour
2710 void wxGrid::DrawAllGridLines( wxDC
& dc
)
2712 if ( !m_gridLinesEnabled
||
2714 !m_numCols
) return;
2717 m_gridWin
->GetClientSize(&cw
, &ch
);
2719 // virtual coords of visible area
2721 int top
, bottom
, left
, right
;
2722 CalcUnscrolledPosition( 0, 0, &left
, &top
);
2723 CalcUnscrolledPosition( cw
, ch
, &right
, &bottom
);
2725 dc
.SetPen( wxPen(GetGridLineColour(), 1, wxSOLID
) );
2727 // horizontal grid lines
2730 for ( i
= 0; i
<= m_numRows
; i
++ )
2732 if ( m_rowBottoms
[i
] > bottom
)
2736 else if ( m_rowBottoms
[i
] >= top
)
2738 dc
.DrawLine( left
, m_rowBottoms
[i
], right
, m_rowBottoms
[i
] );
2743 // vertical grid lines
2745 for ( i
= 0; i
<= m_numCols
; i
++ )
2747 if ( m_colRights
[i
] > right
)
2751 else if ( m_colRights
[i
] >= left
)
2753 dc
.DrawLine( m_colRights
[i
], top
, m_colRights
[i
], bottom
);
2759 void wxGrid::DrawRowLabels( wxDC
& dc
)
2761 if ( !m_numRows
|| !m_numCols
) return;
2764 size_t numLabels
= m_rowLabelsExposed
.GetCount();
2766 for ( i
= 0; i
< numLabels
; i
++ )
2768 DrawRowLabel( dc
, m_rowLabelsExposed
[i
] );
2773 void wxGrid::DrawRowLabel( wxDC
& dc
, int row
)
2775 if ( m_rowHeights
[row
] <= 0 ) return;
2777 // draw the label's horizontal border (the vertical border is
2778 // provided by the cell area window margin)
2780 dc
.SetPen( *wxBLACK_PEN
);
2782 dc
.DrawLine( 0, m_rowBottoms
[row
]+1,
2783 m_rowLabelWidth
, m_rowBottoms
[row
]+1 );
2785 dc
.SetPen( *wxWHITE_PEN
);
2787 dc
.DrawLine( 0, m_rowBottoms
[row
]+2,
2788 m_rowLabelWidth
, m_rowBottoms
[row
]+2 );
2790 dc
.SetBackgroundMode( wxTRANSPARENT
);
2791 dc
.SetTextForeground( GetLabelTextColour() );
2792 dc
.SetFont( GetLabelFont() );
2795 GetRowLabelAlignment( &hAlign
, &vAlign
);
2799 rect
.SetY( m_rowBottoms
[row
] - m_rowHeights
[row
] + 2 );
2800 rect
.SetWidth( m_rowLabelWidth
- 4 );
2801 rect
.SetHeight( m_rowHeights
[row
] - 4 );
2802 DrawTextRectangle( dc
, GetRowLabelValue( row
), rect
, hAlign
, vAlign
);
2806 void wxGrid::DrawColLabels( wxDC
& dc
)
2808 if ( !m_numRows
|| !m_numCols
) return;
2811 size_t numLabels
= m_colLabelsExposed
.GetCount();
2813 for ( i
= 0; i
< numLabels
; i
++ )
2815 DrawColLabel( dc
, m_colLabelsExposed
[i
] );
2820 void wxGrid::DrawColLabel( wxDC
& dc
, int col
)
2822 if ( m_colWidths
[col
] <= 0 ) return;
2824 // draw the label's vertical border (the horizontal border is
2825 // provided by the cell area window margin)
2827 dc
.SetPen( *wxBLACK_PEN
);
2829 dc
.DrawLine( m_colRights
[col
]+1, 0,
2830 m_colRights
[col
]+1, m_colLabelHeight
);
2832 dc
.SetPen( *wxWHITE_PEN
);
2834 dc
.DrawLine( m_colRights
[col
]+2, 0,
2835 m_colRights
[col
]+2, m_colLabelHeight
);
2837 dc
.SetBackgroundMode( wxTRANSPARENT
);
2838 dc
.SetTextForeground( GetLabelTextColour() );
2839 dc
.SetFont( GetLabelFont() );
2842 GetColLabelAlignment( &hAlign
, &vAlign
);
2845 rect
.SetX( m_colRights
[col
] - m_colWidths
[col
] + 2 );
2847 rect
.SetWidth( m_colWidths
[col
] - 4 );
2848 rect
.SetHeight( m_colLabelHeight
- 4 );
2849 DrawTextRectangle( dc
, GetColLabelValue( col
), rect
, hAlign
, vAlign
);
2853 void wxGrid::DrawTextRectangle( wxDC
& dc
,
2854 const wxString
& value
,
2859 long textWidth
, textHeight
;
2860 long lineWidth
, lineHeight
;
2861 wxArrayString lines
;
2863 dc
.SetClippingRegion( rect
);
2864 StringToLines( value
, lines
);
2865 if ( lines
.GetCount() )
2867 GetTextBoxSize( dc
, lines
, &textWidth
, &textHeight
);
2868 dc
.GetTextExtent( lines
[0], &lineWidth
, &lineHeight
);
2871 switch ( horizAlign
)
2874 x
= rect
.x
+ (rect
.width
- textWidth
- 1);
2878 x
= rect
.x
+ ((rect
.width
- textWidth
)/2);
2887 switch ( vertAlign
)
2890 y
= rect
.y
+ (rect
.height
- textHeight
- 1);
2894 y
= rect
.y
+ ((rect
.height
- textHeight
)/2);
2903 for ( size_t i
= 0; i
< lines
.GetCount(); i
++ )
2905 dc
.DrawText( lines
[i
], (long)x
, (long)y
);
2910 dc
.DestroyClippingRegion();
2914 // Split multi line text up into an array of strings. Any existing
2915 // contents of the string array are preserved.
2917 void wxGrid::StringToLines( const wxString
& value
, wxArrayString
& lines
)
2919 // TODO: this won't work for WXMAC ? (lines end with '\r')
2920 // => use wxTextFile functions then (VZ)
2923 while ( startPos
< (int)value
.Length() )
2925 pos
= value
.Mid(startPos
).Find( '\n' );
2930 else if ( pos
== 0 )
2932 lines
.Add( wxEmptyString
);
2936 if ( value
[startPos
+pos
-1] == '\r' )
2938 lines
.Add( value
.Mid(startPos
, pos
-1) );
2942 lines
.Add( value
.Mid(startPos
, pos
) );
2947 if ( startPos
< (int)value
.Length() )
2949 lines
.Add( value
.Mid( startPos
) );
2954 void wxGrid::GetTextBoxSize( wxDC
& dc
,
2955 wxArrayString
& lines
,
2956 long *width
, long *height
)
2963 for ( i
= 0; i
< lines
.GetCount(); i
++ )
2965 dc
.GetTextExtent( lines
[i
], &lineW
, &lineH
);
2966 w
= wxMax( w
, lineW
);
2976 // ------ Edit control functions
2980 void wxGrid::EnableEditing( bool edit
)
2982 // TODO: improve this ?
2984 if ( edit
!= m_editable
)
2988 // TODO: extend this for other edit control types
2990 if ( m_editCtrlType
== wxGRID_TEXTCTRL
)
2992 ((wxTextCtrl
*)m_cellEditCtrl
)->SetEditable( m_editable
);
2998 #if 0 // disabled for the moment - the cell control is always active
2999 void wxGrid::EnableCellEditControl( bool enable
)
3001 if ( m_cellEditCtrl
&&
3002 enable
!= m_cellEditCtrlEnabled
)
3004 m_cellEditCtrlEnabled
= enable
;
3006 if ( m_cellEditCtrlEnabled
)
3008 SetEditControlValue();
3009 ShowCellEditControl();
3013 HideCellEditControl();
3014 SaveEditControlValue();
3021 void wxGrid::ShowCellEditControl()
3025 if ( IsCellEditControlEnabled() )
3027 if ( !IsVisible( m_currentCellCoords
) )
3033 rect
= CellToRect( m_currentCellCoords
);
3035 // convert to scrolled coords
3037 int left
, top
, right
, bottom
;
3038 CalcScrolledPosition( rect
.GetLeft(), rect
.GetTop(), &left
, &top
);
3039 CalcScrolledPosition( rect
.GetRight(), rect
.GetBottom(), &right
, &bottom
);
3042 m_gridWin
->GetClientSize( &cw
, &ch
);
3044 // Make the edit control large enough to allow for internal margins
3045 // TODO: remove this if the text ctrl sizing is improved esp. for unix
3048 #if defined(__WXMOTIF__)
3049 if ( m_currentCellCoords
.GetRow() == 0 ||
3050 m_currentCellCoords
.GetCol() == 0 )
3059 if ( m_currentCellCoords
.GetRow() == 0 ||
3060 m_currentCellCoords
.GetCol() == 0 )
3070 #if defined(__WXGTK__)
3073 if (left
!= 0) left_diff
++;
3074 if (top
!= 0) top_diff
++;
3075 rect
.SetLeft( left
+ left_diff
);
3076 rect
.SetTop( top
+ top_diff
);
3077 rect
.SetRight( rect
.GetRight() - left_diff
);
3078 rect
.SetBottom( rect
.GetBottom() - top_diff
);
3080 rect
.SetLeft( wxMax(0, left
- extra
) );
3081 rect
.SetTop( wxMax(0, top
- extra
) );
3082 rect
.SetRight( rect
.GetRight() + 2*extra
);
3083 rect
.SetBottom( rect
.GetBottom() + 2*extra
);
3086 m_cellEditCtrl
->SetSize( rect
);
3087 m_cellEditCtrl
->Show( TRUE
);
3089 switch ( m_editCtrlType
)
3091 case wxGRID_TEXTCTRL
:
3092 ((wxTextCtrl
*) m_cellEditCtrl
)->SetInsertionPointEnd();
3095 case wxGRID_CHECKBOX
:
3096 // TODO: anything ???
3101 // TODO: anything ???
3105 case wxGRID_COMBOBOX
:
3106 // TODO: anything ???
3111 m_cellEditCtrl
->SetFocus();
3117 void wxGrid::HideCellEditControl()
3119 if ( IsCellEditControlEnabled() )
3121 m_cellEditCtrl
->Show( FALSE
);
3126 void wxGrid::SetEditControlValue( const wxString
& value
)
3132 s
= GetCellValue(m_currentCellCoords
);
3136 if ( IsCellEditControlEnabled() )
3138 switch ( m_editCtrlType
)
3140 case wxGRID_TEXTCTRL
:
3141 ((wxGridTextCtrl
*)m_cellEditCtrl
)->SetStartValue(s
);
3144 case wxGRID_CHECKBOX
:
3145 // TODO: implement this
3150 // TODO: implement this
3154 case wxGRID_COMBOBOX
:
3155 // TODO: implement this
3164 void wxGrid::SaveEditControlValue()
3168 wxWindow
*ctrl
= (wxWindow
*)NULL
;
3170 if ( IsCellEditControlEnabled() )
3172 ctrl
= m_cellEditCtrl
;
3179 bool valueChanged
= FALSE
;
3181 switch ( m_editCtrlType
)
3183 case wxGRID_TEXTCTRL
:
3184 valueChanged
= (((wxGridTextCtrl
*)ctrl
)->GetValue() !=
3185 ((wxGridTextCtrl
*)ctrl
)->GetStartValue());
3186 SetCellValue( m_currentCellCoords
,
3187 ((wxTextCtrl
*) ctrl
)->GetValue() );
3190 case wxGRID_CHECKBOX
:
3191 // TODO: implement this
3196 // TODO: implement this
3200 case wxGRID_COMBOBOX
:
3201 // TODO: implement this
3208 SendEvent( EVT_GRID_CELL_CHANGE
,
3209 m_currentCellCoords
.GetRow(),
3210 m_currentCellCoords
.GetCol() );
3217 // ------ Grid location functions
3218 // Note that all of these functions work with the logical coordinates of
3219 // grid cells and labels so you will need to convert from device
3220 // coordinates for mouse events etc.
3223 void wxGrid::XYToCell( int x
, int y
, wxGridCellCoords
& coords
)
3225 int row
= YToRow(y
);
3226 int col
= XToCol(x
);
3228 if ( row
== -1 || col
== -1 )
3230 coords
= wxGridNoCellCoords
;
3234 coords
.Set( row
, col
);
3239 int wxGrid::YToRow( int y
)
3243 for ( i
= 0; i
< m_numRows
; i
++ )
3245 if ( y
< m_rowBottoms
[i
] ) return i
;
3252 int wxGrid::XToCol( int x
)
3256 for ( i
= 0; i
< m_numCols
; i
++ )
3258 if ( x
< m_colRights
[i
] ) return i
;
3265 // return the row number that that the y coord is near the edge of, or
3266 // -1 if not near an edge
3268 int wxGrid::YToEdgeOfRow( int y
)
3272 for ( i
= 0; i
< m_numRows
; i
++ )
3274 if ( m_rowHeights
[i
] > WXGRID_LABEL_EDGE_ZONE
)
3276 d
= abs( y
- m_rowBottoms
[i
] );
3278 if ( d
< WXGRID_LABEL_EDGE_ZONE
) return i
;
3287 // return the col number that that the x coord is near the edge of, or
3288 // -1 if not near an edge
3290 int wxGrid::XToEdgeOfCol( int x
)
3294 for ( i
= 0; i
< m_numCols
; i
++ )
3296 if ( m_colWidths
[i
] > WXGRID_LABEL_EDGE_ZONE
)
3298 d
= abs( x
- m_colRights
[i
] );
3300 if ( d
< WXGRID_LABEL_EDGE_ZONE
) return i
;
3309 wxRect
wxGrid::CellToRect( int row
, int col
)
3311 wxRect
rect( -1, -1, -1, -1 );
3313 if ( row
>= 0 && row
< m_numRows
&&
3314 col
>= 0 && col
< m_numCols
)
3316 rect
.x
= m_colRights
[col
] - m_colWidths
[col
];
3317 rect
.y
= m_rowBottoms
[row
] - m_rowHeights
[row
];
3318 rect
.width
= m_colWidths
[col
];
3319 rect
.height
= m_rowHeights
[ row
];
3326 bool wxGrid::IsVisible( int row
, int col
, bool wholeCellVisible
)
3328 // get the cell rectangle in logical coords
3330 wxRect
r( CellToRect( row
, col
) );
3332 // convert to device coords
3334 int left
, top
, right
, bottom
;
3335 CalcScrolledPosition( r
.GetLeft(), r
.GetTop(), &left
, &top
);
3336 CalcScrolledPosition( r
.GetRight(), r
.GetBottom(), &right
, &bottom
);
3338 // check against the client area of the grid window
3341 m_gridWin
->GetClientSize( &cw
, &ch
);
3343 if ( wholeCellVisible
)
3345 // is the cell wholly visible ?
3347 return ( left
>= 0 && right
<= cw
&&
3348 top
>= 0 && bottom
<= ch
);
3352 // is the cell partly visible ?
3354 return ( ((left
>=0 && left
< cw
) || (right
> 0 && right
<= cw
)) &&
3355 ((top
>=0 && top
< ch
) || (bottom
> 0 && bottom
<= ch
)) );
3360 // make the specified cell location visible by doing a minimal amount
3363 void wxGrid::MakeCellVisible( int row
, int col
)
3366 int xpos
= -1, ypos
= -1;
3368 if ( row
>= 0 && row
< m_numRows
&&
3369 col
>= 0 && col
< m_numCols
)
3371 // get the cell rectangle in logical coords
3373 wxRect
r( CellToRect( row
, col
) );
3375 // convert to device coords
3377 int left
, top
, right
, bottom
;
3378 CalcScrolledPosition( r
.GetLeft(), r
.GetTop(), &left
, &top
);
3379 CalcScrolledPosition( r
.GetRight(), r
.GetBottom(), &right
, &bottom
);
3382 m_gridWin
->GetClientSize( &cw
, &ch
);
3388 else if ( bottom
> ch
)
3390 int h
= r
.GetHeight();
3392 for ( i
= row
-1; i
>= 0; i
-- )
3394 if ( h
+ m_rowHeights
[i
] > ch
) break;
3396 h
+= m_rowHeights
[i
];
3397 ypos
-= m_rowHeights
[i
];
3400 // we divide it later by GRID_SCROLL_LINE, make sure that we don't
3401 // have rounding errors (this is important, because if we do, we
3402 // might not scroll at all and some cells won't be redrawn)
3403 ypos
+= GRID_SCROLL_LINE
/ 2;
3410 else if ( right
> cw
)
3412 int w
= r
.GetWidth();
3414 for ( i
= col
-1; i
>= 0; i
-- )
3416 if ( w
+ m_colWidths
[i
] > cw
) break;
3418 w
+= m_colWidths
[i
];
3419 xpos
-= m_colWidths
[i
];
3422 // see comment for ypos above
3423 xpos
+= GRID_SCROLL_LINE
/ 2;
3426 if ( xpos
!= -1 || ypos
!= -1 )
3428 if ( xpos
!= -1 ) xpos
/= GRID_SCROLL_LINE
;
3429 if ( ypos
!= -1 ) ypos
/= GRID_SCROLL_LINE
;
3430 Scroll( xpos
, ypos
);
3438 // ------ Grid cursor movement functions
3441 bool wxGrid::MoveCursorUp()
3443 if ( m_currentCellCoords
!= wxGridNoCellCoords
&&
3444 m_currentCellCoords
.GetRow() > 0 )
3446 MakeCellVisible( m_currentCellCoords
.GetRow() - 1,
3447 m_currentCellCoords
.GetCol() );
3449 SetCurrentCell( m_currentCellCoords
.GetRow() - 1,
3450 m_currentCellCoords
.GetCol() );
3459 bool wxGrid::MoveCursorDown()
3461 // TODO: allow for scrolling
3463 if ( m_currentCellCoords
!= wxGridNoCellCoords
&&
3464 m_currentCellCoords
.GetRow() < m_numRows
-1 )
3466 MakeCellVisible( m_currentCellCoords
.GetRow() + 1,
3467 m_currentCellCoords
.GetCol() );
3469 SetCurrentCell( m_currentCellCoords
.GetRow() + 1,
3470 m_currentCellCoords
.GetCol() );
3479 bool wxGrid::MoveCursorLeft()
3481 if ( m_currentCellCoords
!= wxGridNoCellCoords
&&
3482 m_currentCellCoords
.GetCol() > 0 )
3484 MakeCellVisible( m_currentCellCoords
.GetRow(),
3485 m_currentCellCoords
.GetCol() - 1 );
3487 SetCurrentCell( m_currentCellCoords
.GetRow(),
3488 m_currentCellCoords
.GetCol() - 1 );
3497 bool wxGrid::MoveCursorRight()
3499 if ( m_currentCellCoords
!= wxGridNoCellCoords
&&
3500 m_currentCellCoords
.GetCol() < m_numCols
- 1 )
3502 MakeCellVisible( m_currentCellCoords
.GetRow(),
3503 m_currentCellCoords
.GetCol() + 1 );
3505 SetCurrentCell( m_currentCellCoords
.GetRow(),
3506 m_currentCellCoords
.GetCol() + 1 );
3515 bool wxGrid::MovePageUp()
3517 if ( m_currentCellCoords
== wxGridNoCellCoords
) return FALSE
;
3519 int row
= m_currentCellCoords
.GetRow();
3523 m_gridWin
->GetClientSize( &cw
, &ch
);
3525 int y
= m_rowBottoms
[ row
] - m_rowHeights
[ row
];
3526 int newRow
= YToRow( y
- ch
+ 1 );
3531 else if ( newRow
== row
)
3536 MakeCellVisible( newRow
, m_currentCellCoords
.GetCol() );
3537 SetCurrentCell( newRow
, m_currentCellCoords
.GetCol() );
3545 bool wxGrid::MovePageDown()
3547 if ( m_currentCellCoords
== wxGridNoCellCoords
) return FALSE
;
3549 int row
= m_currentCellCoords
.GetRow();
3550 if ( row
< m_numRows
)
3553 m_gridWin
->GetClientSize( &cw
, &ch
);
3555 int y
= m_rowBottoms
[ row
] - m_rowHeights
[ row
];
3556 int newRow
= YToRow( y
+ ch
);
3559 newRow
= m_numRows
- 1;
3561 else if ( newRow
== row
)
3566 MakeCellVisible( newRow
, m_currentCellCoords
.GetCol() );
3567 SetCurrentCell( newRow
, m_currentCellCoords
.GetCol() );
3575 bool wxGrid::MoveCursorUpBlock()
3578 m_currentCellCoords
!= wxGridNoCellCoords
&&
3579 m_currentCellCoords
.GetRow() > 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
-1, col
) )
3597 // starting at the top of a block: find the next block
3603 if ( !(m_table
->IsEmptyCell(row
, col
)) ) break;
3608 // starting within a block: find the top of the block
3613 if ( m_table
->IsEmptyCell(row
, col
) )
3621 MakeCellVisible( row
, col
);
3622 SetCurrentCell( row
, col
);
3630 bool wxGrid::MoveCursorDownBlock()
3633 m_currentCellCoords
!= wxGridNoCellCoords
&&
3634 m_currentCellCoords
.GetRow() < m_numRows
-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 ( row
< m_numRows
-1 )
3647 if ( !(m_table
->IsEmptyCell(row
, col
)) ) break;
3650 else if ( m_table
->IsEmptyCell(row
+1, col
) )
3652 // starting at the bottom of a block: find the next block
3655 while ( row
< m_numRows
-1 )
3658 if ( !(m_table
->IsEmptyCell(row
, col
)) ) break;
3663 // starting within a block: find the bottom of the block
3665 while ( row
< m_numRows
-1 )
3668 if ( m_table
->IsEmptyCell(row
, col
) )
3676 MakeCellVisible( row
, col
);
3677 SetCurrentCell( row
, col
);
3685 bool wxGrid::MoveCursorLeftBlock()
3688 m_currentCellCoords
!= wxGridNoCellCoords
&&
3689 m_currentCellCoords
.GetCol() > 0 )
3691 int row
= m_currentCellCoords
.GetRow();
3692 int col
= m_currentCellCoords
.GetCol();
3694 if ( m_table
->IsEmptyCell(row
, col
) )
3696 // starting in an empty cell: find the next block of
3702 if ( !(m_table
->IsEmptyCell(row
, col
)) ) break;
3705 else if ( m_table
->IsEmptyCell(row
, col
-1) )
3707 // starting at the left of a block: find the next block
3713 if ( !(m_table
->IsEmptyCell(row
, col
)) ) break;
3718 // starting within a block: find the left of the block
3723 if ( m_table
->IsEmptyCell(row
, col
) )
3731 MakeCellVisible( row
, col
);
3732 SetCurrentCell( row
, col
);
3740 bool wxGrid::MoveCursorRightBlock()
3743 m_currentCellCoords
!= wxGridNoCellCoords
&&
3744 m_currentCellCoords
.GetCol() < m_numCols
-1 )
3746 int row
= m_currentCellCoords
.GetRow();
3747 int col
= m_currentCellCoords
.GetCol();
3749 if ( m_table
->IsEmptyCell(row
, col
) )
3751 // starting in an empty cell: find the next block of
3754 while ( col
< m_numCols
-1 )
3757 if ( !(m_table
->IsEmptyCell(row
, col
)) ) break;
3760 else if ( m_table
->IsEmptyCell(row
, col
+1) )
3762 // starting at the right of a block: find the next block
3765 while ( col
< m_numCols
-1 )
3768 if ( !(m_table
->IsEmptyCell(row
, col
)) ) break;
3773 // starting within a block: find the right of the block
3775 while ( col
< m_numCols
-1 )
3778 if ( m_table
->IsEmptyCell(row
, col
) )
3786 MakeCellVisible( row
, col
);
3787 SetCurrentCell( row
, col
);
3798 // ------ Label values and formatting
3801 void wxGrid::GetRowLabelAlignment( int *horiz
, int *vert
)
3803 *horiz
= m_rowLabelHorizAlign
;
3804 *vert
= m_rowLabelVertAlign
;
3807 void wxGrid::GetColLabelAlignment( int *horiz
, int *vert
)
3809 *horiz
= m_colLabelHorizAlign
;
3810 *vert
= m_colLabelVertAlign
;
3813 wxString
wxGrid::GetRowLabelValue( int row
)
3817 return m_table
->GetRowLabelValue( row
);
3827 wxString
wxGrid::GetColLabelValue( int col
)
3831 return m_table
->GetColLabelValue( col
);
3841 void wxGrid::SetRowLabelSize( int width
)
3843 // TODO: how to do this with the box sizers ?
3846 void wxGrid::SetColLabelSize( int height
)
3848 // TODO: how to do this with the box sizers ?
3851 void wxGrid::SetLabelBackgroundColour( const wxColour
& colour
)
3853 if ( m_labelBackgroundColour
!= colour
)
3855 m_labelBackgroundColour
= colour
;
3856 m_rowLabelWin
->SetBackgroundColour( colour
);
3857 m_colLabelWin
->SetBackgroundColour( colour
);
3858 m_cornerLabelWin
->SetBackgroundColour( colour
);
3860 if ( !GetBatchCount() )
3862 m_rowLabelWin
->Refresh();
3863 m_colLabelWin
->Refresh();
3864 m_cornerLabelWin
->Refresh();
3869 void wxGrid::SetLabelTextColour( const wxColour
& colour
)
3871 if ( m_labelTextColour
!= colour
)
3873 m_labelTextColour
= colour
;
3874 if ( !GetBatchCount() )
3876 m_rowLabelWin
->Refresh();
3877 m_colLabelWin
->Refresh();
3882 void wxGrid::SetLabelFont( const wxFont
& font
)
3885 if ( !GetBatchCount() )
3887 m_rowLabelWin
->Refresh();
3888 m_colLabelWin
->Refresh();
3892 void wxGrid::SetRowLabelAlignment( int horiz
, int vert
)
3894 if ( horiz
== wxLEFT
|| horiz
== wxCENTRE
|| horiz
== wxRIGHT
)
3896 m_rowLabelHorizAlign
= horiz
;
3899 if ( vert
== wxTOP
|| vert
== wxCENTRE
|| vert
== wxBOTTOM
)
3901 m_rowLabelVertAlign
= vert
;
3904 if ( !GetBatchCount() )
3906 m_rowLabelWin
->Refresh();
3907 m_colLabelWin
->Refresh();
3911 void wxGrid::SetColLabelAlignment( int horiz
, int vert
)
3913 if ( horiz
== wxLEFT
|| horiz
== wxCENTRE
|| horiz
== wxRIGHT
)
3915 m_colLabelHorizAlign
= horiz
;
3918 if ( vert
== wxTOP
|| vert
== wxCENTRE
|| vert
== wxBOTTOM
)
3920 m_colLabelVertAlign
= vert
;
3923 if ( !GetBatchCount() )
3925 m_rowLabelWin
->Refresh();
3926 m_colLabelWin
->Refresh();
3930 void wxGrid::SetRowLabelValue( int row
, const wxString
& s
)
3934 m_table
->SetRowLabelValue( row
, s
);
3935 if ( !GetBatchCount() )
3937 // TODO: Optimize this
3939 m_rowLabelWin
->Refresh();
3944 void wxGrid::SetColLabelValue( int col
, const wxString
& s
)
3948 m_table
->SetColLabelValue( col
, s
);
3949 if ( !GetBatchCount() )
3951 // TODO: optimize this
3953 m_colLabelWin
->Refresh();
3958 void wxGrid::SetGridLineColour( const wxColour
& colour
)
3960 if ( m_gridLineColour
!= colour
)
3962 m_gridLineColour
= colour
;
3964 wxClientDC
dc( m_gridWin
);
3966 DrawAllGridLines( dc
);
3970 void wxGrid::EnableGridLines( bool enable
)
3972 if ( enable
!= m_gridLinesEnabled
)
3974 m_gridLinesEnabled
= enable
;
3976 if ( !GetBatchCount() )
3980 wxClientDC
dc( m_gridWin
);
3982 DrawAllGridLines( dc
);
3986 m_gridWin
->Refresh();
3993 int wxGrid::GetDefaultRowSize()
3995 return m_defaultRowHeight
;
3998 int wxGrid::GetRowSize( int row
)
4000 if ( row
>= 0 && row
< m_numRows
)
4001 return m_rowHeights
[row
];
4003 return 0; // TODO: log an error here
4006 int wxGrid::GetDefaultColSize()
4008 return m_defaultColWidth
;
4011 int wxGrid::GetColSize( int col
)
4013 if ( col
>= 0 && col
< m_numCols
)
4014 return m_colWidths
[col
];
4016 return 0; // TODO: log an error here
4019 wxColour
wxGrid::GetDefaultCellBackgroundColour()
4021 // TODO: replace this temp test code
4023 return wxColour( 255, 255, 255 );
4026 wxColour
wxGrid::GetCellBackgroundColour( int WXUNUSED(row
), int WXUNUSED(col
) )
4028 // TODO: replace this temp test code
4030 return wxColour( 255, 255, 255 );
4033 wxColour
wxGrid::GetDefaultCellTextColour()
4035 // TODO: replace this temp test code
4037 return wxColour( 0, 0, 0 );
4040 wxColour
wxGrid::GetCellTextColour( int WXUNUSED(row
), int WXUNUSED(col
) )
4042 // TODO: replace this temp test code
4044 return wxColour( 0, 0, 0 );
4048 wxFont
wxGrid::GetDefaultCellFont()
4050 return m_defaultCellFont
;
4053 wxFont
wxGrid::GetCellFont( int WXUNUSED(row
), int WXUNUSED(col
) )
4055 // TODO: replace this temp test code
4057 return m_defaultCellFont
;
4060 void wxGrid::GetDefaultCellAlignment( int *horiz
, int *vert
)
4062 // TODO: replace this temp test code
4068 void wxGrid::GetCellAlignment( int WXUNUSED(row
), int WXUNUSED(col
), int *horiz
, int *vert
)
4070 // TODO: replace this temp test code
4076 void wxGrid::SetDefaultRowSize( int height
, bool resizeExistingRows
)
4078 m_defaultRowHeight
= wxMax( height
, WXGRID_MIN_ROW_HEIGHT
);
4080 if ( resizeExistingRows
)
4084 for ( row
= 0; row
< m_numRows
; row
++ )
4086 m_rowHeights
[row
] = m_defaultRowHeight
;
4087 bottom
+= m_defaultRowHeight
;
4088 m_rowBottoms
[row
] = bottom
;
4094 void wxGrid::SetRowSize( int row
, int height
)
4098 if ( row
>= 0 && row
< m_numRows
)
4100 int h
= wxMax( 0, height
);
4101 int diff
= h
- m_rowHeights
[row
];
4103 m_rowHeights
[row
] = h
;
4104 for ( i
= row
; i
< m_numRows
; i
++ )
4106 m_rowBottoms
[i
] += diff
;
4110 // Note: we are ending the event *after* doing
4111 // default processing in this case
4113 SendEvent( EVT_GRID_ROW_SIZE
,
4118 // TODO: log an error here
4122 void wxGrid::SetDefaultColSize( int width
, bool resizeExistingCols
)
4124 m_defaultColWidth
= wxMax( width
, WXGRID_MIN_COL_WIDTH
);
4126 if ( resizeExistingCols
)
4130 for ( col
= 0; col
< m_numCols
; col
++ )
4132 m_colWidths
[col
] = m_defaultColWidth
;
4133 right
+= m_defaultColWidth
;
4134 m_colRights
[col
] = right
;
4140 void wxGrid::SetColSize( int col
, int width
)
4144 if ( col
>= 0 && col
< m_numCols
)
4146 int w
= wxMax( 0, width
);
4147 int diff
= w
- m_colWidths
[col
];
4148 m_colWidths
[col
] = w
;
4150 for ( i
= col
; i
< m_numCols
; i
++ )
4152 m_colRights
[i
] += diff
;
4156 // Note: we are ending the event *after* doing
4157 // default processing in this case
4159 SendEvent( EVT_GRID_COL_SIZE
,
4164 // TODO: log an error here
4168 void wxGrid::SetDefaultCellBackgroundColour( const wxColour
& )
4170 // TODO: everything !!!
4174 void wxGrid::SetCellBackgroundColour( int WXUNUSED(row
), int WXUNUSED(col
), const wxColour
& )
4176 // TODO: everything !!!
4180 void wxGrid::SetDefaultCellTextColour( const wxColour
& )
4182 // TODO: everything !!!
4186 void wxGrid::SetCellTextColour( int WXUNUSED(row
), int WXUNUSED(col
), const wxColour
& )
4188 // TODO: everything !!!
4192 void wxGrid::SetDefaultCellFont( const wxFont
& )
4194 // TODO: everything !!!
4198 void wxGrid::SetCellFont( int WXUNUSED(row
), int WXUNUSED(col
), const wxFont
& )
4200 // TODO: everything !!!
4204 void wxGrid::SetDefaultCellAlignment( int WXUNUSED(horiz
), int WXUNUSED(vert
) )
4206 // TODO: everything !!!
4210 void wxGrid::SetCellAlignment( int WXUNUSED(row
), int WXUNUSED(col
), int WXUNUSED(horiz
), int WXUNUSED(vert
) )
4212 // TODO: everything !!!
4219 // ------ cell value accessor functions
4222 void wxGrid::SetCellValue( int row
, int col
, const wxString
& s
)
4226 m_table
->SetValue( row
, col
, s
.c_str() );
4227 if ( !GetBatchCount() )
4229 wxClientDC
dc( m_gridWin
);
4231 DrawCell( dc
, wxGridCellCoords(row
, col
) );
4234 #if 0 // TODO: edit in place
4236 if ( m_currentCellCoords
.GetRow() == row
&&
4237 m_currentCellCoords
.GetCol() == col
)
4239 SetEditControlValue( s
);
4248 // ------ Block, row and col selection
4251 void wxGrid::SelectRow( int row
, bool addToSelected
)
4255 if ( IsSelection() && addToSelected
)
4257 if ( m_selectedTopLeft
.GetRow() > row
)
4258 m_selectedTopLeft
.SetRow( row
);
4260 m_selectedTopLeft
.SetCol( 0 );
4262 if ( m_selectedBottomRight
.GetRow() < row
)
4263 m_selectedBottomRight
.SetRow( row
);
4265 m_selectedBottomRight
.SetCol( m_numCols
- 1 );
4267 // TODO: optimize this so that we only refresh the newly
4270 r
= SelectionToDeviceRect();
4271 if ( r
!= wxGridNoCellRect
) m_gridWin
->Refresh( TRUE
, &r
);
4275 r
= SelectionToDeviceRect();
4277 if ( r
!= wxGridNoCellRect
) m_gridWin
->Refresh( TRUE
, &r
);
4279 m_selectedTopLeft
.Set( row
, 0 );
4280 m_selectedBottomRight
.Set( row
, m_numCols
-1 );
4281 r
= SelectionToDeviceRect();
4282 m_gridWin
->Refresh( TRUE
, &r
);
4285 wxGridRangeSelectEvent
gridEvt( GetId(),
4286 EVT_GRID_RANGE_SELECT
,
4289 m_selectedBottomRight
);
4291 GetEventHandler()->ProcessEvent(gridEvt
);
4295 void wxGrid::SelectCol( int col
, bool addToSelected
)
4299 if ( IsSelection() && addToSelected
)
4301 if ( m_selectedTopLeft
.GetCol() > col
)
4302 m_selectedTopLeft
.SetCol( col
);
4304 m_selectedTopLeft
.SetRow( 0 );
4306 if ( m_selectedBottomRight
.GetCol() < col
)
4307 m_selectedBottomRight
.SetCol( col
);
4309 m_selectedBottomRight
.SetRow( m_numRows
- 1 );
4311 // TODO: optimize this so that we only refresh the newly
4314 r
= SelectionToDeviceRect();
4315 if ( r
!= wxGridNoCellRect
) m_gridWin
->Refresh( TRUE
, &r
);
4319 r
= SelectionToDeviceRect();
4321 if ( r
!= wxGridNoCellRect
) m_gridWin
->Refresh( TRUE
, &r
);
4323 m_selectedTopLeft
.Set( 0, col
);
4324 m_selectedBottomRight
.Set( m_numRows
-1, col
);
4325 r
= SelectionToDeviceRect();
4326 m_gridWin
->Refresh( TRUE
, &r
);
4329 wxGridRangeSelectEvent
gridEvt( GetId(),
4330 EVT_GRID_RANGE_SELECT
,
4333 m_selectedBottomRight
);
4335 GetEventHandler()->ProcessEvent(gridEvt
);
4339 void wxGrid::SelectBlock( int topRow
, int leftCol
, int bottomRow
, int rightCol
)
4342 bool changed
= FALSE
;
4343 wxGridCellCoords updateTopLeft
, updateBottomRight
;
4345 if ( topRow
> bottomRow
)
4352 if ( leftCol
> rightCol
)
4359 updateTopLeft
= m_selectedTopLeft
;
4360 if (m_selectedTopLeft
!= wxGridCellCoords( topRow
, leftCol
) )
4362 m_selectedTopLeft
= wxGridCellCoords( topRow
, leftCol
);
4363 if (updateTopLeft
== wxGridNoCellCoords
)
4365 updateTopLeft
= m_selectedTopLeft
;
4369 if(updateTopLeft
.GetRow() > topRow
)
4370 updateTopLeft
.SetRow(topRow
);
4371 if (updateTopLeft
.GetCol() > leftCol
)
4372 updateTopLeft
.SetCol(leftCol
);
4377 updateBottomRight
= m_selectedBottomRight
;
4378 if (m_selectedBottomRight
!= wxGridCellCoords( bottomRow
, rightCol
) )
4380 m_selectedBottomRight
= wxGridCellCoords( bottomRow
, rightCol
);
4381 if (updateBottomRight
== wxGridNoCellCoords
)
4383 updateBottomRight
= m_selectedBottomRight
;
4387 if (updateBottomRight
.GetRow() < bottomRow
)
4388 updateBottomRight
.SetRow(bottomRow
);
4389 if (updateBottomRight
.GetCol() < rightCol
)
4390 updateBottomRight
.SetCol(rightCol
);
4397 wxRect
r( BlockToDeviceRect( updateTopLeft
, updateBottomRight
) );
4398 m_gridWin
->Refresh( TRUE
, &r
);
4401 // only generate an event if the block is not being selected by
4402 // dragging the mouse (in which case the event will be generated in
4403 // the mouse event handler)
4404 if ( !m_isDragging
)
4406 wxGridRangeSelectEvent
gridEvt( GetId(),
4407 EVT_GRID_RANGE_SELECT
,
4410 m_selectedBottomRight
);
4412 GetEventHandler()->ProcessEvent(gridEvt
);
4416 void wxGrid::SelectAll()
4418 m_selectedTopLeft
.Set( 0, 0 );
4419 m_selectedBottomRight
.Set( m_numRows
-1, m_numCols
-1 );
4421 m_gridWin
->Refresh();
4425 void wxGrid::ClearSelection()
4427 m_selectedTopLeft
= wxGridNoCellCoords
;
4428 m_selectedBottomRight
= wxGridNoCellCoords
;
4432 // This function returns the rectangle that encloses the given block
4433 // in device coords clipped to the client size of the grid window.
4435 wxRect
wxGrid::BlockToDeviceRect( const wxGridCellCoords
&topLeft
,
4436 const wxGridCellCoords
&bottomRight
)
4438 wxRect
rect( wxGridNoCellRect
);
4441 cellRect
= CellToRect( topLeft
);
4442 if ( cellRect
!= wxGridNoCellRect
)
4448 rect
= wxRect( 0, 0, 0, 0 );
4451 cellRect
= CellToRect( bottomRight
);
4452 if ( cellRect
!= wxGridNoCellRect
)
4458 return wxGridNoCellRect
;
4461 // convert to scrolled coords
4463 int left
, top
, right
, bottom
;
4464 CalcScrolledPosition( rect
.GetLeft(), rect
.GetTop(), &left
, &top
);
4465 CalcScrolledPosition( rect
.GetRight(), rect
.GetBottom(), &right
, &bottom
);
4468 m_gridWin
->GetClientSize( &cw
, &ch
);
4470 rect
.SetLeft( wxMax(0, left
) );
4471 rect
.SetTop( wxMax(0, top
) );
4472 rect
.SetRight( wxMin(cw
, right
) );
4473 rect
.SetBottom( wxMin(ch
, bottom
) );
4481 // ------ Grid event classes
4484 IMPLEMENT_DYNAMIC_CLASS( wxGridEvent
, wxEvent
)
4486 wxGridEvent::wxGridEvent( int id
, wxEventType type
, wxObject
* obj
,
4487 int row
, int col
, int x
, int y
,
4488 bool control
, bool shift
, bool alt
, bool meta
)
4489 : wxNotifyEvent( type
, id
)
4495 m_control
= control
;
4500 SetEventObject(obj
);
4504 IMPLEMENT_DYNAMIC_CLASS( wxGridSizeEvent
, wxEvent
)
4506 wxGridSizeEvent::wxGridSizeEvent( int id
, wxEventType type
, wxObject
* obj
,
4507 int rowOrCol
, int x
, int y
,
4508 bool control
, bool shift
, bool alt
, bool meta
)
4509 : wxNotifyEvent( type
, id
)
4511 m_rowOrCol
= rowOrCol
;
4514 m_control
= control
;
4519 SetEventObject(obj
);
4523 IMPLEMENT_DYNAMIC_CLASS( wxGridRangeSelectEvent
, wxEvent
)
4525 wxGridRangeSelectEvent::wxGridRangeSelectEvent(int id
, wxEventType type
, wxObject
* obj
,
4526 const wxGridCellCoords
& topLeft
,
4527 const wxGridCellCoords
& bottomRight
,
4528 bool control
, bool shift
, bool alt
, bool meta
)
4529 : wxNotifyEvent( type
, id
)
4531 m_topLeft
= topLeft
;
4532 m_bottomRight
= bottomRight
;
4533 m_control
= control
;
4538 SetEventObject(obj
);
4542 #endif // ifndef wxUSE_NEW_GRID