This is an automated email from the git hooks/post-receive script. thansen pushed a commit to branch master in repository aseprite.
commit 0b13e53c67dbb9a5ead0f58251ad455e8e988db7 Author: David Capello <[email protected]> Date: Sat Nov 15 18:31:12 2014 -0300 Fix several issues with keyboard shortcuts customization Changes: * Now default action modifiers can be removed (fix #521) * Now action modifiers have a KeyContext (the key context depend on the action itself, cannot be configured by the user) * Fix Accelerator::check() and Accelerator::operator=() when the unicode char and scancode are nil (i.e. we are comparing only modifiers) * Convert Accelerators to a class to simplify code * Remove unused variables in Accelerator::check() when REPORT_KEYS is defined --- src/app/commands/cmd_keyboard_shortcuts.cpp | 17 ++- src/app/ui/keyboard_shortcuts.cpp | 221 +++++++++++++++++++++------- src/app/ui/keyboard_shortcuts.h | 12 +- src/app/ui/select_accelerator.cpp | 12 +- src/app/ui/select_accelerator.h | 4 +- src/ui/accelerator.cpp | 38 ++++- src/ui/accelerator.h | 33 ++++- 7 files changed, 261 insertions(+), 76 deletions(-) diff --git a/src/app/commands/cmd_keyboard_shortcuts.cpp b/src/app/commands/cmd_keyboard_shortcuts.cpp index 25c519b..6651cf4 100644 --- a/src/app/commands/cmd_keyboard_shortcuts.cpp +++ b/src/app/commands/cmd_keyboard_shortcuts.cpp @@ -82,12 +82,13 @@ private: void onChangeAccel(int index) { Accelerator origAccel = m_key->accels()[index]; - SelectAccelerator window(origAccel); + SelectAccelerator window(origAccel, m_key->keycontext()); window.openWindowInForeground(); if (window.isModified()) { m_key->disableAccel(origAccel); - m_key->add(window.accel(), KeySource::UserDefined); + if (!window.accel().isEmpty()) + m_key->add(window.accel(), KeySource::UserDefined); } getRoot()->layout(); @@ -106,7 +107,7 @@ private: void onAddAccel() { ui::Accelerator accel; - SelectAccelerator window(accel); + SelectAccelerator window(accel, m_key->keycontext()); window.openWindowInForeground(); if (window.isModified()) { @@ -359,8 +360,14 @@ private: fillList(this->menus(), AppMenus::instance()->getRootMenu(), 0); for (Key* key : *app::KeyboardShortcuts::instance()) { std::string text = key->triggerString(); - if (key->keycontext() == KeyContext::Selection) - text += " (w/selection)"; + switch (key->keycontext()) { + case KeyContext::Selection: + text = "Selection context: " + text; + break; + case KeyContext::MovingPixels: + text = "Moving pixels context: " + text; + break; + } KeyItem* keyItem = new KeyItem(text, key, NULL, 0); ListBox* listBox = NULL; diff --git a/src/app/ui/keyboard_shortcuts.cpp b/src/app/ui/keyboard_shortcuts.cpp index cb597a5..5d54719 100644 --- a/src/app/ui/keyboard_shortcuts.cpp +++ b/src/app/ui/keyboard_shortcuts.cpp @@ -39,8 +39,6 @@ #include "ui/accelerator.h" #include "ui/message.h" -#include <algorithm> - #define XML_KEYBOARD_FILE_VERSION "1" namespace { @@ -80,6 +78,13 @@ namespace { return shortcut; } + bool bool_attr_is_true(const TiXmlElement* elem, const char* attribute_name) + { + const char* value = elem->Attribute(attribute_name); + + return (value != NULL) && (strcmp(value, "true") == 0); + } + std::string get_user_friendly_string_for_keyaction(app::KeyAction action) { for (int c=0; actions[c].name; ++c) { @@ -118,6 +123,9 @@ namespace app { using namespace ui; +////////////////////////////////////////////////////////////////////// +// Key + Key::Key(Command* command, const Params* params, KeyContext keyContext) : m_type(KeyType::Command) , m_useUsers(false) @@ -141,12 +149,38 @@ Key::Key(KeyAction action) , m_keycontext(KeyContext::Any) , m_action(action) { -} - -void Key::setUserAccels(const Accelerators& accels) -{ - m_useUsers = true; - m_users = accels; + switch (action) { + case KeyAction::None: + m_keycontext = KeyContext::Any; + break; + case KeyAction::CopySelection: + m_keycontext = KeyContext::MovingPixels; + break; + case KeyAction::SnapToGrid: + m_keycontext = KeyContext::MovingPixels; + break; + case KeyAction::AngleSnap: + m_keycontext = KeyContext::MovingPixels; + break; + case KeyAction::MaintainAspectRatio: + m_keycontext = KeyContext::MovingPixels; + break; + case KeyAction::LockAxis: + m_keycontext = KeyContext::MovingPixels; + break; + case KeyAction::AddSelection: + m_keycontext = KeyContext::Selection; + break; + case KeyAction::SubtractSelection: + m_keycontext = KeyContext::Selection; + break; + case KeyAction::LeftMouseButton: + m_keycontext = KeyContext::Any; + break; + case KeyAction::RightMouseButton: + m_keycontext = KeyContext::Any; + break; + } } void Key::add(const ui::Accelerator& accel, KeySource source) @@ -159,11 +193,16 @@ void Key::add(const ui::Accelerator& accel, KeySource source) m_users = m_accels; } accels = &m_users; + } - KeyboardShortcuts::instance()->disableAccel(accel); + // Remove the accelerator from other commands + if (source == KeySource::UserDefined) { + KeyboardShortcuts::instance()->disableAccel(accel, m_keycontext); + m_userRemoved.remove(accel); } - accels->push_back(accel); + // Add the accelerator + accels->add(accel); } bool Key::isPressed(Message* msg) const @@ -194,7 +233,7 @@ bool Key::checkFromAllegroKeyArray() bool Key::hasAccel(const ui::Accelerator& accel) const { - return (std::find(accels().begin(), accels().end(), accel) != accels().end()); + return accels().has(accel); } void Key::disableAccel(const ui::Accelerator& accel) @@ -204,14 +243,16 @@ void Key::disableAccel(const ui::Accelerator& accel) m_users = m_accels; } - Accelerators::iterator it = std::find(m_users.begin(), m_users.end(), accel); - if (it != m_users.end()) - m_users.erase(it); + m_users.remove(accel); + + if (m_accels.has(accel)) + m_userRemoved.add(accel); } void Key::reset() { m_users.clear(); + m_userRemoved.clear(); m_useUsers = false; } @@ -235,6 +276,9 @@ std::string Key::triggerString() const return "Unknown"; } +////////////////////////////////////////////////////////////////////// +// KeyboardShortcuts + KeyboardShortcuts* KeyboardShortcuts::instance() { static KeyboardShortcuts* singleton = NULL; @@ -270,6 +314,7 @@ void KeyboardShortcuts::importFile(TiXmlElement* rootElement, KeySource source) while (xmlKey) { const char* command_name = xmlKey->Attribute("command"); const char* command_key = get_shortcut(xmlKey); + bool removed = bool_attr_is_true(xmlKey, "removed"); if (command_name && command_key) { Command* command = CommandsModule::instance()->getCommandByName(command_name); @@ -303,15 +348,21 @@ void KeyboardShortcuts::importFile(TiXmlElement* rootElement, KeySource source) // add the keyboard shortcut to the command Key* key = this->command(command_name, ¶ms, keycontext); if (key) { - key->add(Accelerator(command_key), source); - - // Add the shortcut to the menuitems with this - // command (this is only visual, the "manager_msg_proc" - // is the only one that process keyboard shortcuts) - if (key->accels().size() == 1) { - AppMenus::instance()->applyShortcutToMenuitemsWithCommand( - command, ¶ms, key); + Accelerator accel(command_key); + + if (!removed) { + key->add(accel, source); + + // Add the shortcut to the menuitems with this + // command (this is only visual, the "manager_msg_proc" + // is the only one that process keyboard shortcuts) + if (key->accels().size() == 1) { + AppMenus::instance()->applyShortcutToMenuitemsWithCommand( + command, ¶ms, key); + } } + else + key->disableAccel(accel); } } } @@ -327,6 +378,7 @@ void KeyboardShortcuts::importFile(TiXmlElement* rootElement, KeySource source) while (xmlKey) { const char* tool_id = xmlKey->Attribute("tool"); const char* tool_key = get_shortcut(xmlKey); + bool removed = bool_attr_is_true(xmlKey, "removed"); if (tool_id && tool_key) { tools::Tool* tool = App::instance()->getToolBox()->getToolById(tool_id); @@ -334,8 +386,14 @@ void KeyboardShortcuts::importFile(TiXmlElement* rootElement, KeySource source) PRINTF(" - Shortcut for tool `%s': <%s>\n", tool_id, tool_key); Key* key = this->tool(tool); - if (key) - key->add(Accelerator(tool_key), source); + if (key) { + Accelerator accel(tool_key); + + if (!removed) + key->add(accel, source); + else + key->disableAccel(accel); + } } } xmlKey = xmlKey->NextSiblingElement(); @@ -349,14 +407,22 @@ void KeyboardShortcuts::importFile(TiXmlElement* rootElement, KeySource source) while (xmlKey) { const char* tool_id = xmlKey->Attribute("tool"); const char* tool_key = get_shortcut(xmlKey); + bool removed = bool_attr_is_true(xmlKey, "removed"); + if (tool_id && tool_key) { tools::Tool* tool = App::instance()->getToolBox()->getToolById(tool_id); if (tool) { PRINTF(" - Shortcut for quicktool `%s': <%s>\n", tool_id, tool_key); Key* key = this->quicktool(tool); - if (key) - key->add(Accelerator(tool_key), source); + if (key) { + Accelerator accel(tool_key); + + if (!removed) + key->add(accel, source); + else + key->disableAccel(accel); + } } } xmlKey = xmlKey->NextSiblingElement(); @@ -370,6 +436,7 @@ void KeyboardShortcuts::importFile(TiXmlElement* rootElement, KeySource source) while (xmlKey) { const char* tool_action = xmlKey->Attribute("action"); const char* tool_key = get_shortcut(xmlKey); + bool removed = bool_attr_is_true(xmlKey, "removed"); if (tool_action && tool_key) { PRINTF(" - Shortcut for sprite editor `%s': <%s>\n", tool_action, tool_key); @@ -378,8 +445,14 @@ void KeyboardShortcuts::importFile(TiXmlElement* rootElement, KeySource source) if (action != KeyAction::None) { Key* key = this->action(action); - if (key) - key->add(Accelerator(tool_key), source); + if (key) { + Accelerator accel(tool_key); + + if (!removed) + key->add(accel, source); + else + key->disableAccel(accel); + } } } xmlKey = xmlKey->NextSiblingElement(); @@ -424,41 +497,77 @@ void KeyboardShortcuts::exportKeys(TiXmlElement& parent, KeyType type) { for (Key* key : m_keys) { // Save only user defined accelerators. - if (key->type() != type || key->userAccels().empty()) + if (key->type() != type) continue; - for (const ui::Accelerator& accel : key->userAccels()) { - TiXmlElement elem("key"); - - switch (key->type()) { - case KeyType::Command: - elem.SetAttribute("command", key->command()->short_name()); - if (key->params()) { - for (const auto& param : *key->params()) { - if (param.second.empty()) - continue; - - TiXmlElement paramElem("param"); - paramElem.SetAttribute("name", param.first.c_str()); - paramElem.SetAttribute("value", param.second.c_str()); - elem.InsertEndChild(paramElem); - } - } + for (const ui::Accelerator& accel : key->userRemovedAccels()) + exportAccel(parent, key, accel, true); + + for (const ui::Accelerator& accel : key->userAccels()) + exportAccel(parent, key, accel, false); + } +} + +void KeyboardShortcuts::exportAccel(TiXmlElement& parent, Key* key, const ui::Accelerator& accel, bool removed) +{ + TiXmlElement elem("key"); + + switch (key->type()) { + + case KeyType::Command: { + const char* keycontextStr = NULL; + + elem.SetAttribute("command", key->command()->short_name()); + + switch (key->keycontext()) { + case KeyContext::Any: + // Without "context" attribute break; - case KeyType::Tool: - case KeyType::Quicktool: - elem.SetAttribute("tool", key->tool()->getId().c_str()); + case KeyContext::Normal: + keycontextStr = "Normal"; break; - case KeyType::Action: - elem.SetAttribute("action", - base::convert_to<std::string>(key->action()).c_str()); + case KeyContext::Selection: + keycontextStr = "Selection"; + break; + case KeyContext::MovingPixels: + keycontextStr = "MovingPixels"; break; } - elem.SetAttribute("shortcut", accel.toString().c_str()); - parent.InsertEndChild(elem); + if (keycontextStr) + elem.SetAttribute("context", keycontextStr); + + if (key->params()) { + for (const auto& param : *key->params()) { + if (param.second.empty()) + continue; + + TiXmlElement paramElem("param"); + paramElem.SetAttribute("name", param.first.c_str()); + paramElem.SetAttribute("value", param.second.c_str()); + elem.InsertEndChild(paramElem); + } + } + break; } + + case KeyType::Tool: + case KeyType::Quicktool: + elem.SetAttribute("tool", key->tool()->getId().c_str()); + break; + + case KeyType::Action: + elem.SetAttribute("action", + base::convert_to<std::string>(key->action()).c_str()); + break; } + + elem.SetAttribute("shortcut", accel.toString().c_str()); + + if (removed) + elem.SetAttribute("removed", "true"); + + parent.InsertEndChild(elem); } void KeyboardShortcuts::reset() @@ -531,10 +640,10 @@ Key* KeyboardShortcuts::action(KeyAction action) return key; } -void KeyboardShortcuts::disableAccel(const ui::Accelerator& accel) +void KeyboardShortcuts::disableAccel(const ui::Accelerator& accel, KeyContext keyContext) { for (Key* key : m_keys) { - if (key->hasAccel(accel)) + if (key->keycontext() == keyContext && key->hasAccel(accel)) key->disableAccel(accel); } } diff --git a/src/app/ui/keyboard_shortcuts.h b/src/app/ui/keyboard_shortcuts.h index 4c70986..65a61aa 100644 --- a/src/app/ui/keyboard_shortcuts.h +++ b/src/app/ui/keyboard_shortcuts.h @@ -44,6 +44,7 @@ namespace app { Any, Normal, Selection, + MovingPixels, }; enum class KeySource { @@ -83,8 +84,7 @@ namespace app { } const ui::Accelerators& origAccels() const { return m_accels; } const ui::Accelerators& userAccels() const { return m_users; } - - void setUserAccels(const ui::Accelerators& accels); + const ui::Accelerators& userRemovedAccels() const { return m_userRemoved; } void add(const ui::Accelerator& accel, KeySource source); bool isPressed(ui::Message* msg) const; @@ -109,8 +109,9 @@ namespace app { private: KeyType m_type; - ui::Accelerators m_accels; - ui::Accelerators m_users; + ui::Accelerators m_accels; // Default accelerators (from gui.xml) + ui::Accelerators m_users; // User-defined accelerators + ui::Accelerators m_userRemoved; // Default accelerators removed by user bool m_useUsers; KeyContext m_keycontext; @@ -149,7 +150,7 @@ namespace app { Key* quicktool(tools::Tool* tool); Key* action(KeyAction action); - void disableAccel(const ui::Accelerator& accel); + void disableAccel(const ui::Accelerator& accel, KeyContext keyContext); KeyContext getCurrentKeyContext(); bool getCommandFromKeyMessage(ui::Message* msg, Command** command, Params** params); @@ -159,6 +160,7 @@ namespace app { KeyboardShortcuts(); void exportKeys(TiXmlElement& parent, KeyType type); + void exportAccel(TiXmlElement& parent, Key* key, const ui::Accelerator& accel, bool removed); Keys m_keys; diff --git a/src/app/ui/select_accelerator.cpp b/src/app/ui/select_accelerator.cpp index e5ee3e9..046136d 100644 --- a/src/app/ui/select_accelerator.cpp +++ b/src/app/ui/select_accelerator.cpp @@ -63,6 +63,12 @@ protected: keymsg->scancode(), keymsg->unicodeChar() > 32 ? std::tolower(keymsg->unicodeChar()): 0); + + // Convert the accelerator to a string, and parse it + // again. Just to obtain the exact accelerator we'll read + // when we import the gui.xml file or an .aseprite-keys file. + m_accel = Accelerator(m_accel.toString()); + updateText(); AccelChange(&m_accel); @@ -84,8 +90,9 @@ protected: Accelerator m_accel; }; -SelectAccelerator::SelectAccelerator(const ui::Accelerator& accel) +SelectAccelerator::SelectAccelerator(const ui::Accelerator& accel, KeyContext keyContext) : m_keyField(new KeyField(accel)) + , m_keyContext(keyContext) , m_accel(accel) , m_modified(false) { @@ -170,7 +177,8 @@ void SelectAccelerator::updateAssignedTo() std::string res = "None"; for (Key* key : *KeyboardShortcuts::instance()) { - if (key->hasAccel(m_accel)) { + if (key->keycontext() == m_keyContext && + key->hasAccel(m_accel)) { res = key->triggerString(); break; } diff --git a/src/app/ui/select_accelerator.h b/src/app/ui/select_accelerator.h index 475d8c2..843fb28 100644 --- a/src/app/ui/select_accelerator.h +++ b/src/app/ui/select_accelerator.h @@ -20,6 +20,7 @@ #define APP_UI_SELECT_ACCELERATOR_H_INCLUDED #pragma once +#include "app/ui/keyboard_shortcuts.h" #include "ui/accelerator.h" #include "generated_select_accelerator.h" @@ -28,7 +29,7 @@ namespace app { class SelectAccelerator : public app::gen::SelectAccelerator { public: - explicit SelectAccelerator(const ui::Accelerator& accelerator); + SelectAccelerator(const ui::Accelerator& accelerator, KeyContext keyContext); bool isModified() const { return m_modified; } const ui::Accelerator& accel() const { return m_accel; } @@ -45,6 +46,7 @@ namespace app { class KeyField; KeyField* m_keyField; + KeyContext m_keyContext; ui::Accelerator m_origAccel; ui::Accelerator m_accel; bool m_modified; diff --git a/src/ui/accelerator.cpp b/src/ui/accelerator.cpp index d5a9885..4afcbc4 100644 --- a/src/ui/accelerator.cpp +++ b/src/ui/accelerator.cpp @@ -19,11 +19,16 @@ #include <string> #include <vector> +#include <algorithm> + // #define REPORT_KEYS #define PREPROCESS_KEYS namespace ui { +////////////////////////////////////////////////////////////////////// +// Accelerator + Accelerator::Accelerator() : m_modifiers(kKeyNoneModifier) , m_scancode(kKeyNil) @@ -197,6 +202,8 @@ bool Accelerator::operator==(const Accelerator& other) const return true; else if (m_unicodeChar != 0) return (std::tolower(m_unicodeChar) == std::tolower(other.m_unicodeChar)); + else // Only comparing modifiers, and they are equal + return true; } return false; @@ -345,11 +352,6 @@ std::string Accelerator::toString() const bool Accelerator::check(KeyModifiers modifiers, KeyScancode scancode, int unicodeChar) const { -#ifdef REPORT_KEYS - char buf[256]; - std::string buf2; -#endif - // Preprocess the character to be compared with the accelerator #ifdef PREPROCESS_KEYS // Directly scancode @@ -411,15 +413,18 @@ bool Accelerator::check(KeyModifiers modifiers, KeyScancode scancode, int unicod if ((m_modifiers == modifiers) && ((m_scancode != kKeyNil && m_scancode == scancode) || - (m_unicodeChar && m_unicodeChar == unicodeChar))) { + (m_unicodeChar && m_unicodeChar == unicodeChar) || + (m_scancode == kKeyNil && scancode == kKeyNil && !m_unicodeChar && !unicodeChar))) { #ifdef REPORT_KEYS printf("true\n"); + fflush(stdout); #endif return true; } #ifdef REPORT_KEYS printf("false\n"); + fflush(stdout); #endif return false; } @@ -439,4 +444,25 @@ bool Accelerator::checkFromAllegroKeyArray() const (m_modifiers == modifiers)); } +////////////////////////////////////////////////////////////////////// +// Accelerators + +bool Accelerators::has(const Accelerator& accel) const +{ + return (std::find(begin(), end(), accel) != end()); +} + +void Accelerators::add(const Accelerator& accel) +{ + if (!has(accel)) + m_list.push_back(accel); +} + +void Accelerators::remove(const Accelerator& accel) +{ + auto it = std::find(begin(), end(), accel); + if (it != end()) + m_list.erase(it); +} + } // namespace ui diff --git a/src/ui/accelerator.h b/src/ui/accelerator.h index 7014374..cecc663 100644 --- a/src/ui/accelerator.h +++ b/src/ui/accelerator.h @@ -43,7 +43,38 @@ namespace ui { int m_unicodeChar; }; - typedef std::vector<Accelerator> Accelerators; + class Accelerators { + public: + typedef std::vector<Accelerator> List; + typedef List::iterator iterator; + typedef List::const_iterator const_iterator; + + iterator begin() { return m_list.begin(); } + iterator end() { return m_list.end(); } + const_iterator begin() const { return m_list.begin(); } + const_iterator end() const { return m_list.end(); } + + bool empty() const { return m_list.empty(); } + size_t size() const { return m_list.size(); } + + const ui::Accelerator& front() const { return m_list.front(); } + + const ui::Accelerator& operator[](int index) const { + return m_list[index]; + } + + ui::Accelerator& operator[](int index) { + return m_list[index]; + } + + void clear() { m_list.clear(); } + bool has(const Accelerator& accel) const; + void add(const Accelerator& accel); + void remove(const Accelerator& accel); + + private: + List m_list; + }; } // namespace ui -- Alioth's /usr/local/bin/git-commit-notice on /srv/git.debian.org/git/pkg-games/aseprite.git _______________________________________________ Pkg-games-commits mailing list [email protected] http://lists.alioth.debian.org/cgi-bin/mailman/listinfo/pkg-games-commits

