Amended the dynamic menu handling
for the case where we have many windows and you want to change the menu on change of focus Which is a classic example of writing code before it is needed.
This commit is contained in:
parent
a29b8c7e52
commit
cfa234ef09
@ -3,8 +3,7 @@ using ro::base58;
|
||||
static constexpr char SrcFilename[]{ "src/display_wallet.cpp" };
|
||||
display_wallet::display_wallet(wxWindow* parent, wxFileName& walletfile) :
|
||||
wxPanel(parent, myID_WALLET_UI, wxDefaultPosition, wxDefaultSize, wxTAB_TRAVERSAL, wxT("Wallet")),
|
||||
m_db(nullptr),
|
||||
m_menuitem_add_name(this, &display_wallet::add_name_event_handler)
|
||||
m_db(nullptr), m_DisplayWalletEditMenu(1)
|
||||
{
|
||||
wxLogMessage(wxT("Loading %s"), walletfile.GetFullPath());
|
||||
try {
|
||||
@ -73,10 +72,16 @@ display_wallet::display_wallet(wxWindow* parent, wxFileName& walletfile) :
|
||||
this->SetSize(this->GetParent()->GetClientSize());
|
||||
singletonFrame->m_LastUsedWallet.Assign(walletfile);
|
||||
|
||||
wxMenu* menuFile{ singletonFrame->GetMenuBar()->GetMenu(0) };
|
||||
singletonFrame->GetMenuBar()->EnableTop(1, true); //enable edit menu.
|
||||
wxMenu* menuEdit{ singletonFrame->GetMenuBar()->GetMenu(1) };
|
||||
m_menuitem_add_name.Insert(menuEdit, 0, "add name", "create new Zooko identity");
|
||||
m_DisplayWalletEditMenu.Menu->Append(
|
||||
myID_DISPLAY_WALLET_ADD_NAME,
|
||||
"add name", "create new Zooko identity"
|
||||
);
|
||||
m_DisplayWalletEditMenu.Menu->Bind(
|
||||
wxEVT_MENU,
|
||||
&display_wallet::add_name_event_handler,
|
||||
this, myID_DISPLAY_WALLET_ADD_NAME
|
||||
);
|
||||
m_DisplayWalletEditMenu.Replace();
|
||||
}
|
||||
catch (const MyException&) {
|
||||
throw;
|
||||
@ -91,10 +96,8 @@ display_wallet::display_wallet(wxWindow* parent, wxFileName& walletfile) :
|
||||
|
||||
|
||||
}
|
||||
display_wallet::~display_wallet() {
|
||||
assert(true);
|
||||
singletonFrame->GetMenuBar()->EnableTop(1, false); //disable edit menu.
|
||||
|
||||
display_wallet::~display_wallet() {
|
||||
}
|
||||
|
||||
void display_wallet::close_menu_event_handler(wxCommandEvent& event) {
|
||||
|
@ -14,6 +14,6 @@ private:
|
||||
wxBoxSizer* m_rSizer;
|
||||
void close_menu_event_handler(wxCommandEvent&);
|
||||
void add_name_event_handler(wxCommandEvent&);
|
||||
MenuLink m_menuitem_add_name;
|
||||
void OnClose(wxCloseEvent& event);
|
||||
wxMenuTracker m_DisplayWalletEditMenu;
|
||||
};
|
||||
|
@ -1,6 +1,36 @@
|
||||
#include "stdafx.h"
|
||||
static constexpr char SrcFilename[]{ "src/frame.cpp" };
|
||||
|
||||
// ----------------------------------------------------------------------------
|
||||
//wxMenuTracker
|
||||
// ----------------------------------------------------------------------------
|
||||
|
||||
wxMenuTracker::wxMenuTracker(const int i) : Menu(new wxMenu), MenuPosition(i) {};
|
||||
|
||||
wxMenu* wxMenuTracker::InitialAndFinal[]{ nullptr, new wxMenu, nullptr };
|
||||
|
||||
void wxMenuTracker::Replace() {
|
||||
singletonFrame->GetMenuBar()->Replace(
|
||||
MenuPosition,
|
||||
Menu,
|
||||
menu_strings[MenuPosition].head
|
||||
);
|
||||
singletonFrame->GetMenuBar()->EnableTop(MenuPosition, true); //enable edit menu.
|
||||
};
|
||||
wxMenuTracker::~wxMenuTracker() {
|
||||
auto menu_bar = singletonFrame->GetMenuBar();
|
||||
if (menu_bar->GetMenu(MenuPosition) == Menu) {
|
||||
assert(InitialAndFinal[MenuPosition]);
|
||||
menu_bar->Replace(
|
||||
MenuPosition,
|
||||
InitialAndFinal[MenuPosition],
|
||||
menu_strings[MenuPosition].head
|
||||
);
|
||||
menu_bar->EnableTop(MenuPosition, false);
|
||||
delete Menu;
|
||||
}
|
||||
};
|
||||
|
||||
// ----------------------------------------------------------------------------
|
||||
// frame
|
||||
// ----------------------------------------------------------------------------
|
||||
@ -157,18 +187,36 @@ Frame::Frame(const wxString& wxs)
|
||||
menuFile->Bind(wxEVT_MENU, &Frame::OnDeleteConfiguration, this, myID_DELETECONFIG);
|
||||
menuFile->Append(wxID_EXIT);
|
||||
menuFile->Bind(wxEVT_MENU, &Frame::OnExit, this, wxID_EXIT);
|
||||
|
||||
|
||||
wxMenu* menuEdit = wxMenuTracker::InitialAndFinal[1];
|
||||
wxMenu* menuHelp = new wxMenu;
|
||||
menuHelp->Append(wxID_ABOUT);
|
||||
menuHelp->Bind(wxEVT_MENU, &Frame::OnAbout, this, wxID_ABOUT);
|
||||
wxMenuBar* menuBar = new wxMenuBar;
|
||||
menuBar->Append(menuFile, menu_strings[0].head);
|
||||
menuBar->Append(new wxMenu, menu_strings[1].head); //Edit menu, initially empty and disabled
|
||||
menuBar->Append(menuEdit, menu_strings[1].head); //Edit menu, initially empty and disabled
|
||||
menuBar->Append(menuHelp, menu_strings[2].head);
|
||||
SetMenuBar(menuBar);
|
||||
CreateStatusBar();
|
||||
menuBar->EnableTop(1, false); //disable edit menu.
|
||||
// child controls
|
||||
if constexpr (debug_mode) {
|
||||
// Check that the initial values of all replaceable menus
|
||||
// are at their default values as if the window handling them
|
||||
// had just been destroyed and not yet replaced.
|
||||
for (int i = 0; i < std::size(wxMenuTracker::InitialAndFinal); i++) {
|
||||
assert(
|
||||
!wxMenuTracker::InitialAndFinal[i]
|
||||
||
|
||||
(
|
||||
wxMenuTracker::InitialAndFinal[i] == menuBar->GetMenu(i)
|
||||
&&
|
||||
!menuBar->IsEnabledTop(i)
|
||||
)
|
||||
);
|
||||
|
||||
}
|
||||
}
|
||||
CreateStatusBar();
|
||||
// child controls
|
||||
wxPanel* panel{ nullptr };
|
||||
m_panel = panel;
|
||||
wxConfigBase& Config = singletonApp->m_Config;
|
||||
@ -511,11 +559,29 @@ Frame::~Frame() {
|
||||
wxConfigBase& Config = singletonApp->m_Config;
|
||||
StorePositionToConfig();
|
||||
Config.SetPath(wxT("/TipOfTheDay"));
|
||||
Config.Write("show", (int)m_showTipsAtStartup);
|
||||
Config.Write("index", (int)m_TipOfTheDayIndex);
|
||||
Config.SetPath(wxT("/FileDialog"));
|
||||
Config.Write("index", (int)m_FileDialogFilterIndex);
|
||||
Config.Write(wxT("LastUsed"), m_LastUsedWallet.GetFullPath());
|
||||
Config.SetPath(wxT("/"));
|
||||
Config.Flush();
|
||||
Config.Write("show", (int)m_showTipsAtStartup);
|
||||
Config.Write("index", (int)m_TipOfTheDayIndex);
|
||||
Config.SetPath(wxT("/FileDialog"));
|
||||
Config.Write("index", (int)m_FileDialogFilterIndex);
|
||||
Config.Write(wxT("LastUsed"), m_LastUsedWallet.GetFullPath());
|
||||
Config.SetPath(wxT("/"));
|
||||
Config.Flush();
|
||||
if constexpr (debug_mode) {
|
||||
// Check that the final values of all replaceable menus
|
||||
// are at what they should be because the window handling
|
||||
// them should have been destroyed.
|
||||
auto menuBar = this->GetMenuBar();
|
||||
for (int i = 0; i < std::size(wxMenuTracker::InitialAndFinal); i++) {
|
||||
assert(
|
||||
!wxMenuTracker::InitialAndFinal[i]
|
||||
||
|
||||
(
|
||||
wxMenuTracker::InitialAndFinal[i] == menuBar->GetMenu(i)
|
||||
&&
|
||||
!menuBar->IsEnabledTop(i)
|
||||
)
|
||||
);
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
|
35
src/frame.h
35
src/frame.h
@ -1,4 +1,39 @@
|
||||
#pragma once
|
||||
// wxWidgets has drop down menus, wxMenu, owned by the wxMenuBar,
|
||||
// which is owned by the Frame window, but menus subject to replacement need
|
||||
// to be destroyed by the child window.
|
||||
// wxMenuOwner tracks a drop down menu that might be at a location in
|
||||
// the menubar, places it in that location in the menubar on demand,
|
||||
// and on destruction destroys it
|
||||
// If, on destruction wxMenuBar is still pointing to this wxMenu, it
|
||||
// replaces it with the default (empty) menu for that location.
|
||||
// and disables it.
|
||||
// We maintain an array of default empty wxMenu menus that are nullptr for
|
||||
// locations not subject to replacement, and are the disabled initial and final
|
||||
// wxMenuBar values for locations in the Menubar where the real drop down
|
||||
// in the menubar will be installed by wxMenuTracker.
|
||||
struct wxMenuTracker {
|
||||
wxMenuTracker(int);
|
||||
void Replace();
|
||||
~wxMenuTracker() noexcept;
|
||||
// Non nullptr members of InitialAndFinal have to be explicitly initially placed
|
||||
// in the menubar in the frame constructor and explicitly disabled in
|
||||
// the frame initializer. In the debug build, congruence between the menu bar
|
||||
// and InitialAndFinal should be checked with assert.
|
||||
static wxMenu* InitialAndFinal[3];
|
||||
wxMenuTracker(wxMenuTracker&&) = delete; // Move constructor
|
||||
wxMenuTracker(const wxMenuTracker&) = delete; // Copy constructor
|
||||
wxMenuTracker& operator=(wxMenuTracker&&) = delete; // Move assignment.
|
||||
wxMenuTracker& operator=(const wxMenuTracker&) = delete; // Copy assignment.
|
||||
bool operator==(const wxMenuTracker&) const = delete;
|
||||
auto operator<=>(const wxMenuTracker&) const = delete;
|
||||
wxMenu* Menu;
|
||||
const int MenuPosition;
|
||||
// The menu title is defined elsewhere as an array
|
||||
// of const strings
|
||||
// menu_strings[MenuPosition].head
|
||||
};
|
||||
|
||||
template <typename T>
|
||||
// This class exists to record the needed to unbind a drop down menu action and delete
|
||||
// the corresponding item from the drop down menu when the handler is destroyed.
|
||||
|
@ -106,7 +106,7 @@ enum MyIDs {
|
||||
myID_DELETECONFIG = wxID_HIGHEST + 1, myID_ERRORMESSAGE, myID_Hello,
|
||||
myID_MAINFRAME,
|
||||
myID_MAINFRAME_PANEL, myID_TESTWINDOW, myID_WELCOME_TO_ROCOIN, myID_WALLET_UI,
|
||||
mID_CLOSE_WALLET, myID_MYEXIT
|
||||
mID_CLOSE_WALLET, myID_MYEXIT, myID_DISPLAY_WALLET_ADD_NAME
|
||||
};
|
||||
|
||||
#include "localization.h"
|
||||
|
Loading…
Reference in New Issue
Block a user