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
This commit is contained in:
Vadim Zeitlin
2006-08-19 22:36:10 +00:00
parent 8f4931874c
commit 0be2741893
12 changed files with 82 additions and 169 deletions

View File

@@ -32,7 +32,6 @@ extern WXDLLEXPORT_DATA(const wxChar) wxDialogNameStr[];
class WXDLLEXPORT wxDialogBase : public wxTopLevelWindow class WXDLLEXPORT wxDialogBase : public wxTopLevelWindow
{ {
public: public:
enum enum
{ {
// all flags allowed in wxDialogBase::CreateButtonSizer() // all flags allowed in wxDialogBase::CreateButtonSizer()
@@ -72,6 +71,20 @@ public:
#endif // wxUSE_BUTTON #endif // wxUSE_BUTTON
protected: 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 // The return code from modal dialog
int m_returnCode; int m_returnCode;
@@ -81,6 +94,10 @@ protected:
// The identifier for cancel button (usually wxID_CANCEL) // The identifier for cancel button (usually wxID_CANCEL)
int m_escapeId; int m_escapeId;
private:
// handle Esc key presses
void OnCharHook(wxKeyEvent& event);
DECLARE_NO_COPY_CLASS(wxDialogBase) DECLARE_NO_COPY_CLASS(wxDialogBase)
DECLARE_EVENT_TABLE() DECLARE_EVENT_TABLE()
WX_DECLARE_CONTROL_CONTAINER(); WX_DECLARE_CONTROL_CONTAINER();

View File

@@ -52,9 +52,6 @@ public:
void OnOK( wxCommandEvent &event ); void OnOK( wxCommandEvent &event );
void OnPaint( wxPaintEvent& event ); void OnPaint( wxPaintEvent& event );
void OnCloseWindow( wxCloseEvent& event ); void OnCloseWindow( wxCloseEvent& event );
/*
void OnCharHook( wxKeyEvent& event );
*/
virtual bool Show( bool show = TRUE ); virtual bool Show( bool show = TRUE );
virtual int ShowModal(); virtual int ShowModal();

View File

@@ -79,7 +79,6 @@ public:
// -------------- // --------------
// event handlers // event handlers
void OnCharHook(wxKeyEvent& event);
void OnCloseWindow(wxCloseEvent& event); void OnCloseWindow(wxCloseEvent& event);
// Standard buttons // Standard buttons

View File

@@ -17,8 +17,6 @@ class WXDLLEXPORT wxEventLoop;
// Dialog boxes // Dialog boxes
class WXDLLEXPORT wxDialog : public wxDialogBase class WXDLLEXPORT wxDialog : public wxDialogBase
{ {
DECLARE_DYNAMIC_CLASS(wxDialog)
public: public:
wxDialog(); wxDialog();
@@ -70,7 +68,6 @@ public:
// Responds to colour changes // Responds to colour changes
void OnSysColourChanged(wxSysColourChangedEvent& event); void OnSysColourChanged(wxSysColourChangedEvent& event);
void OnCharHook(wxKeyEvent& event);
void OnCloseWindow(wxCloseEvent& event); void OnCloseWindow(wxCloseEvent& event);
private: private:
@@ -97,7 +94,7 @@ protected:
private: private:
DECLARE_EVENT_TABLE() DECLARE_EVENT_TABLE()
DECLARE_DYNAMIC_CLASS(wxDialog)
}; };
#endif #endif // _WX_DIALOG_H_
// _WX_DIALOG_H_

View File

@@ -86,7 +86,6 @@ public:
virtual void Raise(); virtual void Raise();
// event handlers // event handlers
void OnCharHook(wxKeyEvent& event);
void OnCloseWindow(wxCloseEvent& event); void OnCloseWindow(wxCloseEvent& event);
// Standard buttons // Standard buttons
@@ -123,9 +122,6 @@ public:
wxDEPRECATED( bool IsModalShowing() const ); wxDEPRECATED( bool IsModalShowing() const );
#endif // WXWIN_COMPATIBILITY_2_6 #endif // WXWIN_COMPATIBILITY_2_6
// handle Escape here
virtual bool MSWProcessMessage(WXMSG* pMsg);
protected: protected:
// find the window to use as parent for this dialog if none has been // find the window to use as parent for this dialog if none has been
// specified explicitly by the user // specified explicitly by the user
@@ -139,11 +135,6 @@ protected:
// end either modal or modeless dialog // end either modal or modeless dialog
void EndDialog(int rc); 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: private:
wxWindow* m_oldFocus; wxWindow* m_oldFocus;
bool m_endModalCalled; // allow for closing within InitDialog bool m_endModalCalled; // allow for closing within InitDialog

View File

@@ -68,7 +68,6 @@ public:
// //
// Event handlers // Event handlers
// //
void OnCharHook(wxKeyEvent& rEvent);
void OnCloseWindow(wxCloseEvent& rEvent); void OnCloseWindow(wxCloseEvent& rEvent);
// //

View File

@@ -99,6 +99,7 @@ private:
// ---------------------------------------------------------------------------- // ----------------------------------------------------------------------------
BEGIN_EVENT_TABLE(wxDialogBase, wxTopLevelWindow) BEGIN_EVENT_TABLE(wxDialogBase, wxTopLevelWindow)
EVT_CHAR_HOOK(wxDialogBase::OnCharHook)
WX_EVENT_TABLE_CONTROL_CONTAINER(wxDialogBase) WX_EVENT_TABLE_CONTROL_CONTAINER(wxDialogBase)
END_EVENT_TABLE() END_EVENT_TABLE()
@@ -417,3 +418,58 @@ wxStdDialogButtonSizer *wxDialogBase::CreateStdDialogButtonSizer( long flags )
} }
#endif // wxUSE_BUTTON #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();
}

View File

@@ -1152,43 +1152,6 @@ gtk_window_key_press_callback( GtkWidget *widget,
ret = win->GetParent()->GetEventHandler()->ProcessEvent( new_event ); ret = win->GetParent()->GetEventHandler()->ProcessEvent( new_event );
} }
// generate wxID_CANCEL if <esc> 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) if (ret)
{ {
g_signal_stop_emission_by_name (widget, "key_press_event"); g_signal_stop_emission_by_name (widget, "key_press_event");

View File

@@ -34,8 +34,6 @@ BEGIN_EVENT_TABLE(wxDialog, wxDialogBase)
EVT_BUTTON(wxID_APPLY, wxDialog::OnApply) EVT_BUTTON(wxID_APPLY, wxDialog::OnApply)
EVT_BUTTON(wxID_CANCEL, wxDialog::OnCancel) EVT_BUTTON(wxID_CANCEL, wxDialog::OnCancel)
EVT_CHAR_HOOK(wxDialog::OnCharHook)
EVT_SYS_COLOUR_CHANGED(wxDialog::OnSysColourChanged) EVT_SYS_COLOUR_CHANGED(wxDialog::OnSysColourChanged)
EVT_CLOSE(wxDialog::OnCloseWindow) EVT_CLOSE(wxDialog::OnCloseWindow)
@@ -102,24 +100,14 @@ wxDialog::~wxDialog()
Show(false); Show(false);
} }
// By default, pressing escape cancels the dialog; on mac command-stop does the same thing // On mac command-stop does the same thing as Esc, let the base class know
void wxDialog::OnCharHook(wxKeyEvent& event) // about it
bool wxDialog::IsEscapeKey(const wxKeyEvent& event)
{ {
if (( event.m_keyCode == WXK_ESCAPE || if ( event.GetKeyCode() == '.' && event.GetModifiers() == wxMOD_CMD )
( event.m_keyCode == '.' && event.MetaDown() ) ) return true;
&& 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; return wxDialogBase::IsEscapeKey(event);
}
// We didn't process this event.
event.Skip();
} }
bool wxDialog::IsModal() const bool wxDialog::IsModal() const

View File

@@ -75,7 +75,6 @@ BEGIN_EVENT_TABLE(wxDialog, wxTopLevelWindow)
EVT_BUTTON(wxID_OK, wxDialog::OnOK) EVT_BUTTON(wxID_OK, wxDialog::OnOK)
EVT_BUTTON(wxID_APPLY, wxDialog::OnApply) EVT_BUTTON(wxID_APPLY, wxDialog::OnApply)
EVT_BUTTON(wxID_CANCEL, wxDialog::OnCancel) EVT_BUTTON(wxID_CANCEL, wxDialog::OnCancel)
EVT_CHAR_HOOK(wxDialog::OnCharHook)
EVT_SYS_COLOUR_CHANGED(wxDialog::OnSysColourChanged) EVT_SYS_COLOUR_CHANGED(wxDialog::OnSysColourChanged)
EVT_CLOSE(wxDialog::OnCloseWindow) EVT_CLOSE(wxDialog::OnCloseWindow)
END_EVENT_TABLE() 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) void wxDialog::DoSetSize(int x, int y, int width, int height, int sizeFlags)
{ {
XtVaSetValues((Widget) m_mainWidget, XmNresizePolicy, XmRESIZE_ANY, NULL); XtVaSetValues((Widget) m_mainWidget, XmNresizePolicy, XmRESIZE_ANY, NULL);

View File

@@ -389,17 +389,6 @@ void wxDialog::EndDialog(int rc)
// wxWin event handlers // 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 // Standard buttons
void wxDialog::OnOK(wxCommandEvent& WXUNUSED(event)) void wxDialog::OnOK(wxCommandEvent& WXUNUSED(event))
{ {
@@ -499,36 +488,6 @@ wxToolBar *wxDialog::OnCreateToolBar(long style,
// dialog Windows messages processing // 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 wxDialog::MSWWindowProc(WXUINT message, WXWPARAM wParam, WXLPARAM lParam)
{ {
WXLRESULT rc = 0; WXLRESULT rc = 0;

View File

@@ -39,7 +39,6 @@ BEGIN_EVENT_TABLE(wxDialog, wxDialogBase)
EVT_BUTTON(wxID_OK, wxDialog::OnOK) EVT_BUTTON(wxID_OK, wxDialog::OnOK)
EVT_BUTTON(wxID_APPLY, wxDialog::OnApply) EVT_BUTTON(wxID_APPLY, wxDialog::OnApply)
EVT_BUTTON(wxID_CANCEL, wxDialog::OnCancel) EVT_BUTTON(wxID_CANCEL, wxDialog::OnCancel)
EVT_CHAR_HOOK(wxDialog::OnCharHook)
EVT_SYS_COLOUR_CHANGED(wxDialog::OnSysColourChanged) EVT_SYS_COLOUR_CHANGED(wxDialog::OnSysColourChanged)
EVT_CLOSE(wxDialog::OnCloseWindow) EVT_CLOSE(wxDialog::OnCloseWindow)
@@ -163,40 +162,6 @@ wxDialog::~wxDialog()
Show(false); Show(false);
} // end of wxDialog::~wxDialog } // 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 // showing the dialogs
// ---------------------------------------------------------------------------- // ----------------------------------------------------------------------------