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:
@@ -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 );
|
||||
|
@@ -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()
|
||||
|
@@ -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);
|
||||
};
|
||||
|
||||
|
@@ -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
|
||||
|
@@ -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
|
||||
|
@@ -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();
|
||||
|
@@ -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)
|
||||
{
|
||||
|
Reference in New Issue
Block a user