Skip to content

Commit

Permalink
Reallocate static ranges for wxMenuItem
Browse files Browse the repository at this point in the history
Previously different menus may use conflict ids in range 10000~.

Fix #53
See also Aegisub#131
  • Loading branch information
wangqr authored and arch1t3cht committed Dec 17, 2024
1 parent abb2597 commit 4ff5628
Show file tree
Hide file tree
Showing 7 changed files with 45 additions and 26 deletions.
5 changes: 3 additions & 2 deletions src/base_grid.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -54,9 +54,10 @@
#include <wx/scrolbar.h>
#include <wx/sizer.h>

// Check menu.h for id range allocation before editing this enum
enum {
GRID_SCROLLBAR = 1730,
MENU_SHOW_COL = 1250 // Needs 15 IDs after this
MENU_SHOW_COL = (wxID_HIGHEST + 1) + 2000 // Needs 15 IDs after this
};

BaseGrid::BaseGrid(wxWindow* parent, agi::Context *context)
Expand Down Expand Up @@ -542,7 +543,7 @@ void BaseGrid::OnMouseEvent(wxMouseEvent &event) {
void BaseGrid::OnContextMenu(wxContextMenuEvent &evt) {
wxPoint pos = evt.GetPosition();
if (pos == wxDefaultPosition || ScreenToClient(pos).y > lineHeight) {
if (!context_menu) context_menu = menu::GetMenu("grid_context", context);
if (!context_menu) context_menu = menu::GetMenu("grid_context", (wxID_HIGHEST + 1) + 8000, context);
menu::OpenPopupMenu(context_menu.get(), this);
}
else {
Expand Down
2 changes: 1 addition & 1 deletion src/frame_main.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -127,7 +127,7 @@ FrameMain::FrameMain()
EnableToolBar(*OPT_GET("App/Show Toolbar"));

StartupLog("Initialize menu bar");
menu::GetMenuBar("main", this, context.get());
menu::GetMenuBar("main", this, (wxID_HIGHEST + 1) + 10000, context.get());

StartupLog("Create status bar");
CreateStatusBar(2);
Expand Down
17 changes: 15 additions & 2 deletions src/include/aegisub/menu.h
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,19 @@ class wxMenu;
class wxMenuBar;
class wxWindow;

/*
ID allocation for menu items:
... - wxID_ANY(-1), wxID_LOWEST(4999) - wxID_HIGHEST(5999) Reserved by wxWidgets, see documentation for wxID_HIGHEST
(wxID_HIGHEST + 1) + 2000 ~ (wxID_HIGHEST + 1) + 2014 Grid column list, see base_grid.cpp
(wxID_HIGHEST + 1) + 3000 ~ (wxID_HIGHEST + 1) + 3001 Context menu, see timeedit_ctrl.cpp
(wxID_HIGHEST + 1) + 4000 ~ (wxID_HIGHEST + 1) + 7999 Context menu, see subs_edit_ctrl.cpp
(wxID_HIGHEST + 1) + 8000 ~ (wxID_HIGHEST + 1) + 8019 Grid context menu, see base_grid.cpp
(wxID_HIGHEST + 1) + 9000 ~ (wxID_HIGHEST + 1) + 9004 Video context menu, see video_display.cpp
(wxID_HIGHEST + 1) + 10000 ~ (wxID_HIGHEST + 1) + 10999 Main menu
*/

namespace menu {
DEFINE_EXCEPTION(Error, agi::Exception);
DEFINE_EXCEPTION(UnknownMenu, Error);
Expand All @@ -39,15 +52,15 @@ namespace menu {
/// Throws:
/// UnknownMenu if no menu with the given name was found
/// BadMenu if there is a menu with the given name, but it is invalid
void GetMenuBar(std::string const& name, wxFrame *window, agi::Context *c);
void GetMenuBar(std::string const& name, wxFrame *window, int id_base, agi::Context *c);

/// @brief Get the menu with the specified name as a wxMenu
/// @param name Name of the menu
///
/// Throws:
/// UnknownMenu if no menu with the given name was found
/// BadMenu if there is a menu with the given name, but it is invalid
std::unique_ptr<wxMenu> GetMenu(std::string const& name, agi::Context *c);
std::unique_ptr<wxMenu> GetMenu(std::string const& name, int id_base, agi::Context *c);

/// @brief Open a popup menu at the mouse
/// @param menu Menu to open
Expand Down
35 changes: 19 additions & 16 deletions src/menu.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -50,10 +50,11 @@
#endif

namespace {
/// Window ID of first menu item
static const int MENU_ID_BASE = 10000;

class MruMenu final : public wxMenu {
/// Window ID of first menu item
const int id_base;

std::string type;
std::vector<wxMenuItem *> items;
std::vector<std::string> *cmds;
Expand All @@ -65,16 +66,16 @@ class MruMenu final : public wxMenu {

for (size_t i = GetMenuItemCount(); i < new_size; ++i) {
if (i >= items.size()) {
items.push_back(new wxMenuItem(this, MENU_ID_BASE + cmds->size(), "_"));
items.push_back(new wxMenuItem(this, id_base + cmds->size(), "_"));
cmds->push_back(agi::format("recent/%s/%d", boost::to_lower_copy(type), i));
}
Append(items[i]);
}
}

public:
MruMenu(std::string type, std::vector<std::string> *cmds)
: type(std::move(type))
MruMenu(int id_base, std::string type, std::vector<std::string> *cmds)
: id_base(id_base), type(std::move(type))
, cmds(cmds)
{
}
Expand Down Expand Up @@ -117,6 +118,8 @@ class MruMenu final : public wxMenu {
/// on submenus in many cases, and registering large numbers of wxEVT_UPDATE_UI
/// handlers makes everything involves events unusably slow.
class CommandManager {
/// Window ID of first menu item
const int id_base;
/// Menu items which need to do something on menu open
std::vector<std::pair<std::string, wxMenuItem*>> dynamic_items;
/// Menu items which need to be updated only when hotkeys change
Expand Down Expand Up @@ -164,8 +167,8 @@ class CommandManager {
}

public:
CommandManager(agi::Context *context)
: context(context)
CommandManager(int id_base, agi::Context *context)
: id_base(id_base), context(context)
, hotkeys_changed(hotkey::inst->AddHotkeyChangeListener(&CommandManager::OnHotkeysChanged, this))
{
}
Expand Down Expand Up @@ -193,7 +196,7 @@ class CommandManager {

menu_text += "\t" + to_wx(hotkey::get_hotkey_str_first("Default", co->name()));

wxMenuItem *item = new wxMenuItem(parent, MENU_ID_BASE + items.size(), menu_text, co->StrHelp(), kind);
wxMenuItem *item = new wxMenuItem(parent, id_base + items.size(), menu_text, co->StrHelp(), kind);
#ifndef __WXMAC__
/// @todo Maybe make this a configuration option instead?
if (kind == wxITEM_NORMAL)
Expand Down Expand Up @@ -228,7 +231,7 @@ class CommandManager {
/// @param name MRU type
/// @param parent Menu to append the new MRU menu to
void AddRecent(std::string const& name, wxMenu *parent) {
mru.push_back(new MruMenu(name, &items));
mru.push_back(new MruMenu(id_base, name, &items));
parent->AppendSubMenu(mru.back(), _("&Recent"));
}

Expand All @@ -242,7 +245,7 @@ class CommandManager {
void OnMenuClick(wxCommandEvent &evt) {
// This also gets clicks on unrelated things such as the toolbar, so
// the window ID ranges really need to be unique
size_t id = static_cast<size_t>(evt.GetId() - MENU_ID_BASE);
size_t id = static_cast<size_t>(evt.GetId() - id_base);
if (id < items.size() && context)
cmd::call(items[id], context);

Expand Down Expand Up @@ -275,13 +278,13 @@ class CommandManager {
/// Wrapper for wxMenu to add a command manager
struct CommandMenu final : public wxMenu {
CommandManager cm;
CommandMenu(agi::Context *c) : cm(c) { }
CommandMenu(int id_base, agi::Context *c) : cm(id_base, c) { }
};

/// Wrapper for wxMenuBar to add a command manager
struct CommandMenuBar final : public wxMenuBar {
CommandManager cm;
CommandMenuBar(agi::Context *c) : cm(c) { }
CommandMenuBar(int id_base, agi::Context *c) : cm(id_base, c) { }
};

/// Read a string from a json object
Expand Down Expand Up @@ -497,7 +500,7 @@ class AutomationMenu final : public wxMenu {
}

namespace menu {
void GetMenuBar(std::string const& name, wxFrame *window, agi::Context *c) {
void GetMenuBar(std::string const& name, wxFrame *window, int id_base, agi::Context *c) {
#ifdef __WXMAC__
auto bind_events = [&](CommandMenuBar *menu) {
window->Bind(wxEVT_ACTIVATE, [=](wxActivateEvent&) { menu->cm.SetContext(c); });
Expand All @@ -513,7 +516,7 @@ namespace menu {
}
#endif

auto menu = std::make_unique<CommandMenuBar>(c);
auto menu = std::make_unique<CommandMenuBar>(id_base, c);
for (auto const& item : get_menu(name)) {
std::string submenu, disp;
read_entry(item, "submenu", &submenu);
Expand Down Expand Up @@ -546,8 +549,8 @@ namespace menu {
menu.release();
}

std::unique_ptr<wxMenu> GetMenu(std::string const& name, agi::Context *c) {
auto menu = std::make_unique<CommandMenu>(c);
std::unique_ptr<wxMenu> GetMenu(std::string const& name, int id_base, agi::Context *c) {
auto menu = std::make_unique<CommandMenu>(id_base, c);
build_menu(name, c, &menu->cm, menu.get());
menu->Bind(wxEVT_MENU_OPEN, &CommandManager::OnMenuOpen, &menu->cm);
menu->Bind(wxEVT_MENU, &CommandManager::OnMenuClick, &menu->cm);
Expand Down
7 changes: 4 additions & 3 deletions src/subs_edit_ctrl.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -60,8 +60,9 @@
#define LANGS_MAX 1000

/// Event ids
// Check menu.h for id range allocation before editing this enum
enum {
EDIT_MENU_SPLIT_PRESERVE = 1400,
EDIT_MENU_SPLIT_PRESERVE = (wxID_HIGHEST + 1) + 4000,
EDIT_MENU_SPLIT_ESTIMATE,
EDIT_MENU_SPLIT_VIDEO,
EDIT_MENU_CUT,
Expand All @@ -72,9 +73,9 @@ enum {
EDIT_MENU_REMOVE_FROM_DICT,
EDIT_MENU_SUGGESTION,
EDIT_MENU_SUGGESTIONS,
EDIT_MENU_THESAURUS = 1450,
EDIT_MENU_THESAURUS = (wxID_HIGHEST + 1) + 5000,
EDIT_MENU_THESAURUS_SUGS,
EDIT_MENU_DIC_LANGUAGE = 1600,
EDIT_MENU_DIC_LANGUAGE = (wxID_HIGHEST + 1) + 6000,
EDIT_MENU_DIC_LANGS,
EDIT_MENU_THES_LANGUAGE = EDIT_MENU_DIC_LANGUAGE + LANGS_MAX,
EDIT_MENU_THES_LANGS
Expand Down
3 changes: 2 additions & 1 deletion src/timeedit_ctrl.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -48,8 +48,9 @@

#define TimeEditWindowStyle

// Check menu.h for id range allocation before editing this enum
enum {
Time_Edit_Copy = 1320,
Time_Edit_Copy = (wxID_HIGHEST + 1) + 3000,
Time_Edit_Paste
};

Expand Down
2 changes: 1 addition & 1 deletion src/video_display.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -368,7 +368,7 @@ void VideoDisplay::OnMouseWheel(wxMouseEvent& event) {
}

void VideoDisplay::OnContextMenu(wxContextMenuEvent&) {
if (!context_menu) context_menu = menu::GetMenu("video_context", con);
if (!context_menu) context_menu = menu::GetMenu("video_context", (wxID_HIGHEST + 1) + 9000, con);
SetCursor(wxNullCursor);
menu::OpenPopupMenu(context_menu.get(), this);
}
Expand Down

0 comments on commit 4ff5628

Please sign in to comment.