From: Vadim Zeitlin Date: Sat, 19 Aug 2006 22:36:10 +0000 (+0000) Subject: centralized Esc key handling for closing the dialogs in wxDialogBase: X-Git-Url: https://git.saurik.com/wxWidgets.git/commitdiff_plain/0be274189380d9de3c60836dab2fc080f21f88ee?hp=8f4931874c9a832e8d6cc4fe47dd8bbbf943a418 centralized Esc key handling for closing the dialogs in wxDialogBase: 1. added wxDialogBase::OnCharHook() and removed this event handler from all the other ports 2. also removed ad hoc code doing the same thing in wxMSW (MSWProcessMessage() override in wxDialog) and wxGTK (in gtk_window_key_press_callback()) 3. reimplemented EmulateButtonClickIfPresent() portably and also moved it to wxDialogBase from wxMSW wxDialog git-svn-id: https://svn.wxwidgets.org/svn/wx/wxWidgets/trunk@40686 c3d73ce0-8a6f-49c7-b76d-6d57e0e08775 --- diff --git a/include/wx/dialog.h b/include/wx/dialog.h index 9552597133..ae621112ef 100644 --- a/include/wx/dialog.h +++ b/include/wx/dialog.h @@ -32,7 +32,6 @@ extern WXDLLEXPORT_DATA(const wxChar) wxDialogNameStr[]; class WXDLLEXPORT wxDialogBase : public wxTopLevelWindow { public: - enum { // all flags allowed in wxDialogBase::CreateButtonSizer() @@ -72,6 +71,20 @@ public: #endif // wxUSE_BUTTON protected: + // emulate click of a button with the given id if it's present in the dialog + // + // return true if button was "clicked" or false if we don't have it + bool EmulateButtonClickIfPresent(int id); + + // this function is used by OnCharHook() to decide whether the given key + // should close the dialog + // + // for most platforms the default implementation (which just checks for + // Esc) is sufficient, but Mac port also adds Cmd-. here and other ports + // could do something different if needed + virtual bool IsEscapeKey(const wxKeyEvent& event); + + // The return code from modal dialog int m_returnCode; @@ -81,6 +94,10 @@ protected: // The identifier for cancel button (usually wxID_CANCEL) int m_escapeId; +private: + // handle Esc key presses + void OnCharHook(wxKeyEvent& event); + DECLARE_NO_COPY_CLASS(wxDialogBase) DECLARE_EVENT_TABLE() WX_DECLARE_CONTROL_CONTAINER(); diff --git a/include/wx/gtk/dialog.h b/include/wx/gtk/dialog.h index 46e0074dfd..883d33c52d 100644 --- a/include/wx/gtk/dialog.h +++ b/include/wx/gtk/dialog.h @@ -52,9 +52,6 @@ public: void OnOK( wxCommandEvent &event ); void OnPaint( wxPaintEvent& event ); void OnCloseWindow( wxCloseEvent& event ); - /* - void OnCharHook( wxKeyEvent& event ); - */ virtual bool Show( bool show = TRUE ); virtual int ShowModal(); diff --git a/include/wx/mac/carbon/dialog.h b/include/wx/mac/carbon/dialog.h index 2cd80c2b75..b9135f1498 100644 --- a/include/wx/mac/carbon/dialog.h +++ b/include/wx/mac/carbon/dialog.h @@ -79,7 +79,6 @@ public: // -------------- // event handlers - void OnCharHook(wxKeyEvent& event); void OnCloseWindow(wxCloseEvent& event); // Standard buttons diff --git a/include/wx/motif/dialog.h b/include/wx/motif/dialog.h index be53d02123..189ad15400 100644 --- a/include/wx/motif/dialog.h +++ b/include/wx/motif/dialog.h @@ -17,8 +17,6 @@ class WXDLLEXPORT wxEventLoop; // Dialog boxes class WXDLLEXPORT wxDialog : public wxDialogBase { - DECLARE_DYNAMIC_CLASS(wxDialog) - public: wxDialog(); @@ -70,7 +68,6 @@ public: // Responds to colour changes void OnSysColourChanged(wxSysColourChangedEvent& event); - void OnCharHook(wxKeyEvent& event); void OnCloseWindow(wxCloseEvent& event); private: @@ -97,7 +94,7 @@ protected: private: DECLARE_EVENT_TABLE() + DECLARE_DYNAMIC_CLASS(wxDialog) }; -#endif -// _WX_DIALOG_H_ +#endif // _WX_DIALOG_H_ diff --git a/include/wx/msw/dialog.h b/include/wx/msw/dialog.h index 2553a5b2bc..ed6efac834 100644 --- a/include/wx/msw/dialog.h +++ b/include/wx/msw/dialog.h @@ -86,7 +86,6 @@ public: virtual void Raise(); // event handlers - void OnCharHook(wxKeyEvent& event); void OnCloseWindow(wxCloseEvent& event); // Standard buttons @@ -123,9 +122,6 @@ public: wxDEPRECATED( bool IsModalShowing() const ); #endif // WXWIN_COMPATIBILITY_2_6 - // handle Escape here - virtual bool MSWProcessMessage(WXMSG* pMsg); - protected: // find the window to use as parent for this dialog if none has been // specified explicitly by the user @@ -139,11 +135,6 @@ protected: // end either modal or modeless dialog void EndDialog(int rc); - // emulate click of a button with the given id if it's present in the dialog - // - // return true if button was "clicked" or false if we don't have it - bool EmulateButtonClickIfPresent(int id); - private: wxWindow* m_oldFocus; bool m_endModalCalled; // allow for closing within InitDialog diff --git a/include/wx/os2/dialog.h b/include/wx/os2/dialog.h index d4ae70e32c..44fc45a67b 100644 --- a/include/wx/os2/dialog.h +++ b/include/wx/os2/dialog.h @@ -68,7 +68,6 @@ public: // // Event handlers // - void OnCharHook(wxKeyEvent& rEvent); void OnCloseWindow(wxCloseEvent& rEvent); // diff --git a/src/common/dlgcmn.cpp b/src/common/dlgcmn.cpp index b25ccf532c..3b4bb1e460 100644 --- a/src/common/dlgcmn.cpp +++ b/src/common/dlgcmn.cpp @@ -99,6 +99,7 @@ private: // ---------------------------------------------------------------------------- BEGIN_EVENT_TABLE(wxDialogBase, wxTopLevelWindow) + EVT_CHAR_HOOK(wxDialogBase::OnCharHook) WX_EVENT_TABLE_CONTROL_CONTAINER(wxDialogBase) END_EVENT_TABLE() @@ -417,3 +418,58 @@ wxStdDialogButtonSizer *wxDialogBase::CreateStdDialogButtonSizer( long flags ) } #endif // wxUSE_BUTTON + +// ---------------------------------------------------------------------------- +// event handling stuff +// ---------------------------------------------------------------------------- + +bool wxDialogBase::EmulateButtonClickIfPresent(int id) +{ + wxButton *btn = wxDynamicCast(FindWindow(id), wxButton); + + if ( !btn || !btn->IsEnabled() || !btn->IsShown() ) + return false; + + wxCommandEvent event(wxEVT_COMMAND_BUTTON_CLICKED, id); + event.SetEventObject(btn); + btn->GetEventHandler()->ProcessEvent(event); + + return true; +} + +bool wxDialogBase::IsEscapeKey(const wxKeyEvent& event) +{ + // for most platforms, Esc key is used to close the dialogs + return event.GetKeyCode() == WXK_ESCAPE && + event.GetModifiers() == wxMOD_NONE; +} + +void wxDialogBase::OnCharHook(wxKeyEvent& event) +{ + if ( event.GetKeyCode() == WXK_ESCAPE ) + { + int idCancel = GetEscapeId(); + switch ( idCancel ) + { + case wxID_NONE: + // don't handle Esc specially at all + break; + + case wxID_ANY: + // this value is special: it means translate Esc to wxID_CANCEL + // but if there is no such button, then fall back to wxID_OK + if ( EmulateButtonClickIfPresent(wxID_CANCEL) ) + return; + idCancel = wxID_OK; + // fall through + + default: + // translate Esc to button press for the button with given id + if ( EmulateButtonClickIfPresent(idCancel) ) + return; + } + } + + event.Skip(); +} + diff --git a/src/gtk/window.cpp b/src/gtk/window.cpp index 9d92740270..28a95cf3c4 100644 --- a/src/gtk/window.cpp +++ b/src/gtk/window.cpp @@ -1152,43 +1152,6 @@ gtk_window_key_press_callback( GtkWidget *widget, ret = win->GetParent()->GetEventHandler()->ProcessEvent( new_event ); } - // generate wxID_CANCEL if has been pressed (typically in dialogs) - if ( !ret && - (gdk_event->keyval == GDK_Escape) ) - { - // however only do it if we have a Cancel button in the dialog, - // otherwise the user code may get confused by the events from a - // nonexistent button and, worse, a wxButton might get button event - // from another button which is not really expected - wxWindow *winForCancel = win, - *btnCancel = NULL; - while ( winForCancel ) - { - btnCancel = winForCancel->FindWindow(wxID_CANCEL); - if ( btnCancel ) - { - // found a cancel button - break; - } - - if ( winForCancel->IsTopLevel() ) - { - // no need to look further - break; - } - - // maybe our parent has a cancel button? - winForCancel = winForCancel->GetParent(); - } - - if ( btnCancel ) - { - wxCommandEvent eventClick(wxEVT_COMMAND_BUTTON_CLICKED, wxID_CANCEL); - eventClick.SetEventObject(btnCancel); - ret = btnCancel->GetEventHandler()->ProcessEvent(eventClick); - } - } - if (ret) { g_signal_stop_emission_by_name (widget, "key_press_event"); diff --git a/src/mac/carbon/dialog.cpp b/src/mac/carbon/dialog.cpp index 0a478ad303..f75fdfbd7a 100644 --- a/src/mac/carbon/dialog.cpp +++ b/src/mac/carbon/dialog.cpp @@ -34,8 +34,6 @@ BEGIN_EVENT_TABLE(wxDialog, wxDialogBase) EVT_BUTTON(wxID_APPLY, wxDialog::OnApply) EVT_BUTTON(wxID_CANCEL, wxDialog::OnCancel) - EVT_CHAR_HOOK(wxDialog::OnCharHook) - EVT_SYS_COLOUR_CHANGED(wxDialog::OnSysColourChanged) EVT_CLOSE(wxDialog::OnCloseWindow) @@ -102,24 +100,14 @@ wxDialog::~wxDialog() Show(false); } -// By default, pressing escape cancels the dialog; on mac command-stop does the same thing -void wxDialog::OnCharHook(wxKeyEvent& event) +// On mac command-stop does the same thing as Esc, let the base class know +// about it +bool wxDialog::IsEscapeKey(const wxKeyEvent& event) { - if (( event.m_keyCode == WXK_ESCAPE || - ( event.m_keyCode == '.' && event.MetaDown() ) ) - && FindWindow(wxID_CANCEL) ) - { - // Behaviour changed in 2.0: we'll send a Cancel message - // to the dialog instead of Close. - wxCommandEvent cancelEvent(wxEVT_COMMAND_BUTTON_CLICKED, wxID_CANCEL); - cancelEvent.SetEventObject( this ); - GetEventHandler()->ProcessEvent(cancelEvent); - - return; - } + if ( event.GetKeyCode() == '.' && event.GetModifiers() == wxMOD_CMD ) + return true; - // We didn't process this event. - event.Skip(); + return wxDialogBase::IsEscapeKey(event); } bool wxDialog::IsModal() const diff --git a/src/motif/dialog.cpp b/src/motif/dialog.cpp index 2536d0e5e0..24c99802b9 100644 --- a/src/motif/dialog.cpp +++ b/src/motif/dialog.cpp @@ -75,7 +75,6 @@ BEGIN_EVENT_TABLE(wxDialog, wxTopLevelWindow) EVT_BUTTON(wxID_OK, wxDialog::OnOK) EVT_BUTTON(wxID_APPLY, wxDialog::OnApply) EVT_BUTTON(wxID_CANCEL, wxDialog::OnCancel) - EVT_CHAR_HOOK(wxDialog::OnCharHook) EVT_SYS_COLOUR_CHANGED(wxDialog::OnSysColourChanged) EVT_CLOSE(wxDialog::OnCloseWindow) END_EVENT_TABLE() @@ -233,23 +232,6 @@ wxDialog::~wxDialog() } } -// By default, pressing escape cancels the dialog -void wxDialog::OnCharHook(wxKeyEvent& event) -{ - if (event.m_keyCode == WXK_ESCAPE) - { - // Behaviour changed in 2.0: we'll send a Cancel message - // to the dialog instead of Close. - wxCommandEvent cancelEvent(wxEVT_COMMAND_BUTTON_CLICKED, wxID_CANCEL); - cancelEvent.SetEventObject( this ); - GetEventHandler()->ProcessEvent(cancelEvent); - - return; - } - // We didn't process this event. - event.Skip(); -} - void wxDialog::DoSetSize(int x, int y, int width, int height, int sizeFlags) { XtVaSetValues((Widget) m_mainWidget, XmNresizePolicy, XmRESIZE_ANY, NULL); diff --git a/src/msw/dialog.cpp b/src/msw/dialog.cpp index ed5230d7d1..23b9309817 100644 --- a/src/msw/dialog.cpp +++ b/src/msw/dialog.cpp @@ -389,17 +389,6 @@ void wxDialog::EndDialog(int rc) // wxWin event handlers // ---------------------------------------------------------------------------- -bool wxDialog::EmulateButtonClickIfPresent(int id) -{ - wxButton *btn = wxDynamicCast(FindWindow(id), wxButton); - - if ( !btn || !btn->IsEnabled() || !btn->IsShown() ) - return false; - - btn->MSWCommand(BN_CLICKED, 0 /* unused */); - return true; -} - // Standard buttons void wxDialog::OnOK(wxCommandEvent& WXUNUSED(event)) { @@ -499,36 +488,6 @@ wxToolBar *wxDialog::OnCreateToolBar(long style, // dialog Windows messages processing // --------------------------------------------------------------------------- -bool wxDialog::MSWProcessMessage(WXMSG* pMsg) -{ - const MSG * const msg = wx_reinterpret_cast(MSG *, pMsg); - if ( msg->message == WM_KEYDOWN && msg->wParam == VK_ESCAPE ) - { - int idCancel = GetEscapeId(); - switch ( idCancel ) - { - case wxID_NONE: - // don't handle Esc specially at all - break; - - case wxID_ANY: - // this value is special: it means translate Esc to wxID_CANCEL - // but if there is no such button, then fall back to wxID_OK - if ( EmulateButtonClickIfPresent(wxID_CANCEL) ) - return true; - idCancel = wxID_OK; - // fall through - - default: - // translate Esc to button press for the button with given id - if ( EmulateButtonClickIfPresent(idCancel) ) - return true; - } - } - - return wxDialogBase::MSWProcessMessage(pMsg); -} - WXLRESULT wxDialog::MSWWindowProc(WXUINT message, WXWPARAM wParam, WXLPARAM lParam) { WXLRESULT rc = 0; diff --git a/src/os2/dialog.cpp b/src/os2/dialog.cpp index 99e6b11d2c..b383594b26 100644 --- a/src/os2/dialog.cpp +++ b/src/os2/dialog.cpp @@ -39,7 +39,6 @@ BEGIN_EVENT_TABLE(wxDialog, wxDialogBase) EVT_BUTTON(wxID_OK, wxDialog::OnOK) EVT_BUTTON(wxID_APPLY, wxDialog::OnApply) EVT_BUTTON(wxID_CANCEL, wxDialog::OnCancel) - EVT_CHAR_HOOK(wxDialog::OnCharHook) EVT_SYS_COLOUR_CHANGED(wxDialog::OnSysColourChanged) EVT_CLOSE(wxDialog::OnCloseWindow) @@ -163,40 +162,6 @@ wxDialog::~wxDialog() Show(false); } // end of wxDialog::~wxDialog -// -// By default, pressing escape cancels the dialog -// -void wxDialog::OnCharHook( - wxKeyEvent& rEvent -) -{ - if (GetHWND()) - { - if (rEvent.m_keyCode == WXK_ESCAPE) - { - // - // Behaviour changed in 2.0: we'll send a Cancel message - // to the dialog instead of Close. - // - wxCommandEvent vCancelEvent( wxEVT_COMMAND_BUTTON_CLICKED - ,wxID_CANCEL - ); - - vCancelEvent.SetEventObject( this ); - GetEventHandler()->ProcessEvent(vCancelEvent); - - // - // Ensure that there is another message for this window so the - // ShowModal loop will exit and won't get stuck in GetMessage(). - // - ::WinPostMsg(GetHwnd(), WM_NULL, 0, 0); - return; - } - } - // We didn't process this event. - rEvent.Skip(); -} - // ---------------------------------------------------------------------------- // showing the dialogs // ----------------------------------------------------------------------------