1 /////////////////////////////////////////////////////////////////////////////
2 // Name: src/generic/datavgen.cpp
3 // Purpose: wxDataViewCtrl generic implementation
4 // Author: Robert Roebling
6 // Copyright: (c) 1998 Robert Roebling
7 // Licence: wxWindows licence
8 /////////////////////////////////////////////////////////////////////////////
10 // For compilers that support precompilation, includes "wx.h".
11 #include "wx/wxprec.h"
13 #if wxUSE_DATAVIEWCTRL
15 #include "wx/dataview.h"
17 #ifdef wxUSE_GENERICDATAVIEWCTRL
24 #include "wx/stockitem.h"
25 #include "wx/dcclient.h"
26 #include "wx/calctrl.h"
27 #include "wx/popupwin.h"
28 #include "wx/renderer.h"
32 #include "wx/msw/wrapwin.h"
35 //-----------------------------------------------------------------------------
37 //-----------------------------------------------------------------------------
41 //-----------------------------------------------------------------------------
42 // wxDataViewHeaderWindow
43 //-----------------------------------------------------------------------------
45 class wxDataViewHeaderWindow
: public wxWindow
48 wxDataViewHeaderWindow( wxDataViewCtrl
*parent
,
50 const wxPoint
&pos
= wxDefaultPosition
,
51 const wxSize
&size
= wxDefaultSize
,
52 const wxString
&name
= wxT("wxdataviewctrlheaderwindow") );
53 ~wxDataViewHeaderWindow();
55 void SetOwner( wxDataViewCtrl
* owner
) { m_owner
= owner
; }
56 wxDataViewCtrl
*GetOwner() { return m_owner
; }
58 void OnPaint( wxPaintEvent
&event
);
59 void OnMouse( wxMouseEvent
&event
);
60 void OnSetFocus( wxFocusEvent
&event
);
63 wxDataViewCtrl
*m_owner
;
64 wxCursor
*m_resizeCursor
;
67 DECLARE_DYNAMIC_CLASS(wxDataViewHeaderWindow
)
71 //-----------------------------------------------------------------------------
72 // wxDataViewRenameTimer
73 //-----------------------------------------------------------------------------
75 class wxDataViewRenameTimer
: public wxTimer
78 wxDataViewMainWindow
*m_owner
;
81 wxDataViewRenameTimer( wxDataViewMainWindow
*owner
);
85 //-----------------------------------------------------------------------------
86 // wxDataViewTextCtrlWrapper: wraps a wxTextCtrl for inline editing
87 //-----------------------------------------------------------------------------
89 class wxDataViewTextCtrlWrapper
: public wxEvtHandler
92 // NB: text must be a valid object but not Create()d yet
93 wxDataViewTextCtrlWrapper( wxDataViewMainWindow
*owner
,
95 wxDataViewListModel
*model
,
96 size_t col
, size_t row
,
99 wxTextCtrl
*GetText() const { return m_text
; }
101 void AcceptChangesAndFinish();
104 void OnChar( wxKeyEvent
&event
);
105 void OnKeyUp( wxKeyEvent
&event
);
106 void OnKillFocus( wxFocusEvent
&event
);
108 bool AcceptChanges();
112 wxDataViewMainWindow
*m_owner
;
114 wxString m_startValue
;
115 wxDataViewListModel
*m_model
;
119 bool m_aboutToFinish
;
121 DECLARE_EVENT_TABLE()
124 //-----------------------------------------------------------------------------
125 // wxDataViewMainWindow
126 //-----------------------------------------------------------------------------
128 class wxDataViewMainWindow
: public wxWindow
131 wxDataViewMainWindow( wxDataViewCtrl
*parent
,
133 const wxPoint
&pos
= wxDefaultPosition
,
134 const wxSize
&size
= wxDefaultSize
,
135 const wxString
&name
= wxT("wxdataviewctrlmainwindow") );
136 ~wxDataViewMainWindow();
138 // notifications from wxDataViewListModel
141 bool RowInserted( size_t before
);
142 bool RowDeleted( size_t row
);
143 bool RowChanged( size_t row
);
144 bool ValueChanged( size_t col
, size_t row
);
145 bool RowsReordered( size_t *new_order
);
148 void SetOwner( wxDataViewCtrl
* owner
) { m_owner
= owner
; }
149 wxDataViewCtrl
*GetOwner() { return m_owner
; }
151 void OnPaint( wxPaintEvent
&event
);
152 void OnMouse( wxMouseEvent
&event
);
153 void OnSetFocus( wxFocusEvent
&event
);
155 void UpdateDisplay();
156 void RecalculateDisplay();
157 void OnInternalIdle();
159 void OnRenameTimer();
160 void FinishEditing( wxTextCtrl
*text
);
162 void ScrollWindow( int dx
, int dy
, const wxRect
*rect
);
164 wxDataViewCtrl
*m_owner
;
168 wxDataViewColumn
*m_currentCol
;
171 wxDataViewRenameTimer
*m_renameTimer
;
172 wxDataViewTextCtrlWrapper
*m_textctrlWrapper
;
176 DECLARE_DYNAMIC_CLASS(wxDataViewMainWindow
)
177 DECLARE_EVENT_TABLE()
180 // ---------------------------------------------------------
181 // wxGenericDataViewListModelNotifier
182 // ---------------------------------------------------------
184 class wxGenericDataViewListModelNotifier
: public wxDataViewListModelNotifier
187 wxGenericDataViewListModelNotifier( wxDataViewMainWindow
*mainWindow
)
188 { m_mainWindow
= mainWindow
; }
190 virtual bool RowAppended()
191 { return m_mainWindow
->RowAppended(); }
192 virtual bool RowPrepended()
193 { return m_mainWindow
->RowPrepended(); }
194 virtual bool RowInserted( size_t before
)
195 { return m_mainWindow
->RowInserted( before
); }
196 virtual bool RowDeleted( size_t row
)
197 { return m_mainWindow
->RowDeleted( row
); }
198 virtual bool RowChanged( size_t row
)
199 { return m_mainWindow
->RowChanged( row
); }
200 virtual bool ValueChanged( size_t col
, size_t row
)
201 { return m_mainWindow
->ValueChanged( col
, row
); }
202 virtual bool RowsReordered( size_t *new_order
)
203 { return m_mainWindow
->RowsReordered( new_order
); }
204 virtual bool Cleared()
205 { return m_mainWindow
->Cleared(); }
207 wxDataViewMainWindow
*m_mainWindow
;
210 // ---------------------------------------------------------
212 // ---------------------------------------------------------
214 IMPLEMENT_ABSTRACT_CLASS(wxDataViewCell
, wxDataViewCellBase
)
216 wxDataViewCell::wxDataViewCell( const wxString
&varianttype
, wxDataViewCellMode mode
) :
217 wxDataViewCellBase( varianttype
, mode
)
222 wxDataViewCell::~wxDataViewCell()
228 wxDC
*wxDataViewCell::GetDC()
232 if (GetOwner() == NULL
)
234 if (GetOwner()->GetOwner() == NULL
)
236 m_dc
= new wxClientDC( GetOwner()->GetOwner() );
242 // ---------------------------------------------------------
243 // wxDataViewCustomCell
244 // ---------------------------------------------------------
246 IMPLEMENT_ABSTRACT_CLASS(wxDataViewCustomCell
, wxDataViewCell
)
248 wxDataViewCustomCell::wxDataViewCustomCell( const wxString
&varianttype
,
249 wxDataViewCellMode mode
) :
250 wxDataViewCell( varianttype
, mode
)
254 // ---------------------------------------------------------
255 // wxDataViewTextCell
256 // ---------------------------------------------------------
258 IMPLEMENT_ABSTRACT_CLASS(wxDataViewTextCell
, wxDataViewCustomCell
)
260 wxDataViewTextCell::wxDataViewTextCell( const wxString
&varianttype
, wxDataViewCellMode mode
) :
261 wxDataViewCustomCell( varianttype
, mode
)
265 bool wxDataViewTextCell::SetValue( const wxVariant
&value
)
267 m_text
= value
.GetString();
272 bool wxDataViewTextCell::GetValue( wxVariant
& WXUNUSED(value
) )
277 bool wxDataViewTextCell::Render( wxRect cell
, wxDC
*dc
, int WXUNUSED(state
) )
279 dc
->DrawText( m_text
, cell
.x
, cell
.y
);
284 wxSize
wxDataViewTextCell::GetSize()
286 return wxSize(80,20);
289 // ---------------------------------------------------------
290 // wxDataViewToggleCell
291 // ---------------------------------------------------------
293 IMPLEMENT_ABSTRACT_CLASS(wxDataViewToggleCell
, wxDataViewCustomCell
)
295 wxDataViewToggleCell::wxDataViewToggleCell( const wxString
&varianttype
,
296 wxDataViewCellMode mode
) :
297 wxDataViewCustomCell( varianttype
, mode
)
302 bool wxDataViewToggleCell::SetValue( const wxVariant
&value
)
304 m_toggle
= value
.GetBool();
309 bool wxDataViewToggleCell::GetValue( wxVariant
&WXUNUSED(value
) )
314 bool wxDataViewToggleCell::Render( wxRect cell
, wxDC
*dc
, int WXUNUSED(state
) )
316 // User wxRenderer here
319 rect
.x
= cell
.x
+ cell
.width
/2 - 10;
321 rect
.y
= cell
.y
+ cell
.height
/2 - 10;
326 flags
|= wxCONTROL_CHECKED
;
327 if (GetMode() != wxDATAVIEW_CELL_ACTIVATABLE
)
328 flags
|= wxCONTROL_DISABLED
;
330 wxRendererNative::Get().DrawCheckButton(
331 GetOwner()->GetOwner(),
339 bool wxDataViewToggleCell::Activate( wxRect
WXUNUSED(cell
), wxDataViewListModel
*model
, size_t col
, size_t row
)
341 bool value
= !m_toggle
;
342 wxVariant variant
= value
;
343 model
->SetValue( variant
, col
, row
);
344 model
->ValueChanged( col
, row
);
348 wxSize
wxDataViewToggleCell::GetSize()
350 return wxSize(20,20);
353 // ---------------------------------------------------------
354 // wxDataViewProgressCell
355 // ---------------------------------------------------------
357 IMPLEMENT_ABSTRACT_CLASS(wxDataViewProgressCell
, wxDataViewCustomCell
)
359 wxDataViewProgressCell::wxDataViewProgressCell( const wxString
&label
,
360 const wxString
&varianttype
, wxDataViewCellMode mode
) :
361 wxDataViewCustomCell( varianttype
, mode
)
367 wxDataViewProgressCell::~wxDataViewProgressCell()
371 bool wxDataViewProgressCell::SetValue( const wxVariant
&value
)
373 m_value
= (long) value
;
375 if (m_value
< 0) m_value
= 0;
376 if (m_value
> 100) m_value
= 100;
381 bool wxDataViewProgressCell::Render( wxRect cell
, wxDC
*dc
, int WXUNUSED(state
) )
383 double pct
= (double)m_value
/ 100.0;
385 bar
.width
= (int)(cell
.width
* pct
);
386 dc
->SetPen( *wxTRANSPARENT_PEN
);
387 dc
->SetBrush( *wxBLUE_BRUSH
);
388 dc
->DrawRectangle( bar
);
390 dc
->SetBrush( *wxTRANSPARENT_BRUSH
);
391 dc
->SetPen( *wxBLACK_PEN
);
392 dc
->DrawRectangle( cell
);
397 wxSize
wxDataViewProgressCell::GetSize()
399 return wxSize(40,12);
402 // ---------------------------------------------------------
403 // wxDataViewDateCell
404 // ---------------------------------------------------------
406 class wxDataViewDateCellPopupTransient
: public wxPopupTransientWindow
409 wxDataViewDateCellPopupTransient( wxWindow
* parent
, wxDateTime
*value
,
410 wxDataViewListModel
*model
, size_t col
, size_t row
) :
411 wxPopupTransientWindow( parent
, wxBORDER_SIMPLE
)
416 m_cal
= new wxCalendarCtrl( this, wxID_ANY
, *value
);
417 wxBoxSizer
*sizer
= new wxBoxSizer( wxHORIZONTAL
);
418 sizer
->Add( m_cal
, 1, wxGROW
);
423 virtual void OnDismiss()
427 void OnCalendar( wxCalendarEvent
&event
);
429 wxCalendarCtrl
*m_cal
;
430 wxDataViewListModel
*m_model
;
435 DECLARE_EVENT_TABLE()
438 BEGIN_EVENT_TABLE(wxDataViewDateCellPopupTransient
,wxPopupTransientWindow
)
439 EVT_CALENDAR( wxID_ANY
, wxDataViewDateCellPopupTransient::OnCalendar
)
442 void wxDataViewDateCellPopupTransient::OnCalendar( wxCalendarEvent
&event
)
444 wxDateTime date
= event
.GetDate();
445 wxVariant value
= date
;
446 m_model
->SetValue( value
, m_col
, m_row
);
447 m_model
->ValueChanged( m_col
, m_row
);
451 IMPLEMENT_ABSTRACT_CLASS(wxDataViewDateCell
, wxDataViewCustomCell
)
453 wxDataViewDateCell::wxDataViewDateCell( const wxString
&varianttype
,
454 wxDataViewCellMode mode
) :
455 wxDataViewCustomCell( varianttype
, mode
)
459 bool wxDataViewDateCell::SetValue( const wxVariant
&value
)
461 m_date
= value
.GetDateTime();
466 bool wxDataViewDateCell::Render( wxRect cell
, wxDC
*dc
, int WXUNUSED(state
) )
468 dc
->SetFont( GetOwner()->GetOwner()->GetFont() );
469 wxString tmp
= m_date
.FormatDate();
470 dc
->DrawText( tmp
, cell
.x
, cell
.y
);
475 wxSize
wxDataViewDateCell::GetSize()
477 wxDataViewCtrl
* view
= GetOwner()->GetOwner();
478 wxString tmp
= m_date
.FormatDate();
480 view
->GetTextExtent( tmp
, &x
, &y
, &d
);
481 return wxSize(x
,y
+d
);
484 bool wxDataViewDateCell::Activate( wxRect
WXUNUSED(cell
), wxDataViewListModel
*model
, size_t col
, size_t row
)
487 model
->GetValue( variant
, col
, row
);
488 wxDateTime value
= variant
.GetDateTime();
490 wxDataViewDateCellPopupTransient
*popup
= new wxDataViewDateCellPopupTransient(
491 GetOwner()->GetOwner()->GetParent(), &value
, model
, col
, row
);
492 wxPoint pos
= wxGetMousePosition();
495 popup
->Popup( popup
->m_cal
);
500 // ---------------------------------------------------------
502 // ---------------------------------------------------------
504 IMPLEMENT_ABSTRACT_CLASS(wxDataViewColumn
, wxDataViewColumnBase
)
506 wxDataViewColumn::wxDataViewColumn( const wxString
&title
, wxDataViewCell
*cell
, size_t model_column
,
507 int fixed_width
, wxDataViewColumnSizing sizing
, int flags
) :
508 wxDataViewColumnBase( title
, cell
, model_column
, flags
)
512 m_width
= fixed_width
;
513 m_fixedWidth
= fixed_width
;
516 wxDataViewColumn::~wxDataViewColumn()
520 void wxDataViewColumn::SetTitle( const wxString
&title
)
522 wxDataViewColumnBase::SetTitle( title
);
526 int wxDataViewColumn::GetWidth()
531 void wxDataViewColumn::SetFixedWidth( int width
)
533 m_fixedWidth
= width
;
535 if (m_sizing
== wxDATAVIEW_COL_WIDTH_FIXED
)
542 int wxDataViewColumn::GetFixedWidth()
547 //-----------------------------------------------------------------------------
548 // wxDataViewHeaderWindow
549 //-----------------------------------------------------------------------------
551 IMPLEMENT_ABSTRACT_CLASS(wxDataViewHeaderWindow
, wxWindow
)
553 BEGIN_EVENT_TABLE(wxDataViewHeaderWindow
,wxWindow
)
554 EVT_PAINT (wxDataViewHeaderWindow::OnPaint
)
555 EVT_MOUSE_EVENTS (wxDataViewHeaderWindow::OnMouse
)
556 EVT_SET_FOCUS (wxDataViewHeaderWindow::OnSetFocus
)
559 wxDataViewHeaderWindow::wxDataViewHeaderWindow( wxDataViewCtrl
*parent
, wxWindowID id
,
560 const wxPoint
&pos
, const wxSize
&size
, const wxString
&name
) :
561 wxWindow( parent
, id
, pos
, size
, 0, name
)
565 m_resizeCursor
= new wxCursor( wxCURSOR_SIZEWE
);
567 wxVisualAttributes attr
= wxPanel::GetClassDefaultAttributes();
568 SetOwnForegroundColour( attr
.colFg
);
569 SetOwnBackgroundColour( attr
.colBg
);
571 SetOwnFont( attr
.font
);
574 wxDataViewHeaderWindow::~wxDataViewHeaderWindow()
576 delete m_resizeCursor
;
579 void wxDataViewHeaderWindow::OnPaint( wxPaintEvent
&WXUNUSED(event
) )
582 GetClientSize( &w
, &h
);
584 wxPaintDC
dc( this );
587 m_owner
->GetScrollPixelsPerUnit( &xpix
, NULL
);
590 m_owner
->GetViewStart( &x
, NULL
);
592 // account for the horz scrollbar offset
593 dc
.SetDeviceOrigin( -x
* xpix
, 0 );
595 dc
.SetFont( GetFont() );
597 size_t cols
= GetOwner()->GetNumberOfColumns();
600 for (i
= 0; i
< cols
; i
++)
602 wxDataViewColumn
*col
= GetOwner()->GetColumn( i
);
603 int width
= col
->GetWidth();
605 // the width of the rect to draw: make it smaller to fit entirely
606 // inside the column rect
615 wxRendererNative::Get().DrawHeaderButton
619 wxRect(xpos
+1, 1, cw
-1, ch
-1),
620 m_parent
->IsEnabled() ? 0
621 : (int)wxCONTROL_DISABLED
624 dc
.DrawText( col
->GetTitle(), xpos
+3, 3 );
630 void wxDataViewHeaderWindow::OnMouse( wxMouseEvent
&WXUNUSED(event
) )
634 void wxDataViewHeaderWindow::OnSetFocus( wxFocusEvent
&event
)
639 //-----------------------------------------------------------------------------
640 // wxDataViewRenameTimer
641 //-----------------------------------------------------------------------------
643 wxDataViewRenameTimer::wxDataViewRenameTimer( wxDataViewMainWindow
*owner
)
648 void wxDataViewRenameTimer::Notify()
650 m_owner
->OnRenameTimer();
653 //-----------------------------------------------------------------------------
654 // wxDataViewTextCtrlWrapper: wraps a wxTextCtrl for inline editing
655 //-----------------------------------------------------------------------------
657 BEGIN_EVENT_TABLE(wxDataViewTextCtrlWrapper
, wxEvtHandler
)
658 EVT_CHAR (wxDataViewTextCtrlWrapper::OnChar
)
659 EVT_KEY_UP (wxDataViewTextCtrlWrapper::OnKeyUp
)
660 EVT_KILL_FOCUS (wxDataViewTextCtrlWrapper::OnKillFocus
)
663 wxDataViewTextCtrlWrapper::wxDataViewTextCtrlWrapper(
664 wxDataViewMainWindow
*owner
,
666 wxDataViewListModel
*model
,
667 size_t col
, size_t row
,
677 m_aboutToFinish
= false;
680 model
->GetValue( value
, col
, row
);
681 m_startValue
= value
.GetString();
683 m_owner
->GetOwner()->CalcScrolledPosition(
684 rectLabel
.x
, rectLabel
.y
, &rectLabel
.x
, &rectLabel
.y
);
686 m_text
->Create( owner
, wxID_ANY
, m_startValue
,
687 wxPoint(rectLabel
.x
-2,rectLabel
.y
-2),
688 wxSize(rectLabel
.width
+7,rectLabel
.height
+4) );
691 m_text
->PushEventHandler(this);
694 void wxDataViewTextCtrlWrapper::AcceptChangesAndFinish()
696 m_aboutToFinish
= true;
698 // Notify the owner about the changes
701 // Even if vetoed, close the control (consistent with MSW)
705 void wxDataViewTextCtrlWrapper::OnChar( wxKeyEvent
&event
)
707 switch ( event
.m_keyCode
)
710 AcceptChangesAndFinish();
714 // m_owner->OnRenameCancelled( m_itemEdited );
723 void wxDataViewTextCtrlWrapper::OnKeyUp( wxKeyEvent
&event
)
731 // auto-grow the textctrl
732 wxSize parentSize
= m_owner
->GetSize();
733 wxPoint myPos
= m_text
->GetPosition();
734 wxSize mySize
= m_text
->GetSize();
736 m_text
->GetTextExtent(m_text
->GetValue() + _T("MM"), &sx
, &sy
);
737 if (myPos
.x
+ sx
> parentSize
.x
)
738 sx
= parentSize
.x
- myPos
.x
;
741 m_text
->SetSize(sx
, wxDefaultCoord
);
746 void wxDataViewTextCtrlWrapper::OnKillFocus( wxFocusEvent
&event
)
748 if ( !m_finished
&& !m_aboutToFinish
)
751 //if ( !AcceptChanges() )
752 // m_owner->OnRenameCancelled( m_itemEdited );
757 // We must let the native text control handle focus
761 bool wxDataViewTextCtrlWrapper::AcceptChanges()
763 const wxString value
= m_text
->GetValue();
765 if ( value
== m_startValue
)
766 // nothing changed, always accept
769 // if ( !m_owner->OnRenameAccept(m_itemEdited, value) )
770 // vetoed by the user
773 // accepted, do rename the item
776 m_model
->SetValue( variant
, m_col
, m_row
);
777 m_model
->ValueChanged( m_col
, m_row
);
782 void wxDataViewTextCtrlWrapper::Finish()
788 m_text
->RemoveEventHandler(this);
789 m_owner
->FinishEditing(m_text
);
792 wxPendingDelete
.Append( this );
796 //-----------------------------------------------------------------------------
797 // wxDataViewMainWindow
798 //-----------------------------------------------------------------------------
800 IMPLEMENT_ABSTRACT_CLASS(wxDataViewMainWindow
, wxWindow
)
802 BEGIN_EVENT_TABLE(wxDataViewMainWindow
,wxWindow
)
803 EVT_PAINT (wxDataViewMainWindow::OnPaint
)
804 EVT_MOUSE_EVENTS (wxDataViewMainWindow::OnMouse
)
805 EVT_SET_FOCUS (wxDataViewMainWindow::OnSetFocus
)
808 wxDataViewMainWindow::wxDataViewMainWindow( wxDataViewCtrl
*parent
, wxWindowID id
,
809 const wxPoint
&pos
, const wxSize
&size
, const wxString
&name
) :
810 wxWindow( parent
, id
, pos
, size
, 0, name
)
814 m_lastOnSame
= false;
815 m_renameTimer
= new wxDataViewRenameTimer( this );
816 m_textctrlWrapper
= NULL
;
818 // TODO: user better initial values/nothing selected
822 // TODO: we need to calculate this smartly
828 wxDataViewMainWindow::~wxDataViewMainWindow()
830 delete m_renameTimer
;
833 void wxDataViewMainWindow::OnRenameTimer()
835 // We have to call this here because changes may just have
836 // been made and no screen update taken place.
842 size_t cols
= GetOwner()->GetNumberOfColumns();
844 for (i
= 0; i
< cols
; i
++)
846 wxDataViewColumn
*c
= GetOwner()->GetColumn( i
);
847 if (c
== m_currentCol
)
849 xpos
+= c
->GetWidth();
851 wxRect
labelRect( xpos
, m_currentRow
* m_lineHeight
, m_currentCol
->GetWidth(), m_lineHeight
);
853 wxClassInfo
*textControlClass
= CLASSINFO(wxTextCtrl
);
855 wxTextCtrl
* const text
= (wxTextCtrl
*)textControlClass
->CreateObject();
856 m_textctrlWrapper
= new wxDataViewTextCtrlWrapper(this, text
, GetOwner()->GetModel(),
857 m_currentCol
->GetModelColumn(), m_currentRow
, labelRect
);
860 void wxDataViewMainWindow::FinishEditing( wxTextCtrl
*text
)
863 m_textctrlWrapper
= NULL
;
865 // SetFocusIgnoringChildren();
868 bool wxDataViewMainWindow::RowAppended()
873 bool wxDataViewMainWindow::RowPrepended()
878 bool wxDataViewMainWindow::RowInserted( size_t WXUNUSED(before
) )
883 bool wxDataViewMainWindow::RowDeleted( size_t WXUNUSED(row
) )
888 bool wxDataViewMainWindow::RowChanged( size_t WXUNUSED(row
) )
893 bool wxDataViewMainWindow::ValueChanged( size_t WXUNUSED(col
), size_t row
)
895 wxRect
rect( 0, row
*m_lineHeight
, 10000, m_lineHeight
);
896 m_owner
->CalcScrolledPosition( rect
.x
, rect
.y
, &rect
.x
, &rect
.y
);
897 Refresh( true, &rect
);
902 bool wxDataViewMainWindow::RowsReordered( size_t *WXUNUSED(new_order
) )
909 bool wxDataViewMainWindow::Cleared()
914 void wxDataViewMainWindow::UpdateDisplay()
919 void wxDataViewMainWindow::OnInternalIdle()
921 wxWindow::OnInternalIdle();
925 RecalculateDisplay();
930 void wxDataViewMainWindow::RecalculateDisplay()
932 wxDataViewListModel
*model
= GetOwner()->GetModel();
940 size_t cols
= GetOwner()->GetNumberOfColumns();
942 for (i
= 0; i
< cols
; i
++)
944 wxDataViewColumn
*col
= GetOwner()->GetColumn( i
);
945 width
+= col
->GetWidth();
948 int height
= model
->GetNumberOfRows() * m_lineHeight
;
950 SetVirtualSize( width
, height
);
951 GetOwner()->SetScrollRate( 10, m_lineHeight
);
956 void wxDataViewMainWindow::ScrollWindow( int dx
, int dy
, const wxRect
*rect
)
958 wxWindow::ScrollWindow( dx
, dy
, rect
);
959 GetOwner()->m_headerArea
->ScrollWindow( dx
, 0 );
962 void wxDataViewMainWindow::OnPaint( wxPaintEvent
&WXUNUSED(event
) )
964 wxPaintDC
dc( this );
966 GetOwner()->PrepareDC( dc
);
968 dc
.SetFont( GetFont() );
970 wxRect update
= GetUpdateRegion().GetBox();
971 m_owner
->CalcUnscrolledPosition( update
.x
, update
.y
, &update
.x
, &update
.y
);
973 wxDataViewListModel
*model
= GetOwner()->GetModel();
975 size_t item_start
= wxMax( 0, (update
.y
/ m_lineHeight
) );
976 size_t item_count
= wxMin( ((update
.y
+ update
.height
) / m_lineHeight
) - item_start
+ 1,
977 (int)(model
->GetNumberOfRows()-item_start
) );
981 cell_rect
.height
= m_lineHeight
;
982 size_t cols
= GetOwner()->GetNumberOfColumns();
984 for (i
= 0; i
< cols
; i
++)
986 wxDataViewColumn
*col
= GetOwner()->GetColumn( i
);
987 wxDataViewCell
*cell
= col
->GetCell();
988 cell_rect
.width
= col
->GetWidth();
991 for (item
= item_start
; item
< item_start
+item_count
; item
++)
993 cell_rect
.y
= item
*m_lineHeight
;
995 model
->GetValue( value
, col
->GetModelColumn(), item
);
996 cell
->SetValue( value
);
997 wxSize size
= cell
->GetSize();
998 // cannot be bigger than allocated space
999 size
.x
= wxMin( size
.x
, cell_rect
.width
);
1000 size
.y
= wxMin( size
.y
, cell_rect
.height
);
1001 // TODO: check for left/right/centre alignment here
1004 item_rect
.x
= cell_rect
.x
+ (cell_rect
.width
/ 2) - (size
.x
/ 2);
1005 item_rect
.y
= cell_rect
.y
+ (cell_rect
.height
/ 2) - (size
.y
/ 2);
1007 item_rect
.width
= size
.x
;
1008 item_rect
.height
= size
.y
;
1009 cell
->Render( item_rect
, &dc
, 0 );
1012 cell_rect
.x
+= cell_rect
.width
;
1016 void wxDataViewMainWindow::OnMouse( wxMouseEvent
&event
)
1018 int x
= event
.GetX();
1019 int y
= event
.GetY();
1020 m_owner
->CalcUnscrolledPosition( x
, y
, &x
, &y
);
1022 wxDataViewColumn
*col
= NULL
;
1025 size_t cols
= GetOwner()->GetNumberOfColumns();
1027 for (i
= 0; i
< cols
; i
++)
1029 wxDataViewColumn
*c
= GetOwner()->GetColumn( i
);
1030 if (x
< xpos
+ c
->GetWidth())
1035 xpos
+= c
->GetWidth();
1039 wxDataViewCell
*cell
= col
->GetCell();
1041 size_t row
= y
/ m_lineHeight
;
1043 wxDataViewListModel
*model
= GetOwner()->GetModel();
1045 if (event
.ButtonDClick())
1047 m_renameTimer
->Stop();
1048 m_lastOnSame
= false;
1051 if (event
.LeftDClick())
1053 if (cell
->GetMode() == wxDATAVIEW_CELL_ACTIVATABLE
)
1056 model
->GetValue( value
, col
->GetModelColumn(), row
);
1057 cell
->SetValue( value
);
1058 wxRect
cell_rect( xpos
, row
* m_lineHeight
, col
->GetWidth(), m_lineHeight
);
1059 cell
->Activate( cell_rect
, model
, col
->GetModelColumn(), row
);
1068 if ((col
== m_currentCol
) & (row
== m_currentRow
) &&
1069 (cell
->GetMode() == wxDATAVIEW_CELL_EDITABLE
) )
1071 m_renameTimer
->Start( 100, true );
1075 m_lastOnSame
= false;
1077 if (event
.LeftDown())
1079 wxDataViewColumn
*oldCurrentCol
= m_currentCol
;
1080 size_t oldCurrentRow
= m_currentRow
;
1082 // Update selection here...
1086 m_lastOnSame
= (col
== oldCurrentCol
) && (row
== oldCurrentRow
);
1094 void wxDataViewMainWindow::OnSetFocus( wxFocusEvent
&event
)
1099 //-----------------------------------------------------------------------------
1101 //-----------------------------------------------------------------------------
1103 IMPLEMENT_DYNAMIC_CLASS(wxDataViewCtrl
, wxDataViewCtrlBase
)
1105 BEGIN_EVENT_TABLE(wxDataViewCtrl
, wxDataViewCtrlBase
)
1106 EVT_SIZE(wxDataViewCtrl::OnSize
)
1109 wxDataViewCtrl::~wxDataViewCtrl()
1112 GetModel()->RemoveNotifier( m_notifier
);
1115 void wxDataViewCtrl::Init()
1120 bool wxDataViewCtrl::Create(wxWindow
*parent
, wxWindowID id
,
1121 const wxPoint
& pos
, const wxSize
& size
,
1122 long style
, const wxValidator
& validator
)
1124 if (!wxControl::Create( parent
, id
, pos
, size
, style
| wxScrolledWindowStyle
|wxSUNKEN_BORDER
, validator
))
1130 MacSetClipChildren( true ) ;
1133 m_clientArea
= new wxDataViewMainWindow( this, wxID_ANY
);
1134 m_headerArea
= new wxDataViewHeaderWindow( this, wxID_ANY
, wxDefaultPosition
, wxSize(wxDefaultCoord
,25) );
1136 SetTargetWindow( m_clientArea
);
1138 wxBoxSizer
*sizer
= new wxBoxSizer( wxVERTICAL
);
1139 sizer
->Add( m_headerArea
, 0, wxGROW
);
1140 sizer
->Add( m_clientArea
, 1, wxGROW
);
1147 WXLRESULT
wxDataViewCtrl::MSWWindowProc(WXUINT nMsg
,
1151 WXLRESULT rc
= wxDataViewCtrlBase::MSWWindowProc(nMsg
, wParam
, lParam
);
1154 // we need to process arrows ourselves for scrolling
1155 if ( nMsg
== WM_GETDLGCODE
)
1157 rc
|= DLGC_WANTARROWS
;
1165 void wxDataViewCtrl::OnSize( wxSizeEvent
&WXUNUSED(event
) )
1167 // We need to override OnSize so that our scrolled
1168 // window a) does call Layout() to use sizers for
1169 // positioning the controls but b) does not query
1170 // the sizer for their size and use that for setting
1171 // the scrollable area as set that ourselves by
1172 // calling SetScrollbar() further down.
1179 bool wxDataViewCtrl::AssociateModel( wxDataViewListModel
*model
)
1181 if (!wxDataViewCtrlBase::AssociateModel( model
))
1184 m_notifier
= new wxGenericDataViewListModelNotifier( m_clientArea
);
1186 model
->AddNotifier( m_notifier
);
1188 m_clientArea
->UpdateDisplay();
1193 bool wxDataViewCtrl::AppendColumn( wxDataViewColumn
*col
)
1195 if (!wxDataViewCtrlBase::AppendColumn(col
))
1198 m_clientArea
->UpdateDisplay();
1204 // !wxUSE_GENERICDATAVIEWCTRL
1207 // wxUSE_DATAVIEWCTRL