mirror of
https://review.haiku-os.org/haiku
synced 2025-02-07 06:16:11 +01:00
Tracker: Live updating shiftable menu items
Live updating menu classes listen for B_MODIFIERS_CHANGED messages and update the item label and shortcut on Shift or Control. -- File -- Create link => Create relative link Move to Trash => Delete Cut => Cut more Copy => Copy more Paste => Paste links Identify => Force identify -- Window -- Close => Close all Open parent enable/disable on Control to open root window -- Window => Arrange by/Desktop -- Clean up => Clean up all Create TLiveMenu and TLivePopUpMenu classes that inherit from BMenu and BPopUpMenu respectively. Create TLiveFileMenu, TLivePosePopUpMenu, TLiveWindowMenu and TLiveWindowPopUpMenu subclasses for the File and Window menu and context menus respectively. Create TLiveMixin to share methods between menus. Pass in parent window and use window shortcuts to enable/disable "Open parent". Change-Id: I5dfbd4d468fad02894f1f31aa08d1abf630a4b5d Reviewed-on: https://review.haiku-os.org/c/haiku/+/2293 Reviewed-by: John Scipione <jscipione@gmail.com>
This commit is contained in:
parent
5b1284db40
commit
683100d673
@ -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;
|
||||
|
@ -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);
|
||||
}
|
||||
|
@ -52,6 +52,7 @@ for architectureObject in [ MultiArchSubDirSetup ] {
|
||||
IconCache.cpp
|
||||
IconMenuItem.cpp
|
||||
InfoWindow.cpp
|
||||
LiveMenu.cpp
|
||||
MimeTypeList.cpp
|
||||
MiniMenuField.cpp
|
||||
Model.cpp
|
||||
|
309
src/kits/tracker/LiveMenu.cpp
Normal file
309
src/kits/tracker/LiveMenu.cpp
Normal file
@ -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 <string.h>
|
||||
|
||||
#include <Application.h>
|
||||
#include <Locale.h>
|
||||
#include <MenuItem.h>
|
||||
#include <Window.h>
|
||||
|
||||
#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);
|
||||
}
|
121
src/kits/tracker/LiveMenu.h
Normal file
121
src/kits/tracker/LiveMenu.h
Normal file
@ -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 <Menu.h>
|
||||
#include <PopUpMenu.h>
|
||||
|
||||
#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
|
Loading…
x
Reference in New Issue
Block a user