scrollpad: explicitely include iostream
[ncmpcpp.git] / src / bindings.h
blob0ec753323ad9ab1f8f523169461b020bd178871c
1 /***************************************************************************
2 * Copyright (C) 2008-2014 by Andrzej Rybczak *
3 * electricityispower@gmail.com *
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 ***************************************************************************/
21 #ifndef NCMPCPP_BINDINGS_H
22 #define NCMPCPP_BINDINGS_H
24 #include <algorithm>
25 #include <boost/bind.hpp>
26 #include <cassert>
27 #include <unordered_map>
28 #include "actions.h"
29 #include "macro_utilities.h"
31 /// Key for binding actions to it. Supports non-ascii characters.
32 struct Key
34 enum Type { Standard, NCurses };
36 Key(wchar_t ch, Type ct) : m_char(ch), m_type(ct) { }
38 wchar_t getChar() const {
39 return m_char;
41 Type getType() const {
42 return m_type;
45 # define KEYS_DEFINE_OPERATOR(CMP) \
46 bool operator CMP (const Key &k) const { \
47 if (m_char CMP k.m_char) \
48 return true; \
49 if (m_char != k.m_char) \
50 return false; \
51 return m_type CMP k.m_type; \
53 KEYS_DEFINE_OPERATOR(<);
54 KEYS_DEFINE_OPERATOR(<=);
55 KEYS_DEFINE_OPERATOR(>);
56 KEYS_DEFINE_OPERATOR(>=);
57 # undef KEYS_DEFINE_OPERATOR
59 bool operator==(const Key &k) const {
60 return m_char == k.m_char && m_type == k.m_type;
62 bool operator!=(const Key &k) const {
63 return !(*this == k);
66 static Key read(NC::Window &w);
67 static Key noOp;
69 private:
70 wchar_t m_char;
71 Type m_type;
74 /// Represents either single action or chain of actions bound to a certain key
75 struct Binding
77 typedef std::vector<Actions::BaseAction *> ActionChain;
79 template <typename ArgT>
80 Binding(ArgT &&actions)
81 : m_actions(std::forward<ArgT>(actions)) {
82 assert(!m_actions.empty());
84 Binding(Actions::Type at)
85 : Binding(ActionChain({&Actions::get(at)})) { }
87 bool execute() const {
88 return std::all_of(m_actions.begin(), m_actions.end(),
89 boost::bind(&Actions::BaseAction::execute, _1)
93 bool isSingle() const {
94 return m_actions.size() == 1;
97 Actions::BaseAction *action() const {
98 assert(isSingle());
99 return m_actions[0];
102 private:
103 ActionChain m_actions;
106 /// Represents executable command
107 struct Command
109 template <typename ArgT>
110 Command(ArgT &&binding_, bool immediate_)
111 : m_binding(std::forward<ArgT>(binding_)), m_immediate(immediate_) { }
113 const Binding &binding() const { return m_binding; }
114 bool immediate() const { return m_immediate; }
116 private:
117 Binding m_binding;
118 bool m_immediate;
121 /// Keybindings configuration
122 class BindingsConfiguration
124 struct KeyHash {
125 size_t operator()(const Key &k) const {
126 return (k.getChar() << 1) | (k.getType() == Key::Standard);
129 typedef std::unordered_map<std::string, Command> CommandsSet;
130 typedef std::unordered_map<Key, std::vector<Binding>, KeyHash> BindingsMap;
132 public:
133 typedef BindingsMap::value_type::second_type::iterator BindingIterator;
134 typedef BindingsMap::value_type::second_type::const_iterator ConstBindingIterator;
136 bool read(const std::string &file);
137 void generateDefaults();
139 const Command *findCommand(const std::string &name) {
140 const Command *ptr = 0;
141 auto it = m_commands.find(name);
142 if (it != m_commands.end())
143 ptr = &it->second;
144 return ptr;
147 std::pair<BindingIterator, BindingIterator> get(const Key &k) {
148 std::pair<BindingIterator, BindingIterator> result;
149 auto it = m_bindings.find(k);
150 if (it != m_bindings.end()) {
151 result.first = it->second.begin();
152 result.second = it->second.end();
153 } else {
154 auto list_end = m_bindings.begin()->second.end();
155 result.first = list_end;
156 result.second = list_end;
158 return result;
161 BindingsMap::const_iterator begin() const { return m_bindings.begin(); }
162 BindingsMap::const_iterator end() const { return m_bindings.end(); }
164 private:
165 bool notBound(const Key &k) const {
166 return k != Key::noOp && m_bindings.find(k) == m_bindings.end();
169 template <typename ArgT>
170 void bind(Key k, ArgT &&t) {
171 m_bindings[k].push_back(std::forward<ArgT>(t));
174 BindingsMap m_bindings;
175 CommandsSet m_commands;
178 extern BindingsConfiguration Bindings;
180 #endif // NCMPCPP_BINDINGS_H