diff --git a/src/kits/tracker/ContainerWindow.cpp b/src/kits/tracker/ContainerWindow.cpp index f2007205db..2e7a672275 100644 --- a/src/kits/tracker/ContainerWindow.cpp +++ b/src/kits/tracker/ContainerWindow.cpp @@ -79,6 +79,7 @@ All rights reserved. #include "FavoritesMenu.h" #include "FindPanel.h" #include "IconMenuItem.h" +#include "LiveMenu.h" #include "MimeTypes.h" #include "Model.h" #include "MountMenu.h" @@ -634,13 +635,13 @@ void BContainerWindow::AddContextMenus() { // create context sensitive menus - fPoseContextMenu = new BPopUpMenu("PoseContext", false, false); + fPoseContextMenu = new TLivePosePopUpMenu("PoseContext", this, false, false); AddPoseContextMenu(fPoseContextMenu); fVolumeContextMenu = new BPopUpMenu("VolumeContext", false, false); AddVolumeContextMenu(fVolumeContextMenu); - fWindowContextMenu = new BPopUpMenu("WindowContext", false, false); + fWindowContextMenu = new TLiveWindowPopUpMenu("WindowContext", this, false, false); AddWindowContextMenu(fWindowContextMenu); fDropContextMenu = new BPopUpMenu("DropContext", false, false); @@ -714,11 +715,11 @@ BContainerWindow::RepopulateMenus() } delete fPoseContextMenu; - fPoseContextMenu = new BPopUpMenu("PoseContext", false, false); + fPoseContextMenu = new TLivePosePopUpMenu("PoseContext", this, false, false); AddPoseContextMenu(fPoseContextMenu); delete fWindowContextMenu; - fWindowContextMenu = new BPopUpMenu("WindowContext", false, false); + fWindowContextMenu = new TLiveWindowPopUpMenu("WindowContext", this, false, false); AddWindowContextMenu(fWindowContextMenu); } @@ -1695,11 +1696,11 @@ BContainerWindow::IsShowing(const entry_ref* entry) const void BContainerWindow::AddMenus() { - fFileMenu = new BMenu(B_TRANSLATE("File")); + fFileMenu = new TLiveFileMenu(B_TRANSLATE("File"), this); AddFileMenu(fFileMenu); fMenuBar->AddItem(fFileMenu); - fWindowMenu = new BMenu(B_TRANSLATE("Window")); + fWindowMenu = new TLiveWindowMenu(B_TRANSLATE("Window"), this); fMenuBar->AddItem(fWindowMenu); AddWindowMenu(fWindowMenu); @@ -3458,7 +3459,7 @@ BContainerWindow::NewArrangeByMenu() ASSERT(fAttrMenu); // create a new "Arrange by >" menu - BMenu* menu = new BMenu(Shortcuts()->ArrangeByLabel()); + TLiveArrangeByMenu* menu = new TLiveArrangeByMenu(Shortcuts()->ArrangeByLabel(), this); // add Attributes items to "Arrange by >" BMenuItem* item; diff --git a/src/kits/tracker/FilePanelPriv.cpp b/src/kits/tracker/FilePanelPriv.cpp index 37399b6ae2..f20bd7b10c 100644 --- a/src/kits/tracker/FilePanelPriv.cpp +++ b/src/kits/tracker/FilePanelPriv.cpp @@ -75,6 +75,7 @@ All rights reserved. #include "FSUtils.h" #include "FavoritesMenu.h" #include "IconMenuItem.h" +#include "LiveMenu.h" #include "MimeTypes.h" #include "NavMenu.h" #include "Shortcuts.h" @@ -851,7 +852,7 @@ TFilePanel::AddMenus() { // File - fFileMenu = new BMenu(B_TRANSLATE("File")); + fFileMenu = new TLiveFileMenu(B_TRANSLATE("File"), this); AddFileMenu(fFileMenu); fMenuBar->AddItem(fFileMenu); @@ -1124,19 +1125,19 @@ TFilePanel::RepopulateMenus() fMenuBar->RemoveItem(fFileMenu); delete fFileMenu; if (ShouldAddMenus()) { - fFileMenu = new BMenu(B_TRANSLATE("File")); - TFilePanel::AddFileMenu(fFileMenu); + fFileMenu = new TLiveFileMenu(B_TRANSLATE("File"), this); + AddFileMenu(fFileMenu); fMenuBar->AddItem(fFileMenu, 0); } } delete fPoseContextMenu; - fPoseContextMenu = new BPopUpMenu("PoseContext", false, false); + fPoseContextMenu = new TLivePosePopUpMenu("PoseContext", this, false, false); fPoseContextMenu->SetFont(be_plain_font); TFilePanel::AddPoseContextMenu(fPoseContextMenu); delete fWindowContextMenu; - fWindowContextMenu = new BPopUpMenu("WindowContext", false, false); + fWindowContextMenu = new TLiveWindowPopUpMenu("WindowContext", this, false, false); fWindowContextMenu->SetFont(be_plain_font); TFilePanel::AddWindowContextMenu(fWindowContextMenu); } diff --git a/src/kits/tracker/Jamfile b/src/kits/tracker/Jamfile index f29fa14677..b60d34589b 100644 --- a/src/kits/tracker/Jamfile +++ b/src/kits/tracker/Jamfile @@ -52,6 +52,7 @@ for architectureObject in [ MultiArchSubDirSetup ] { IconCache.cpp IconMenuItem.cpp InfoWindow.cpp + LiveMenu.cpp MimeTypeList.cpp MiniMenuField.cpp Model.cpp diff --git a/src/kits/tracker/LiveMenu.cpp b/src/kits/tracker/LiveMenu.cpp new file mode 100644 index 0000000000..aa24c9bf6d --- /dev/null +++ b/src/kits/tracker/LiveMenu.cpp @@ -0,0 +1,309 @@ +/* + * Copyright 2020-2024 Haiku, Inc. All rights reserved. + * Distributed under the terms of the MIT License. + * + * Authors: + * John Scipione, jscipione@gmail.com + */ + + +#include "LiveMenu.h" + +#include + +#include +#include +#include +#include + +#include "Commands.h" +#include "TrackerSettings.h" + + +// #pragma mark - TLiveMixin + + +TLiveMixin::TLiveMixin(const BContainerWindow* window) +{ + fWindow = window; +} + + +void +TLiveMixin::UpdateFileMenu(BMenu* menu) +{ + if (menu == NULL) + return; + + if (menu->Window()->LockLooper()) { + int32 itemCount = menu->CountItems(); + for (int32 index = 0; index < itemCount; index++) { + BMenuItem* item = menu->ItemAt(index); + if (item == NULL || item->Message() == NULL) + continue; + + switch (item->Message()->what) { + // Move to Trash/Delete + case kMoveSelectionToTrash: + case kDeleteSelection: + if (!fWindow->Shortcuts()->IsTrash()) + fWindow->Shortcuts()->UpdateMoveToTrashItem(item); + break; + + // Create link/Create relative link + case kCreateLink: + case kCreateRelativeLink: + fWindow->Shortcuts()->UpdateCreateLinkItem(item); + break; + + // Cut/Cut more + case B_CUT: + case kCutMoreSelectionToClipboard: + fWindow->Shortcuts()->UpdateCutItem(item); + break; + + // Copy/Copy more + case B_COPY: + case kCopyMoreSelectionToClipboard: + fWindow->Shortcuts()->UpdateCopyItem(item); + break; + + // Paste/Paste links + case B_PASTE: + case kPasteLinksFromClipboard: + fWindow->Shortcuts()->UpdatePasteItem(item); + break; + + // Identify/Force identify + case kIdentifyEntry: + fWindow->Shortcuts()->UpdateIdentifyItem(item); + break; + } + } + + menu->Window()->UnlockLooper(); + } +} + + +void +TLiveMixin::UpdateWindowMenu(BMenu* menu) +{ + if (menu == NULL) + return; + + // update using the window version of TShortcuts class + + if (menu->Window()->LockLooper()) { + int32 itemCount = menu->CountItems(); + for (int32 index = 0; index < itemCount; index++) { + BMenuItem* item = menu->ItemAt(index); + if (item == NULL || item->Message() == NULL) + continue; + + switch (item->Message()->what) { + // Clean up/Clean up all + case kCleanup: + case kCleanupAll: + fWindow->Shortcuts()->UpdateCleanupItem(item); + break; + + // Open parent + case kOpenParentDir: + fWindow->Shortcuts()->UpdateOpenParentItem(item); + break; + + // Close/Close all + case B_QUIT_REQUESTED: + case kCloseAllWindows: + fWindow->Shortcuts()->UpdateCloseItem(item); + break; + } + } + + menu->Window()->UnlockLooper(); + } +} + + +// #pragma mark - TLiveMenu + + +TLiveMenu::TLiveMenu(const char* label) + : + BMenu(label) +{ +} + + +TLiveMenu::~TLiveMenu() +{ +} + + +void +TLiveMenu::MessageReceived(BMessage* message) +{ + if (message != NULL && message->what == B_MODIFIERS_CHANGED) + Update(); + else + BMenu::MessageReceived(message); +} + + +void +TLiveMenu::Update() +{ + // hook method +} + + +// #pragma mark - TLivePopUpMenu + + +TLivePopUpMenu::TLivePopUpMenu(const char* label, bool radioMode, bool labelFromMarked, + menu_layout layout) + : + BPopUpMenu(label, radioMode, labelFromMarked, layout) +{ +} + + +TLivePopUpMenu::~TLivePopUpMenu() +{ +} + + +void +TLivePopUpMenu::MessageReceived(BMessage* message) +{ + if (message != NULL && message->what == B_MODIFIERS_CHANGED) + Update(); + else + BMenu::MessageReceived(message); +} + + +void +TLivePopUpMenu::Update() +{ + // hook method +} + + +// #pragma mark - TLiveArrangeByMenu + + +TLiveArrangeByMenu::TLiveArrangeByMenu(const char* label, const BContainerWindow* window) + : + TLiveMenu(label), + TLiveMixin(window) +{ +} + + +TLiveArrangeByMenu::~TLiveArrangeByMenu() +{ +} + + +void +TLiveArrangeByMenu::Update() +{ + // Clean up/Clean up all + TShortcuts().UpdateCleanupItem(TShortcuts().FindItem(this, kCleanup, kCleanupAll)); +} + + +// #pragma mark - TLiveFileMenu + + +TLiveFileMenu::TLiveFileMenu(const char* label, const BContainerWindow* window) + : + TLiveMenu(label), + TLiveMixin(window) +{ +} + + +TLiveFileMenu::~TLiveFileMenu() +{ +} + + +void +TLiveFileMenu::Update() +{ + UpdateFileMenu(this); +} + + +// #pragma mark - TLivePosePopUpMenu + + +TLivePosePopUpMenu::TLivePosePopUpMenu(const char* label, const BContainerWindow* window, + bool radioMode, bool labelFromMarked, menu_layout layout) + : + TLivePopUpMenu(label, radioMode, labelFromMarked, layout), + TLiveMixin(window) +{ +} + + +TLivePosePopUpMenu::~TLivePosePopUpMenu() +{ +} + + +void +TLivePosePopUpMenu::Update() +{ + UpdateFileMenu(this); +} + + +// #pragma mark - TLiveWindowMenu + + +TLiveWindowMenu::TLiveWindowMenu(const char* label, const BContainerWindow* window) + : + TLiveMenu(label), + TLiveMixin(window) +{ +} + + +TLiveWindowMenu::~TLiveWindowMenu() +{ +} + + +void +TLiveWindowMenu::Update() +{ + UpdateWindowMenu(this); +} + + +// #pragma mark - TLiveWindowPopUpMenu + + +TLiveWindowPopUpMenu::TLiveWindowPopUpMenu(const char* label, const BContainerWindow* window, + bool radioMode, bool labelFromMarked, menu_layout layout) + : + TLivePopUpMenu(label, radioMode, labelFromMarked, layout), + TLiveMixin(window) +{ +} + + +TLiveWindowPopUpMenu::~TLiveWindowPopUpMenu() +{ +} + + +void +TLiveWindowPopUpMenu::Update() +{ + UpdateWindowMenu(this); +} diff --git a/src/kits/tracker/LiveMenu.h b/src/kits/tracker/LiveMenu.h new file mode 100644 index 0000000000..52364c1c0a --- /dev/null +++ b/src/kits/tracker/LiveMenu.h @@ -0,0 +1,121 @@ +/* + * Copyright 2020-2024 Haiku, Inc. All rights reserved. + * Distributed under the terms of the MIT License. + * + * Authors: + * John Scipione, jscipione@gmail.com + */ +#ifndef _LIVE_MENU_H +#define _LIVE_MENU_H + + +#include +#include + +#include "ContainerWindow.h" +#include "Shortcuts.h" + + +namespace BPrivate { + + +// mixin class for sharing virtual methods +struct TLiveMixin { + TLiveMixin(const BContainerWindow* window); + + virtual void UpdateFileMenu(BMenu* menu); + virtual void UpdateWindowMenu(BMenu* menu); + +private: + const BContainerWindow* fWindow; +}; + + +class TLiveMenu : public BMenu { +public: + TLiveMenu(const char* label); + virtual ~TLiveMenu(); + + virtual void MessageReceived(BMessage* message); + +protected: + virtual void Update(); +}; + + +class TLivePopUpMenu : public BPopUpMenu { +public: + TLivePopUpMenu(const char* label, + bool radioMode = true, + bool labelFromMarked = true, + menu_layout layout = B_ITEMS_IN_COLUMN); + virtual ~TLivePopUpMenu(); + + virtual void MessageReceived(BMessage* message); + +protected: + virtual void Update(); + +private: + const BContainerWindow* fWindow; +}; + + +class TLiveArrangeByMenu: public TLiveMenu, public TLiveMixin { +public: + TLiveArrangeByMenu(const char* label, const BContainerWindow* window); + virtual ~TLiveArrangeByMenu(); + +protected: + virtual void Update(); +}; + + +class TLiveFileMenu : public TLiveMenu, public TLiveMixin { +public: + TLiveFileMenu(const char* label, const BContainerWindow* window); + virtual ~TLiveFileMenu(); + +protected: + virtual void Update(); +}; + +class TLivePosePopUpMenu : public TLivePopUpMenu, public TLiveMixin { +public: + TLivePosePopUpMenu(const char* label, const BContainerWindow* window, + bool radioMode = true, bool labelFromMarked = true, + menu_layout layout = B_ITEMS_IN_COLUMN); + virtual ~TLivePosePopUpMenu(); + +protected: + virtual void Update(); +}; + + +class TLiveWindowMenu : public TLiveMenu, public TLiveMixin { +public: + TLiveWindowMenu(const char* label, const BContainerWindow* window); + virtual ~TLiveWindowMenu(); + +protected: + virtual void Update(); +}; + +class TLiveWindowPopUpMenu : public TLivePopUpMenu, public TLiveMixin { +public: + TLiveWindowPopUpMenu(const char* label, const BContainerWindow* window, + bool radioMode = true, bool labelFromMarked = true, + menu_layout layout = B_ITEMS_IN_COLUMN); + virtual ~TLiveWindowPopUpMenu(); + +protected: + virtual void Update(); +}; + + +} // namespace BPrivate + +using namespace BPrivate; + + +#endif // _LIVE_MENU_H