mirror of
https://gitlab.com/kicad/code/kicad.git
synced 2025-03-30 06:56:57 +00:00
Allow context menus in footprint chooser when called from Eeschema.
Also moves several RAII utility classes (some of which were duplicated in open code) to a common header file.
This commit is contained in:
parent
9d051d096e
commit
b74c2791f4
@ -42,43 +42,6 @@
|
||||
|
||||
#include <algorithm>
|
||||
|
||||
/// Toggle a window's "enable" status to disabled, then enabled on destruction.
|
||||
class WDO_ENABLE_DISABLE
|
||||
{
|
||||
wxWindow* m_win;
|
||||
|
||||
public:
|
||||
|
||||
WDO_ENABLE_DISABLE( wxWindow* aWindow ) :
|
||||
m_win( aWindow )
|
||||
{
|
||||
if( m_win )
|
||||
m_win->Disable();
|
||||
}
|
||||
|
||||
~WDO_ENABLE_DISABLE()
|
||||
{
|
||||
if( m_win )
|
||||
{
|
||||
m_win->Enable();
|
||||
m_win->Raise(); // let's focus back on the parent window
|
||||
}
|
||||
}
|
||||
|
||||
void SuspendForTrueModal()
|
||||
{
|
||||
if( m_win )
|
||||
m_win->Enable();
|
||||
}
|
||||
|
||||
void ResumeAfterTrueModal()
|
||||
{
|
||||
if( m_win )
|
||||
m_win->Disable();
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
BEGIN_EVENT_TABLE( DIALOG_SHIM, wxDialog )
|
||||
EVT_CHAR_HOOK( DIALOG_SHIM::OnCharHook )
|
||||
END_EVENT_TABLE()
|
||||
@ -521,15 +484,7 @@ int DIALOG_SHIM::ShowModal()
|
||||
|
||||
int DIALOG_SHIM::ShowQuasiModal()
|
||||
{
|
||||
// This is an exception safe way to zero a pointer before returning.
|
||||
// Yes, even though DismissModal() clears this first normally, this is
|
||||
// here in case there's an exception before the dialog is dismissed.
|
||||
struct NULLER
|
||||
{
|
||||
void*& m_what;
|
||||
NULLER( void*& aPtr ) : m_what( aPtr ) {}
|
||||
~NULLER() { m_what = nullptr; } // indeed, set it to NULL on destruction
|
||||
} clear_this( (void*&) m_qmodal_loop );
|
||||
NULLER raii_nuller( (void*&) m_qmodal_loop );
|
||||
|
||||
// release the mouse if it's currently captured as the window having it
|
||||
// will be disabled when this dialog is shown -- but will still keep the
|
||||
@ -545,7 +500,7 @@ int DIALOG_SHIM::ShowQuasiModal()
|
||||
"window?" ) );
|
||||
|
||||
// quasi-modal: disable only my "optimal" parent
|
||||
m_qmodal_parent_disabler = new WDO_ENABLE_DISABLE( parent );
|
||||
m_qmodal_parent_disabler = new WINDOW_DISABLER( parent );
|
||||
|
||||
// Apple in its infinite wisdom will raise a disabled window before even passing
|
||||
// us the event, so we have no way to stop it. Instead, we must set an order on
|
||||
|
@ -32,6 +32,7 @@
|
||||
#include <wx/utils.h>
|
||||
#include <wx/evtloop.h>
|
||||
#include <wx/socket.h>
|
||||
#include <core/raii.h>
|
||||
|
||||
|
||||
BEGIN_EVENT_TABLE( KIWAY_PLAYER, EDA_BASE_FRAME )
|
||||
@ -103,16 +104,7 @@ bool KIWAY_PLAYER::ShowModal( wxString* aResult, wxWindow* aResultantFocusWindow
|
||||
vtable and therefore cross-module capable.
|
||||
*/
|
||||
|
||||
// This is an exception safe way to zero a pointer before returning.
|
||||
// Yes, even though DismissModal() clears this first normally, this is
|
||||
// here in case there's an exception before the dialog is dismissed.
|
||||
struct NULLER
|
||||
{
|
||||
void*& m_what;
|
||||
NULLER( void*& aPtr ) : m_what( aPtr ) {}
|
||||
~NULLER() { m_what = nullptr; } // indeed, set it to NULL on destruction
|
||||
} clear_this( (void*&) m_modal_loop );
|
||||
|
||||
NULLER raii_nuller( (void*&) m_modal_loop );
|
||||
|
||||
m_modal_resultant_parent = aResultantFocusWindow;
|
||||
|
||||
@ -122,34 +114,21 @@ bool KIWAY_PLAYER::ShowModal( wxString* aResult, wxWindow* aResultantFocusWindow
|
||||
SetFocus();
|
||||
|
||||
{
|
||||
// We have to disable all frames but the modal one.
|
||||
// wxWindowDisabler does that, but it also disables all top level windows
|
||||
// We do not want to disable top level windows which are child of the modal one,
|
||||
// if they are enabled.
|
||||
// An example is an aui toolbar which was moved
|
||||
// or a dialog or another frame or miniframe opened by the modal one.
|
||||
wxWindowList wlist = GetChildren();
|
||||
std::vector<wxWindow*> enabledTopLevelWindows;
|
||||
// Using wxWindowDisabler() has two issues: it will disable top-level windows that are
|
||||
// our *children* (such as sub-frames), and it will disable all context menus we try to
|
||||
// put up. Fortunatly we already had to cross this Rubicon for QuasiModal dialogs, so
|
||||
// we re-use that strategy.
|
||||
wxWindow* parent = GetParent();
|
||||
|
||||
for( unsigned ii = 0; ii < wlist.size(); ii++ )
|
||||
{
|
||||
if( wlist[ii]->IsTopLevel() && wlist[ii]->IsEnabled() )
|
||||
enabledTopLevelWindows.push_back( wlist[ii] );
|
||||
}
|
||||
while( parent && !parent->IsTopLevel() )
|
||||
parent = parent->GetParent();
|
||||
|
||||
// exception safe way to disable all top level windows except the modal one,
|
||||
// re-enables only those that were disabled on exit
|
||||
wxWindowDisabler toggle( this );
|
||||
|
||||
for( unsigned ii = 0; ii < enabledTopLevelWindows.size(); ii++ )
|
||||
enabledTopLevelWindows[ii]->Enable( true );
|
||||
WINDOW_DISABLER raii_parent_disabler( parent );
|
||||
|
||||
wxGUIEventLoop event_loop;
|
||||
m_modal_loop = &event_loop;
|
||||
event_loop.Run();
|
||||
|
||||
} // End of scope for some variables.
|
||||
// End nesting before setting focus below.
|
||||
}
|
||||
|
||||
if( aResult )
|
||||
*aResult = m_modal_string;
|
||||
|
@ -30,6 +30,7 @@
|
||||
#include <kiway_holder.h>
|
||||
#include <wx/dialog.h>
|
||||
#include <map>
|
||||
#include <core/raii.h>
|
||||
|
||||
class EDA_BASE_FRAME;
|
||||
|
||||
@ -37,43 +38,6 @@ class wxGridEvent;
|
||||
class wxGUIEventLoop;
|
||||
|
||||
|
||||
struct WINDOW_THAWER
|
||||
{
|
||||
WINDOW_THAWER( wxWindow* aWindow )
|
||||
{
|
||||
m_window = aWindow;
|
||||
m_freezeCount = 0;
|
||||
|
||||
while( m_window->IsFrozen() )
|
||||
{
|
||||
m_window->Thaw();
|
||||
m_freezeCount++;
|
||||
}
|
||||
}
|
||||
|
||||
~WINDOW_THAWER()
|
||||
{
|
||||
while( m_freezeCount > 0 )
|
||||
{
|
||||
m_window->Freeze();
|
||||
m_freezeCount--;
|
||||
}
|
||||
}
|
||||
|
||||
protected:
|
||||
wxWindow* m_window;
|
||||
int m_freezeCount;
|
||||
};
|
||||
|
||||
|
||||
class WDO_ENABLE_DISABLE;
|
||||
|
||||
// These macros are for DIALOG_SHIM only, NOT for KIWAY_PLAYER. KIWAY_PLAYER
|
||||
// has its own support for quasi modal and its platform specific issues are different
|
||||
// than for a wxDialog.
|
||||
#define SHOWQUASIMODAL ShowQuasiModal
|
||||
#define ENDQUASIMODAL EndQuasiModal
|
||||
|
||||
/**
|
||||
* Dialog helper object to sit in the inheritance tree between wxDialog and any class written
|
||||
* by wxFormBuilder.
|
||||
@ -243,7 +207,7 @@ protected:
|
||||
wxGUIEventLoop* 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;
|
||||
WINDOW_DISABLER* m_qmodal_parent_disabler;
|
||||
|
||||
EDA_BASE_FRAME* m_parentFrame;
|
||||
|
||||
|
122
libs/core/include/core/raii.h
Normal file
122
libs/core/include/core/raii.h
Normal file
@ -0,0 +1,122 @@
|
||||
/*
|
||||
* This program source code file is part of KiCad, a free EDA CAD application.
|
||||
*
|
||||
* Copyright The KiCad Developers, see AUTHORS.TXT for contributors.
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU General Public License
|
||||
* as published by the Free Software Foundation; either version 3
|
||||
* of the License, or (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, you may find one here:
|
||||
* http://www.gnu.org/licenses/old-licenses/gpl-3.0.html
|
||||
* or you may search the http://www.gnu.org website for the version 3 license,
|
||||
* or you may write to the Free Software Foundation, Inc.,
|
||||
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA
|
||||
*/
|
||||
|
||||
#ifndef RAII_H
|
||||
#define RAII_H
|
||||
|
||||
#include <wx/window.h>
|
||||
|
||||
|
||||
/*
|
||||
* Exception-safe (and 'return' safe) scoped handlers following the "resource allocation is
|
||||
* initialization" pattern.
|
||||
*/
|
||||
|
||||
|
||||
// Exception-safe method for nulling a pointer
|
||||
class NULLER
|
||||
{
|
||||
public:
|
||||
NULLER( void*& aPtr )
|
||||
: m_what( aPtr )
|
||||
{}
|
||||
|
||||
~NULLER()
|
||||
{
|
||||
m_what = nullptr;
|
||||
}
|
||||
|
||||
private:
|
||||
void*& m_what;
|
||||
};
|
||||
|
||||
|
||||
// Temporarily un-freeze a window, and then re-freeze on destruction
|
||||
class WINDOW_THAWER
|
||||
{
|
||||
public:
|
||||
WINDOW_THAWER( wxWindow* aWindow )
|
||||
{
|
||||
m_window = aWindow;
|
||||
m_freezeCount = 0;
|
||||
|
||||
while( m_window->IsFrozen() )
|
||||
{
|
||||
m_window->Thaw();
|
||||
m_freezeCount++;
|
||||
}
|
||||
}
|
||||
|
||||
~WINDOW_THAWER()
|
||||
{
|
||||
while( m_freezeCount > 0 )
|
||||
{
|
||||
m_window->Freeze();
|
||||
m_freezeCount--;
|
||||
}
|
||||
}
|
||||
|
||||
protected:
|
||||
wxWindow* m_window;
|
||||
int m_freezeCount;
|
||||
};
|
||||
|
||||
|
||||
/// Temporarily disable a window, and then re-enable on destruction.
|
||||
class WINDOW_DISABLER
|
||||
{
|
||||
public:
|
||||
WINDOW_DISABLER( wxWindow* aWindow ) :
|
||||
m_win( aWindow )
|
||||
{
|
||||
if( m_win )
|
||||
m_win->Disable();
|
||||
}
|
||||
|
||||
~WINDOW_DISABLER()
|
||||
{
|
||||
if( m_win )
|
||||
{
|
||||
m_win->Enable();
|
||||
m_win->Raise(); // let's focus back on the parent window
|
||||
}
|
||||
}
|
||||
|
||||
void SuspendForTrueModal()
|
||||
{
|
||||
if( m_win )
|
||||
m_win->Enable();
|
||||
}
|
||||
|
||||
void ResumeAfterTrueModal()
|
||||
{
|
||||
if( m_win )
|
||||
m_win->Disable();
|
||||
}
|
||||
|
||||
private:
|
||||
wxWindow* m_win;
|
||||
};
|
||||
|
||||
|
||||
#endif // RAII_H
|
Loading…
Reference in New Issue
Block a user