Fix dialog OK button event issues on OSX.
Move the OSX dialog fix ups later so they come after some wxWindow deferred processing. Also provides a facility for doing a selectAll in each text field so that tabbing between text fields behaves correctly. Fixes: lp:1599157 * https://bugs.launchpad.net/kicad/+bug/1599157
This commit is contained in:
parent
8bb03067c1
commit
88f23f17c1
|
@ -58,6 +58,7 @@ DIALOG_SHIM::DIALOG_SHIM( wxWindow* aParent, wxWindowID id, const wxString& titl
|
|||
const wxPoint& pos, const wxSize& size, long style, const wxString& name ) :
|
||||
wxDialog( aParent, id, title, pos, size, style, name ),
|
||||
KIWAY_HOLDER( 0 ),
|
||||
m_fixupsRun( false ),
|
||||
m_qmodal_loop( 0 ),
|
||||
m_qmodal_showing( false ),
|
||||
m_qmodal_parent_disabler( 0 )
|
||||
|
@ -85,9 +86,7 @@ DIALOG_SHIM::DIALOG_SHIM( wxWindow* aParent, wxWindowID id, const wxString& titl
|
|||
Pgm().App().SetTopWindow( parent_kiwayplayer );
|
||||
#endif
|
||||
|
||||
#if DLGSHIM_USE_SETFOCUS
|
||||
Connect( wxEVT_INIT_DIALOG, wxInitDialogEventHandler( DIALOG_SHIM::onInit ) );
|
||||
#endif
|
||||
Connect( wxEVT_PAINT, wxPaintEventHandler( DIALOG_SHIM::OnPaint ) );
|
||||
}
|
||||
|
||||
|
||||
|
@ -114,20 +113,6 @@ void DIALOG_SHIM::FinishDialogSettings()
|
|||
Center();
|
||||
}
|
||||
|
||||
void DIALOG_SHIM::FixOSXCancelButtonIssue()
|
||||
{
|
||||
#ifdef __WXMAC__
|
||||
// A ugly hack to fix an issue on OSX: ctrl+c closes the dialog instead of
|
||||
// copying a text if a button with wxID_CANCEL is used in a wxStdDialogButtonSizer
|
||||
// created by wxFormBuilder: the label is &Cancel, and this accelerator key has priority
|
||||
// to copy text standard accelerator, and the dlg is closed when trying to copy text
|
||||
wxButton* button = dynamic_cast< wxButton* > ( wxWindow::FindWindowById( wxID_CANCEL, this ) );
|
||||
|
||||
if( button )
|
||||
button->SetLabel( _( "Cancel" ) );
|
||||
#endif
|
||||
}
|
||||
|
||||
|
||||
// our hashtable is an implementation secret, don't need or want it in a header file
|
||||
#include <hashtables.h>
|
||||
|
@ -175,8 +160,6 @@ bool DIALOG_SHIM::Show( bool show )
|
|||
ret = wxDialog::Show( show );
|
||||
}
|
||||
|
||||
FixOSXCancelButtonIssue();
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
@ -194,58 +177,93 @@ bool DIALOG_SHIM::Enable( bool enable )
|
|||
}
|
||||
|
||||
|
||||
#if DLGSHIM_USE_SETFOCUS
|
||||
// Traverse all items in the dialog. If selectTextInTextCtrls, do a SelectAll()
|
||||
// in each so that tab followed by typing will replace the existing value.
|
||||
// Also collects the firstTextCtrl and the item with focus (if any).
|
||||
static void recursiveDescent( wxWindowList& children, const bool selectTextInTextCtrls,
|
||||
wxWindow* & firstTextCtrl, wxWindow* & windowWithFocus )
|
||||
{
|
||||
for( wxWindowList::iterator it = children.begin(); it != children.end(); ++it )
|
||||
{
|
||||
wxWindow* child = *it;
|
||||
|
||||
static bool findWindowRecursively( const wxWindowList& children, const wxWindow* wanted )
|
||||
{
|
||||
for( wxWindowList::const_iterator it = children.begin(); it != children.end(); ++it )
|
||||
{
|
||||
const wxWindow* child = *it;
|
||||
if( child->HasFocus() )
|
||||
windowWithFocus = child;
|
||||
|
||||
if( wanted == child )
|
||||
return true;
|
||||
else
|
||||
wxTextCtrl* childTextCtrl = dynamic_cast<wxTextCtrl*>( child );
|
||||
if( childTextCtrl )
|
||||
{
|
||||
if( findWindowRecursively( child->GetChildren(), wanted ) )
|
||||
return true;
|
||||
if( !firstTextCtrl && childTextCtrl->IsEnabled() && childTextCtrl->IsEditable() )
|
||||
firstTextCtrl = childTextCtrl;
|
||||
|
||||
if( selectTextInTextCtrls )
|
||||
{
|
||||
wxTextEntry* asTextEntry = dynamic_cast<wxTextEntry*>( childTextCtrl );
|
||||
// Respect an existing selection
|
||||
if( asTextEntry->GetStringSelection().IsEmpty() )
|
||||
asTextEntry->SelectAll();
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
recursiveDescent( child->GetChildren(), selectTextInTextCtrls, firstTextCtrl,
|
||||
windowWithFocus );
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
static bool findWindowRecursively( const wxWindow* topmost, const wxWindow* wanted )
|
||||
#ifdef __WXMAC__
|
||||
static void fixOSXCancelButtonIssue( wxWindow *aWindow )
|
||||
{
|
||||
// wanted may be NULL and that is ok.
|
||||
// A ugly hack to fix an issue on OSX: cmd+c closes the dialog instead of
|
||||
// copying the text if a button with wxID_CANCEL is used in a
|
||||
// wxStdDialogButtonSizer created by wxFormBuilder: the label is &Cancel, and
|
||||
// this accelerator key has priority over the standard copy accelerator.
|
||||
wxButton* button = dynamic_cast<wxButton*>( wxWindow::FindWindowById( wxID_CANCEL, aWindow ) );
|
||||
|
||||
if( wanted == topmost )
|
||||
return true;
|
||||
|
||||
return findWindowRecursively( topmost->GetChildren(), wanted );
|
||||
}
|
||||
|
||||
|
||||
/// Set the focus if it is not already set in a derived constructor to a specific control.
|
||||
void DIALOG_SHIM::onInit( wxInitDialogEvent& aEvent )
|
||||
{
|
||||
wxWindow* focusWnd = wxWindow::FindFocus();
|
||||
|
||||
// If focusWnd is not already this window or a child of it, then SetFocus().
|
||||
// Otherwise the derived class's constructor SetFocus() already to a specific
|
||||
// child control.
|
||||
|
||||
if( !findWindowRecursively( this, focusWnd ) )
|
||||
{
|
||||
// Linux wxGTK needs this to allow the ESCAPE key to close a wxDialog window.
|
||||
SetFocus();
|
||||
}
|
||||
|
||||
aEvent.Skip(); // derived class's handler should be called too
|
||||
if( button )
|
||||
button->SetLabel( _( "Cancel" ) );
|
||||
}
|
||||
#endif
|
||||
|
||||
|
||||
void DIALOG_SHIM::OnPaint( wxPaintEvent &event )
|
||||
{
|
||||
if( !m_fixupsRun )
|
||||
{
|
||||
#if DLGSHIM_SELECT_ALL_IN_TEXT_CONTROLS
|
||||
const bool selectAllInTextCtrls = true;
|
||||
#else
|
||||
const bool selectAllInTextCtrls = false;
|
||||
#endif
|
||||
wxWindow* firstTextCtrl = NULL;
|
||||
wxWindow* windowWithFocus = NULL;
|
||||
|
||||
recursiveDescent( GetChildren(), selectAllInTextCtrls, firstTextCtrl,
|
||||
windowWithFocus );
|
||||
|
||||
#if DLGSHIM_USE_SETFOCUS
|
||||
// While it would be nice to honour any focus already set (which was
|
||||
// recorded in windowWithFocus), the reality is that it's currently wrong
|
||||
// far more often than it's right.
|
||||
// So just focus on the first text control if we have one; otherwise the
|
||||
// focus on the dialog itself, which will at least allow esc, return, etc.
|
||||
// to function.
|
||||
if( firstTextCtrl )
|
||||
firstTextCtrl->SetFocus();
|
||||
else
|
||||
SetFocus();
|
||||
#endif
|
||||
|
||||
#ifdef __WXMAC__
|
||||
fixOSXCancelButtonIssue( this );
|
||||
#endif
|
||||
|
||||
m_fixupsRun = true;
|
||||
}
|
||||
|
||||
event.Skip();
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
Quasi-Modal Mode Explained:
|
||||
|
||||
|
|
|
@ -38,6 +38,16 @@
|
|||
#define DLGSHIM_USE_SETFOCUS 0
|
||||
#endif
|
||||
|
||||
#ifdef __WXMAC__
|
||||
/**
|
||||
* MACOS requires this option so that tabbing between text controls will
|
||||
* arrive with the text selected.
|
||||
**/
|
||||
#define DLGSHIM_SELECT_ALL_IN_TEXT_CONTROLS 1
|
||||
#else
|
||||
#define DLGSHIM_SELECT_ALL_IN_TEXT_CONTROLS 0
|
||||
#endif
|
||||
|
||||
class WDO_ENABLE_DISABLE;
|
||||
class EVENT_LOOP;
|
||||
|
||||
|
@ -96,6 +106,8 @@ public:
|
|||
|
||||
bool Enable( bool enable ) override;
|
||||
|
||||
void OnPaint( wxPaintEvent &event );
|
||||
|
||||
protected:
|
||||
|
||||
/**
|
||||
|
@ -115,15 +127,7 @@ protected:
|
|||
*/
|
||||
void FinishDialogSettings();
|
||||
|
||||
/** A ugly hack to fix an issue on OSX:
|
||||
* when typing ctrl+c in a wxTextCtrl inside a dialog, it is closed instead of
|
||||
* copying a text if a button with wxID_CANCEL is used in a wxStdDialogButtonSizer,
|
||||
* when the dlg is created by wxFormBuilder:
|
||||
* the label is &Cancel, and this accelerator key has priority
|
||||
* to copy text standard accelerator, and the dlg is closed when trying to copy text
|
||||
* this function do nothing on other platforms
|
||||
*/
|
||||
void FixOSXCancelButtonIssue();
|
||||
bool m_fixupsRun;
|
||||
|
||||
std::string m_hash_key; // alternate for class_map when classname re-used.
|
||||
|
||||
|
@ -131,11 +135,6 @@ protected:
|
|||
EVENT_LOOP* m_qmodal_loop; // points to nested event_loop, NULL means not qmodal and dismissed
|
||||
bool m_qmodal_showing;
|
||||
WDO_ENABLE_DISABLE* m_qmodal_parent_disabler;
|
||||
|
||||
#if DLGSHIM_USE_SETFOCUS
|
||||
private:
|
||||
void onInit( wxInitDialogEvent& aEvent );
|
||||
#endif
|
||||
};
|
||||
|
||||
#endif // DIALOG_SHIM_
|
||||
|
|
Loading…
Reference in New Issue