Add ability to use mnemonic without modifiers in alerts

Requested in https://community.aseprite.org/t/16845
This commit is contained in:
David Capello 2023-03-23 16:15:51 -03:00
parent 53c851c547
commit 11abe10c20
4 changed files with 42 additions and 12 deletions

View File

@ -111,7 +111,12 @@ void Alert::addSeparator()
void Alert::addButton(const std::string& text)
{
auto button = new Button(text);
button->processMnemonicFromText();
// Process the mnemonic next to & character and "false" means that
// the mnemonic letter can be used without Alt or Command key
// modifiers.
button->processMnemonicFromText('&', false);
button->setMinSize(gfx::Size(60*guiscale(), 0));
m_buttons.push_back(button);

View File

@ -80,8 +80,11 @@ bool ButtonBase::onProcessMessage(Message* msg)
KeyScancode scancode = keymsg->scancode();
if (isEnabled() && isVisible()) {
bool mnemonicPressed =
((msg->altPressed() || msg->cmdPressed()) &&
const bool mnemonicPressed =
(mnemonic() &&
(!mnemonicRequiresModifiers() ||
msg->altPressed() ||
msg->cmdPressed()) &&
isMnemonicPressed(keymsg));
// For kButtonWidget

View File

@ -1503,12 +1503,18 @@ gfx::Point Widget::mousePosInDisplay() const
return display()->nativeWindow()->pointFromScreen(get_mouse_position());
}
void Widget::setMnemonic(int mnemonic)
void Widget::setMnemonic(const int mnemonic,
const bool requireModifiers)
{
m_mnemonic = mnemonic;
static_assert((kMnemonicCharMask & kMnemonicModifiersMask) == 0);
ASSERT((mnemonic & kMnemonicModifiersMask) == 0);
m_mnemonic =
(mnemonic & kMnemonicCharMask) |
(requireModifiers ? kMnemonicModifiersMask: 0);
}
void Widget::processMnemonicFromText(int escapeChar)
void Widget::processMnemonicFromText(const int escapeChar,
const bool requireModifiers)
{
// Avoid calling setText() when the widget doesn't have the HAS_TEXT flag
if (!hasText())
@ -1526,7 +1532,7 @@ void Widget::processMnemonicFromText(int escapeChar)
break; // Ill-formed string (it ends with escape character)
}
else if (chr != escapeChar) {
setMnemonic(chr);
setMnemonic(chr, requireModifiers);
}
}
newText.push_back(chr);

View File

@ -372,14 +372,23 @@ namespace ui {
// Returns lower-case letter that represet the mnemonic of the widget
// (the underscored character, i.e. the letter after & symbol).
int mnemonic() const { return m_mnemonic; }
void setMnemonic(int mnemonic);
int mnemonic() const {
return (m_mnemonic & kMnemonicCharMask);
}
bool mnemonicRequiresModifiers() const {
return (m_mnemonic & kMnemonicModifiersMask ? true: false);
}
void setMnemonic(const int mnemonic,
const bool requireModifiers);
// Assigns mnemonic from the character preceded by the given
// escapeChar ('&' by default).
void processMnemonicFromText(int escapeChar = '&');
void processMnemonicFromText(const int escapeChar = '&',
const bool requireModifiers = true);
// Returns true if the mnemonic character is pressed.
// Returns true if the mnemonic character is pressed (without modifiers).
// TODO maybe we can add check for modifiers now that this
// information is included in the Widget
bool isMnemonicPressed(const ui::KeyMessage* keyMsg) const;
// Signals
@ -437,7 +446,14 @@ namespace ui {
Widget* m_parent; // Who is the parent?
int m_parentIndex; // Location/index of this widget in the parent's Widget::m_children vector
gfx::Size* m_sizeHint;
int m_mnemonic; // Keyboard shortcut to access this widget like Alt+mnemonic
// Keyboard shortcut to access this widget like Alt+mnemonic. If
// kMnemonicModifiersMask bit is zero, it means that the mnemonic
// can be used without Alt or Command key modifiers (useful for
// buttons in ui::Alert).
static constexpr int kMnemonicCharMask = 0x7f;
static constexpr int kMnemonicModifiersMask = 0x80;
int m_mnemonic;
// Widget size limits
gfx::Size m_minSize, m_maxSize;