Update all controls using in-place editors to handle Escape/Return correctly.

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
This commit is contained in:
Vadim Zeitlin
2011-12-02 00:50:41 +00:00
parent 4d7bc8e761
commit 64ac3db840
7 changed files with 143 additions and 9 deletions

View File

@@ -402,6 +402,10 @@ public:
wxTextCtrl *GetText() const { return m_text; } 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(): // Different reasons for calling EndEdit():
// //
// It was called because: // It was called because:
@@ -557,6 +561,7 @@ public:
// called to switch the selection from the current item to newCurrent, // called to switch the selection from the current item to newCurrent,
void OnArrowChar( size_t newCurrent, const wxKeyEvent& event ); void OnArrowChar( size_t newCurrent, const wxKeyEvent& event );
void OnCharHook( wxKeyEvent &event );
void OnChar( wxKeyEvent &event ); void OnChar( wxKeyEvent &event );
void OnKeyDown( wxKeyEvent &event ); void OnKeyDown( wxKeyEvent &event );
void OnKeyUp( wxKeyEvent &event ); void OnKeyUp( wxKeyEvent &event );

View File

@@ -466,6 +466,10 @@ private:
// destroy m_textCtrl if it's currently valid and reset it to NULL // destroy m_textCtrl if it's currently valid and reset it to NULL
void DeleteEditControl(); 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_DYNAMIC_CLASS(wxListCtrl)
DECLARE_EVENT_TABLE() DECLARE_EVENT_TABLE()

View File

@@ -439,6 +439,13 @@ protected:
bool m_quickBestSize; 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); wxDECLARE_NO_COPY_CLASS(wxTreeCtrlBase);
}; };

View File

@@ -179,6 +179,8 @@ wxTreeCtrlBase::wxTreeCtrlBase()
// quick DoGetBestSize calculation // quick DoGetBestSize calculation
m_quickBestSize = true; m_quickBestSize = true;
Connect(wxEVT_CHAR_HOOK, wxKeyEventHandler(wxTreeCtrlBase::OnCharHook));
} }
wxTreeCtrlBase::~wxTreeCtrlBase() wxTreeCtrlBase::~wxTreeCtrlBase()
@@ -349,4 +351,26 @@ bool wxTreeCtrlBase::IsEmpty() const
return !GetRootItem().IsOk(); 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 #endif // wxUSE_TREECTRL

View File

@@ -48,6 +48,7 @@
#include "wx/headerctrl.h" #include "wx/headerctrl.h"
#include "wx/dnd.h" #include "wx/dnd.h"
#include "wx/stopwatch.h" #include "wx/stopwatch.h"
#include "wx/weakref.h"
//----------------------------------------------------------------------------- //-----------------------------------------------------------------------------
// classes // classes
@@ -599,6 +600,7 @@ public:
wxBitmap CreateItemBitmap( unsigned int row, int &indent ); wxBitmap CreateItemBitmap( unsigned int row, int &indent );
#endif // wxUSE_DRAG_AND_DROP #endif // wxUSE_DRAG_AND_DROP
void OnPaint( wxPaintEvent &event ); void OnPaint( wxPaintEvent &event );
void OnCharHook( wxKeyEvent &event );
void OnChar( wxKeyEvent &event ); void OnChar( wxKeyEvent &event );
void OnVerticalNavigation(unsigned int newCurrent, const wxKeyEvent& event); void OnVerticalNavigation(unsigned int newCurrent, const wxKeyEvent& event);
void OnLeftKey(); void OnLeftKey();
@@ -696,6 +698,10 @@ public:
void OnColumnsCountChanged(); 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: private:
int RecalculateCount(); int RecalculateCount();
@@ -753,6 +759,12 @@ private:
// This is the tree node under the cursor // This is the tree node under the cursor
wxDataViewTreeNode * m_underMouse; 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: private:
DECLARE_DYNAMIC_CLASS(wxDataViewMainWindow) DECLARE_DYNAMIC_CLASS(wxDataViewMainWindow)
DECLARE_EVENT_TABLE() DECLARE_EVENT_TABLE()
@@ -1338,6 +1350,7 @@ BEGIN_EVENT_TABLE(wxDataViewMainWindow,wxWindow)
EVT_MOUSE_EVENTS (wxDataViewMainWindow::OnMouse) EVT_MOUSE_EVENTS (wxDataViewMainWindow::OnMouse)
EVT_SET_FOCUS (wxDataViewMainWindow::OnSetFocus) EVT_SET_FOCUS (wxDataViewMainWindow::OnSetFocus)
EVT_KILL_FOCUS (wxDataViewMainWindow::OnKillFocus) EVT_KILL_FOCUS (wxDataViewMainWindow::OnKillFocus)
EVT_CHAR_HOOK (wxDataViewMainWindow::OnCharHook)
EVT_CHAR (wxDataViewMainWindow::OnChar) EVT_CHAR (wxDataViewMainWindow::OnChar)
END_EVENT_TABLE() END_EVENT_TABLE()
@@ -1349,6 +1362,8 @@ wxDataViewMainWindow::wxDataViewMainWindow( wxDataViewCtrl *parent, wxWindowID i
{ {
SetOwner( parent ); SetOwner( parent );
m_editorRenderer = NULL;
m_lastOnSame = false; m_lastOnSame = false;
m_renameTimer = new wxDataViewRenameTimer( this ); m_renameTimer = new wxDataViewRenameTimer( this );
@@ -2005,9 +2020,25 @@ void wxDataViewMainWindow::OnRenameTimer()
wxDataViewItem item = GetItemByRow( m_currentRow ); 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; 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 ) void wxDataViewMainWindow::OnChar( wxKeyEvent &event )
{ {
wxWindow * const parent = GetParent(); wxWindow * const parent = GetParent();
@@ -4939,12 +4991,7 @@ void wxDataViewCtrl::StartEditor( const wxDataViewItem & item, unsigned int colu
if (!col) if (!col)
return; return;
wxDataViewRenderer* renderer = col->GetRenderer(); m_clientArea->StartEditing(item, col);
if (renderer->GetMode() != wxDATAVIEW_CELL_EDITABLE)
return;
const wxRect itemRect = GetItemRect(item, col);
renderer->StartEditing(item, itemRect);
} }
#endif // !wxUSE_GENERICDATAVIEWCTRL #endif // !wxUSE_GENERICDATAVIEWCTRL

View File

@@ -1461,6 +1461,12 @@ bool wxListTextCtrlWrapper::AcceptChanges()
} }
void wxListTextCtrlWrapper::OnChar( wxKeyEvent &event ) void wxListTextCtrlWrapper::OnChar( wxKeyEvent &event )
{
if ( !CheckForEndEditKey(event) )
event.Skip();
}
bool wxListTextCtrlWrapper::CheckForEndEditKey(const wxKeyEvent& event)
{ {
switch ( event.m_keyCode ) switch ( event.m_keyCode )
{ {
@@ -1473,8 +1479,10 @@ void wxListTextCtrlWrapper::OnChar( wxKeyEvent &event )
break; break;
default: default:
event.Skip(); return false;
} }
return true;
} }
void wxListTextCtrlWrapper::OnKeyUp( wxKeyEvent &event ) void wxListTextCtrlWrapper::OnKeyUp( wxKeyEvent &event )
@@ -1518,6 +1526,7 @@ void wxListTextCtrlWrapper::OnKillFocus( wxFocusEvent &event )
BEGIN_EVENT_TABLE(wxListMainWindow, wxWindow) BEGIN_EVENT_TABLE(wxListMainWindow, wxWindow)
EVT_PAINT (wxListMainWindow::OnPaint) EVT_PAINT (wxListMainWindow::OnPaint)
EVT_MOUSE_EVENTS (wxListMainWindow::OnMouse) EVT_MOUSE_EVENTS (wxListMainWindow::OnMouse)
EVT_CHAR_HOOK (wxListMainWindow::OnCharHook)
EVT_CHAR (wxListMainWindow::OnChar) EVT_CHAR (wxListMainWindow::OnChar)
EVT_KEY_DOWN (wxListMainWindow::OnKeyDown) EVT_KEY_DOWN (wxListMainWindow::OnKeyDown)
EVT_KEY_UP (wxListMainWindow::OnKeyUp) EVT_KEY_UP (wxListMainWindow::OnKeyUp)
@@ -2713,6 +2722,22 @@ void wxListMainWindow::OnKeyUp( wxKeyEvent &event )
event.Skip(); 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 ) void wxListMainWindow::OnChar( wxKeyEvent &event )
{ {
wxWindow *parent = GetParent(); wxWindow *parent = GetParent();

View File

@@ -228,6 +228,7 @@ public:
BEGIN_EVENT_TABLE(wxListCtrl, wxControl) BEGIN_EVENT_TABLE(wxListCtrl, wxControl)
EVT_PAINT(wxListCtrl::OnPaint) EVT_PAINT(wxListCtrl::OnPaint)
EVT_CHAR_HOOK(wxListCtrl::OnCharHook)
END_EVENT_TABLE() 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 WXLRESULT
wxListCtrl::MSWWindowProc(WXUINT nMsg, WXWPARAM wParam, WXLPARAM lParam) wxListCtrl::MSWWindowProc(WXUINT nMsg, WXWPARAM wParam, WXLPARAM lParam)
{ {