/[pcsx2_0.9.7]/branch/r3113_0.9.7_beta/3rdparty/wxWidgets/src/generic/datavgen.cpp
ViewVC logotype

Annotation of /branch/r3113_0.9.7_beta/3rdparty/wxWidgets/src/generic/datavgen.cpp

Parent Directory Parent Directory | Revision Log Revision Log


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

  ViewVC Help
Powered by ViewVC 1.1.22