mirror of
https://gitlab.com/kicad/code/kicad.git
synced 2025-09-15 02:33:15 +02: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>
|
#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 )
|
BEGIN_EVENT_TABLE( DIALOG_SHIM, wxDialog )
|
||||||
EVT_CHAR_HOOK( DIALOG_SHIM::OnCharHook )
|
EVT_CHAR_HOOK( DIALOG_SHIM::OnCharHook )
|
||||||
END_EVENT_TABLE()
|
END_EVENT_TABLE()
|
||||||
@ -521,15 +484,7 @@ int DIALOG_SHIM::ShowModal()
|
|||||||
|
|
||||||
int DIALOG_SHIM::ShowQuasiModal()
|
int DIALOG_SHIM::ShowQuasiModal()
|
||||||
{
|
{
|
||||||
// This is an exception safe way to zero a pointer before returning.
|
NULLER raii_nuller( (void*&) m_qmodal_loop );
|
||||||
// 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 );
|
|
||||||
|
|
||||||
// release the mouse if it's currently captured as the window having it
|
// 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
|
// will be disabled when this dialog is shown -- but will still keep the
|
||||||
@ -545,7 +500,7 @@ int DIALOG_SHIM::ShowQuasiModal()
|
|||||||
"window?" ) );
|
"window?" ) );
|
||||||
|
|
||||||
// quasi-modal: disable only my "optimal" parent
|
// 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
|
// 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
|
// 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/utils.h>
|
||||||
#include <wx/evtloop.h>
|
#include <wx/evtloop.h>
|
||||||
#include <wx/socket.h>
|
#include <wx/socket.h>
|
||||||
|
#include <core/raii.h>
|
||||||
|
|
||||||
|
|
||||||
BEGIN_EVENT_TABLE( KIWAY_PLAYER, EDA_BASE_FRAME )
|
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.
|
vtable and therefore cross-module capable.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
// This is an exception safe way to zero a pointer before returning.
|
NULLER raii_nuller( (void*&) m_modal_loop );
|
||||||
// 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 );
|
|
||||||
|
|
||||||
|
|
||||||
m_modal_resultant_parent = aResultantFocusWindow;
|
m_modal_resultant_parent = aResultantFocusWindow;
|
||||||
|
|
||||||
@ -122,34 +114,21 @@ bool KIWAY_PLAYER::ShowModal( wxString* aResult, wxWindow* aResultantFocusWindow
|
|||||||
SetFocus();
|
SetFocus();
|
||||||
|
|
||||||
{
|
{
|
||||||
// We have to disable all frames but the modal one.
|
// Using wxWindowDisabler() has two issues: it will disable top-level windows that are
|
||||||
// wxWindowDisabler does that, but it also disables all top level windows
|
// our *children* (such as sub-frames), and it will disable all context menus we try to
|
||||||
// We do not want to disable top level windows which are child of the modal one,
|
// put up. Fortunatly we already had to cross this Rubicon for QuasiModal dialogs, so
|
||||||
// if they are enabled.
|
// we re-use that strategy.
|
||||||
// An example is an aui toolbar which was moved
|
wxWindow* parent = GetParent();
|
||||||
// or a dialog or another frame or miniframe opened by the modal one.
|
|
||||||
wxWindowList wlist = GetChildren();
|
|
||||||
std::vector<wxWindow*> enabledTopLevelWindows;
|
|
||||||
|
|
||||||
for( unsigned ii = 0; ii < wlist.size(); ii++ )
|
while( parent && !parent->IsTopLevel() )
|
||||||
{
|
parent = parent->GetParent();
|
||||||
if( wlist[ii]->IsTopLevel() && wlist[ii]->IsEnabled() )
|
|
||||||
enabledTopLevelWindows.push_back( wlist[ii] );
|
|
||||||
}
|
|
||||||
|
|
||||||
// exception safe way to disable all top level windows except the modal one,
|
WINDOW_DISABLER raii_parent_disabler( parent );
|
||||||
// re-enables only those that were disabled on exit
|
|
||||||
wxWindowDisabler toggle( this );
|
|
||||||
|
|
||||||
for( unsigned ii = 0; ii < enabledTopLevelWindows.size(); ii++ )
|
|
||||||
enabledTopLevelWindows[ii]->Enable( true );
|
|
||||||
|
|
||||||
wxGUIEventLoop event_loop;
|
wxGUIEventLoop event_loop;
|
||||||
m_modal_loop = &event_loop;
|
m_modal_loop = &event_loop;
|
||||||
event_loop.Run();
|
event_loop.Run();
|
||||||
|
}
|
||||||
} // End of scope for some variables.
|
|
||||||
// End nesting before setting focus below.
|
|
||||||
|
|
||||||
if( aResult )
|
if( aResult )
|
||||||
*aResult = m_modal_string;
|
*aResult = m_modal_string;
|
||||||
|
@ -30,6 +30,7 @@
|
|||||||
#include <kiway_holder.h>
|
#include <kiway_holder.h>
|
||||||
#include <wx/dialog.h>
|
#include <wx/dialog.h>
|
||||||
#include <map>
|
#include <map>
|
||||||
|
#include <core/raii.h>
|
||||||
|
|
||||||
class EDA_BASE_FRAME;
|
class EDA_BASE_FRAME;
|
||||||
|
|
||||||
@ -37,43 +38,6 @@ class wxGridEvent;
|
|||||||
class wxGUIEventLoop;
|
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
|
* Dialog helper object to sit in the inheritance tree between wxDialog and any class written
|
||||||
* by wxFormBuilder.
|
* by wxFormBuilder.
|
||||||
@ -243,7 +207,7 @@ protected:
|
|||||||
wxGUIEventLoop* m_qmodal_loop; // points to nested event_loop, NULL means not qmodal
|
wxGUIEventLoop* m_qmodal_loop; // points to nested event_loop, NULL means not qmodal
|
||||||
// and dismissed
|
// and dismissed
|
||||||
bool m_qmodal_showing;
|
bool m_qmodal_showing;
|
||||||
WDO_ENABLE_DISABLE* m_qmodal_parent_disabler;
|
WINDOW_DISABLER* m_qmodal_parent_disabler;
|
||||||
|
|
||||||
EDA_BASE_FRAME* m_parentFrame;
|
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…
x
Reference in New Issue
Block a user