Define class PopupMenuTable to make it easy to attach and detach handlers...
... to the parent TrackPanel window
This commit is contained in:
parent
14d45eda33
commit
cba51e1bf8
|
@ -1238,6 +1238,7 @@
|
|||
5ED1D0B11CDE560C00471E3C /* BackedPanel.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 5ED1D0AF1CDE560C00471E3C /* BackedPanel.cpp */; };
|
||||
5EF17C231D1F0A690090A642 /* ScrubbingToolBar.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 5EF17C211D1F0A690090A642 /* ScrubbingToolBar.cpp */; };
|
||||
5EF958851DEB121800191280 /* InconsistencyException.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 5EF958831DEB121800191280 /* InconsistencyException.cpp */; };
|
||||
5E73963B1DAFD82D00BA0A4D /* PopupMenuTable.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 5E7396391DAFD82D00BA0A4D /* PopupMenuTable.cpp */; };
|
||||
8406A93812D0F2510011EA01 /* EQDefaultCurves.xml in Resources */ = {isa = PBXBuildFile; fileRef = 8406A93712D0F2510011EA01 /* EQDefaultCurves.xml */; };
|
||||
8484F31413086237002DF7F0 /* DeviceManager.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 8484F31213086237002DF7F0 /* DeviceManager.cpp */; };
|
||||
AA0084191EA8C6E70070CCE3 /* TracksBehaviorsPrefs.cpp in Sources */ = {isa = PBXBuildFile; fileRef = AA0084181EA8C6E70070CCE3 /* TracksBehaviorsPrefs.cpp */; };
|
||||
|
@ -3072,6 +3073,8 @@
|
|||
5EF17C221D1F0A690090A642 /* ScrubbingToolBar.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = ScrubbingToolBar.h; sourceTree = "<group>"; };
|
||||
5EF958831DEB121800191280 /* InconsistencyException.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = InconsistencyException.cpp; sourceTree = "<group>"; };
|
||||
5EF958841DEB121800191280 /* InconsistencyException.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = InconsistencyException.h; sourceTree = "<group>"; };
|
||||
5E7396391DAFD82D00BA0A4D /* PopupMenuTable.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = PopupMenuTable.cpp; sourceTree = "<group>"; };
|
||||
5E73963A1DAFD82D00BA0A4D /* PopupMenuTable.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = PopupMenuTable.h; sourceTree = "<group>"; };
|
||||
82FF184D13CF01A600C1B664 /* dBTable.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = dBTable.cpp; path = sbsms/src/dBTable.cpp; sourceTree = "<group>"; };
|
||||
82FF184E13CF01A600C1B664 /* dBTable.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = dBTable.h; path = sbsms/src/dBTable.h; sourceTree = "<group>"; };
|
||||
82FF184F13CF01A600C1B664 /* slide.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = slide.cpp; path = sbsms/src/slide.cpp; sourceTree = "<group>"; };
|
||||
|
@ -4442,6 +4445,8 @@
|
|||
5ED1D0A91CDE55BD00471E3C /* Overlay.cpp */,
|
||||
5ED1D0AA1CDE55BD00471E3C /* Overlay.h */,
|
||||
5ED1D0AB1CDE55BD00471E3C /* OverlayPanel.cpp */,
|
||||
5E7396391DAFD82D00BA0A4D /* PopupMenuTable.cpp */,
|
||||
5E73963A1DAFD82D00BA0A4D /* PopupMenuTable.h */,
|
||||
5ED1D0AC1CDE55BD00471E3C /* OverlayPanel.h */,
|
||||
28530C4A0DF2105200555C94 /* ProgressDialog.cpp */,
|
||||
28530C4B0DF2105200555C94 /* ProgressDialog.h */,
|
||||
|
@ -7606,6 +7611,7 @@
|
|||
1790B18709883BFD008A330A /* QualityPrefs.cpp in Sources */,
|
||||
1790B18809883BFD008A330A /* SpectrumPrefs.cpp in Sources */,
|
||||
1790B18909883BFD008A330A /* Prefs.cpp in Sources */,
|
||||
5E73963B1DAFD82D00BA0A4D /* PopupMenuTable.cpp in Sources */,
|
||||
1790B18A09883BFD008A330A /* Printing.cpp in Sources */,
|
||||
1790B18B09883BFD008A330A /* Project.cpp in Sources */,
|
||||
1790B18C09883BFD008A330A /* Resample.cpp in Sources */,
|
||||
|
|
|
@ -622,6 +622,8 @@ audacity_SOURCES = \
|
|||
widgets/Overlay.h \
|
||||
widgets/OverlayPanel.cpp \
|
||||
widgets/OverlayPanel.h \
|
||||
widgets/PopupMenuTable.cpp \
|
||||
widgets/PopupMenuTable.h \
|
||||
widgets/ProgressDialog.cpp \
|
||||
widgets/ProgressDialog.h \
|
||||
widgets/Ruler.cpp \
|
||||
|
|
|
@ -0,0 +1,94 @@
|
|||
/**********************************************************************
|
||||
|
||||
Audacity: A Digital Audio Editor
|
||||
|
||||
PopupMenuTable.cpp
|
||||
|
||||
Paul Licameli split from TrackPanel.cpp
|
||||
|
||||
**********************************************************************/
|
||||
|
||||
#include "../Audacity.h"
|
||||
#include "PopupMenuTable.h"
|
||||
|
||||
PopupMenuTable::Menu::~Menu()
|
||||
{
|
||||
Disconnect();
|
||||
}
|
||||
|
||||
void PopupMenuTable::Menu::Extend(PopupMenuTable *pTable)
|
||||
{
|
||||
auto connect = [&]( const PopupMenuTable::Entry *pEntry ) {
|
||||
this->pParent->Connect
|
||||
(pEntry->id, wxEVT_COMMAND_MENU_SELECTED,
|
||||
pEntry->func, NULL, pTable);
|
||||
};
|
||||
|
||||
for (const PopupMenuTable::Entry *pEntry = &*pTable->Get().begin();
|
||||
pEntry->IsValid(); ++pEntry) {
|
||||
switch (pEntry->type) {
|
||||
case PopupMenuTable::Entry::Item:
|
||||
{
|
||||
this->Append(pEntry->id, pEntry->caption);
|
||||
connect( pEntry );
|
||||
break;
|
||||
}
|
||||
case PopupMenuTable::Entry::RadioItem:
|
||||
{
|
||||
this->AppendRadioItem(pEntry->id, pEntry->caption);
|
||||
connect( pEntry );
|
||||
break;
|
||||
}
|
||||
case PopupMenuTable::Entry::CheckItem:
|
||||
{
|
||||
this->AppendCheckItem(pEntry->id, pEntry->caption);
|
||||
connect( pEntry );
|
||||
break;
|
||||
}
|
||||
case PopupMenuTable::Entry::Separator:
|
||||
this->AppendSeparator();
|
||||
break;
|
||||
case PopupMenuTable::Entry::SubMenu:
|
||||
{
|
||||
const auto subTable = pEntry->subTable;
|
||||
auto subMenu = BuildMenu( this->pParent, subTable, pUserData );
|
||||
this->AppendSubMenu( subMenu.release(), pEntry->caption );
|
||||
}
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
pTable->InitMenu(this, pUserData);
|
||||
}
|
||||
|
||||
void PopupMenuTable::Menu::DisconnectTable(PopupMenuTable *pTable)
|
||||
{
|
||||
for (const PopupMenuTable::Entry *pEntry = &*pTable->Get().begin();
|
||||
pEntry->IsValid(); ++pEntry) {
|
||||
if ( pEntry->IsItem() )
|
||||
pParent->Disconnect( pEntry->id, wxEVT_COMMAND_MENU_SELECTED,
|
||||
pEntry->func, NULL, pTable );
|
||||
else if ( pEntry->IsSubMenu() )
|
||||
// recur
|
||||
DisconnectTable(pEntry->subTable);
|
||||
}
|
||||
|
||||
pTable->DestroyMenu();
|
||||
}
|
||||
|
||||
void PopupMenuTable::Menu::Disconnect()
|
||||
{
|
||||
for ( auto pTable : tables )
|
||||
DisconnectTable(pTable);
|
||||
}
|
||||
|
||||
// static
|
||||
std::unique_ptr<PopupMenuTable::Menu> PopupMenuTable::BuildMenu
|
||||
( wxEvtHandler *pParent, PopupMenuTable *pTable, void *pUserData )
|
||||
{
|
||||
// Rebuild as needed each time. That makes it safe in case of language change.
|
||||
std::unique_ptr<Menu> theMenu{ safenew Menu( pParent, pUserData ) };
|
||||
theMenu->Extend(pTable);
|
||||
return std::move( theMenu );
|
||||
}
|
|
@ -0,0 +1,196 @@
|
|||
/**********************************************************************
|
||||
|
||||
Audacity: A Digital Audio Editor
|
||||
|
||||
PopupMenuTable.h
|
||||
|
||||
Paul Licameli
|
||||
|
||||
This file defines PopupMenuTable, which inherits from wxEventHandler,
|
||||
|
||||
associated macros simplifying the population of tables,
|
||||
|
||||
and PopupMenuTable::Menu which is buildable from one or more such
|
||||
tables, and automatically attaches and detaches the event handlers.
|
||||
|
||||
**********************************************************************/
|
||||
|
||||
#ifndef __AUDACITY_POPUP_MENU_TABLE__
|
||||
#define __AUDACITY_POPUP_MENU_TABLE__
|
||||
|
||||
class wxCommandEvent;
|
||||
class wxString;
|
||||
#include <vector>
|
||||
#include <wx/event.h>
|
||||
#include <wx/menu.h>
|
||||
#include "../MemoryX.h"
|
||||
|
||||
#include "../TranslatableStringArray.h"
|
||||
|
||||
class PopupMenuTable;
|
||||
|
||||
struct PopupMenuTableEntry
|
||||
{
|
||||
enum Type { Item, RadioItem, CheckItem, Separator, SubMenu, Invalid };
|
||||
|
||||
Type type;
|
||||
int id;
|
||||
wxString caption;
|
||||
wxObjectEventFunction func;
|
||||
PopupMenuTable *subTable;
|
||||
|
||||
PopupMenuTableEntry(Type type_, int id_, wxString caption_,
|
||||
wxObjectEventFunction func_, PopupMenuTable *subTable_)
|
||||
: type(type_)
|
||||
, id(id_)
|
||||
, caption(caption_)
|
||||
, func(func_)
|
||||
, subTable(subTable_)
|
||||
{}
|
||||
|
||||
bool IsItem() const { return type == Item || type == RadioItem || type == CheckItem; }
|
||||
bool IsSubMenu() const { return type == SubMenu; }
|
||||
bool IsValid() const { return type != Invalid; }
|
||||
};
|
||||
|
||||
class PopupMenuTable : public TranslatableArray< std::vector<PopupMenuTableEntry> >
|
||||
{
|
||||
public:
|
||||
typedef PopupMenuTableEntry Entry;
|
||||
|
||||
class Menu
|
||||
: public wxMenu
|
||||
{
|
||||
friend class PopupMenuTable;
|
||||
|
||||
Menu(wxEvtHandler *pParent_, void *pUserData_)
|
||||
: pParent{ pParent_ }, tables{}, pUserData{ pUserData_ } {}
|
||||
|
||||
public:
|
||||
virtual ~Menu();
|
||||
|
||||
void Extend(PopupMenuTable *pTable);
|
||||
void DisconnectTable(PopupMenuTable *pTable);
|
||||
void Disconnect();
|
||||
|
||||
private:
|
||||
wxEvtHandler *pParent;
|
||||
std::vector<PopupMenuTable*> tables;
|
||||
void *pUserData;
|
||||
};
|
||||
|
||||
// Called when the menu is about to pop up.
|
||||
// Your chance to enable and disable items.
|
||||
virtual void InitMenu(Menu *pMenu, void *pUserData) = 0;
|
||||
|
||||
// Called when menu is destroyed.
|
||||
virtual void DestroyMenu() = 0;
|
||||
|
||||
// Optional pUserData gets passed to the InitMenu routines of tables.
|
||||
// No memory management responsibility is assumed by this function.
|
||||
static std::unique_ptr<Menu> BuildMenu
|
||||
(wxEvtHandler *pParent, PopupMenuTable *pTable, void *pUserData = NULL);
|
||||
};
|
||||
|
||||
/*
|
||||
The following macros make it easy to attach a popup menu to a window.
|
||||
|
||||
Exmple of usage:
|
||||
|
||||
In class MyTable (maybe in the private section),
|
||||
which inherits from PopupMenuTable,
|
||||
|
||||
DECLARE_POPUP_MENU(MyTable);
|
||||
virtual void InitMenu(Menu *pMenu, void *pUserData);
|
||||
virtual void DestroyMenu();
|
||||
|
||||
Then in MyTable.cpp,
|
||||
|
||||
void MyTable::InitMenu(Menu *pMenu, void *pUserData)
|
||||
{
|
||||
auto pData = static_cast<MyData*>(pUserData);
|
||||
// Remember pData, enable or disable menu items
|
||||
}
|
||||
|
||||
void MyTable::DestroyMenu()
|
||||
{
|
||||
// Do cleanup
|
||||
}
|
||||
|
||||
BEGIN_POPUP_MENU(MyTable)
|
||||
// This is inside a function and can contain arbitrary code. But usually
|
||||
// you only need a sequence of macro calls:
|
||||
|
||||
POPUP_MENU_ITEM(OnCutSelectedTextID, _("Cu&t"), OnCutSelectedText)
|
||||
// etc.
|
||||
|
||||
END_POPUP_MENU()
|
||||
|
||||
where OnCutSelectedText is a (maybe private) member function of MyTable.
|
||||
|
||||
Elswhere,
|
||||
|
||||
MyTable myTable;
|
||||
MyData data;
|
||||
auto pMenu = PopupMenuTable::BuildMenu(pParent, &myTable, &data);
|
||||
|
||||
// Optionally:
|
||||
OtherTable otherTable;
|
||||
pMenu->Extend(&otherTable);
|
||||
|
||||
pParent->PopupMenu(pMenu.get(), event.m_x, event.m_y);
|
||||
|
||||
That's all!
|
||||
*/
|
||||
|
||||
#define DECLARE_POPUP_MENU(HandlerClass) \
|
||||
virtual void Populate();
|
||||
|
||||
// begins function
|
||||
#define BEGIN_POPUP_MENU(HandlerClass) \
|
||||
void HandlerClass::Populate() { \
|
||||
typedef HandlerClass My;
|
||||
|
||||
#define POPUP_MENU_APPEND(type, id, string, memFn, subTable) \
|
||||
mContents.push_back( Entry { \
|
||||
type, \
|
||||
id, \
|
||||
string, \
|
||||
memFn, \
|
||||
subTable \
|
||||
} );
|
||||
|
||||
#define POPUP_MENU_APPEND_ITEM(type, id, string, memFn) \
|
||||
POPUP_MENU_APPEND( \
|
||||
type, \
|
||||
id, \
|
||||
string, \
|
||||
(wxObjectEventFunction)(wxEventFunction)(wxCommandEventFunction) \
|
||||
(&My::memFn), \
|
||||
nullptr )
|
||||
|
||||
#define POPUP_MENU_ITEM(id, string, memFn) \
|
||||
POPUP_MENU_APPEND_ITEM(Entry::Item, id, string, memFn);
|
||||
|
||||
#define POPUP_MENU_RADIO_ITEM(id, string, memFn) \
|
||||
POPUP_MENU_APPEND_ITEM(Entry::RadioItem, id, string, memFn);
|
||||
|
||||
#define POPUP_MENU_CHECK_ITEM(id, string, memFn) \
|
||||
POPUP_MENU_APPEND_ITEM(Entry::CheckItem, id, string, memFn);
|
||||
|
||||
// classname names a class that derives from MenuTable and defines Instance()
|
||||
#define POPUP_MENU_SUB_MENU(id, string, classname) \
|
||||
POPUP_MENU_APPEND( \
|
||||
Entry::SubMenu, id, string, nullptr, &classname::Instance() );
|
||||
|
||||
#define POPUP_MENU_SEPARATOR() \
|
||||
POPUP_MENU_APPEND( \
|
||||
Entry::Separator, -1, wxT(""), nullptr, nullptr );
|
||||
|
||||
// ends function
|
||||
#define END_POPUP_MENU() \
|
||||
POPUP_MENU_APPEND( \
|
||||
Entry::Invalid, -1, wxT(""), nullptr, nullptr ) \
|
||||
}
|
||||
|
||||
#endif
|
|
@ -256,6 +256,7 @@
|
|||
<ClCompile Include="..\..\..\src\widgets\Overlay.cpp" />
|
||||
<ClCompile Include="..\..\..\src\widgets\OverlayPanel.cpp" />
|
||||
<ClCompile Include="..\..\..\src\widgets\wxPanelWrapper.cpp" />
|
||||
<ClCompile Include="..\..\..\src\widgets\PopupMenuTable.cpp" />
|
||||
<ClCompile Include="..\..\..\src\WrappedType.cpp" />
|
||||
<ClCompile Include="..\..\..\src\effects\Amplify.cpp" />
|
||||
<ClCompile Include="..\..\..\src\effects\AutoDuck.cpp" />
|
||||
|
@ -511,6 +512,7 @@
|
|||
<ClInclude Include="..\..\..\src\widgets\OverlayPanel.h" />
|
||||
<ClInclude Include="..\..\..\src\widgets\wxPanelWrapper.h" />
|
||||
<ClInclude Include="..\..\..\src\wxFileNameWrapper.h" />
|
||||
<ClInclude Include="..\..\..\src\widgets\PopupMenuTable.h" />
|
||||
<ClInclude Include="..\..\configwin.h" />
|
||||
<ClInclude Include="..\..\..\src\Dependencies.h" />
|
||||
<ClInclude Include="..\..\..\src\DeviceManager.h" />
|
||||
|
@ -1169,4 +1171,4 @@
|
|||
<ImportGroup Label="ExtensionTargets">
|
||||
<Import Project="..\..\ny.targets" />
|
||||
</ImportGroup>
|
||||
</Project>
|
||||
</Project>
|
||||
|
|
|
@ -986,6 +986,9 @@
|
|||
<ClCompile Include="..\..\..\src\tracks\playabletrack\wavetrack\ui\WaveTrackVRulerControls.cpp">
|
||||
<Filter>src\tracks\playabletrack\wavetrack\ui</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="..\..\..\src\widgets\PopupMenuTable.cpp">
|
||||
<Filter>src\widgets</Filter>
|
||||
</ClCompile>
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<ClInclude Include="..\..\..\src\AboutDialog.h">
|
||||
|
@ -1966,6 +1969,9 @@
|
|||
<ClInclude Include="..\..\..\src\tracks\playabletrack\wavetrack\ui\WaveTrackVRulerControls.h">
|
||||
<Filter>src\tracks\playabletrack\wavetrack\ui</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="..\..\..\src\widgets\PopupMenuTable.h">
|
||||
<Filter>src\widgets</Filter>
|
||||
</ClInclude>
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<Image Include="..\..\audacity.ico">
|
||||
|
|
Loading…
Reference in New Issue