]> git.saurik.com Git - wxWidgets.git/blame - src/generic/datavgen.cpp
cleanup for 10.5
[wxWidgets.git] / src / generic / datavgen.cpp
CommitLineData
4ed7af08 1/////////////////////////////////////////////////////////////////////////////
f554a14b 2// Name: src/generic/datavgen.cpp
4ed7af08
RR
3// Purpose: wxDataViewCtrl generic implementation
4// Author: Robert Roebling
5// Id: $Id$
6// Copyright: (c) 1998 Robert Roebling
7// Licence: wxWindows licence
8/////////////////////////////////////////////////////////////////////////////
9
10// For compilers that support precompilation, includes "wx.h".
11#include "wx/wxprec.h"
12
ed4b0fdc
WS
13#ifdef __BORLANDC__
14 #pragma hdrstop
15#endif
16
4ed7af08
RR
17#if wxUSE_DATAVIEWCTRL
18
19#include "wx/dataview.h"
20
21#ifdef wxUSE_GENERICDATAVIEWCTRL
22
f554a14b 23#ifndef WX_PRECOMP
57bd4c60
WS
24 #ifdef __WXMSW__
25 #include "wx/msw/wrapwin.h"
26 #endif
f554a14b
WS
27 #include "wx/sizer.h"
28 #include "wx/log.h"
ed4b0fdc 29 #include "wx/dcclient.h"
c0badb70 30 #include "wx/timer.h"
9eddec69 31 #include "wx/settings.h"
f554a14b
WS
32#endif
33
4ed7af08 34#include "wx/stockitem.h"
4ed7af08
RR
35#include "wx/calctrl.h"
36#include "wx/popupwin.h"
4ed7af08 37#include "wx/renderer.h"
2e992e06 38#include "wx/dcbuffer.h"
2586d4a1 39#include "wx/icon.h"
4ed7af08 40
4ed7af08
RR
41//-----------------------------------------------------------------------------
42// classes
43//-----------------------------------------------------------------------------
44
45class wxDataViewCtrl;
46
a0f3af5f
RR
47//-----------------------------------------------------------------------------
48// wxDataViewHeaderWindow
49//-----------------------------------------------------------------------------
4ed7af08 50
a0f3af5f 51class wxDataViewHeaderWindow: public wxWindow
4ed7af08
RR
52{
53public:
a0f3af5f
RR
54 wxDataViewHeaderWindow( wxDataViewCtrl *parent,
55 wxWindowID id,
56 const wxPoint &pos = wxDefaultPosition,
57 const wxSize &size = wxDefaultSize,
58 const wxString &name = wxT("wxdataviewctrlheaderwindow") );
d3c7fc99 59 virtual ~wxDataViewHeaderWindow();
4ed7af08 60
a0f3af5f
RR
61 void SetOwner( wxDataViewCtrl* owner ) { m_owner = owner; }
62 wxDataViewCtrl *GetOwner() { return m_owner; }
4ed7af08 63
a0f3af5f
RR
64 void OnPaint( wxPaintEvent &event );
65 void OnMouse( wxMouseEvent &event );
66 void OnSetFocus( wxFocusEvent &event );
f554a14b 67
a0f3af5f
RR
68private:
69 wxDataViewCtrl *m_owner;
70 wxCursor *m_resizeCursor;
f554a14b 71
a0f3af5f
RR
72private:
73 DECLARE_DYNAMIC_CLASS(wxDataViewHeaderWindow)
74 DECLARE_EVENT_TABLE()
75};
4ed7af08 76
0fcce6b9
RR
77//-----------------------------------------------------------------------------
78// wxDataViewRenameTimer
79//-----------------------------------------------------------------------------
80
81class wxDataViewRenameTimer: public wxTimer
82{
83private:
84 wxDataViewMainWindow *m_owner;
85
86public:
87 wxDataViewRenameTimer( wxDataViewMainWindow *owner );
88 void Notify();
89};
90
91//-----------------------------------------------------------------------------
92// wxDataViewTextCtrlWrapper: wraps a wxTextCtrl for inline editing
93//-----------------------------------------------------------------------------
94
95class wxDataViewTextCtrlWrapper : public wxEvtHandler
96{
97public:
98 // NB: text must be a valid object but not Create()d yet
99 wxDataViewTextCtrlWrapper( wxDataViewMainWindow *owner,
100 wxTextCtrl *text,
101 wxDataViewListModel *model,
0a71f9e9 102 unsigned int col, unsigned int row,
0fcce6b9
RR
103 wxRect cellLabel );
104
105 wxTextCtrl *GetText() const { return m_text; }
106
107 void AcceptChangesAndFinish();
108
109protected:
110 void OnChar( wxKeyEvent &event );
111 void OnKeyUp( wxKeyEvent &event );
112 void OnKillFocus( wxFocusEvent &event );
113
114 bool AcceptChanges();
115 void Finish();
116
117private:
118 wxDataViewMainWindow *m_owner;
119 wxTextCtrl *m_text;
120 wxString m_startValue;
121 wxDataViewListModel *m_model;
0a71f9e9
RR
122 unsigned int m_col;
123 unsigned int m_row;
0fcce6b9
RR
124 bool m_finished;
125 bool m_aboutToFinish;
126
127 DECLARE_EVENT_TABLE()
128};
129
a0f3af5f
RR
130//-----------------------------------------------------------------------------
131// wxDataViewMainWindow
132//-----------------------------------------------------------------------------
4ed7af08 133
0a71f9e9 134WX_DEFINE_SORTED_USER_EXPORTED_ARRAY_SIZE_T(unsigned int, wxDataViewSelection, WXDLLIMPEXP_ADV);
cab07038 135
a0f3af5f 136class wxDataViewMainWindow: public wxWindow
4ed7af08 137{
a0f3af5f
RR
138public:
139 wxDataViewMainWindow( wxDataViewCtrl *parent,
140 wxWindowID id,
141 const wxPoint &pos = wxDefaultPosition,
142 const wxSize &size = wxDefaultSize,
143 const wxString &name = wxT("wxdataviewctrlmainwindow") );
d3c7fc99 144 virtual ~wxDataViewMainWindow();
4ed7af08 145
a0f3af5f
RR
146 // notifications from wxDataViewListModel
147 bool RowAppended();
148 bool RowPrepended();
0a71f9e9
RR
149 bool RowInserted( unsigned int before );
150 bool RowDeleted( unsigned int row );
151 bool RowChanged( unsigned int row );
152 bool ValueChanged( unsigned int col, unsigned int row );
153 bool RowsReordered( unsigned int *new_order );
a0f3af5f 154 bool Cleared();
4ed7af08 155
a0f3af5f
RR
156 void SetOwner( wxDataViewCtrl* owner ) { m_owner = owner; }
157 wxDataViewCtrl *GetOwner() { return m_owner; }
4ed7af08 158
a0f3af5f 159 void OnPaint( wxPaintEvent &event );
0a71f9e9 160 void OnArrowChar(unsigned int newCurrent, const wxKeyEvent& event);
cab07038 161 void OnChar( wxKeyEvent &event );
a0f3af5f
RR
162 void OnMouse( wxMouseEvent &event );
163 void OnSetFocus( wxFocusEvent &event );
cab07038 164 void OnKillFocus( wxFocusEvent &event );
f554a14b 165
a0f3af5f
RR
166 void UpdateDisplay();
167 void RecalculateDisplay();
168 void OnInternalIdle();
f554a14b 169
0fcce6b9
RR
170 void OnRenameTimer();
171 void FinishEditing( wxTextCtrl *text );
172
a0f3af5f 173 void ScrollWindow( int dx, int dy, const wxRect *rect );
120b9b05 174
0a71f9e9
RR
175 bool HasCurrentRow() { return m_currentRow != (unsigned int)-1; }
176 void ChangeCurrentRow( unsigned int row );
120b9b05 177
cab07038
RR
178 bool IsSingleSel() const { return !GetParent()->HasFlag(wxDV_MULTIPLE); };
179 bool IsEmpty() { return GetRowCount() == 0; }
120b9b05 180
cab07038 181 int GetCountPerPage();
e21f75bd 182 int GetEndOfLastCol();
0a71f9e9
RR
183 unsigned int GetFirstVisibleRow();
184 unsigned int GetLastVisibleRow();
185 unsigned int GetRowCount();
120b9b05 186
cab07038 187 void SelectAllRows( bool on );
0a71f9e9
RR
188 void SelectRow( unsigned int row, bool on );
189 void SelectRows( unsigned int from, unsigned int to, bool on );
190 void ReverseRowSelection( unsigned int row );
191 bool IsRowSelected( unsigned int row );
120b9b05 192
0a71f9e9
RR
193 void RefreshRow( unsigned int row );
194 void RefreshRows( unsigned int from, unsigned int to );
195 void RefreshRowsAfter( unsigned int firstRow );
120b9b05 196
a0f3af5f 197private:
0fcce6b9
RR
198 wxDataViewCtrl *m_owner;
199 int m_lineHeight;
200 bool m_dirty;
120b9b05 201
0fcce6b9 202 wxDataViewColumn *m_currentCol;
0a71f9e9 203 unsigned int m_currentRow;
cab07038 204 wxDataViewSelection m_selection;
120b9b05 205
0fcce6b9
RR
206 wxDataViewRenameTimer *m_renameTimer;
207 wxDataViewTextCtrlWrapper *m_textctrlWrapper;
208 bool m_lastOnSame;
f554a14b 209
cab07038
RR
210 bool m_hasFocus;
211
e21f75bd
RR
212 int m_dragCount;
213 wxPoint m_dragStart;
214
215 // for double click logic
0a71f9e9 216 unsigned int m_lineLastClicked,
e21f75bd
RR
217 m_lineBeforeLastClicked,
218 m_lineSelectSingleOnUp;
cab07038 219
a0f3af5f
RR
220private:
221 DECLARE_DYNAMIC_CLASS(wxDataViewMainWindow)
222 DECLARE_EVENT_TABLE()
223};
4ed7af08 224
f554a14b 225// ---------------------------------------------------------
a0f3af5f 226// wxGenericDataViewListModelNotifier
f554a14b 227// ---------------------------------------------------------
a0f3af5f
RR
228
229class wxGenericDataViewListModelNotifier: public wxDataViewListModelNotifier
4ed7af08 230{
a0f3af5f
RR
231public:
232 wxGenericDataViewListModelNotifier( wxDataViewMainWindow *mainWindow )
233 { m_mainWindow = mainWindow; }
f554a14b 234
a0f3af5f
RR
235 virtual bool RowAppended()
236 { return m_mainWindow->RowAppended(); }
237 virtual bool RowPrepended()
238 { return m_mainWindow->RowPrepended(); }
0a71f9e9 239 virtual bool RowInserted( unsigned int before )
a0f3af5f 240 { return m_mainWindow->RowInserted( before ); }
0a71f9e9 241 virtual bool RowDeleted( unsigned int row )
a0f3af5f 242 { return m_mainWindow->RowDeleted( row ); }
0a71f9e9 243 virtual bool RowChanged( unsigned int row )
a0f3af5f 244 { return m_mainWindow->RowChanged( row ); }
0a71f9e9 245 virtual bool ValueChanged( unsigned int col, unsigned int row )
a0f3af5f 246 { return m_mainWindow->ValueChanged( col, row ); }
0a71f9e9 247 virtual bool RowsReordered( unsigned int *new_order )
a0f3af5f
RR
248 { return m_mainWindow->RowsReordered( new_order ); }
249 virtual bool Cleared()
250 { return m_mainWindow->Cleared(); }
f554a14b 251
a0f3af5f
RR
252 wxDataViewMainWindow *m_mainWindow;
253};
4ed7af08 254
f554a14b 255// ---------------------------------------------------------
baa9ebc4 256// wxDataViewRenderer
f554a14b 257// ---------------------------------------------------------
4ed7af08 258
baa9ebc4 259IMPLEMENT_ABSTRACT_CLASS(wxDataViewRenderer, wxDataViewRendererBase)
4ed7af08 260
baa9ebc4
RR
261wxDataViewRenderer::wxDataViewRenderer( const wxString &varianttype, wxDataViewCellMode mode ) :
262 wxDataViewRendererBase( varianttype, mode )
4ed7af08 263{
3d9d7cc4 264 m_dc = NULL;
4ed7af08
RR
265}
266
baa9ebc4 267wxDataViewRenderer::~wxDataViewRenderer()
3d9d7cc4
RR
268{
269 if (m_dc)
270 delete m_dc;
271}
272
baa9ebc4 273wxDC *wxDataViewRenderer::GetDC()
3d9d7cc4
RR
274{
275 if (m_dc == NULL)
276 {
277 if (GetOwner() == NULL)
278 return NULL;
279 if (GetOwner()->GetOwner() == NULL)
280 return NULL;
281 m_dc = new wxClientDC( GetOwner()->GetOwner() );
282 }
f554a14b 283
3d9d7cc4
RR
284 return m_dc;
285}
286
f554a14b 287// ---------------------------------------------------------
baa9ebc4 288// wxDataViewCustomRenderer
f554a14b 289// ---------------------------------------------------------
3d9d7cc4 290
baa9ebc4 291IMPLEMENT_ABSTRACT_CLASS(wxDataViewCustomRenderer, wxDataViewRenderer)
3d9d7cc4 292
baa9ebc4 293wxDataViewCustomRenderer::wxDataViewCustomRenderer( const wxString &varianttype,
3d9d7cc4 294 wxDataViewCellMode mode ) :
baa9ebc4 295 wxDataViewRenderer( varianttype, mode )
3d9d7cc4
RR
296{
297}
298
f554a14b 299// ---------------------------------------------------------
baa9ebc4 300// wxDataViewTextRenderer
f554a14b 301// ---------------------------------------------------------
4ed7af08 302
baa9ebc4 303IMPLEMENT_CLASS(wxDataViewTextRenderer, wxDataViewCustomRenderer)
4ed7af08 304
baa9ebc4
RR
305wxDataViewTextRenderer::wxDataViewTextRenderer( const wxString &varianttype, wxDataViewCellMode mode ) :
306 wxDataViewCustomRenderer( varianttype, mode )
4ed7af08
RR
307{
308}
309
baa9ebc4 310bool wxDataViewTextRenderer::SetValue( const wxVariant &value )
4ed7af08 311{
90675b95 312 m_text = value.GetString();
f554a14b 313
90675b95 314 return true;
4ed7af08
RR
315}
316
baa9ebc4 317bool wxDataViewTextRenderer::GetValue( wxVariant& WXUNUSED(value) )
4ed7af08
RR
318{
319 return false;
320}
321
baa9ebc4 322bool wxDataViewTextRenderer::Render( wxRect cell, wxDC *dc, int WXUNUSED(state) )
3d9d7cc4 323{
90675b95
RR
324 dc->DrawText( m_text, cell.x, cell.y );
325
326 return true;
3d9d7cc4
RR
327}
328
baa9ebc4 329wxSize wxDataViewTextRenderer::GetSize()
3d9d7cc4
RR
330{
331 return wxSize(80,20);
332}
333
2586d4a1 334// ---------------------------------------------------------
baa9ebc4 335// wxDataViewBitmapRenderer
2586d4a1
RR
336// ---------------------------------------------------------
337
baa9ebc4 338IMPLEMENT_CLASS(wxDataViewBitmapRenderer, wxDataViewCustomRenderer)
2586d4a1 339
baa9ebc4
RR
340wxDataViewBitmapRenderer::wxDataViewBitmapRenderer( const wxString &varianttype, wxDataViewCellMode mode ) :
341 wxDataViewCustomRenderer( varianttype, mode )
2586d4a1
RR
342{
343}
344
baa9ebc4 345bool wxDataViewBitmapRenderer::SetValue( const wxVariant &value )
2586d4a1
RR
346{
347 if (value.GetType() == wxT("wxBitmap"))
348 m_bitmap << value;
349 if (value.GetType() == wxT("wxIcon"))
350 m_icon << value;
351
352 return true;
353}
354
baa9ebc4 355bool wxDataViewBitmapRenderer::GetValue( wxVariant& WXUNUSED(value) )
2586d4a1
RR
356{
357 return false;
358}
359
baa9ebc4 360bool wxDataViewBitmapRenderer::Render( wxRect cell, wxDC *dc, int WXUNUSED(state) )
2586d4a1
RR
361{
362 if (m_bitmap.Ok())
363 dc->DrawBitmap( m_bitmap, cell.x, cell.y );
364 else if (m_icon.Ok())
365 dc->DrawIcon( m_icon, cell.x, cell.y );
366
367 return true;
368}
369
baa9ebc4 370wxSize wxDataViewBitmapRenderer::GetSize()
2586d4a1
RR
371{
372 if (m_bitmap.Ok())
373 return wxSize( m_bitmap.GetWidth(), m_bitmap.GetHeight() );
374 else if (m_icon.Ok())
375 return wxSize( m_icon.GetWidth(), m_icon.GetHeight() );
376
377 return wxSize(16,16);
378}
379
f554a14b 380// ---------------------------------------------------------
baa9ebc4 381// wxDataViewToggleRenderer
f554a14b 382// ---------------------------------------------------------
4ed7af08 383
baa9ebc4 384IMPLEMENT_ABSTRACT_CLASS(wxDataViewToggleRenderer, wxDataViewCustomRenderer)
4ed7af08 385
baa9ebc4 386wxDataViewToggleRenderer::wxDataViewToggleRenderer( const wxString &varianttype,
4ed7af08 387 wxDataViewCellMode mode ) :
baa9ebc4 388 wxDataViewCustomRenderer( varianttype, mode )
4ed7af08 389{
90675b95 390 m_toggle = false;
4ed7af08
RR
391}
392
baa9ebc4 393bool wxDataViewToggleRenderer::SetValue( const wxVariant &value )
4ed7af08 394{
90675b95 395 m_toggle = value.GetBool();
f554a14b 396
a8461d31 397 return true;
4ed7af08
RR
398}
399
baa9ebc4 400bool wxDataViewToggleRenderer::GetValue( wxVariant &WXUNUSED(value) )
4ed7af08
RR
401{
402 return false;
403}
f554a14b 404
baa9ebc4 405bool wxDataViewToggleRenderer::Render( wxRect cell, wxDC *dc, int WXUNUSED(state) )
4ed7af08 406{
90675b95 407 // User wxRenderer here
f554a14b 408
90675b95
RR
409 wxRect rect;
410 rect.x = cell.x + cell.width/2 - 10;
411 rect.width = 20;
412 rect.y = cell.y + cell.height/2 - 10;
413 rect.height = 20;
120b9b05 414
862d8041 415 int flags = 0;
90675b95 416 if (m_toggle)
862d8041
RR
417 flags |= wxCONTROL_CHECKED;
418 if (GetMode() != wxDATAVIEW_CELL_ACTIVATABLE)
419 flags |= wxCONTROL_DISABLED;
420
90b903c2 421 wxRendererNative::Get().DrawCheckBox(
862d8041
RR
422 GetOwner()->GetOwner(),
423 *dc,
424 rect,
425 flags );
f554a14b 426
90675b95 427 return true;
4ed7af08
RR
428}
429
baa9ebc4 430bool wxDataViewToggleRenderer::Activate( wxRect WXUNUSED(cell), wxDataViewListModel *model, unsigned int col, unsigned int row )
0fdc2321
RR
431{
432 bool value = !m_toggle;
433 wxVariant variant = value;
434 model->SetValue( variant, col, row );
f554a14b 435 model->ValueChanged( col, row );
0fdc2321
RR
436 return true;
437}
438
baa9ebc4 439wxSize wxDataViewToggleRenderer::GetSize()
4ed7af08 440{
3d9d7cc4 441 return wxSize(20,20);
4ed7af08
RR
442}
443
f554a14b 444// ---------------------------------------------------------
baa9ebc4 445// wxDataViewProgressRenderer
f554a14b 446// ---------------------------------------------------------
4ed7af08 447
baa9ebc4 448IMPLEMENT_ABSTRACT_CLASS(wxDataViewProgressRenderer, wxDataViewCustomRenderer)
4ed7af08 449
baa9ebc4 450wxDataViewProgressRenderer::wxDataViewProgressRenderer( const wxString &label,
4ed7af08 451 const wxString &varianttype, wxDataViewCellMode mode ) :
baa9ebc4 452 wxDataViewCustomRenderer( varianttype, mode )
4ed7af08
RR
453{
454 m_label = label;
455 m_value = 0;
456}
457
baa9ebc4 458wxDataViewProgressRenderer::~wxDataViewProgressRenderer()
4ed7af08
RR
459{
460}
461
baa9ebc4 462bool wxDataViewProgressRenderer::SetValue( const wxVariant &value )
4ed7af08
RR
463{
464 m_value = (long) value;
f554a14b 465
4ed7af08
RR
466 if (m_value < 0) m_value = 0;
467 if (m_value > 100) m_value = 100;
f554a14b 468
4ed7af08
RR
469 return true;
470}
f554a14b 471
baa9ebc4 472bool wxDataViewProgressRenderer::Render( wxRect cell, wxDC *dc, int WXUNUSED(state) )
4ed7af08
RR
473{
474 double pct = (double)m_value / 100.0;
475 wxRect bar = cell;
476 bar.width = (int)(cell.width * pct);
477 dc->SetPen( *wxTRANSPARENT_PEN );
478 dc->SetBrush( *wxBLUE_BRUSH );
479 dc->DrawRectangle( bar );
480
481 dc->SetBrush( *wxTRANSPARENT_BRUSH );
482 dc->SetPen( *wxBLACK_PEN );
483 dc->DrawRectangle( cell );
f554a14b 484
4ed7af08
RR
485 return true;
486}
487
baa9ebc4 488wxSize wxDataViewProgressRenderer::GetSize()
4ed7af08
RR
489{
490 return wxSize(40,12);
491}
f554a14b
WS
492
493// ---------------------------------------------------------
baa9ebc4 494// wxDataViewDateRenderer
f554a14b 495// ---------------------------------------------------------
4ed7af08 496
baa9ebc4 497class wxDataViewDateRendererPopupTransient: public wxPopupTransientWindow
4ed7af08 498{
f554a14b 499public:
baa9ebc4 500 wxDataViewDateRendererPopupTransient( wxWindow* parent, wxDateTime *value,
0a71f9e9 501 wxDataViewListModel *model, unsigned int col, unsigned int row ) :
4ed7af08
RR
502 wxPopupTransientWindow( parent, wxBORDER_SIMPLE )
503 {
504 m_model = model;
505 m_col = col;
506 m_row = row;
f554a14b 507 m_cal = new wxCalendarCtrl( this, wxID_ANY, *value );
4ed7af08
RR
508 wxBoxSizer *sizer = new wxBoxSizer( wxHORIZONTAL );
509 sizer->Add( m_cal, 1, wxGROW );
510 SetSizer( sizer );
511 sizer->Fit( this );
512 }
f554a14b 513
4ed7af08 514 void OnCalendar( wxCalendarEvent &event );
f554a14b 515
4ed7af08 516 wxCalendarCtrl *m_cal;
f554a14b 517 wxDataViewListModel *m_model;
0a71f9e9
RR
518 unsigned int m_col;
519 unsigned int m_row;
f554a14b 520
a8461d31
PC
521protected:
522 virtual void OnDismiss()
523 {
524 }
525
4ed7af08
RR
526private:
527 DECLARE_EVENT_TABLE()
528};
529
baa9ebc4
RR
530BEGIN_EVENT_TABLE(wxDataViewDateRendererPopupTransient,wxPopupTransientWindow)
531 EVT_CALENDAR( wxID_ANY, wxDataViewDateRendererPopupTransient::OnCalendar )
4ed7af08
RR
532END_EVENT_TABLE()
533
baa9ebc4 534void wxDataViewDateRendererPopupTransient::OnCalendar( wxCalendarEvent &event )
4ed7af08
RR
535{
536 wxDateTime date = event.GetDate();
537 wxVariant value = date;
538 m_model->SetValue( value, m_col, m_row );
539 m_model->ValueChanged( m_col, m_row );
540 DismissAndNotify();
541}
542
baa9ebc4 543IMPLEMENT_ABSTRACT_CLASS(wxDataViewDateRenderer, wxDataViewCustomRenderer)
4ed7af08 544
baa9ebc4 545wxDataViewDateRenderer::wxDataViewDateRenderer( const wxString &varianttype,
4ed7af08 546 wxDataViewCellMode mode ) :
baa9ebc4 547 wxDataViewCustomRenderer( varianttype, mode )
4ed7af08
RR
548{
549}
f554a14b 550
baa9ebc4 551bool wxDataViewDateRenderer::SetValue( const wxVariant &value )
4ed7af08
RR
552{
553 m_date = value.GetDateTime();
f554a14b 554
4ed7af08
RR
555 return true;
556}
557
baa9ebc4 558bool wxDataViewDateRenderer::Render( wxRect cell, wxDC *dc, int WXUNUSED(state) )
4ed7af08
RR
559{
560 dc->SetFont( GetOwner()->GetOwner()->GetFont() );
561 wxString tmp = m_date.FormatDate();
562 dc->DrawText( tmp, cell.x, cell.y );
563
564 return true;
565}
566
baa9ebc4 567wxSize wxDataViewDateRenderer::GetSize()
4ed7af08
RR
568{
569 wxDataViewCtrl* view = GetOwner()->GetOwner();
570 wxString tmp = m_date.FormatDate();
571 wxCoord x,y,d;
572 view->GetTextExtent( tmp, &x, &y, &d );
573 return wxSize(x,y+d);
574}
575
baa9ebc4 576bool wxDataViewDateRenderer::Activate( wxRect WXUNUSED(cell), wxDataViewListModel *model, unsigned int col, unsigned int row )
4ed7af08
RR
577{
578 wxVariant variant;
579 model->GetValue( variant, col, row );
580 wxDateTime value = variant.GetDateTime();
581
baa9ebc4 582 wxDataViewDateRendererPopupTransient *popup = new wxDataViewDateRendererPopupTransient(
4ed7af08
RR
583 GetOwner()->GetOwner()->GetParent(), &value, model, col, row );
584 wxPoint pos = wxGetMousePosition();
585 popup->Move( pos );
586 popup->Layout();
587 popup->Popup( popup->m_cal );
588
589 return true;
590}
591
f554a14b 592// ---------------------------------------------------------
4ed7af08 593// wxDataViewColumn
f554a14b 594// ---------------------------------------------------------
4ed7af08
RR
595
596IMPLEMENT_ABSTRACT_CLASS(wxDataViewColumn, wxDataViewColumnBase)
597
baa9ebc4 598wxDataViewColumn::wxDataViewColumn( const wxString &title, wxDataViewRenderer *cell, unsigned int model_column,
008b5a66
RR
599 int width, int flags ) :
600 wxDataViewColumnBase( title, cell, model_column, width, flags )
4ed7af08 601{
008b5a66
RR
602 m_width = width;
603 if (m_width < 0)
604 m_width = 80;
4ed7af08
RR
605}
606
07a84e7b
RR
607wxDataViewColumn::wxDataViewColumn( const wxBitmap &bitmap, wxDataViewRenderer *cell, unsigned int model_column,
608 int width, int flags ) :
609 wxDataViewColumnBase( bitmap, cell, model_column, width, flags )
610{
611 m_width = width;
612 if (m_width < 0)
613 m_width = 30;
614}
615
47cef10f
RR
616void wxDataViewColumn::SetAlignment( wxAlignment WXUNUSED(align) )
617{
618 // TODO
619}
620
31fb32e1
RR
621void wxDataViewColumn::SetSortable( bool WXUNUSED(sortable) )
622{
623 // TODO
624}
625
626bool wxDataViewColumn::GetSortable()
627{
628 // TODO
629 return false;
630}
631
47cef10f
RR
632void wxDataViewColumn::SetSortOrder( bool WXUNUSED(ascending) )
633{
634 // TODO
635}
636
31fb32e1
RR
637bool wxDataViewColumn::IsSortOrderAscending()
638{
639 // TODO
640 return true;
641}
642
643
4ed7af08
RR
644wxDataViewColumn::~wxDataViewColumn()
645{
646}
647
648void wxDataViewColumn::SetTitle( const wxString &title )
649{
650 wxDataViewColumnBase::SetTitle( title );
f554a14b 651
4ed7af08
RR
652}
653
47cef10f
RR
654void wxDataViewColumn::SetBitmap( const wxBitmap &bitmap )
655{
656 wxDataViewColumnBase::SetBitmap( bitmap );
657
658}
659
533544f2
RR
660int wxDataViewColumn::GetWidth()
661{
662 return m_width;
663}
664
4ed7af08
RR
665//-----------------------------------------------------------------------------
666// wxDataViewHeaderWindow
667//-----------------------------------------------------------------------------
668
45778c96 669IMPLEMENT_ABSTRACT_CLASS(wxDataViewHeaderWindow, wxWindow)
4ed7af08
RR
670
671BEGIN_EVENT_TABLE(wxDataViewHeaderWindow,wxWindow)
672 EVT_PAINT (wxDataViewHeaderWindow::OnPaint)
673 EVT_MOUSE_EVENTS (wxDataViewHeaderWindow::OnMouse)
674 EVT_SET_FOCUS (wxDataViewHeaderWindow::OnSetFocus)
675END_EVENT_TABLE()
676
677wxDataViewHeaderWindow::wxDataViewHeaderWindow( wxDataViewCtrl *parent, wxWindowID id,
678 const wxPoint &pos, const wxSize &size, const wxString &name ) :
679 wxWindow( parent, id, pos, size, 0, name )
680{
681 SetOwner( parent );
4b3feaa7 682
4ed7af08 683 m_resizeCursor = new wxCursor( wxCURSOR_SIZEWE );
f554a14b 684
4ed7af08 685 wxVisualAttributes attr = wxPanel::GetClassDefaultAttributes();
2e992e06 686 SetBackgroundStyle( wxBG_STYLE_CUSTOM );
4ed7af08
RR
687 SetOwnForegroundColour( attr.colFg );
688 SetOwnBackgroundColour( attr.colBg );
689 if (!m_hasFont)
690 SetOwnFont( attr.font );
691}
692
693wxDataViewHeaderWindow::~wxDataViewHeaderWindow()
694{
695 delete m_resizeCursor;
696}
697
f554a14b 698void wxDataViewHeaderWindow::OnPaint( wxPaintEvent &WXUNUSED(event) )
4ed7af08 699{
4b3feaa7
RR
700 int w, h;
701 GetClientSize( &w, &h );
702
2e992e06
VZ
703 wxAutoBufferedPaintDC dc( this );
704
705 dc.SetBackground(GetBackgroundColour());
706 dc.Clear();
f554a14b 707
4ed7af08
RR
708 int xpix;
709 m_owner->GetScrollPixelsPerUnit( &xpix, NULL );
710
711 int x;
712 m_owner->GetViewStart( &x, NULL );
713
714 // account for the horz scrollbar offset
715 dc.SetDeviceOrigin( -x * xpix, 0 );
f554a14b 716
4ed7af08 717 dc.SetFont( GetFont() );
f554a14b 718
0a71f9e9
RR
719 unsigned int cols = GetOwner()->GetNumberOfColumns();
720 unsigned int i;
4b3feaa7
RR
721 int xpos = 0;
722 for (i = 0; i < cols; i++)
723 {
724 wxDataViewColumn *col = GetOwner()->GetColumn( i );
725 int width = col->GetWidth();
f554a14b 726
4b3feaa7
RR
727 int cw = width;
728 int ch = h;
4b3feaa7
RR
729
730 wxRendererNative::Get().DrawHeaderButton
731 (
732 this,
733 dc,
72664514 734 wxRect(xpos, 0, cw, ch-1),
4b3feaa7
RR
735 m_parent->IsEnabled() ? 0
736 : (int)wxCONTROL_DISABLED
737 );
738
f554a14b
WS
739 dc.DrawText( col->GetTitle(), xpos+3, 3 );
740
4b3feaa7
RR
741 xpos += width;
742 }
4ed7af08
RR
743}
744
f554a14b 745void wxDataViewHeaderWindow::OnMouse( wxMouseEvent &WXUNUSED(event) )
4ed7af08
RR
746{
747}
748
749void wxDataViewHeaderWindow::OnSetFocus( wxFocusEvent &event )
750{
cab07038 751 GetParent()->SetFocus();
4ed7af08
RR
752 event.Skip();
753}
754
0fcce6b9
RR
755//-----------------------------------------------------------------------------
756// wxDataViewRenameTimer
757//-----------------------------------------------------------------------------
758
759wxDataViewRenameTimer::wxDataViewRenameTimer( wxDataViewMainWindow *owner )
760{
761 m_owner = owner;
762}
763
764void wxDataViewRenameTimer::Notify()
765{
766 m_owner->OnRenameTimer();
767}
768
769//-----------------------------------------------------------------------------
770// wxDataViewTextCtrlWrapper: wraps a wxTextCtrl for inline editing
771//-----------------------------------------------------------------------------
772
773BEGIN_EVENT_TABLE(wxDataViewTextCtrlWrapper, wxEvtHandler)
774 EVT_CHAR (wxDataViewTextCtrlWrapper::OnChar)
775 EVT_KEY_UP (wxDataViewTextCtrlWrapper::OnKeyUp)
776 EVT_KILL_FOCUS (wxDataViewTextCtrlWrapper::OnKillFocus)
777END_EVENT_TABLE()
778
779wxDataViewTextCtrlWrapper::wxDataViewTextCtrlWrapper(
780 wxDataViewMainWindow *owner,
781 wxTextCtrl *text,
782 wxDataViewListModel *model,
0a71f9e9 783 unsigned int col, unsigned int row,
0fcce6b9
RR
784 wxRect rectLabel )
785{
786 m_owner = owner;
787 m_model = model;
788 m_row = row;
789 m_col = col;
120b9b05
WS
790 m_text = text;
791
0fcce6b9
RR
792 m_finished = false;
793 m_aboutToFinish = false;
120b9b05 794
0fcce6b9
RR
795 wxVariant value;
796 model->GetValue( value, col, row );
797 m_startValue = value.GetString();
120b9b05 798
0fcce6b9
RR
799 m_owner->GetOwner()->CalcScrolledPosition(
800 rectLabel.x, rectLabel.y, &rectLabel.x, &rectLabel.y );
801
802 m_text->Create( owner, wxID_ANY, m_startValue,
803 wxPoint(rectLabel.x-2,rectLabel.y-2),
804 wxSize(rectLabel.width+7,rectLabel.height+4) );
805 m_text->SetFocus();
120b9b05 806
0fcce6b9
RR
807 m_text->PushEventHandler(this);
808}
809
810void wxDataViewTextCtrlWrapper::AcceptChangesAndFinish()
811{
812 m_aboutToFinish = true;
813
814 // Notify the owner about the changes
815 AcceptChanges();
816
817 // Even if vetoed, close the control (consistent with MSW)
818 Finish();
819}
820
821void wxDataViewTextCtrlWrapper::OnChar( wxKeyEvent &event )
822{
823 switch ( event.m_keyCode )
824 {
825 case WXK_RETURN:
826 AcceptChangesAndFinish();
827 break;
828
829 case WXK_ESCAPE:
830 // m_owner->OnRenameCancelled( m_itemEdited );
831 Finish();
832 break;
833
834 default:
835 event.Skip();
836 }
837}
838
839void wxDataViewTextCtrlWrapper::OnKeyUp( wxKeyEvent &event )
840{
841 if (m_finished)
842 {
843 event.Skip();
844 return;
845 }
846
847 // auto-grow the textctrl
848 wxSize parentSize = m_owner->GetSize();
849 wxPoint myPos = m_text->GetPosition();
850 wxSize mySize = m_text->GetSize();
851 int sx, sy;
852 m_text->GetTextExtent(m_text->GetValue() + _T("MM"), &sx, &sy);
853 if (myPos.x + sx > parentSize.x)
854 sx = parentSize.x - myPos.x;
855 if (mySize.x > sx)
856 sx = mySize.x;
857 m_text->SetSize(sx, wxDefaultCoord);
858
859 event.Skip();
860}
861
862void wxDataViewTextCtrlWrapper::OnKillFocus( wxFocusEvent &event )
863{
864 if ( !m_finished && !m_aboutToFinish )
865 {
866 AcceptChanges();
867 //if ( !AcceptChanges() )
868 // m_owner->OnRenameCancelled( m_itemEdited );
120b9b05 869
0fcce6b9
RR
870 Finish();
871 }
872
873 // We must let the native text control handle focus
874 event.Skip();
875}
876
877bool wxDataViewTextCtrlWrapper::AcceptChanges()
878{
879 const wxString value = m_text->GetValue();
880
881 if ( value == m_startValue )
882 // nothing changed, always accept
883 return true;
884
885// if ( !m_owner->OnRenameAccept(m_itemEdited, value) )
886 // vetoed by the user
887// return false;
888
889 // accepted, do rename the item
890 wxVariant variant;
891 variant = value;
892 m_model->SetValue( variant, m_col, m_row );
893 m_model->ValueChanged( m_col, m_row );
894
895 return true;
896}
897
898void wxDataViewTextCtrlWrapper::Finish()
899{
900 if ( !m_finished )
901 {
902 m_finished = true;
903
904 m_text->RemoveEventHandler(this);
905 m_owner->FinishEditing(m_text);
906
907 // delete later
908 wxPendingDelete.Append( this );
909 }
910}
911
4ed7af08
RR
912//-----------------------------------------------------------------------------
913// wxDataViewMainWindow
914//-----------------------------------------------------------------------------
915
0a71f9e9 916int LINKAGEMODE wxDataViewSelectionCmp( unsigned int row1, unsigned int row2 )
cab07038
RR
917{
918 if (row1 > row2) return 1;
919 if (row1 == row2) return 0;
920 return -1;
921}
922
923
45778c96 924IMPLEMENT_ABSTRACT_CLASS(wxDataViewMainWindow, wxWindow)
4ed7af08
RR
925
926BEGIN_EVENT_TABLE(wxDataViewMainWindow,wxWindow)
927 EVT_PAINT (wxDataViewMainWindow::OnPaint)
928 EVT_MOUSE_EVENTS (wxDataViewMainWindow::OnMouse)
929 EVT_SET_FOCUS (wxDataViewMainWindow::OnSetFocus)
cab07038
RR
930 EVT_KILL_FOCUS (wxDataViewMainWindow::OnKillFocus)
931 EVT_CHAR (wxDataViewMainWindow::OnChar)
4ed7af08
RR
932END_EVENT_TABLE()
933
934wxDataViewMainWindow::wxDataViewMainWindow( wxDataViewCtrl *parent, wxWindowID id,
935 const wxPoint &pos, const wxSize &size, const wxString &name ) :
72664514 936 wxWindow( parent, id, pos, size, wxWANTS_CHARS, name ),
cab07038 937 m_selection( wxDataViewSelectionCmp )
120b9b05 938
4ed7af08
RR
939{
940 SetOwner( parent );
f554a14b 941
0fcce6b9
RR
942 m_lastOnSame = false;
943 m_renameTimer = new wxDataViewRenameTimer( this );
944 m_textctrlWrapper = NULL;
120b9b05 945
0fcce6b9
RR
946 // TODO: user better initial values/nothing selected
947 m_currentCol = NULL;
948 m_currentRow = 0;
949
950 // TODO: we need to calculate this smartly
4b3feaa7 951 m_lineHeight = 20;
e21f75bd
RR
952
953 m_dragCount = 0;
954 m_dragStart = wxPoint(0,0);
0a71f9e9
RR
955 m_lineLastClicked = (unsigned int) -1;
956 m_lineBeforeLastClicked = (unsigned int) -1;
957 m_lineSelectSingleOnUp = (unsigned int) -1;
120b9b05 958
cab07038 959 m_hasFocus = false;
f554a14b 960
2e992e06 961 SetBackgroundStyle( wxBG_STYLE_CUSTOM );
72664514
RR
962 SetBackgroundColour( *wxWHITE );
963
4b3feaa7 964 UpdateDisplay();
4ed7af08
RR
965}
966
967wxDataViewMainWindow::~wxDataViewMainWindow()
968{
0fcce6b9
RR
969 delete m_renameTimer;
970}
971
972void wxDataViewMainWindow::OnRenameTimer()
973{
974 // We have to call this here because changes may just have
975 // been made and no screen update taken place.
976 if ( m_dirty )
977 wxSafeYield();
978
979
980 int xpos = 0;
0a71f9e9
RR
981 unsigned int cols = GetOwner()->GetNumberOfColumns();
982 unsigned int i;
0fcce6b9
RR
983 for (i = 0; i < cols; i++)
984 {
985 wxDataViewColumn *c = GetOwner()->GetColumn( i );
986 if (c == m_currentCol)
987 break;
988 xpos += c->GetWidth();
989 }
990 wxRect labelRect( xpos, m_currentRow * m_lineHeight, m_currentCol->GetWidth(), m_lineHeight );
991
992 wxClassInfo *textControlClass = CLASSINFO(wxTextCtrl);
993
994 wxTextCtrl * const text = (wxTextCtrl *)textControlClass->CreateObject();
120b9b05 995 m_textctrlWrapper = new wxDataViewTextCtrlWrapper(this, text, GetOwner()->GetModel(),
0fcce6b9
RR
996 m_currentCol->GetModelColumn(), m_currentRow, labelRect );
997}
998
999void wxDataViewMainWindow::FinishEditing( wxTextCtrl *text )
1000{
1001 delete text;
1002 m_textctrlWrapper = NULL;
1003 SetFocus();
1004 // SetFocusIgnoringChildren();
4ed7af08
RR
1005}
1006
a0f3af5f
RR
1007bool wxDataViewMainWindow::RowAppended()
1008{
1009 return false;
1010}
1011
1012bool wxDataViewMainWindow::RowPrepended()
1013{
1014 return false;
1015}
1016
0a71f9e9 1017bool wxDataViewMainWindow::RowInserted( unsigned int WXUNUSED(before) )
a0f3af5f
RR
1018{
1019 return false;
1020}
1021
0a71f9e9 1022bool wxDataViewMainWindow::RowDeleted( unsigned int WXUNUSED(row) )
a0f3af5f
RR
1023{
1024 return false;
1025}
1026
0a71f9e9 1027bool wxDataViewMainWindow::RowChanged( unsigned int WXUNUSED(row) )
a0f3af5f
RR
1028{
1029 return false;
1030}
1031
0a71f9e9 1032bool wxDataViewMainWindow::ValueChanged( unsigned int WXUNUSED(col), unsigned int row )
a0f3af5f 1033{
0fdc2321
RR
1034 wxRect rect( 0, row*m_lineHeight, 10000, m_lineHeight );
1035 m_owner->CalcScrolledPosition( rect.x, rect.y, &rect.x, &rect.y );
1036 Refresh( true, &rect );
1037
1038 return true;
a0f3af5f
RR
1039}
1040
0a71f9e9 1041bool wxDataViewMainWindow::RowsReordered( unsigned int *WXUNUSED(new_order) )
a0f3af5f 1042{
0fcce6b9 1043 Refresh();
120b9b05 1044
0fcce6b9 1045 return true;
a0f3af5f
RR
1046}
1047
1048bool wxDataViewMainWindow::Cleared()
1049{
1050 return false;
1051}
1052
4b3feaa7
RR
1053void wxDataViewMainWindow::UpdateDisplay()
1054{
1055 m_dirty = true;
1056}
1057
1058void wxDataViewMainWindow::OnInternalIdle()
1059{
1060 wxWindow::OnInternalIdle();
f554a14b 1061
4b3feaa7
RR
1062 if (m_dirty)
1063 {
1064 RecalculateDisplay();
1065 m_dirty = false;
1066 }
1067}
1068
1069void wxDataViewMainWindow::RecalculateDisplay()
1070{
1071 wxDataViewListModel *model = GetOwner()->GetModel();
1072 if (!model)
1073 {
1074 Refresh();
1075 return;
1076 }
f554a14b 1077
4b3feaa7 1078 int width = 0;
0a71f9e9
RR
1079 unsigned int cols = GetOwner()->GetNumberOfColumns();
1080 unsigned int i;
4b3feaa7
RR
1081 for (i = 0; i < cols; i++)
1082 {
1083 wxDataViewColumn *col = GetOwner()->GetColumn( i );
1084 width += col->GetWidth();
1085 }
f554a14b 1086
4b3feaa7
RR
1087 int height = model->GetNumberOfRows() * m_lineHeight;
1088
1089 SetVirtualSize( width, height );
1090 GetOwner()->SetScrollRate( 10, m_lineHeight );
f554a14b 1091
4b3feaa7
RR
1092 Refresh();
1093}
1094
1095void wxDataViewMainWindow::ScrollWindow( int dx, int dy, const wxRect *rect )
1096{
1097 wxWindow::ScrollWindow( dx, dy, rect );
1098 GetOwner()->m_headerArea->ScrollWindow( dx, 0 );
1099}
1100
f554a14b 1101void wxDataViewMainWindow::OnPaint( wxPaintEvent &WXUNUSED(event) )
4ed7af08 1102{
2e992e06
VZ
1103 wxAutoBufferedPaintDC dc( this );
1104
1105 dc.SetBackground(GetBackgroundColour());
1106 dc.Clear();
4ed7af08 1107
4b3feaa7 1108 GetOwner()->PrepareDC( dc );
4ed7af08
RR
1109
1110 dc.SetFont( GetFont() );
90675b95
RR
1111
1112 wxRect update = GetUpdateRegion().GetBox();
1113 m_owner->CalcUnscrolledPosition( update.x, update.y, &update.x, &update.y );
f554a14b 1114
90675b95 1115 wxDataViewListModel *model = GetOwner()->GetModel();
f554a14b 1116
0a71f9e9
RR
1117 unsigned int item_start = wxMax( 0, (update.y / m_lineHeight) );
1118 unsigned int item_count = wxMin( (int)(((update.y + update.height) / m_lineHeight) - item_start + 1),
a87594c6 1119 (int)(model->GetNumberOfRows()-item_start) );
90675b95 1120
120b9b05 1121
cab07038 1122
0a71f9e9 1123 unsigned int item;
cab07038
RR
1124 for (item = item_start; item < item_start+item_count; item++)
1125 {
1126 if (m_selection.Index( item ) != wxNOT_FOUND)
1127 {
daebb44c
RR
1128 int flags = wxCONTROL_SELECTED;
1129 if (item == m_currentRow)
1130 flags |= wxCONTROL_CURRENT;
1131 if (m_hasFocus)
1132 flags |= wxCONTROL_FOCUSED;
e21f75bd 1133 wxRect rect( 0, item*m_lineHeight+1, GetEndOfLastCol(), m_lineHeight-2 );
daebb44c
RR
1134 wxRendererNative::Get().DrawItemSelectionRect
1135 (
1136 this,
1137 dc,
1138 rect,
1139 flags
1140 );
1141 }
1142 else
1143 {
1144 if (item == m_currentRow)
1145 {
1146 int flags = wxCONTROL_CURRENT;
1147 if (m_hasFocus)
1148 flags |= wxCONTROL_FOCUSED; // should have no effect
1149 wxRect rect( 0, item*m_lineHeight+1, GetEndOfLastCol(), m_lineHeight-2 );
1150 wxRendererNative::Get().DrawItemSelectionRect
1151 (
1152 this,
1153 dc,
1154 rect,
1155 flags
1156 );
120b9b05 1157
daebb44c 1158 }
cab07038
RR
1159 }
1160 }
120b9b05 1161
90675b95
RR
1162 wxRect cell_rect;
1163 cell_rect.x = 0;
1164 cell_rect.height = m_lineHeight;
0a71f9e9
RR
1165 unsigned int cols = GetOwner()->GetNumberOfColumns();
1166 unsigned int i;
90675b95
RR
1167 for (i = 0; i < cols; i++)
1168 {
1169 wxDataViewColumn *col = GetOwner()->GetColumn( i );
baa9ebc4 1170 wxDataViewRenderer *cell = col->GetRenderer();
90675b95 1171 cell_rect.width = col->GetWidth();
f554a14b 1172
0fcce6b9 1173 for (item = item_start; item < item_start+item_count; item++)
90675b95
RR
1174 {
1175 cell_rect.y = item*m_lineHeight;
1176 wxVariant value;
1177 model->GetValue( value, col->GetModelColumn(), item );
1178 cell->SetValue( value );
4064f7de
RR
1179 wxSize size = cell->GetSize();
1180 // cannot be bigger than allocated space
1181 size.x = wxMin( size.x, cell_rect.width );
1182 size.y = wxMin( size.y, cell_rect.height );
1183 // TODO: check for left/right/centre alignment here
1184 wxRect item_rect;
1185 // for now: centre
1186 item_rect.x = cell_rect.x + (cell_rect.width / 2) - (size.x / 2);
1187 item_rect.y = cell_rect.y + (cell_rect.height / 2) - (size.y / 2);
f554a14b 1188
4064f7de
RR
1189 item_rect.width = size.x;
1190 item_rect.height= size.y;
1191 cell->Render( item_rect, &dc, 0 );
90675b95 1192 }
f554a14b 1193
90675b95
RR
1194 cell_rect.x += cell_rect.width;
1195 }
4ed7af08
RR
1196}
1197
cab07038
RR
1198int wxDataViewMainWindow::GetCountPerPage()
1199{
1200 wxSize size = GetClientSize();
1201 return size.y / m_lineHeight;
1202}
1203
e21f75bd
RR
1204int wxDataViewMainWindow::GetEndOfLastCol()
1205{
1206 int width = 0;
0a71f9e9 1207 unsigned int i;
e21f75bd
RR
1208 for (i = 0; i < GetOwner()->GetNumberOfColumns(); i++)
1209 {
1210 wxDataViewColumn *c = GetOwner()->GetColumn( i );
1211 width += c->GetWidth();
1212 }
1213 return width;
1214}
1215
0a71f9e9 1216unsigned int wxDataViewMainWindow::GetFirstVisibleRow()
72664514
RR
1217{
1218 int x = 0;
1219 int y = 0;
1220 m_owner->CalcUnscrolledPosition( x, y, &x, &y );
120b9b05 1221
72664514
RR
1222 return y / m_lineHeight;
1223}
1224
0a71f9e9 1225unsigned int wxDataViewMainWindow::GetLastVisibleRow()
72664514
RR
1226{
1227 wxSize client_size = GetClientSize();
1228 m_owner->CalcUnscrolledPosition( client_size.x, client_size.y, &client_size.x, &client_size.y );
1229
5637e131 1230 return wxMin( GetRowCount()-1, ((unsigned)client_size.y/m_lineHeight)+1 );
72664514
RR
1231}
1232
0a71f9e9 1233unsigned int wxDataViewMainWindow::GetRowCount()
cab07038
RR
1234{
1235 return GetOwner()->GetModel()->GetNumberOfRows();
1236}
1237
0a71f9e9 1238void wxDataViewMainWindow::ChangeCurrentRow( unsigned int row )
e21f75bd
RR
1239{
1240 m_currentRow = row;
120b9b05 1241
e21f75bd
RR
1242 // send event
1243}
1244
cab07038
RR
1245void wxDataViewMainWindow::SelectAllRows( bool on )
1246{
4a851b11
VZ
1247 if (IsEmpty())
1248 return;
120b9b05 1249
cab07038
RR
1250 if (on)
1251 {
72664514 1252 m_selection.Clear();
0a71f9e9 1253 for (unsigned int i = 0; i < GetRowCount(); i++)
cab07038 1254 m_selection.Add( i );
72664514
RR
1255 Refresh();
1256 }
1257 else
1258 {
0a71f9e9
RR
1259 unsigned int first_visible = GetFirstVisibleRow();
1260 unsigned int last_visible = GetLastVisibleRow();
1261 unsigned int i;
72664514 1262 for (i = 0; i < m_selection.GetCount(); i++)
120b9b05 1263 {
0a71f9e9 1264 unsigned int row = m_selection[i];
72664514
RR
1265 if ((row >= first_visible) && (row <= last_visible))
1266 RefreshRow( row );
1267 }
1268 m_selection.Clear();
cab07038 1269 }
cab07038
RR
1270}
1271
0a71f9e9 1272void wxDataViewMainWindow::SelectRow( unsigned int row, bool on )
cab07038
RR
1273{
1274 if (m_selection.Index( row ) == wxNOT_FOUND)
1275 {
1276 if (on)
1277 {
1278 m_selection.Add( row );
1279 RefreshRow( row );
1280 }
1281 }
1282 else
1283 {
1284 if (!on)
1285 {
1286 m_selection.Remove( row );
1287 RefreshRow( row );
1288 }
1289 }
1290}
1291
0a71f9e9 1292void wxDataViewMainWindow::SelectRows( unsigned int from, unsigned int to, bool on )
cab07038
RR
1293{
1294 if (from > to)
1295 {
0a71f9e9 1296 unsigned int tmp = from;
cab07038
RR
1297 from = to;
1298 to = tmp;
1299 }
1300
0a71f9e9 1301 unsigned int i;
cab07038
RR
1302 for (i = from; i <= to; i++)
1303 {
1304 if (m_selection.Index( i ) == wxNOT_FOUND)
1305 {
1306 if (on)
1307 m_selection.Add( i );
1308 }
1309 else
1310 {
1311 if (!on)
1312 m_selection.Remove( i );
1313 }
1314 }
1315 RefreshRows( from, to );
1316}
1317
0a71f9e9 1318void wxDataViewMainWindow::ReverseRowSelection( unsigned int row )
cab07038
RR
1319{
1320 if (m_selection.Index( row ) == wxNOT_FOUND)
1321 m_selection.Add( row );
1322 else
1323 m_selection.Remove( row );
120b9b05 1324 RefreshRow( row );
cab07038
RR
1325}
1326
0a71f9e9 1327bool wxDataViewMainWindow::IsRowSelected( unsigned int row )
cab07038
RR
1328{
1329 return (m_selection.Index( row ) != wxNOT_FOUND);
1330}
1331
0a71f9e9 1332void wxDataViewMainWindow::RefreshRow( unsigned int row )
cab07038 1333{
e21f75bd 1334 wxRect rect( 0, row*m_lineHeight, GetEndOfLastCol(), m_lineHeight );
cab07038 1335 m_owner->CalcScrolledPosition( rect.x, rect.y, &rect.x, &rect.y );
120b9b05 1336
cab07038
RR
1337 wxSize client_size = GetClientSize();
1338 wxRect client_rect( 0, 0, client_size.x, client_size.y );
1339 wxRect intersect_rect = client_rect.Intersect( rect );
1340 if (intersect_rect.width > 0)
1341 Refresh( true, &intersect_rect );
1342}
1343
0a71f9e9 1344void wxDataViewMainWindow::RefreshRows( unsigned int from, unsigned int to )
cab07038
RR
1345{
1346 if (from > to)
1347 {
0a71f9e9 1348 unsigned int tmp = to;
cab07038
RR
1349 to = from;
1350 from = tmp;
1351 }
1352
e21f75bd 1353 wxRect rect( 0, from*m_lineHeight, GetEndOfLastCol(), (to-from+1) * m_lineHeight );
cab07038 1354 m_owner->CalcScrolledPosition( rect.x, rect.y, &rect.x, &rect.y );
120b9b05 1355
cab07038
RR
1356 wxSize client_size = GetClientSize();
1357 wxRect client_rect( 0, 0, client_size.x, client_size.y );
1358 wxRect intersect_rect = client_rect.Intersect( rect );
1359 if (intersect_rect.width > 0)
1360 Refresh( true, &intersect_rect );
1361}
1362
0a71f9e9 1363void wxDataViewMainWindow::RefreshRowsAfter( unsigned int firstRow )
cab07038 1364{
0a71f9e9 1365 unsigned int count = GetRowCount();
4a851b11
VZ
1366 if (firstRow > count)
1367 return;
120b9b05 1368
e21f75bd 1369 wxRect rect( 0, firstRow*m_lineHeight, GetEndOfLastCol(), count * m_lineHeight );
cab07038 1370 m_owner->CalcScrolledPosition( rect.x, rect.y, &rect.x, &rect.y );
120b9b05 1371
cab07038
RR
1372 wxSize client_size = GetClientSize();
1373 wxRect client_rect( 0, 0, client_size.x, client_size.y );
1374 wxRect intersect_rect = client_rect.Intersect( rect );
1375 if (intersect_rect.width > 0)
1376 Refresh( true, &intersect_rect );
1377}
1378
0a71f9e9 1379void wxDataViewMainWindow::OnArrowChar(unsigned int newCurrent, const wxKeyEvent& event)
cab07038 1380{
4a851b11 1381 wxCHECK_RET( newCurrent < GetRowCount(),
cab07038
RR
1382 _T("invalid item index in OnArrowChar()") );
1383
1384 // if there is no selection, we cannot move it anywhere
1385 if (!HasCurrentRow())
1386 return;
1387
0a71f9e9 1388 unsigned int oldCurrent = m_currentRow;
cab07038
RR
1389
1390 // in single selection we just ignore Shift as we can't select several
1391 // items anyhow
e21f75bd 1392 if ( event.ShiftDown() && !IsSingleSel() )
cab07038
RR
1393 {
1394 RefreshRow( oldCurrent );
120b9b05 1395
e21f75bd 1396 ChangeCurrentRow( newCurrent );
cab07038
RR
1397
1398 // select all the items between the old and the new one
1399 if ( oldCurrent > newCurrent )
1400 {
1401 newCurrent = oldCurrent;
1402 oldCurrent = m_currentRow;
1403 }
1404
1405 SelectRows( oldCurrent, newCurrent, true );
1406 }
1407 else // !shift
1408 {
72664514 1409 RefreshRow( oldCurrent );
120b9b05 1410
cab07038
RR
1411 // all previously selected items are unselected unless ctrl is held
1412 if ( !event.ControlDown() )
1413 SelectAllRows(false);
1414
e21f75bd 1415 ChangeCurrentRow( newCurrent );
cab07038
RR
1416
1417 if ( !event.ControlDown() )
1418 SelectRow( m_currentRow, true );
72664514
RR
1419 else
1420 RefreshRow( m_currentRow );
cab07038
RR
1421 }
1422
1423 // MoveToFocus();
1424}
1425
1426void wxDataViewMainWindow::OnChar( wxKeyEvent &event )
1427{
1428 if (event.GetKeyCode() == WXK_TAB)
1429 {
1430 wxNavigationKeyEvent nevent;
1431 nevent.SetWindowChange( event.ControlDown() );
1432 nevent.SetDirection( !event.ShiftDown() );
1433 nevent.SetEventObject( GetParent()->GetParent() );
1434 nevent.SetCurrentFocus( m_parent );
1435 if (GetParent()->GetParent()->GetEventHandler()->ProcessEvent( nevent ))
1436 return;
1437 }
1438
1439 // no item -> nothing to do
1440 if (!HasCurrentRow())
1441 {
1442 event.Skip();
1443 return;
1444 }
120b9b05 1445
cab07038
RR
1446 // don't use m_linesPerPage directly as it might not be computed yet
1447 const int pageSize = GetCountPerPage();
1448 wxCHECK_RET( pageSize, _T("should have non zero page size") );
1449
1450 switch ( event.GetKeyCode() )
1451 {
1452 case WXK_UP:
1453 if ( m_currentRow > 0 )
1454 OnArrowChar( m_currentRow - 1, event );
1455 break;
1456
1457 case WXK_DOWN:
4a851b11 1458 if ( m_currentRow < GetRowCount() - 1 )
cab07038
RR
1459 OnArrowChar( m_currentRow + 1, event );
1460 break;
1461
1462 case WXK_END:
1463 if (!IsEmpty())
1464 OnArrowChar( GetRowCount() - 1, event );
1465 break;
1466
1467 case WXK_HOME:
1468 if (!IsEmpty())
1469 OnArrowChar( 0, event );
1470 break;
1471
1472 case WXK_PAGEUP:
1473 {
1474 int steps = pageSize - 1;
1475 int index = m_currentRow - steps;
1476 if (index < 0)
1477 index = 0;
1478
1479 OnArrowChar( index, event );
1480 }
1481 break;
1482
1483 case WXK_PAGEDOWN:
1484 {
1485 int steps = pageSize - 1;
0a71f9e9
RR
1486 unsigned int index = m_currentRow + steps;
1487 unsigned int count = GetRowCount();
cab07038
RR
1488 if ( index >= count )
1489 index = count - 1;
1490
1491 OnArrowChar( index, event );
1492 }
1493 break;
1494
1495 default:
1496 event.Skip();
1497 }
1498}
1499
4ed7af08
RR
1500void wxDataViewMainWindow::OnMouse( wxMouseEvent &event )
1501{
e21f75bd
RR
1502 if (event.GetEventType() == wxEVT_MOUSEWHEEL)
1503 {
1504 // let the base handle mouse wheel events.
1505 event.Skip();
1506 return;
1507 }
1508
0fdc2321
RR
1509 int x = event.GetX();
1510 int y = event.GetY();
1511 m_owner->CalcUnscrolledPosition( x, y, &x, &y );
1512
1513 wxDataViewColumn *col = NULL;
1514
1515 int xpos = 0;
0a71f9e9
RR
1516 unsigned int cols = GetOwner()->GetNumberOfColumns();
1517 unsigned int i;
0fdc2321
RR
1518 for (i = 0; i < cols; i++)
1519 {
1520 wxDataViewColumn *c = GetOwner()->GetColumn( i );
1521 if (x < xpos + c->GetWidth())
1522 {
1523 col = c;
1524 break;
1525 }
1526 xpos += c->GetWidth();
1527 }
f554a14b 1528 if (!col)
0fdc2321 1529 return;
baa9ebc4 1530 wxDataViewRenderer *cell = col->GetRenderer();
f554a14b 1531
0a71f9e9 1532 unsigned int current = y / m_lineHeight;
120b9b05 1533
e21f75bd
RR
1534 if ((current > GetRowCount()) || (x > GetEndOfLastCol()))
1535 {
1536 // Unselect all if below the last row ?
1537 return;
1538 }
f554a14b 1539
0fdc2321
RR
1540 wxDataViewListModel *model = GetOwner()->GetModel();
1541
e21f75bd
RR
1542 if (event.Dragging())
1543 {
1544 if (m_dragCount == 0)
1545 {
1546 // we have to report the raw, physical coords as we want to be
1547 // able to call HitTest(event.m_pointDrag) from the user code to
1548 // get the item being dragged
1549 m_dragStart = event.GetPosition();
1550 }
1551
1552 m_dragCount++;
1553
1554 if (m_dragCount != 3)
1555 return;
1556
1557 if (event.LeftIsDown())
1558 {
1559 // Notify cell about drag
1560 }
1561 return;
1562 }
1563 else
1564 {
1565 m_dragCount = 0;
1566 }
1567
1568 bool forceClick = false;
1569
0fcce6b9
RR
1570 if (event.ButtonDClick())
1571 {
1572 m_renameTimer->Stop();
1573 m_lastOnSame = false;
1574 }
1575
0fdc2321
RR
1576 if (event.LeftDClick())
1577 {
e21f75bd 1578 if ( current == m_lineLastClicked )
0fdc2321 1579 {
e21f75bd
RR
1580 if (cell->GetMode() == wxDATAVIEW_CELL_ACTIVATABLE)
1581 {
1582 wxVariant value;
1583 model->GetValue( value, col->GetModelColumn(), current );
1584 cell->SetValue( value );
1585 wxRect cell_rect( xpos, current * m_lineHeight, col->GetWidth(), m_lineHeight );
1586 cell->Activate( cell_rect, model, col->GetModelColumn(), current );
1587 }
1588 return;
1589 }
1590 else
1591 {
1592 // The first click was on another item, so don't interpret this as
1593 // a double click, but as a simple click instead
1594 forceClick = true;
0fdc2321 1595 }
120b9b05 1596 }
f554a14b 1597
0fcce6b9
RR
1598 if (event.LeftUp())
1599 {
0a71f9e9 1600 if (m_lineSelectSingleOnUp != (unsigned int)-1)
e21f75bd
RR
1601 {
1602 // select single line
1603 SelectAllRows( false );
1604 SelectRow( m_lineSelectSingleOnUp, true );
1605 }
120b9b05 1606
0fcce6b9
RR
1607 if (m_lastOnSame)
1608 {
a8461d31 1609 if ((col == m_currentCol) && (current == m_currentRow) &&
0fcce6b9
RR
1610 (cell->GetMode() == wxDATAVIEW_CELL_EDITABLE) )
1611 {
1612 m_renameTimer->Start( 100, true );
1613 }
1614 }
1615
1616 m_lastOnSame = false;
0a71f9e9 1617 m_lineSelectSingleOnUp = (unsigned int)-1;
120b9b05 1618 }
e21f75bd
RR
1619 else
1620 {
1621 // This is necessary, because after a DnD operation in
1622 // from and to ourself, the up event is swallowed by the
1623 // DnD code. So on next non-up event (which means here and
1624 // now) m_lineSelectSingleOnUp should be reset.
0a71f9e9 1625 m_lineSelectSingleOnUp = (unsigned int)-1;
e21f75bd
RR
1626 }
1627
1628 if (event.RightDown())
1629 {
1630 m_lineBeforeLastClicked = m_lineLastClicked;
1631 m_lineLastClicked = current;
1632
1633 // If the item is already selected, do not update the selection.
1634 // Multi-selections should not be cleared if a selected item is clicked.
1635 if (!IsRowSelected(current))
1636 {
1637 SelectAllRows(false);
1638 ChangeCurrentRow(current);
1639 SelectRow(m_currentRow,true);
1640 }
1641
1642 // notify cell about right click
1643 // cell->...
120b9b05 1644
e21f75bd
RR
1645 // Allow generation of context menu event
1646 event.Skip();
1647 }
1648 else if (event.MiddleDown())
1649 {
1650 // notify cell about middle click
1651 // cell->...
1652 }
1653 if (event.LeftDown() || forceClick)
0fcce6b9 1654 {
72664514
RR
1655#ifdef __WXMSW__
1656 SetFocus();
1657#endif
120b9b05 1658
e21f75bd
RR
1659 m_lineBeforeLastClicked = m_lineLastClicked;
1660 m_lineLastClicked = current;
1661
0a71f9e9 1662 unsigned int oldCurrentRow = m_currentRow;
e21f75bd
RR
1663 bool oldWasSelected = IsRowSelected(m_currentRow);
1664
1665 bool cmdModifierDown = event.CmdDown();
1666 if ( IsSingleSel() || !(cmdModifierDown || event.ShiftDown()) )
1667 {
1668 if ( IsSingleSel() || !IsRowSelected(current) )
1669 {
1670 SelectAllRows( false );
1671
1672 ChangeCurrentRow(current);
1673
1674 SelectRow(m_currentRow,true);
1675 }
1676 else // multi sel & current is highlighted & no mod keys
1677 {
1678 m_lineSelectSingleOnUp = current;
1679 ChangeCurrentRow(current); // change focus
1680 }
1681 }
1682 else // multi sel & either ctrl or shift is down
1683 {
1684 if (cmdModifierDown)
1685 {
1686 ChangeCurrentRow(current);
1687
1688 ReverseRowSelection(m_currentRow);
1689 }
1690 else if (event.ShiftDown())
1691 {
1692 ChangeCurrentRow(current);
1693
0a71f9e9 1694 unsigned int lineFrom = oldCurrentRow,
e21f75bd
RR
1695 lineTo = current;
1696
1697 if ( lineTo < lineFrom )
1698 {
1699 lineTo = lineFrom;
1700 lineFrom = m_currentRow;
1701 }
1702
1703 SelectRows(lineFrom, lineTo, true);
1704 }
1705 else // !ctrl, !shift
1706 {
1707 // test in the enclosing if should make it impossible
1708 wxFAIL_MSG( _T("how did we get here?") );
1709 }
1710 }
1711
72664514
RR
1712 if (m_currentRow != oldCurrentRow)
1713 RefreshRow( oldCurrentRow );
e21f75bd 1714
0fcce6b9 1715 wxDataViewColumn *oldCurrentCol = m_currentCol;
120b9b05 1716
0fcce6b9
RR
1717 // Update selection here...
1718 m_currentCol = col;
120b9b05 1719
e21f75bd 1720 m_lastOnSame = !forceClick && ((col == oldCurrentCol) && (current == oldCurrentRow)) && oldWasSelected;
0fdc2321 1721 }
4ed7af08
RR
1722}
1723
1724void wxDataViewMainWindow::OnSetFocus( wxFocusEvent &event )
1725{
cab07038 1726 m_hasFocus = true;
120b9b05 1727
cab07038
RR
1728 if (HasCurrentRow())
1729 Refresh();
120b9b05 1730
cab07038
RR
1731 event.Skip();
1732}
1733
1734void wxDataViewMainWindow::OnKillFocus( wxFocusEvent &event )
1735{
1736 m_hasFocus = false;
120b9b05 1737
cab07038
RR
1738 if (HasCurrentRow())
1739 Refresh();
120b9b05 1740
4ed7af08
RR
1741 event.Skip();
1742}
1743
1744//-----------------------------------------------------------------------------
1745// wxDataViewCtrl
1746//-----------------------------------------------------------------------------
1747
1748IMPLEMENT_DYNAMIC_CLASS(wxDataViewCtrl, wxDataViewCtrlBase)
1749
4b3feaa7
RR
1750BEGIN_EVENT_TABLE(wxDataViewCtrl, wxDataViewCtrlBase)
1751 EVT_SIZE(wxDataViewCtrl::OnSize)
1752END_EVENT_TABLE()
1753
4ed7af08
RR
1754wxDataViewCtrl::~wxDataViewCtrl()
1755{
1756 if (m_notifier)
1757 GetModel()->RemoveNotifier( m_notifier );
1758}
1759
1760void wxDataViewCtrl::Init()
1761{
1762 m_notifier = NULL;
1763}
1764
1765bool wxDataViewCtrl::Create(wxWindow *parent, wxWindowID id,
f554a14b 1766 const wxPoint& pos, const wxSize& size,
4ed7af08
RR
1767 long style, const wxValidator& validator )
1768{
4b3feaa7
RR
1769 if (!wxControl::Create( parent, id, pos, size, style | wxScrolledWindowStyle|wxSUNKEN_BORDER, validator))
1770 return false;
1771
4ed7af08 1772 Init();
f554a14b 1773
4ed7af08
RR
1774#ifdef __WXMAC__
1775 MacSetClipChildren( true ) ;
1776#endif
1777
f554a14b 1778 m_clientArea = new wxDataViewMainWindow( this, wxID_ANY );
72664514
RR
1779#ifdef __WXMSW__
1780 m_headerArea = new wxDataViewHeaderWindow( this, wxID_ANY, wxDefaultPosition, wxSize(wxDefaultCoord,22) );
1781#else
f554a14b 1782 m_headerArea = new wxDataViewHeaderWindow( this, wxID_ANY, wxDefaultPosition, wxSize(wxDefaultCoord,25) );
120b9b05 1783#endif
f554a14b 1784
4ed7af08 1785 SetTargetWindow( m_clientArea );
f554a14b 1786
4ed7af08
RR
1787 wxBoxSizer *sizer = new wxBoxSizer( wxVERTICAL );
1788 sizer->Add( m_headerArea, 0, wxGROW );
1789 sizer->Add( m_clientArea, 1, wxGROW );
1790 SetSizer( sizer );
1791
1792 return true;
1793}
1794
1795#ifdef __WXMSW__
1796WXLRESULT wxDataViewCtrl::MSWWindowProc(WXUINT nMsg,
1797 WXWPARAM wParam,
1798 WXLPARAM lParam)
1799{
b910a8ad 1800 WXLRESULT rc = wxDataViewCtrlBase::MSWWindowProc(nMsg, wParam, lParam);
4ed7af08
RR
1801
1802#ifndef __WXWINCE__
1803 // we need to process arrows ourselves for scrolling
1804 if ( nMsg == WM_GETDLGCODE )
1805 {
1806 rc |= DLGC_WANTARROWS;
1807 }
1808#endif
1809
1810 return rc;
1811}
1812#endif
1813
f554a14b 1814void wxDataViewCtrl::OnSize( wxSizeEvent &WXUNUSED(event) )
4ed7af08 1815{
4b3feaa7
RR
1816 // We need to override OnSize so that our scrolled
1817 // window a) does call Layout() to use sizers for
1818 // positioning the controls but b) does not query
1819 // the sizer for their size and use that for setting
1820 // the scrollable area as set that ourselves by
1821 // calling SetScrollbar() further down.
1822
1823 Layout();
1824
1825 AdjustScrollbars();
4ed7af08
RR
1826}
1827
1828bool wxDataViewCtrl::AssociateModel( wxDataViewListModel *model )
1829{
1830 if (!wxDataViewCtrlBase::AssociateModel( model ))
1831 return false;
1832
a0f3af5f 1833 m_notifier = new wxGenericDataViewListModelNotifier( m_clientArea );
4ed7af08 1834
f554a14b 1835 model->AddNotifier( m_notifier );
4ed7af08 1836
4b3feaa7 1837 m_clientArea->UpdateDisplay();
f554a14b 1838
4ed7af08
RR
1839 return true;
1840}
1841
1842bool wxDataViewCtrl::AppendColumn( wxDataViewColumn *col )
1843{
1844 if (!wxDataViewCtrlBase::AppendColumn(col))
1845 return false;
f554a14b 1846
4b3feaa7 1847 m_clientArea->UpdateDisplay();
f554a14b 1848
4ed7af08
RR
1849 return true;
1850}
1851
df387169 1852void wxDataViewCtrl::SetSelection( int WXUNUSED(row) )
6ff7eee7 1853{
df387169 1854 // FIXME - TODO
6ff7eee7
RR
1855}
1856
df387169 1857void wxDataViewCtrl::SetSelectionRange( unsigned int WXUNUSED(from), unsigned int WXUNUSED(to) )
6ff7eee7 1858{
df387169 1859 // FIXME - TODO
6ff7eee7
RR
1860}
1861
df387169 1862void wxDataViewCtrl::SetSelections( const wxArrayInt& WXUNUSED(aSelections) )
6ff7eee7 1863{
df387169 1864 // FIXME - TODO
6ff7eee7 1865}
df387169
WS
1866
1867void wxDataViewCtrl::Unselect( unsigned int WXUNUSED(row) )
fc211fe5 1868{
df387169 1869 // FIXME - TODO
fc211fe5
RR
1870}
1871
df387169 1872bool wxDataViewCtrl::IsSelected( unsigned int WXUNUSED(row) ) const
6ff7eee7 1873{
df387169
WS
1874 // FIXME - TODO
1875
6ff7eee7
RR
1876 return false;
1877}
1878
1879int wxDataViewCtrl::GetSelection() const
1880{
df387169
WS
1881 // FIXME - TODO
1882
6ff7eee7
RR
1883 return -1;
1884}
1885
df387169 1886int wxDataViewCtrl::GetSelections(wxArrayInt& WXUNUSED(aSelections) ) const
6ff7eee7 1887{
df387169
WS
1888 // FIXME - TODO
1889
6ff7eee7
RR
1890 return 0;
1891}
1892
f554a14b 1893#endif
4ed7af08
RR
1894 // !wxUSE_GENERICDATAVIEWCTRL
1895
f554a14b 1896#endif
4ed7af08 1897 // wxUSE_DATAVIEWCTRL