| FazBrowse GitHub Viewer | Trending | | Home |
| Tools: [Download Repo ZIP] [Original HTTPS Page] |
1 parent f0b95bd commit 390da5b
1 file changed
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
@@ -353,6 +353,13 @@ class MenuItemImplGtk4 final : public MenuItem { | |||
| 353 | 353 | } | |
| 354 | 354 | }; | |
| 355 | 355 | ||
| 356 | + // A menu tree (a menu bar or a standalone popup menu, together with all of its | ||
| 357 | + // submenus) shares a single Gio::SimpleActionGroup. That group is inserted into the | ||
| 358 | + // relevant widget exactly once, under the "ss" prefix. Because the group object is | ||
| 359 | + // mutable and stays referenced by the widget after insertion, actions added to (or | ||
| 360 | + // removed from) it later - e.g. when a submenu is repopulated - take effect immediately, | ||
| 361 | + // with no need to re-insert anything into the widget. This avoids stale/missing actions | ||
| 362 | + // (which GTK renders as permanently disabled menu items) after a menu is rebuilt. | ||
| 356 | 363 | class MenuImplGtk4 final : public Menu { | |
| 357 | 364 | public: | |
| 358 | 365 | Glib::RefPtr<Gio::Menu> gioMenu; | |
@@ -361,9 +368,9 @@ class MenuImplGtk4 final : public Menu { | |||
| 361 | 368 | std::vector<std::shared_ptr<MenuImplGtk4>> subMenus; | |
| 362 | 369 | Glib::RefPtr<Gio::Menu> currentSection; | |
| 363 | 370 | ||
| 364 | - MenuImplGtk4() { | ||
| 371 | + MenuImplGtk4(Glib::RefPtr<Gio::SimpleActionGroup> sharedActionGroup = {}) { | ||
| 365 | 372 | gioMenu = Gio::Menu::create(); | |
| 366 | - actionGroup = Gio::SimpleActionGroup::create(); | ||
| 373 | + actionGroup = sharedActionGroup ? sharedActionGroup : Gio::SimpleActionGroup::create(); | ||
| 367 | 374 | currentSection = Gio::Menu::create(); | |
| 368 | 375 | gioMenu->append_section("", currentSection); | |
| 369 | 376 | } | |
@@ -384,7 +391,7 @@ class MenuImplGtk4 final : public Menu { | |||
| 384 | 391 | } | |
| 385 | 392 | ||
| 386 | 393 | MenuRef AddSubMenu(const std::string &label) override { | |
| 387 | - auto subMenu = std::make_shared<MenuImplGtk4>(); | ||
| 394 | + auto subMenu = std::make_shared<MenuImplGtk4>(actionGroup); | ||
| 388 | 395 | subMenus.push_back(subMenu); | |
| 389 | 396 | ||
| 390 | 397 | currentSection->append_submenu(PrepareMnemonics(label), subMenu->gioMenu); | |
@@ -427,20 +434,28 @@ class MenuImplGtk4 final : public Menu { | |||
| 427 | 434 | popover->unparent(); | |
| 428 | 435 | } | |
| 429 | 436 | ||
| 437 | + // All submenus of this menu share the same actionGroup, so it only needs to be | ||
| 438 | + // inserted into the widget once. | ||
| 430 | 439 | void InsertActionsInto(Gtk::Widget *widget) { | |
| 431 | 440 | widget->insert_action_group("ss", actionGroup); | |
| 432 | - for(auto &sub : subMenus) { | ||
| 433 | - sub->InsertActionsInto(widget); | ||
| 434 | - } | ||
| 435 | 441 | } | |
| 436 | 442 | ||
| 443 | + // Remove only the actions owned by this submenu (and its children) from the shared | ||
| 444 | + // group, then reset the menu model. The shared actionGroup itself is preserved (and | ||
| 445 | + // not replaced) since it may already be inserted into a widget; any items added | ||
| 446 | + // after Clear() become visible/enabled immediately. | ||
| 437 | 447 | void Clear() override { | |
| 448 | + for(auto &item : menuItems) { | ||
| 449 | + actionGroup->remove_action(item->actionName); | ||
| 450 | + } | ||
| 451 | + for(auto &sub : subMenus) { | ||
| 452 | + sub->Clear(); | ||
| 453 | + } | ||
| 438 | 454 | gioMenu->remove_all(); | |
| 439 | 455 | currentSection = Gio::Menu::create(); | |
| 440 | 456 | gioMenu->append_section("", currentSection); | |
| 441 | 457 | menuItems.clear(); | |
| 442 | 458 | subMenus.clear(); | |
| 443 | - actionGroup = Gio::SimpleActionGroup::create(); | ||
| 444 | 459 | } | |
| 445 | 460 | }; | |
| 446 | 461 | ||
@@ -460,7 +475,7 @@ class MenuBarImplGtk4 final : public MenuBar { | |||
| 460 | 475 | } | |
| 461 | 476 | ||
| 462 | 477 | MenuRef AddSubMenu(const std::string &label) override { | |
| 463 | - auto subMenu = std::make_shared<MenuImplGtk4>(); | ||
| 478 | + auto subMenu = std::make_shared<MenuImplGtk4>(actionGroup); | ||
| 464 | 479 | subMenus.push_back(subMenu); | |
| 465 | 480 | ||
| 466 | 481 | gioMenu->append_submenu(PrepareMnemonics(label), subMenu->gioMenu); | |
@@ -469,24 +484,16 @@ class MenuBarImplGtk4 final : public MenuBar { | |||
| 469 | 484 | } | |
| 470 | 485 | ||
| 471 | 486 | void Clear() override { | |
| 487 | + for(auto &sub : subMenus) { | ||
| 488 | + sub->Clear(); | ||
| 489 | + } | ||
| 472 | 490 | gioMenu->remove_all(); | |
| 473 | 491 | subMenus.clear(); | |
| 474 | - actionGroup = Gio::SimpleActionGroup::create(); | ||
| 475 | - } | ||
| 476 | - | ||
| 477 | - void CollectActions(const std::shared_ptr<MenuImplGtk4> &menu) { | ||
| 478 | - for(auto &item : menu->menuItems) { | ||
| 479 | - actionGroup->add_action(item->action); | ||
| 480 | - } | ||
| 481 | - for(auto &sub : menu->subMenus) { | ||
| 482 | - CollectActions(sub); | ||
| 483 | - } | ||
| 484 | 492 | } | |
| 485 | 493 | ||
| 494 | + // All submenus share this menu bar's actionGroup, so it only needs to be inserted | ||
| 495 | + // into the widget once; there is no need to recursively collect actions. | ||
| 486 | 496 | void InsertActionsInto(Gtk::Widget *widget) { | |
| 487 | - for(auto &sub : subMenus) { | ||
| 488 | - CollectActions(sub); | ||
| 489 | - } | ||
| 490 | 497 | widget->insert_action_group("ss", actionGroup); | |
| 491 | 498 | } | |
| 492 | 499 | }; | |
| Back | FazBrowse Home | New Git URL |
0 commit comments