mirror of
https://github.com/aseprite/aseprite.git
synced 2025-03-29 19:20:09 +00:00
Add ShowMenu command so the user can customize Alt+top level menu mnemonic shortcuts (#3239)
This commit is contained in:
parent
3645afd9a2
commit
b4d3692927
26
data/gui.xml
26
data/gui.xml
@ -1,6 +1,6 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<!-- Aseprite -->
|
||||
<!-- Copyright (C) 2018-2021 Igara Studio S.A. -->
|
||||
<!-- Copyright (C) 2018-2022 Igara Studio S.A. -->
|
||||
<!-- Copyright (C) 2001-2018 David Capello -->
|
||||
<gui>
|
||||
<!-- Keyboard shortcuts -->
|
||||
@ -8,6 +8,16 @@
|
||||
|
||||
<!-- Keyboard shortcuts for commands (menu options) -->
|
||||
<commands>
|
||||
<!-- Top-level menu access -->
|
||||
<key command="ShowMenu" shortcut="Alt+F"><param name="menu" value="file_menu" /></key>
|
||||
<key command="ShowMenu" shortcut="Alt+E"><param name="menu" value="edit_menu" /></key>
|
||||
<key command="ShowMenu" shortcut="Alt+S"><param name="menu" value="sprite_menu" /></key>
|
||||
<key command="ShowMenu" shortcut="Alt+L"><param name="menu" value="layer_menu" /></key>
|
||||
<key command="ShowMenu" shortcut="Alt+R"><param name="menu" value="frame_menu" /></key>
|
||||
<key command="ShowMenu" shortcut="Alt+T"><param name="menu" value="select_menu" /></key>
|
||||
<key command="ShowMenu" shortcut="Alt+V"><param name="menu" value="view_menu" /></key>
|
||||
<key command="ShowMenu" shortcut="Alt+H"><param name="menu" value="help_menu" /></key>
|
||||
|
||||
<!-- File -->
|
||||
<key command="NewFile" shortcut="Ctrl+N" mac="Cmd+N" />
|
||||
<key command="OpenFile" shortcut="Ctrl+O" mac="Cmd+O" />
|
||||
@ -614,7 +624,7 @@
|
||||
<menus>
|
||||
<!-- main bar menu -->
|
||||
<menu id="main_menu">
|
||||
<menu text="@.file">
|
||||
<menu text="@.file" id="file_menu">
|
||||
<item command="NewFile" text="@.file_new" group="file_new" />
|
||||
<item command="OpenFile" text="@.file_open" group="file_open" />
|
||||
<menu text="@.file_open_recent" group="file_recent">
|
||||
@ -643,7 +653,7 @@
|
||||
<separator group="file_app" />
|
||||
<item command="Exit" text="@.file_exit" />
|
||||
</menu>
|
||||
<menu text="@.edit">
|
||||
<menu text="@.edit" id="edit_menu">
|
||||
<item command="Undo" text="@.edit_undo" />
|
||||
<item command="Redo" text="@.edit_redo" />
|
||||
<item command="UndoHistory" text="@.edit_undo_history" group="edit_undo" />
|
||||
@ -743,7 +753,7 @@
|
||||
<item command="KeyboardShortcuts" text="@.edit_keyboard_shortcuts" />
|
||||
<item command="Options" text="@.edit_preferences" />
|
||||
</menu>
|
||||
<menu text="@.sprite">
|
||||
<menu text="@.sprite" id="sprite_menu">
|
||||
<item command="SpriteProperties" text="@.sprite_properties" group="sprite_properties" />
|
||||
<menu text="@.sprite_color_mode" group="sprite_color">
|
||||
<item command="ChangePixelFormat" text="@.sprite_color_mode_rgb">
|
||||
@ -790,7 +800,7 @@
|
||||
<item command="CropSprite" text="@.sprite_crop" />
|
||||
<item command="AutocropSprite" text="@.sprite_trim" group="sprite_crop" />
|
||||
</menu>
|
||||
<menu text="@.layer">
|
||||
<menu text="@.layer" id="layer_menu">
|
||||
<item command="LayerProperties" text="@.layer_properties" />
|
||||
<item command="LayerVisibility" text="@.layer_visible" />
|
||||
<item command="LayerLock" text="@.layer_lock_layers" />
|
||||
@ -825,7 +835,7 @@
|
||||
<param name="visibleOnly" value="true" />
|
||||
</item>
|
||||
</menu>
|
||||
<menu text="@.frame">
|
||||
<menu text="@.frame" id="frame_menu">
|
||||
<item command="FrameProperties" text="@.frame_properties">
|
||||
<param name="frame" value="current" />
|
||||
</item>
|
||||
@ -867,7 +877,7 @@
|
||||
</item>
|
||||
<item command="ReverseFrames" text="@.frame_reverse_frames" group="cel_frames" />
|
||||
</menu>
|
||||
<menu text="@.select">
|
||||
<menu text="@.select" id="select_menu">
|
||||
<item command="MaskAll" text="@.select_all" />
|
||||
<item command="DeselectMask" text="@.select_deselect" />
|
||||
<item command="ReselectMask" text="@.select_reselect" />
|
||||
@ -889,7 +899,7 @@
|
||||
<item command="LoadMask" text="@.select_load_from_file" />
|
||||
<item command="SaveMask" text="@.select_save_to_file" group="select_files" />
|
||||
</menu>
|
||||
<menu text="@.view">
|
||||
<menu text="@.view" id="view_menu">
|
||||
<item command="DuplicateView" text="@.view_duplicate_view" group="view_new" />
|
||||
<separator />
|
||||
<item command="ShowExtras" text="@.view_show_extras" />
|
||||
|
@ -1,5 +1,5 @@
|
||||
# Aseprite
|
||||
# Copyright (C) 2018-2021 Igara Studio S.A.
|
||||
# Copyright (C) 2018-2022 Igara Studio S.A.
|
||||
# Copyright (C) 2016-2018 David Capello
|
||||
|
||||
[advanced_mode]
|
||||
@ -433,6 +433,7 @@ ShowDynamics = Show Dynamics
|
||||
ShowExtras = Show Extras
|
||||
ShowGrid = Show Grid
|
||||
ShowLayerEdges = Show Layer Edges
|
||||
ShowMenu = Show Menu: {0}
|
||||
ShowOnionSkin = Show Onion Skin
|
||||
ShowPaletteOptions = Show Palette Options
|
||||
ShowPalettePresets = Show Palette Presets
|
||||
|
@ -304,6 +304,7 @@ if(ENABLE_UI)
|
||||
commands/filters/filter_target_buttons.cpp
|
||||
commands/filters/filter_window.cpp
|
||||
commands/screenshot.cpp
|
||||
commands/show_menu.cpp
|
||||
file_selector.cpp
|
||||
modules/editors.cpp
|
||||
modules/gfx.cpp
|
||||
|
@ -1,5 +1,5 @@
|
||||
// Aseprite
|
||||
// Copyright (C) 2018-2021 Igara Studio S.A.
|
||||
// Copyright (C) 2018-2022 Igara Studio S.A.
|
||||
// Copyright (C) 2001-2018 David Capello
|
||||
//
|
||||
// This program is distributed under the terms of
|
||||
@ -145,6 +145,7 @@ FOR_EACH_COMMAND(ShowBrushPreview)
|
||||
FOR_EACH_COMMAND(ShowExtras)
|
||||
FOR_EACH_COMMAND(ShowGrid)
|
||||
FOR_EACH_COMMAND(ShowLayerEdges)
|
||||
FOR_EACH_COMMAND(ShowMenu)
|
||||
FOR_EACH_COMMAND(ShowOnionSkin)
|
||||
FOR_EACH_COMMAND(ShowPixelGrid)
|
||||
FOR_EACH_COMMAND(ShowSelectionEdges)
|
||||
|
83
src/app/commands/show_menu.cpp
Normal file
83
src/app/commands/show_menu.cpp
Normal file
@ -0,0 +1,83 @@
|
||||
// Aseprite
|
||||
// Copyright (C) 2022 Igara Studio S.A.
|
||||
//
|
||||
// This program is distributed under the terms of
|
||||
// the End-User License Agreement for Aseprite.
|
||||
|
||||
#ifdef HAVE_CONFIG_H
|
||||
#include "config.h"
|
||||
#endif
|
||||
|
||||
#include "app/app_menus.h"
|
||||
#include "app/commands/command.h"
|
||||
#include "app/commands/new_params.h"
|
||||
#include "app/context.h"
|
||||
#include "app/i18n/strings.h"
|
||||
#include "fmt/format.h"
|
||||
|
||||
namespace app {
|
||||
|
||||
struct ShowMenuParams : public NewParams {
|
||||
Param<std::string> menu { this, "", "menu" };
|
||||
};
|
||||
|
||||
class ShowMenuCommand : public CommandWithNewParams<ShowMenuParams> {
|
||||
public:
|
||||
ShowMenuCommand();
|
||||
|
||||
protected:
|
||||
bool onNeedsParams() const override { return true; }
|
||||
void onExecute(Context* ctx) override;
|
||||
std::string onGetFriendlyName() const override;
|
||||
|
||||
MenuItem* findMenuItem() const;
|
||||
void openSubmenuById(Menu* menu, const std::string& id);
|
||||
};
|
||||
|
||||
ShowMenuCommand::ShowMenuCommand()
|
||||
: CommandWithNewParams<ShowMenuParams>(CommandId::ShowMenu(), CmdUIOnlyFlag)
|
||||
{
|
||||
}
|
||||
|
||||
void ShowMenuCommand::onExecute(Context* ctx)
|
||||
{
|
||||
if (!ctx->isUIAvailable())
|
||||
return;
|
||||
|
||||
if (MenuItem* menuitem = findMenuItem())
|
||||
menuitem->openSubmenu();
|
||||
}
|
||||
|
||||
std::string ShowMenuCommand::onGetFriendlyName() const
|
||||
{
|
||||
std::string name;
|
||||
if (MenuItem* menuitem = findMenuItem())
|
||||
name = menuitem->text();
|
||||
else
|
||||
name = params().menu();
|
||||
return fmt::format(Strings::commands_ShowMenu(), name);
|
||||
}
|
||||
|
||||
MenuItem* ShowMenuCommand::findMenuItem() const
|
||||
{
|
||||
std::string id = params().menu();
|
||||
if (id.empty())
|
||||
return nullptr;
|
||||
|
||||
if (AppMenus* menus = AppMenus::instance()) {
|
||||
if (Menu* root = menus->getRootMenu()) {
|
||||
if (auto menuitem = root->findItemById(id.c_str())) {
|
||||
if (menuitem->type() == ui::kMenuItemWidget)
|
||||
return static_cast<MenuItem*>(menuitem);
|
||||
}
|
||||
}
|
||||
}
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
Command* CommandFactory::createShowMenuCommand()
|
||||
{
|
||||
return new ShowMenuCommand;
|
||||
}
|
||||
|
||||
} // namespace app
|
@ -1,5 +1,5 @@
|
||||
// Aseprite
|
||||
// Copyright (C) 2020 Igara Studio S.A
|
||||
// Copyright (C) 2020-2022 Igara Studio S.A
|
||||
// Copyright (C) 2001-2015 David Capello
|
||||
//
|
||||
// This program is distributed under the terms of
|
||||
@ -18,6 +18,9 @@
|
||||
namespace app {
|
||||
|
||||
MainMenuBar::MainMenuBar()
|
||||
// We process Alt+mnemonics with ShowMenu commands (instead of the
|
||||
// integrated method in ui::MenuBox::onProcessMessage()).
|
||||
: MenuBar(MenuBar::ProcessTopLevelShortcuts::kNo)
|
||||
{
|
||||
Extensions& extensions = App::instance()->extensions();
|
||||
|
||||
|
@ -546,12 +546,10 @@ void MainWindow::configureWorkspaceLayout()
|
||||
|
||||
if (os::instance()->menus() == nullptr ||
|
||||
pref.general.showMenuBar()) {
|
||||
if (!m_menuBar->parent())
|
||||
menuBarPlaceholder()->insertChild(0, m_menuBar);
|
||||
m_menuBar->resetMaxSize();
|
||||
}
|
||||
else {
|
||||
if (m_menuBar->parent())
|
||||
menuBarPlaceholder()->removeChild(m_menuBar);
|
||||
m_menuBar->setMaxSize(gfx::Size(0, 0));
|
||||
}
|
||||
|
||||
m_menuBar->setVisible(normal);
|
||||
|
@ -193,8 +193,9 @@ MenuBox::~MenuBox()
|
||||
|
||||
bool MenuBar::m_expandOnMouseover = false;
|
||||
|
||||
MenuBar::MenuBar()
|
||||
MenuBar::MenuBar(ProcessTopLevelShortcuts processShortcuts)
|
||||
: MenuBox(kMenuBarWidget)
|
||||
, m_processTopLevelShortcuts(processShortcuts == ProcessTopLevelShortcuts::kYes)
|
||||
{
|
||||
createBase();
|
||||
}
|
||||
@ -273,6 +274,12 @@ void MenuItem::setSubmenu(Menu* menu)
|
||||
}
|
||||
}
|
||||
|
||||
void MenuItem::openSubmenu()
|
||||
{
|
||||
if (auto menu = static_cast<Menu*>(parent()))
|
||||
menu->highlightItem(this, true, true, true);
|
||||
}
|
||||
|
||||
bool MenuItem::isHighlighted() const
|
||||
{
|
||||
return m_highlighted;
|
||||
@ -574,7 +581,8 @@ bool MenuBox::onProcessMessage(Message* msg)
|
||||
// Check for ALT+some underlined letter
|
||||
if (((this->type() == kMenuBoxWidget) && (msg->modifiers() == kKeyNoneModifier || // <-- Inside menu-boxes we can use letters without Alt modifier pressed
|
||||
msg->modifiers() == kKeyAltModifier)) ||
|
||||
((this->type() == kMenuBarWidget) && (msg->modifiers() == kKeyAltModifier))) {
|
||||
((this->type() == kMenuBarWidget) && (msg->modifiers() == kKeyAltModifier) &&
|
||||
static_cast<MenuBar*>(this)->processTopLevelShortcuts())) {
|
||||
auto keymsg = static_cast<KeyMessage*>(msg);
|
||||
selected = check_for_letter(menu, keymsg);
|
||||
if (selected) {
|
||||
|
@ -93,12 +93,22 @@ namespace ui {
|
||||
|
||||
class MenuBar : public MenuBox {
|
||||
public:
|
||||
MenuBar();
|
||||
enum class ProcessTopLevelShortcuts { kNo, kYes };
|
||||
|
||||
MenuBar(ProcessTopLevelShortcuts processShortcuts);
|
||||
|
||||
bool processTopLevelShortcuts() const {
|
||||
return m_processTopLevelShortcuts;
|
||||
}
|
||||
|
||||
static bool expandOnMouseover();
|
||||
static void setExpandOnMouseover(bool state);
|
||||
|
||||
private:
|
||||
// True if we should open top-level menus with Alt+mnemonic (this
|
||||
// flag is not used by Aseprite), top-level menus are opened with
|
||||
// the ShowMenu command now.
|
||||
bool m_processTopLevelShortcuts;
|
||||
static bool m_expandOnMouseover;
|
||||
};
|
||||
|
||||
@ -110,6 +120,10 @@ namespace ui {
|
||||
Menu* getSubmenu();
|
||||
void setSubmenu(Menu* submenu);
|
||||
|
||||
// Open the submenu of this menu item (the menu item should be
|
||||
// positioned in a correct position on the screen).
|
||||
void openSubmenu();
|
||||
|
||||
bool isHighlighted() const;
|
||||
void setHighlighted(bool state);
|
||||
|
||||
|
Loading…
x
Reference in New Issue
Block a user