1 /*************************************************************************** 2 * Copyright (C) 2008-2021 by Andrzej Rybczak * 3 * andrzej@rybczak.net * 4 * * 5 * This program is free software; you can redistribute it and/or modify * 6 * it under the terms of the GNU General Public License as published by * 7 * the Free Software Foundation; either version 2 of the License, or * 8 * (at your option) any later version. * 9 * * 10 * This program is distributed in the hope that it will be useful, * 11 * but WITHOUT ANY WARRANTY; without even the implied warranty of * 12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * 13 * GNU General Public License for more details. * 14 * * 15 * You should have received a copy of the GNU General Public License * 16 * along with this program; if not, write to the * 17 * Free Software Foundation, Inc., * 18 * 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA. * 19 ***************************************************************************/ 20 21 #ifndef NCMPCPP_BINDINGS_H 22 #define NCMPCPP_BINDINGS_H 23 24 #include <algorithm> 25 #include <cassert> 26 #include <unordered_map> 27 #include "actions.h" 28 #include "macro_utilities.h" 29 30 NC::Key::Type readKey(NC::Window &w); 31 std::wstring keyToWString(const NC::Key::Type key); 32 33 /// Represents either single action or chain of actions bound to a certain key 34 struct Binding 35 { 36 typedef std::vector<std::shared_ptr<Actions::BaseAction>> ActionChain; 37 38 template <typename ArgT> BindingBinding39 Binding(ArgT &&actions_) 40 : m_actions(std::forward<ArgT>(actions_)) { 41 assert(!m_actions.empty()); 42 } BindingBinding43 Binding(Actions::Type at) 44 : Binding(ActionChain({Actions::get_(at)})) { } 45 executeBinding46 bool execute() const { 47 return std::all_of(m_actions.begin(), m_actions.end(), 48 std::bind(&Actions::BaseAction::execute, std::placeholders::_1) 49 ); 50 } 51 isSingleBinding52 bool isSingle() const { 53 return m_actions.size() == 1; 54 } 55 actionBinding56 Actions::BaseAction &action() const { 57 assert(isSingle()); 58 assert(m_actions[0] != nullptr); 59 return *m_actions[0]; 60 } 61 actionsBinding62 const ActionChain &actions() const { 63 return m_actions; 64 } 65 66 private: 67 ActionChain m_actions; 68 }; 69 70 /// Represents executable command 71 struct Command 72 { 73 template <typename ArgT> CommandCommand74 Command(ArgT &&binding_, bool immediate_) 75 : m_impl(std::forward<ArgT>(binding_), immediate_) { } 76 bindingCommand77 const Binding &binding() const { return std::get<0>(m_impl); } immediateCommand78 bool immediate() const { return std::get<1>(m_impl); } 79 80 private: 81 std::tuple<Binding, bool> m_impl; 82 }; 83 84 /// Keybindings configuration 85 class BindingsConfiguration 86 { 87 typedef std::unordered_map<std::string, Command> CommandsSet; 88 typedef std::unordered_map<NC::Key::Type, std::vector<Binding>> BindingsMap; 89 90 public: 91 typedef BindingsMap::value_type::second_type::iterator BindingIterator; 92 typedef BindingsMap::value_type::second_type::const_iterator ConstBindingIterator; 93 typedef std::pair<BindingIterator, BindingIterator> BindingIteratorPair; 94 95 bool read(const std::vector<std::string> &binding_paths); 96 void generateDefaults(); 97 98 const Command *findCommand(const std::string &name); 99 BindingIteratorPair get(const NC::Key::Type &k); 100 begin()101 BindingsMap::const_iterator begin() const { return m_bindings.begin(); } end()102 BindingsMap::const_iterator end() const { return m_bindings.end(); } 103 104 private: notBound(const NC::Key::Type & k)105 bool notBound(const NC::Key::Type &k) const { 106 return k != NC::Key::None && m_bindings.find(k) == m_bindings.end(); 107 } 108 109 template <typename ArgT> bind(NC::Key::Type k,ArgT && t)110 void bind(NC::Key::Type k, ArgT &&t) { 111 m_bindings[k].push_back(std::forward<ArgT>(t)); 112 } 113 114 bool read(const std::string &file); 115 116 BindingsMap m_bindings; 117 CommandsSet m_commands; 118 }; 119 120 extern BindingsConfiguration Bindings; 121 122 #endif // NCMPCPP_BINDINGS_H 123