]> git.saurik.com Git - wxWidgets.git/commitdiff
Update all controls using in-place editors to handle Escape/Return correctly.
authorVadim Zeitlin <vadim@wxwidgets.org>
Fri, 2 Dec 2011 00:50:41 +0000 (00:50 +0000)
committerVadim Zeitlin <vadim@wxwidgets.org>
Fri, 2 Dec 2011 00:50:41 +0000 (00:50 +0000)
Define EVT_CHAR_HOOK handlers to ensure that pressing Escape/Return while an
in-place edit control is active affects only it and is not used for the
keyboard navigation.

Closes #9102.

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

include/wx/generic/private/listctrl.h
include/wx/msw/listctrl.h
include/wx/treectrl.h
src/common/treebase.cpp
src/generic/datavgen.cpp
src/generic/listctrl.cpp
src/msw/listctrl.cpp

index 4ee47ff1d441e71b647479d62a6bb716deb1e424..30dc76f73647ad3c03418a2224703e789f9dee6b 100644 (file)
@@ -402,6 +402,10 @@ public:
 
     wxTextCtrl *GetText() const { return m_text; }
 
+    // Check if the given key event should stop editing and return true if it
+    // does or false otherwise.
+    bool CheckForEndEditKey(const wxKeyEvent& event);
+
     // Different reasons for calling EndEdit():
     //
     // It was called because:
@@ -557,6 +561,7 @@ public:
     // called to switch the selection from the current item to newCurrent,
     void OnArrowChar( size_t newCurrent, const wxKeyEvent& event );
 
+    void OnCharHook( wxKeyEvent &event );
     void OnChar( wxKeyEvent &event );
     void OnKeyDown( wxKeyEvent &event );
     void OnKeyUp( wxKeyEvent &event );
index 280c3f842b77b4f7012adeaa03663bb0f1f44f33..172197bf6206192f0b017cb02b046f685e3d1cb5 100644 (file)
@@ -466,6 +466,10 @@ private:
     // destroy m_textCtrl if it's currently valid and reset it to NULL
     void DeleteEditControl();
 
+    // Intercept Escape and Enter keys to avoid them being stolen from our
+    // in-place editor control.
+    void OnCharHook(wxKeyEvent& event);
+
 
     DECLARE_DYNAMIC_CLASS(wxListCtrl)
     DECLARE_EVENT_TABLE()
index b93495de26b9cb1455c25ca419cf94de398a71bf..b07eccb344f5711ea5f7fde43380031cd632f284 100644 (file)
@@ -439,6 +439,13 @@ protected:
     bool        m_quickBestSize;
 
 
+private:
+    // Intercept Escape and Return keys to ensure that our in-place edit
+    // control always gets them before they're used for dialog navigation or
+    // anything else.
+    void OnCharHook(wxKeyEvent& event);
+
+
     wxDECLARE_NO_COPY_CLASS(wxTreeCtrlBase);
 };
 
index 06e31ddbc3e3979dab634f4f170d855d1e3f29b0..4c0965c435c9e9b1ea9a7446efb919002da77b4e 100644 (file)
@@ -179,6 +179,8 @@ wxTreeCtrlBase::wxTreeCtrlBase()
 
     // quick DoGetBestSize calculation
     m_quickBestSize = true;
+
+    Connect(wxEVT_CHAR_HOOK, wxKeyEventHandler(wxTreeCtrlBase::OnCharHook));
 }
 
 wxTreeCtrlBase::~wxTreeCtrlBase()
@@ -349,4 +351,26 @@ bool wxTreeCtrlBase::IsEmpty() const
     return !GetRootItem().IsOk();
 }
 
+void wxTreeCtrlBase::OnCharHook(wxKeyEvent& event)
+{
+    if ( GetEditControl() )
+    {
+        bool discardChanges = false;
+        switch ( event.GetKeyCode() )
+        {
+            case WXK_ESCAPE:
+                discardChanges = true;
+                // fall through
+
+            case WXK_RETURN:
+                EndEditLabel(GetSelection(), discardChanges);
+
+                // Do not call Skip() below.
+                return;
+        }
+    }
+
+    event.Skip();
+}
+
 #endif // wxUSE_TREECTRL
index 63e562a411776064a2b920246fcf87c9036b78ee..8b1b0007786bac841afc221adebc44b27e81dc87 100644 (file)
@@ -48,6 +48,7 @@
 #include "wx/headerctrl.h"
 #include "wx/dnd.h"
 #include "wx/stopwatch.h"
+#include "wx/weakref.h"
 
 //-----------------------------------------------------------------------------
 // classes
@@ -599,6 +600,7 @@ public:
     wxBitmap CreateItemBitmap( unsigned int row, int &indent );
 #endif // wxUSE_DRAG_AND_DROP
     void OnPaint( wxPaintEvent &event );
+    void OnCharHook( wxKeyEvent &event );
     void OnChar( wxKeyEvent &event );
     void OnVerticalNavigation(unsigned int newCurrent, const wxKeyEvent& event);
     void OnLeftKey();
@@ -696,6 +698,10 @@ public:
 
     void OnColumnsCountChanged();
 
+    // Called by wxDataViewCtrl and our own OnRenameTimer() to start edit the
+    // specified item in the given column.
+    void StartEditing(const wxDataViewItem& item, const wxDataViewColumn* col);
+
 private:
     int RecalculateCount();
 
@@ -753,6 +759,12 @@ private:
     // This is the tree node under the cursor
     wxDataViewTreeNode * m_underMouse;
 
+    // The control used for editing or NULL.
+    wxWeakRef<wxWindow> m_editorCtrl;
+
+    // Id m_editorCtrl is non-NULL, pointer to the associated renderer.
+    wxDataViewRenderer* m_editorRenderer;
+
 private:
     DECLARE_DYNAMIC_CLASS(wxDataViewMainWindow)
     DECLARE_EVENT_TABLE()
@@ -1338,6 +1350,7 @@ BEGIN_EVENT_TABLE(wxDataViewMainWindow,wxWindow)
     EVT_MOUSE_EVENTS  (wxDataViewMainWindow::OnMouse)
     EVT_SET_FOCUS     (wxDataViewMainWindow::OnSetFocus)
     EVT_KILL_FOCUS    (wxDataViewMainWindow::OnKillFocus)
+    EVT_CHAR_HOOK     (wxDataViewMainWindow::OnCharHook)
     EVT_CHAR          (wxDataViewMainWindow::OnChar)
 END_EVENT_TABLE()
 
@@ -1349,6 +1362,8 @@ wxDataViewMainWindow::wxDataViewMainWindow( wxDataViewCtrl *parent, wxWindowID i
 {
     SetOwner( parent );
 
+    m_editorRenderer = NULL;
+
     m_lastOnSame = false;
     m_renameTimer = new wxDataViewRenameTimer( this );
 
@@ -2005,9 +2020,25 @@ void wxDataViewMainWindow::OnRenameTimer()
 
     wxDataViewItem item = GetItemByRow( m_currentRow );
 
-    wxRect labelRect = GetItemRect(item, m_currentCol);
+    StartEditing( item, m_currentCol );
+}
 
-    m_currentCol->GetRenderer()->StartEditing( item, labelRect );
+void
+wxDataViewMainWindow::StartEditing(const wxDataViewItem& item,
+                                   const wxDataViewColumn* col)
+{
+    wxDataViewRenderer* renderer = col->GetRenderer();
+    if (renderer->GetMode() != wxDATAVIEW_CELL_EDITABLE)
+        return;
+
+    const wxRect itemRect = GetItemRect(item, col);
+    if ( renderer->StartEditing(item, itemRect) )
+    {
+        // Save the renderer to be able to finish/cancel editing it later and
+        // save the control to be able to detect if we're still editing it.
+        m_editorRenderer = renderer;
+        m_editorCtrl = renderer->GetEditorCtrl();
+    }
 }
 
 //-----------------------------------------------------------------------------
@@ -3404,6 +3435,27 @@ wxDataViewMainWindow::FindColumnForEditing(const wxDataViewItem& item, wxDataVie
    return candidate;
 }
 
+void wxDataViewMainWindow::OnCharHook(wxKeyEvent& event)
+{
+    if ( m_editorCtrl )
+    {
+        // Handle any keys special for the in-place editor and return without
+        // calling Skip() below.
+        switch ( event.GetKeyCode() )
+        {
+            case WXK_ESCAPE:
+                m_editorRenderer->CancelEditing();
+                return;
+
+            case WXK_RETURN:
+                m_editorRenderer->FinishEditing();
+                return;
+        }
+    }
+
+    event.Skip();
+}
+
 void wxDataViewMainWindow::OnChar( wxKeyEvent &event )
 {
     wxWindow * const parent = GetParent();
@@ -4939,12 +4991,7 @@ void wxDataViewCtrl::StartEditor( const wxDataViewItem & item, unsigned int colu
     if (!col)
         return;
 
-    wxDataViewRenderer* renderer = col->GetRenderer();
-    if (renderer->GetMode() != wxDATAVIEW_CELL_EDITABLE)
-        return;
-
-    const wxRect itemRect = GetItemRect(item, col);
-    renderer->StartEditing(item, itemRect);
+    m_clientArea->StartEditing(item, col);
 }
 
 #endif // !wxUSE_GENERICDATAVIEWCTRL
index 5d4767f939cb1c75381d8fcd2cffaae1ffa8fa4c..03e26f11e56a9cdf3693d538470e8548252e89ef 100644 (file)
@@ -1461,6 +1461,12 @@ bool wxListTextCtrlWrapper::AcceptChanges()
 }
 
 void wxListTextCtrlWrapper::OnChar( wxKeyEvent &event )
+{
+    if ( !CheckForEndEditKey(event) )
+        event.Skip();
+}
+
+bool wxListTextCtrlWrapper::CheckForEndEditKey(const wxKeyEvent& event)
 {
     switch ( event.m_keyCode )
     {
@@ -1473,8 +1479,10 @@ void wxListTextCtrlWrapper::OnChar( wxKeyEvent &event )
             break;
 
         default:
-            event.Skip();
+            return false;
     }
+
+    return true;
 }
 
 void wxListTextCtrlWrapper::OnKeyUp( wxKeyEvent &event )
@@ -1518,6 +1526,7 @@ void wxListTextCtrlWrapper::OnKillFocus( wxFocusEvent &event )
 BEGIN_EVENT_TABLE(wxListMainWindow, wxWindow)
   EVT_PAINT          (wxListMainWindow::OnPaint)
   EVT_MOUSE_EVENTS   (wxListMainWindow::OnMouse)
+  EVT_CHAR_HOOK      (wxListMainWindow::OnCharHook)
   EVT_CHAR           (wxListMainWindow::OnChar)
   EVT_KEY_DOWN       (wxListMainWindow::OnKeyDown)
   EVT_KEY_UP         (wxListMainWindow::OnKeyUp)
@@ -2713,6 +2722,22 @@ void wxListMainWindow::OnKeyUp( wxKeyEvent &event )
     event.Skip();
 }
 
+void wxListMainWindow::OnCharHook( wxKeyEvent &event )
+{
+    if ( m_textctrlWrapper )
+    {
+        // When an in-place editor is active we should ensure that it always
+        // gets the key events that are special to it.
+        if ( m_textctrlWrapper->CheckForEndEditKey(event) )
+        {
+            // Skip the call to wxEvent::Skip() below.
+            return;
+        }
+    }
+
+    event.Skip();
+}
+
 void wxListMainWindow::OnChar( wxKeyEvent &event )
 {
     wxWindow *parent = GetParent();
index 1f06aa3074686793dd222a6d70537e70d7a30527..5bc5c08c56c9f9deb66ff0fb4f2290d16ccb398b 100644 (file)
@@ -228,6 +228,7 @@ public:
 
 BEGIN_EVENT_TABLE(wxListCtrl, wxControl)
     EVT_PAINT(wxListCtrl::OnPaint)
+    EVT_CHAR_HOOK(wxListCtrl::OnCharHook)
 END_EVENT_TABLE()
 
 // ============================================================================
@@ -2973,6 +2974,27 @@ void wxListCtrl::OnPaint(wxPaintEvent& event)
     }
 }
 
+void wxListCtrl::OnCharHook(wxKeyEvent& event)
+{
+    if ( GetEditControl() )
+    {
+        // We need to ensure that Escape is not stolen from the in-place editor
+        // by the containing dialog.
+        //
+        // Notice that we don't have to care about Enter key here as we return
+        // false from MSWShouldPreProcessMessage() for it.
+        if ( event.GetKeyCode() == WXK_ESCAPE )
+        {
+            EndEditLabel(true /* cancel */);
+
+            // Don't call Skip() below.
+            return;
+        }
+    }
+
+    event.Skip();
+}
+
 WXLRESULT
 wxListCtrl::MSWWindowProc(WXUINT nMsg, WXWPARAM wParam, WXLPARAM lParam)
 {