]> git.saurik.com Git - wxWidgets.git/commitdiff
Rewritten in-place editing for generic wxDataViewCtrl
authorRobert Roebling <robert@roebling.de>
Mon, 16 Apr 2007 12:45:25 +0000 (12:45 +0000)
committerRobert Roebling <robert@roebling.de>
Mon, 16 Apr 2007 12:45:25 +0000 (12:45 +0000)
    moving the code (partly) to the renderer and away
    from the wxDataViewCtrl class. Adding new in-plae
    editors (wxChoice) should be much simpler now.
  Also implemented using Validate() before committing
    a change to the data model.

git-svn-id: https://svn.wxwidgets.org/svn/wx/wxWidgets/trunk@45497 c3d73ce0-8a6f-49c7-b76d-6d57e0e08775

include/wx/dataview.h
include/wx/generic/dataview.h
src/generic/datavgen.cpp

index c4953185269b2a08bae8e47ad139b819e69a4c06..52176d23199882e8f1a301613ba361f51a87b745 100644 (file)
@@ -280,7 +280,7 @@ public:
     //       to combine alignment flags (e.g. wxALIGN_LEFT|wxALIGN_BOTTOM)
     virtual void SetAlignment( int align ) = 0;
     virtual int GetAlignment() const = 0;
-
+    
 protected:
     wxString                m_variantType;
     wxDataViewColumn       *m_owner;
index 9f2d6f009f15a9705efdff2356eedd22a41f51f5..b62bc9eee6c3158fdf05cfea200924b5a3a9db48 100644 (file)
@@ -25,6 +25,30 @@ class WXDLLIMPEXP_ADV wxDataViewCtrl;
 class WXDLLIMPEXP_ADV wxDataViewMainWindow;
 class WXDLLIMPEXP_ADV wxDataViewHeaderWindow;
 
+//-----------------------------------------------------------------------------
+// wxDataViewEditorCtrlEvtHandler
+//-----------------------------------------------------------------------------
+
+class wxDataViewEditorCtrlEvtHandler: public wxEvtHandler
+{
+public:
+    wxDataViewEditorCtrlEvtHandler( wxControl *editor, wxDataViewRenderer *owner );
+                         
+    void AcceptChangesAndFinish();
+
+protected:
+    void OnChar( wxKeyEvent &event );
+    void OnKillFocus( wxFocusEvent &event );
+
+private:
+    wxDataViewRenderer     *m_owner;
+    wxControl              *m_editorCtrl;
+    bool                    m_finished;
+
+private:
+    DECLARE_EVENT_TABLE()
+};
+
 // ---------------------------------------------------------
 // wxDataViewRenderer
 // ---------------------------------------------------------
@@ -78,10 +102,24 @@ public:
     // Create DC on request
     virtual wxDC *GetDC();
 
+    // in-place editing
+    virtual bool HasEditorCtrl()
+        { return false; }
+    virtual wxControl* CreateEditorCtrl( wxWindow *parent, wxRect labelRect, const wxVariant &value )
+        { return NULL; }
+    virtual bool GetValueFromEditorCtrl( wxControl* editor, wxVariant &value )
+        { return false; }
+        
+    virtual bool StartEditing( unsigned int row, wxRect labelRect );
+    virtual void CancelEditing();
+    virtual bool FinishEditing();
+    
 private:
-    wxDC                *m_dc;
-    int                  m_align;
-    wxDataViewCellMode   m_mode;
+    wxDC                        *m_dc;
+    int                          m_align;
+    wxDataViewCellMode           m_mode;
+    wxControl                   *m_editorCtrl;
+    unsigned int                 m_row; // for m_editorCtrl
 
 protected:
     DECLARE_DYNAMIC_CLASS_NO_COPY(wxDataViewRenderer)
@@ -102,6 +140,7 @@ protected:
     DECLARE_DYNAMIC_CLASS_NO_COPY(wxDataViewCustomRenderer)
 };
 
+
 // ---------------------------------------------------------
 // wxDataViewTextRenderer
 // ---------------------------------------------------------
@@ -119,8 +158,13 @@ public:
     bool Render( wxRect cell, wxDC *dc, int state );
     wxSize GetSize() const;
 
+    // in-place editing
+    virtual bool HasEditorCtrl();
+    virtual wxControl* CreateEditorCtrl( wxWindow *parent, wxRect labelRect, const wxVariant &value );
+    virtual bool GetValueFromEditorCtrl( wxControl* editor, wxVariant &value );
+        
 private:
-    wxString m_text;
+    wxString   m_text;
 
 protected:
     DECLARE_DYNAMIC_CLASS_NO_COPY(wxDataViewTextRenderer)
@@ -362,6 +406,8 @@ public:     // utility functions not part of the API
     // updates the header window after a change in a column setting
     void OnColumnChange();
 
+    wxDataViewMainWindow* GetMainWindow() { return m_clientArea; }
+
 private:
     wxDataViewListModelNotifier *m_notifier;
     wxDataViewMainWindow        *m_clientArea;
index e8da85b5c47c16d9a3ba1b61711fb46d1bde2c2c..579c2a9db6768a158220cedc92a7305111d636aa 100644 (file)
@@ -33,6 +33,7 @@
     #include "wx/timer.h"
     #include "wx/settings.h"
     #include "wx/msgdlg.h"
+    #include "wx/dcscreen.h"
 #endif
 
 #include "wx/stockitem.h"
@@ -243,45 +244,6 @@ public:
     void Notify();
 };
 
-//-----------------------------------------------------------------------------
-// wxDataViewTextCtrlWrapper: wraps a wxTextCtrl for inline editing
-//-----------------------------------------------------------------------------
-
-class wxDataViewTextCtrlWrapper : public wxEvtHandler
-{
-public:
-    // NB: text must be a valid object but not Create()d yet
-    wxDataViewTextCtrlWrapper( wxDataViewMainWindow *owner,
-                               wxTextCtrl *text,
-                               wxDataViewListModel *model,
-                               unsigned int col, unsigned int row,
-                               wxRect cellLabel );
-
-    wxTextCtrl *GetText() const { return m_text; }
-
-    void AcceptChangesAndFinish();
-
-protected:
-    void OnChar( wxKeyEvent &event );
-    void OnKeyUp( wxKeyEvent &event );
-    void OnKillFocus( wxFocusEvent &event );
-
-    bool AcceptChanges();
-    void Finish();
-
-private:
-    wxDataViewMainWindow   *m_owner;
-    wxTextCtrl             *m_text;
-    wxString                m_startValue;
-    wxDataViewListModel    *m_model;
-    unsigned int                  m_col;
-    unsigned int                  m_row;
-    bool                    m_finished;
-    bool                    m_aboutToFinish;
-
-    DECLARE_EVENT_TABLE()
-};
-
 //-----------------------------------------------------------------------------
 // wxDataViewMainWindow
 //-----------------------------------------------------------------------------
@@ -325,7 +287,6 @@ public:
     void OnInternalIdle();
 
     void OnRenameTimer();
-    void FinishEditing( wxTextCtrl *text );
 
     void ScrollWindow( int dx, int dy, const wxRect *rect = NULL );
 
@@ -367,11 +328,10 @@ private:
     bool                        m_dirty;
 
     wxDataViewColumn           *m_currentCol;
-    unsigned int                      m_currentRow;
+    unsigned int                m_currentRow;
     wxDataViewSelection         m_selection;
 
     wxDataViewRenameTimer      *m_renameTimer;
-    wxDataViewTextCtrlWrapper  *m_textctrlWrapper;
     bool                        m_lastOnSame;
 
     bool                        m_hasFocus;
@@ -458,6 +418,105 @@ wxDC *wxDataViewRenderer::GetDC()
     return m_dc;
 }
 
+bool wxDataViewRenderer::StartEditing( unsigned int row, wxRect labelRect )
+{
+    GetView()->CalcScrolledPosition( labelRect.x, labelRect.y,
+                                     &labelRect.x, &labelRect.y);
+
+    m_row = row; // remember for later
+                                     
+    unsigned int col = GetOwner()->GetModelColumn();
+    wxVariant value;
+    GetOwner()->GetOwner()->GetModel()->GetValue( value, col, row );
+    
+    m_editorCtrl = CreateEditorCtrl( GetOwner()->GetOwner()->GetMainWindow(), labelRect, value );
+    
+    m_editorCtrl->PushEventHandler( new wxDataViewEditorCtrlEvtHandler( m_editorCtrl, this ) );
+    
+    m_editorCtrl->SetFocus();
+    
+    return true;
+}
+
+void wxDataViewRenderer::CancelEditing()
+{
+    // m_editorCtrl->PopEventHandler( true );
+
+    delete m_editorCtrl;
+    
+    GetOwner()->GetOwner()->GetMainWindow()->SetFocus();
+}
+
+bool wxDataViewRenderer::FinishEditing()
+{
+    // m_editorCtrl->PopEventHandler( true );
+
+    wxVariant value;
+    GetValueFromEditorCtrl( m_editorCtrl, value );
+
+    delete m_editorCtrl;
+    
+    GetOwner()->GetOwner()->GetMainWindow()->SetFocus();
+    
+    if (!Validate(value))
+        return false;
+        
+    unsigned int col = GetOwner()->GetModelColumn();
+    GetOwner()->GetOwner()->GetModel()->SetValue( value, col, m_row );
+    GetOwner()->GetOwner()->GetModel()->ValueChanged( col, m_row );
+    
+    return true;
+}
+
+//-----------------------------------------------------------------------------
+// wxDataViewEditorCtrlEvtHandler
+//-----------------------------------------------------------------------------
+
+BEGIN_EVENT_TABLE(wxDataViewEditorCtrlEvtHandler, wxEvtHandler)
+    EVT_CHAR           (wxDataViewEditorCtrlEvtHandler::OnChar)
+    EVT_KILL_FOCUS     (wxDataViewEditorCtrlEvtHandler::OnKillFocus)
+END_EVENT_TABLE()
+
+wxDataViewEditorCtrlEvtHandler::wxDataViewEditorCtrlEvtHandler(
+                                wxControl *editorCtrl,
+                                wxDataViewRenderer *owner )
+{
+    m_owner = owner;
+    m_editorCtrl = editorCtrl;
+
+    m_finished = false;
+}
+
+void wxDataViewEditorCtrlEvtHandler::OnChar( wxKeyEvent &event )
+{
+    switch ( event.m_keyCode )
+    {
+        case WXK_RETURN:
+            m_finished = true;
+            m_owner->FinishEditing();
+            break;
+
+        case WXK_ESCAPE:
+            m_finished = true;
+            m_owner->CancelEditing();
+            break;
+
+        default:
+            event.Skip();
+    }
+}
+
+void wxDataViewEditorCtrlEvtHandler::OnKillFocus( wxFocusEvent &event )
+{
+    if (!m_finished)
+    {
+        m_finished = true;
+        m_owner->FinishEditing();
+    }
+
+    // We must let the native text control handle focus
+    event.Skip();
+}
 
 // ---------------------------------------------------------
 // wxDataViewCustomRenderer
@@ -495,6 +554,26 @@ bool wxDataViewTextRenderer::GetValue( wxVariant& WXUNUSED(value) ) const
     return false;
 }
 
+bool wxDataViewTextRenderer::HasEditorCtrl()
+{ 
+    return true;
+}
+
+wxControl* wxDataViewTextRenderer::CreateEditorCtrl( wxWindow *parent,
+        wxRect labelRect, const wxVariant &value )
+{
+    return new wxTextCtrl( parent, wxID_ANY, value, 
+                           wxPoint(labelRect.x,labelRect.y),
+                           wxSize(labelRect.width,labelRect.height) );
+}
+
+bool wxDataViewTextRenderer::GetValueFromEditorCtrl( wxControl *editor, wxVariant &value )
+{
+    wxTextCtrl *text = (wxTextCtrl*) editor;
+    value = text->GetValue();
+    return true;
+}
+
 bool wxDataViewTextRenderer::Render( wxRect cell, wxDC *dc, int state )
 {
     wxDataViewCtrl *view = GetOwner()->GetOwner();
@@ -1512,149 +1591,6 @@ void wxDataViewRenameTimer::Notify()
     m_owner->OnRenameTimer();
 }
 
-//-----------------------------------------------------------------------------
-// wxDataViewTextCtrlWrapper: wraps a wxTextCtrl for inline editing
-//-----------------------------------------------------------------------------
-
-BEGIN_EVENT_TABLE(wxDataViewTextCtrlWrapper, wxEvtHandler)
-    EVT_CHAR           (wxDataViewTextCtrlWrapper::OnChar)
-    EVT_KEY_UP         (wxDataViewTextCtrlWrapper::OnKeyUp)
-    EVT_KILL_FOCUS     (wxDataViewTextCtrlWrapper::OnKillFocus)
-END_EVENT_TABLE()
-
-wxDataViewTextCtrlWrapper::wxDataViewTextCtrlWrapper(
-                        wxDataViewMainWindow *owner,
-                        wxTextCtrl *text,
-                        wxDataViewListModel *model,
-                        unsigned int col, unsigned int row,
-                        wxRect rectLabel )
-{
-    m_owner = owner;
-    m_model = model;
-    m_row = row;
-    m_col = col;
-    m_text = text;
-
-    m_finished = false;
-    m_aboutToFinish = false;
-
-    wxVariant value;
-    model->GetValue( value, col, row );
-    m_startValue = value.GetString();
-
-    m_owner->GetOwner()->CalcScrolledPosition(
-        rectLabel.x, rectLabel.y, &rectLabel.x, &rectLabel.y );
-
-    m_text->Create( owner, wxID_ANY, m_startValue,
-                    wxPoint(rectLabel.x-2,rectLabel.y-2),
-                    wxSize(rectLabel.width+7,rectLabel.height+4) );
-    m_text->SetFocus();
-
-    m_text->PushEventHandler(this);
-}
-
-void wxDataViewTextCtrlWrapper::AcceptChangesAndFinish()
-{
-    m_aboutToFinish = true;
-
-    // Notify the owner about the changes
-    AcceptChanges();
-
-    // Even if vetoed, close the control (consistent with MSW)
-    Finish();
-}
-
-void wxDataViewTextCtrlWrapper::OnChar( wxKeyEvent &event )
-{
-    switch ( event.m_keyCode )
-    {
-        case WXK_RETURN:
-            AcceptChangesAndFinish();
-            break;
-
-        case WXK_ESCAPE:
-            // m_owner->OnRenameCancelled( m_itemEdited );
-            Finish();
-            break;
-
-        default:
-            event.Skip();
-    }
-}
-
-void wxDataViewTextCtrlWrapper::OnKeyUp( wxKeyEvent &event )
-{
-    if (m_finished)
-    {
-        event.Skip();
-        return;
-    }
-
-    // auto-grow the textctrl
-    wxSize parentSize = m_owner->GetSize();
-    wxPoint myPos = m_text->GetPosition();
-    wxSize mySize = m_text->GetSize();
-    int sx, sy;
-    m_text->GetTextExtent(m_text->GetValue() + _T("MM"), &sx, &sy);
-    if (myPos.x + sx > parentSize.x)
-        sx = parentSize.x - myPos.x;
-    if (mySize.x > sx)
-        sx = mySize.x;
-    m_text->SetSize(sx, wxDefaultCoord);
-
-    event.Skip();
-}
-
-void wxDataViewTextCtrlWrapper::OnKillFocus( wxFocusEvent &event )
-{
-    if ( !m_finished && !m_aboutToFinish )
-    {
-        AcceptChanges();
-        //if ( !AcceptChanges() )
-        //    m_owner->OnRenameCancelled( m_itemEdited );
-
-        Finish();
-    }
-
-    // We must let the native text control handle focus
-    event.Skip();
-}
-
-bool wxDataViewTextCtrlWrapper::AcceptChanges()
-{
-    const wxString value = m_text->GetValue();
-
-    if ( value == m_startValue )
-        // nothing changed, always accept
-        return true;
-
-//    if ( !m_owner->OnRenameAccept(m_itemEdited, value) )
-        // vetoed by the user
-//        return false;
-
-    // accepted, do rename the item
-    wxVariant variant;
-    variant = value;
-    m_model->SetValue( variant, m_col, m_row );
-    m_model->ValueChanged( m_col, m_row );
-
-    return true;
-}
-
-void wxDataViewTextCtrlWrapper::Finish()
-{
-    if ( !m_finished )
-    {
-        m_finished = true;
-
-        m_text->RemoveEventHandler(this);
-        m_owner->FinishEditing(m_text);
-
-        // delete later
-        wxPendingDelete.Append( this );
-    }
-}
-
 //-----------------------------------------------------------------------------
 // wxDataViewMainWindow
 //-----------------------------------------------------------------------------
@@ -1687,7 +1623,6 @@ wxDataViewMainWindow::wxDataViewMainWindow( wxDataViewCtrl *parent, wxWindowID i
 
     m_lastOnSame = false;
     m_renameTimer = new wxDataViewRenameTimer( this );
-    m_textctrlWrapper = NULL;
 
     // TODO: user better initial values/nothing selected
     m_currentCol = NULL;
@@ -1747,44 +1682,37 @@ void wxDataViewMainWindow::OnRenameTimer()
     wxRect labelRect( xpos, m_currentRow * m_lineHeight,
                       m_currentCol->GetWidth(), m_lineHeight );
 
-    wxClassInfo *textControlClass = CLASSINFO(wxTextCtrl);
-
-    wxTextCtrl * const text = (wxTextCtrl *)textControlClass->CreateObject();
-    m_textctrlWrapper = new wxDataViewTextCtrlWrapper(this, text, GetOwner()->GetModel(),
-        m_currentCol->GetModelColumn(), m_currentRow, labelRect );
-}
-
-void wxDataViewMainWindow::FinishEditing( wxTextCtrl *text )
-{
-    delete text;
-    m_textctrlWrapper = NULL;
-    SetFocus();
-  //  SetFocusIgnoringChildren();
+    m_currentCol->GetRenderer()->StartEditing( m_currentRow, labelRect );
 }
 
 bool wxDataViewMainWindow::RowAppended()
 {
-    return false;
+    UpdateDisplay();
+    return true;
 }
 
 bool wxDataViewMainWindow::RowPrepended()
 {
-    return false;
+    UpdateDisplay();
+    return true;
 }
 
 bool wxDataViewMainWindow::RowInserted( unsigned int WXUNUSED(before) )
 {
-    return false;
+    UpdateDisplay();
+    return true;
 }
 
 bool wxDataViewMainWindow::RowDeleted( unsigned int WXUNUSED(row) )
 {
-    return false;
+    UpdateDisplay();
+    return true;
 }
 
 bool wxDataViewMainWindow::RowChanged( unsigned int WXUNUSED(row) )
 {
-    return false;
+    UpdateDisplay();
+    return true;
 }
 
 bool wxDataViewMainWindow::ValueChanged( unsigned int WXUNUSED(col), unsigned int row )
@@ -1801,14 +1729,14 @@ bool wxDataViewMainWindow::ValueChanged( unsigned int WXUNUSED(col), unsigned in
 
 bool wxDataViewMainWindow::RowsReordered( unsigned int *WXUNUSED(new_order) )
 {
-    Refresh();
-
+    UpdateDisplay();
     return true;
 }
 
 bool wxDataViewMainWindow::Cleared()
 {
-    return false;
+    UpdateDisplay();
+    return true;
 }
 
 void wxDataViewMainWindow::UpdateDisplay()