Skip to content

Commit

Permalink
Extracted part of ActionsShortcutsManager as a pure interface in nc::…
Browse files Browse the repository at this point in the history
…utility, DI'ed it into Viewer.
  • Loading branch information
mikekazakov committed Dec 28, 2024
1 parent cbcadc1 commit 097022d
Show file tree
Hide file tree
Showing 20 changed files with 213 additions and 124 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -20,14 +20,9 @@ - (NCViewerView *)makeViewerWithFrame:(NSRect)frame

- (NCViewerViewController *)makeViewerController
{
using nc::core::ActionsShortcutsManager;
auto shortcuts = [](std::string_view _name) -> ActionsShortcutsManager::Shortcut {
auto sc = ActionsShortcutsManager::Instance().ShortcutsFromAction(_name).value();
return sc.empty() ? ActionsShortcutsManager::Shortcut{} : sc.front();
};
return [[NCViewerViewController alloc] initWithHistory:self.internalViewerHistory
config:self.globalConfig
shortcutsProvider:shortcuts];
shortcuts:nc::core::ActionsShortcutsManager::Instance()];
}

@end
Original file line number Diff line number Diff line change
Expand Up @@ -301,7 +301,7 @@ - (void)wireMenuDelegates
{
// set up menu delegates. do this via DI to reduce links to AppDelegate in whole codebase
auto item_for_action = [](const char *_action) -> NSMenuItem * {
const std::optional<int> tag = nc::core::ActionsShortcutsManager::TagFromAction(_action);
const std::optional<int> tag = nc::core::ActionsShortcutsManager::Instance().TagFromAction(_action);
if( tag == std::nullopt )
return nil;
return [NSApp.mainMenu itemWithTagHierarchical:*tag];
Expand Down Expand Up @@ -355,7 +355,9 @@ - (void)wireMenuDelegates
- (void)updateMainMenuFeaturesByVersionAndState
{
// disable some features available in menu by configuration limitation
auto tag_from_lit = [](const char *s) { return nc::core::ActionsShortcutsManager::TagFromAction(s).value_or(-1); };
auto tag_from_lit = [](const char *s) {
return nc::core::ActionsShortcutsManager::Instance().TagFromAction(s).value();
};
auto current_menuitem = [&](const char *s) { return [NSApp.mainMenu itemWithTagHierarchical:tag_from_lit(s)]; };
auto hide = [&](const char *s) {
auto item = current_menuitem(s);
Expand Down Expand Up @@ -627,7 +629,7 @@ - (IBAction)OnMenuToggleAdminMode:(id) [[maybe_unused]] _sender
- (BOOL)validateMenuItem:(NSMenuItem *)item
{
static const int admin_mode_tag =
nc::core::ActionsShortcutsManager::TagFromAction("menu.nimble_commander.toggle_admin_mode").value();
nc::core::ActionsShortcutsManager::Instance().TagFromAction("menu.nimble_commander.toggle_admin_mode").value();
const long tag = item.tag;

if( tag == admin_mode_tag ) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@
#include <Base/Observable.h>
#include <Base/UnorderedUtil.h>
#include <Utility/ActionShortcut.h>
#include <Utility/ActionsShortcutsManager.h>
#include <absl/container/inlined_vector.h>
#include <vector>
#include <span>
Expand All @@ -22,59 +23,50 @@ class Config;

namespace nc::core {

class ActionsShortcutsManager : nc::base::ObservableBase
class ActionsShortcutsManager : public nc::utility::ActionsShortcutsManager, private nc::base::ObservableBase
{
public:
// Shortcut represents a key and its modifiers that have to be pressed to trigger an action.
using Shortcut = nc::utility::ActionShortcut;

// An ordered list of shortcuts.
// The relative order of the shortcuts must be preserved as it has semantic meaning for e.g. menus.
// Empty shortcuts should not be stored in such vectors.
// An inlined vector is used to avoid memory allocating for such tiny memory blocks.
using Shortcuts = absl::InlinedVector<Shortcut, 4>;

// ActionTags represents a list of numberic action tags.
// Normally they are tiny, thus an inline vector is used to avoid memory allocation.
using ActionTags = absl::InlinedVector<int, 4>;

// Create a new shortcut manager which will use the provided config to store the overides.
ActionsShortcutsManager(nc::config::Config &_config);

// Destructor.
virtual ~ActionsShortcutsManager();

// A shared instance of a manager, it uses the GlobalConfig() as its data backend.
static ActionsShortcutsManager &Instance();

// Returns a numeric tag that corresponds to the given action name.
static std::optional<int> TagFromAction(std::string_view _action) noexcept;
std::optional<int> TagFromAction(std::string_view _action) const noexcept override;

// Returns an action name of the given numeric tag.
static std::optional<std::string_view> ActionFromTag(int _tag) noexcept;
std::optional<std::string_view> ActionFromTag(int _tag) const noexcept override;

// Returns a shortcut assigned to the specified action.
// Returns std::nullopt such action cannot be found.
// Overrides have priority over the default shortcuts.
std::optional<Shortcuts> ShortcutsFromAction(std::string_view _action) const noexcept;
std::optional<Shortcuts> ShortcutsFromAction(std::string_view _action) const noexcept override;

// Returns a shortcut assigned to the specified numeric action tag.
// Returns std::nullopt such action cannot be found.
// Overrides have priority over the default shortcuts.
std::optional<Shortcuts> ShortcutsFromTag(int _tag) const noexcept;
std::optional<Shortcuts> ShortcutsFromTag(int _tag) const noexcept override;

// Returns a default shortcut for an action specified by its numeric tag.
// Returns std::nullopt such action cannot be found.
std::optional<Shortcuts> DefaultShortcutsFromTag(int _tag) const noexcept;
std::optional<Shortcuts> DefaultShortcutsFromTag(int _tag) const noexcept override;

// Returns an unordered list of numeric tags of actions that have the specified shortcut.
// An optional domain parameter can be specified to filter the output by only leaving actions that have the
// specified domain in their name.
std::optional<ActionTags> ActionTagsFromShortcut(Shortcut _sc, std::string_view _in_domain = {}) const noexcept;
std::optional<ActionTags> ActionTagsFromShortcut(Shortcut _sc,
std::string_view _in_domain = {}) const noexcept override;

// Syntax sugar around ActionTagsFromShortCut(_sc, _in_domain) and find_first_of(_of_tags).
// Returns the first tag from the specified set.
// The order is not defined in case of ambiguities.
std::optional<int> FirstOfActionTagsFromShortcut(std::span<const int> _of_tags,
Shortcut _sc,
std::string_view _in_domain = {}) const noexcept;
std::string_view _in_domain = {}) const noexcept override;

// Removes any hotkeys overrides.
void RevertToDefaults();
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -473,20 +473,22 @@ static constexpr auto make_array_n(T &&value)
BuildShortcutUsageMap();
}

ActionsShortcutsManager::~ActionsShortcutsManager() = default;

ActionsShortcutsManager &ActionsShortcutsManager::Instance()
{
[[clang::no_destroy]] static ActionsShortcutsManager manager(GlobalConfig());
return manager;
}

std::optional<int> ActionsShortcutsManager::TagFromAction(std::string_view _action) noexcept
std::optional<int> ActionsShortcutsManager::TagFromAction(std::string_view _action) const noexcept
{
if( const auto it = g_ActionToTag.find(_action); it != g_ActionToTag.end() )
return it->second;
return std::nullopt;
}

std::optional<std::string_view> ActionsShortcutsManager::ActionFromTag(int _tag) noexcept
std::optional<std::string_view> ActionsShortcutsManager::ActionFromTag(int _tag) const noexcept
{
if( const auto it = g_TagToAction.find(_tag); it != g_TagToAction.end() )
return std::string_view{it->second.data(), it->second.size()};
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -426,7 +426,7 @@ - (IBAction)onHKChanged:(id)sender
return;

const int tag = static_cast<int>(tf.tag);
const std::optional<std::string_view> action = ActionsShortcutsManager::ActionFromTag(tag);
const std::optional<std::string_view> action = ActionsShortcutsManager::Instance().ActionFromTag(tag);
if( !action )
return;

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -51,14 +51,14 @@ - (int)bidForHandlingKeyDown:(NSEvent *)_event
{
using ASM = ActionsShortcutsManager;
struct Tags {
int file_enter = ASM::TagFromAction("menu.file.enter").value();
int file_open = ASM::TagFromAction("menu.file.open").value();
int go_root = ASM::TagFromAction("panel.go_root").value();
int go_home = ASM::TagFromAction("panel.go_home").value();
int show_preview = ASM::TagFromAction("panel.show_preview").value();
int go_into_folder = ASM::TagFromAction("panel.go_into_folder").value();
int go_into_enclosing_folder = ASM::TagFromAction("panel.go_into_enclosing_folder").value();
int show_context_menu = ASM::TagFromAction("panel.show_context_menu").value();
int file_enter = ASM::Instance().TagFromAction("menu.file.enter").value();
int file_open = ASM::Instance().TagFromAction("menu.file.open").value();
int go_root = ASM::Instance().TagFromAction("panel.go_root").value();
int go_home = ASM::Instance().TagFromAction("panel.go_home").value();
int show_preview = ASM::Instance().TagFromAction("panel.show_preview").value();
int go_into_folder = ASM::Instance().TagFromAction("panel.go_into_folder").value();
int go_into_enclosing_folder = ASM::Instance().TagFromAction("panel.go_into_enclosing_folder").value();
int show_context_menu = ASM::Instance().TagFromAction("panel.show_context_menu").value();
} static const tags;

const std::optional<int> event_action_tag = ASM::Instance().FirstOfActionTagsFromShortcut(
Expand All @@ -76,31 +76,31 @@ - (int)bidForHandlingKeyDown:(NSEvent *)_event

if( event_action_tag == tags.go_home ) {
if( _handle ) {
static int tag = ActionsShortcutsManager::TagFromAction("menu.go.home").value();
static int tag = ASM::Instance().TagFromAction("menu.go.home").value();
[[NSApp menu] performActionForItemWithTagHierarchical:tag];
}
return view::BiddingPriority::High;
}

if( event_action_tag == tags.go_root ) {
if( _handle ) {
static int tag = ActionsShortcutsManager::TagFromAction("menu.go.root").value();
static int tag = ASM::Instance().TagFromAction("menu.go.root").value();
[[NSApp menu] performActionForItemWithTagHierarchical:tag];
}
return view::BiddingPriority::High;
}

if( event_action_tag == tags.go_into_folder ) {
if( _handle ) {
static int tag = ActionsShortcutsManager::TagFromAction("menu.go.into_folder").value();
static int tag = ASM::Instance().TagFromAction("menu.go.into_folder").value();
[[NSApp menu] performActionForItemWithTagHierarchical:tag];
}
return view::BiddingPriority::High;
}

if( event_action_tag == tags.go_into_enclosing_folder ) {
if( _handle ) {
static int tag = ActionsShortcutsManager::TagFromAction("menu.go.enclosing_folder").value();
static int tag = ASM::Instance().TagFromAction("menu.go.enclosing_folder").value();
[[NSApp menu] performActionForItemWithTagHierarchical:tag];
}
return view::BiddingPriority::High;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -537,20 +537,20 @@ - (void)keyDown:(NSEvent *)event
[self checkKeyboardModifierFlags:event.modifierFlags];

struct Tags {
int up = ASM::TagFromAction("panel.move_up").value();
int down = ASM::TagFromAction("panel.move_down").value();
int left = ASM::TagFromAction("panel.move_left").value();
int right = ASM::TagFromAction("panel.move_right").value();
int first = ASM::TagFromAction("panel.move_first").value();
int last = ASM::TagFromAction("panel.move_last").value();
int page_down = ASM::TagFromAction("panel.move_next_page").value();
int page_up = ASM::TagFromAction("panel.move_prev_page").value();
int invert_and_move = ASM::TagFromAction("panel.move_next_and_invert_selection").value();
int invert = ASM::TagFromAction("panel.invert_item_selection").value();
int scroll_down = ASM::TagFromAction("panel.scroll_next_page").value();
int scroll_up = ASM::TagFromAction("panel.scroll_prev_page").value();
int scroll_home = ASM::TagFromAction("panel.scroll_first").value();
int scroll_end = ASM::TagFromAction("panel.scroll_last").value();
int up = ASM::Instance().TagFromAction("panel.move_up").value();
int down = ASM::Instance().TagFromAction("panel.move_down").value();
int left = ASM::Instance().TagFromAction("panel.move_left").value();
int right = ASM::Instance().TagFromAction("panel.move_right").value();
int first = ASM::Instance().TagFromAction("panel.move_first").value();
int last = ASM::Instance().TagFromAction("panel.move_last").value();
int page_down = ASM::Instance().TagFromAction("panel.move_next_page").value();
int page_up = ASM::Instance().TagFromAction("panel.move_prev_page").value();
int invert_and_move = ASM::Instance().TagFromAction("panel.move_next_and_invert_selection").value();
int invert = ASM::Instance().TagFromAction("panel.invert_item_selection").value();
int scroll_down = ASM::Instance().TagFromAction("panel.scroll_next_page").value();
int scroll_up = ASM::Instance().TagFromAction("panel.scroll_prev_page").value();
int scroll_home = ASM::Instance().TagFromAction("panel.scroll_first").value();
int scroll_end = ASM::Instance().TagFromAction("panel.scroll_last").value();
} static const tags;

const auto event_data = ActionShortcut::EventData(event);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -65,12 +65,12 @@ - (BOOL)performKeyEquivalent:(NSEvent *)_event
{
using ASM = nc::core::ActionsShortcutsManager;
struct Tags {
int FocusLeft = ASM::TagFromAction("panel.focus_left_panel").value();
int FocusRight = ASM::TagFromAction("panel.focus_right_panel").value();
int MoveUp = ASM::TagFromAction("menu.view.panels_position.move_up").value();
int MoveDown = ASM::TagFromAction("menu.view.panels_position.move_down").value();
int Show = ASM::TagFromAction("menu.view.panels_position.showpanels").value();
int FocusTerminal = ASM::TagFromAction("menu.view.panels_position.focusterminal").value();
int FocusLeft = ASM::Instance().TagFromAction("panel.focus_left_panel").value();
int FocusRight = ASM::Instance().TagFromAction("panel.focus_right_panel").value();
int MoveUp = ASM::Instance().TagFromAction("menu.view.panels_position.move_up").value();
int MoveDown = ASM::Instance().TagFromAction("menu.view.panels_position.move_down").value();
int Show = ASM::Instance().TagFromAction("menu.view.panels_position.showpanels").value();
int FocusTerminal = ASM::Instance().TagFromAction("menu.view.panels_position.focusterminal").value();
} static const tags;

NSString *characters = _event.charactersIgnoringModifiers;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -259,8 +259,8 @@ - (BOOL)performKeyEquivalent:(NSEvent *)_event
{
using ASM = nc::core::ActionsShortcutsManager;
struct Tags {
int move_left = ASM::TagFromAction("menu.view.panels_position.move_left").value();
int move_right = ASM::TagFromAction("menu.view.panels_position.move_right").value();
int move_left = ASM::Instance().TagFromAction("menu.view.panels_position.move_left").value();
int move_right = ASM::Instance().TagFromAction("menu.view.panels_position.move_right").value();
} static const tags;

const std::optional<int> event_action_tag = ASM::Instance().FirstOfActionTagsFromShortcut(
Expand Down Expand Up @@ -434,9 +434,9 @@ - (BOOL)validateUserInterfaceItem:(id<NSValidatedUserInterfaceItem>)_item
{
using nc::core::ActionsShortcutsManager;
static const int move_left_tag =
ActionsShortcutsManager::TagFromAction("menu.view.panels_position.move_left").value_or(-1);
ActionsShortcutsManager::Instance().TagFromAction("menu.view.panels_position.move_left").value();
static const int move_right_tag =
ActionsShortcutsManager::TagFromAction("menu.view.panels_position.move_right").value_or(-1);
ActionsShortcutsManager::Instance().TagFromAction("menu.view.panels_position.move_right").value();

const long item_tag = _item.tag;
if( item_tag == move_left_tag ) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -224,18 +224,18 @@ - (BOOL)performKeyEquivalent:(NSEvent *)_event
{
using ASM = nc::core::ActionsShortcutsManager;
struct Tags {
int prev = ASM::TagFromAction("panel.show_previous_tab").value();
int next = ASM::TagFromAction("panel.show_next_tab").value();
int t1 = ASM::TagFromAction("panel.show_tab_no_1").value();
int t2 = ASM::TagFromAction("panel.show_tab_no_2").value();
int t3 = ASM::TagFromAction("panel.show_tab_no_3").value();
int t4 = ASM::TagFromAction("panel.show_tab_no_4").value();
int t5 = ASM::TagFromAction("panel.show_tab_no_5").value();
int t6 = ASM::TagFromAction("panel.show_tab_no_6").value();
int t7 = ASM::TagFromAction("panel.show_tab_no_7").value();
int t8 = ASM::TagFromAction("panel.show_tab_no_8").value();
int t9 = ASM::TagFromAction("panel.show_tab_no_9").value();
int t10 = ASM::TagFromAction("panel.show_tab_no_10").value();
int prev = ASM::Instance().TagFromAction("panel.show_previous_tab").value();
int next = ASM::Instance().TagFromAction("panel.show_next_tab").value();
int t1 = ASM::Instance().TagFromAction("panel.show_tab_no_1").value();
int t2 = ASM::Instance().TagFromAction("panel.show_tab_no_2").value();
int t3 = ASM::Instance().TagFromAction("panel.show_tab_no_3").value();
int t4 = ASM::Instance().TagFromAction("panel.show_tab_no_4").value();
int t5 = ASM::Instance().TagFromAction("panel.show_tab_no_5").value();
int t6 = ASM::Instance().TagFromAction("panel.show_tab_no_6").value();
int t7 = ASM::Instance().TagFromAction("panel.show_tab_no_7").value();
int t8 = ASM::Instance().TagFromAction("panel.show_tab_no_8").value();
int t9 = ASM::Instance().TagFromAction("panel.show_tab_no_9").value();
int t10 = ASM::Instance().TagFromAction("panel.show_tab_no_10").value();
} static const tags;

const auto resp_view = nc::objc_cast<NSView>(self.window.firstResponder);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -121,7 +121,7 @@ - (IBAction)OnFileInternalBigViewCommand:(id)sender
- (BOOL)validateMenuItem:(NSMenuItem *)item
{
const long tag = item.tag;
static const int close_tag = nc::core::ActionsShortcutsManager::TagFromAction("menu.file.close").value();
static const int close_tag = nc::core::ActionsShortcutsManager::Instance().TagFromAction("menu.file.close").value();
if( tag == close_tag ) {
item.title = NSLocalizedString(@"Close Viewer", "Menu item title for closing internal viewer state");
return true;
Expand Down
4 changes: 2 additions & 2 deletions Source/NimbleCommander/NimbleCommander/States/MainWindow.mm
Original file line number Diff line number Diff line change
Expand Up @@ -96,14 +96,14 @@ - (BOOL)validateMenuItem:(NSMenuItem *)item
{
const long tag = item.tag;

static const int close_tag = nc::core::ActionsShortcutsManager::TagFromAction("menu.file.close").value();
static const int close_tag = nc::core::ActionsShortcutsManager::Instance().TagFromAction("menu.file.close").value();
if( tag == close_tag ) {
item.title = g_CloseWindowTitle;
return true;
}

static const int close_window_tag =
nc::core::ActionsShortcutsManager::TagFromAction("menu.file.close_window").value();
nc::core::ActionsShortcutsManager::Instance().TagFromAction("menu.file.close_window").value();
if( tag == close_window_tag ) {
item.hidden = true;
return true;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -432,7 +432,7 @@ - (BOOL)validateMenuItem:(NSMenuItem *)item
const long tag = item.tag;

static const int show_toolbal_tag =
nc::core::ActionsShortcutsManager::TagFromAction("menu.view.show_toolbar").value();
nc::core::ActionsShortcutsManager::Instance().TagFromAction("menu.view.show_toolbar").value();
if( tag == show_toolbal_tag ) {
item.title = self.toolbarVisible ? g_HideToolbarTitle : g_ShowToolbarTitle;
return self.window.toolbar != nil;
Expand Down
Loading

0 comments on commit 097022d

Please sign in to comment.