/***************************************************************************************** * * * OpenSpace * * * * Copyright (c) 2014-2022 * * * * Permission is hereby granted, free of charge, to any person obtaining a copy of this * * software and associated documentation files (the "Software"), to deal in the Software * * without restriction, including without limitation the rights to use, copy, modify, * * merge, publish, distribute, sublicense, and/or sell copies of the Software, and to * * permit persons to whom the Software is furnished to do so, subject to the following * * conditions: * * * * The above copyright notice and this permission notice shall be included in all copies * * or substantial portions of the Software. * * * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, * * INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A * * PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT * * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF * * CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE * * OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. * ****************************************************************************************/ #include #include #include #include #include #include #include #include #include #include #include "keybindingmanager_lua.inl" namespace openspace::interaction { KeybindingManager::KeybindingManager() : DocumentationGenerator( "Keybindings", "keybinding", { { "keybindingTemplate", "${WEB}/documentation/keybinding.hbs" } } ) {} void KeybindingManager::keyboardCallback(Key key, KeyModifier modifier, KeyAction action) { if (action == KeyAction::Press || action == KeyAction::Repeat) { // iterate over key bindings auto ret = _keyLua.equal_range({ key, modifier }); for (auto it = ret.first; it != ret.second; ++it) { ghoul_assert(!it->second.empty(), "Action must not be empty"); ghoul_assert( global::actionManager->hasAction(it->second), "Action must be registered" ); global::actionManager->triggerAction(it->second, ghoul::Dictionary()); } } } void KeybindingManager::resetKeyBindings() { _keyLua.clear(); } void KeybindingManager::bindKey(Key key, KeyModifier modifier, std::string action) { #ifdef WIN32 const bool isShift = hasKeyModifier(modifier, KeyModifier::Shift); if (isShift && isKeypadKey(key)) { LWARNINGC( "bindKey", "Windows does not support binding keys to Shift + Keypad as it will " "internally convert these into Home, End, etc, keys" ); } #endif // WIN32 ghoul_assert(!action.empty(), "Action must not be empty"); KeyWithModifier km = { key, modifier }; _keyLua.insert({ km, std::move(action) }); } void KeybindingManager::removeKeyBinding(const KeyWithModifier& key) { // Erase-remove idiom does not work for std::multimap so we have to do this on foot for (auto it = _keyLua.begin(); it != _keyLua.end();) { // If the current iterator is the key that we are looking for, delete it // (std::multimap::erase will return the iterator to the next element for us) if (it->first == key) { it = _keyLua.erase(it); } else { // If it is not, we continue iteration ++it; } } } std::vector> KeybindingManager::keyBinding( const KeyWithModifier& key) const { std::vector> result; auto itRange = _keyLua.equal_range(key); for (auto it = itRange.first; it != itRange.second; ++it) { result.emplace_back(it->first, it->second); } return result; } const std::multimap& KeybindingManager::keyBindings() const { return _keyLua; } std::string KeybindingManager::generateJson() const { ZoneScoped std::stringstream json; json << "["; bool first = true; for (const std::pair& p : _keyLua) { if (!first) { json << ","; } first = false; json << "{"; json << R"("key": ")" << ghoul::to_string(p.first) << "\","; json << R"("action": ")" << p.second << "\""; json << "}"; } json << "]"; return json.str(); } scripting::LuaLibrary KeybindingManager::luaLibrary() { return { "", { codegen::lua::BindKey, codegen::lua::KeyBindings, codegen::lua::ClearKey, codegen::lua::ClearKeys } }; } } // namespace openspace::interaction