bindings: guarantee ordering of bindings of the same key

This commit is contained in:
Andrzej Rybczak
2012-09-20 05:00:11 +02:00
parent 07fc58015e
commit add40d542d
4 changed files with 32 additions and 14 deletions

View File

@@ -277,9 +277,9 @@ void Action::Seek()
Key input = Key::read(*wFooter); Key input = Key::read(*wFooter);
auto k = Bindings.get(input); auto k = Bindings.get(input);
if (k.first == k.second || !k.first->second.isSingle()) // no single action? if (k.first == k.second || !k.first->isSingle()) // no single action?
break; break;
Action *a = k.first->second.action(); Action *a = k.first->action();
if (dynamic_cast<SeekForward *>(a)) if (dynamic_cast<SeekForward *>(a))
{ {
if (songpos < Mpd.GetTotalTime()) if (songpos < Mpd.GetTotalTime())

View File

@@ -137,12 +137,17 @@ private:
/// Keybindings configuration /// Keybindings configuration
class BindingsConfiguration class BindingsConfiguration
{ {
struct KeyHash {
size_t operator()(const Key &k) const {
return (k.getChar() << 1) | (k.getType() == Key::Standard);
}
};
typedef std::unordered_map<std::string, Command> CommandsSet; typedef std::unordered_map<std::string, Command> CommandsSet;
typedef std::multimap<Key, Binding> BindingsMap; typedef std::unordered_map<Key, std::vector<Binding>, KeyHash> BindingsMap;
public: public:
typedef BindingsMap::iterator BindingIterator; typedef BindingsMap::value_type::second_type::iterator BindingIterator;
typedef BindingsMap::const_iterator ConstBindingIterator; typedef BindingsMap::value_type::second_type::const_iterator ConstBindingIterator;
bool read(const std::string &file); bool read(const std::string &file);
void generateDefaults(); void generateDefaults();
@@ -156,19 +161,29 @@ public:
} }
std::pair<BindingIterator, BindingIterator> get(const Key &k) { std::pair<BindingIterator, BindingIterator> get(const Key &k) {
return m_bindings.equal_range(k); std::pair<BindingIterator, BindingIterator> result;
auto it = m_bindings.find(k);
if (it != m_bindings.end()) {
result.first = it->second.begin();
result.second = it->second.end();
} else {
auto list_end = m_bindings.begin()->second.end();
result.first = list_end;
result.second = list_end;
}
return result;
} }
ConstBindingIterator begin() const { return m_bindings.begin(); } BindingsMap::const_iterator begin() const { return m_bindings.begin(); }
ConstBindingIterator end() const { return m_bindings.end(); } BindingsMap::const_iterator end() const { return m_bindings.end(); }
private: private:
bool notBound(const Key &k) const { bool notBound(const Key &k) const {
return k != Key::noOp && m_bindings.find(k) == m_bindings.end(); return k != Key::noOp && m_bindings.find(k) == m_bindings.end();
} }
template <typename T> void bind(Key k, T t) { template <typename T> void bind(Key k, const T &t) {
m_bindings.insert(std::make_pair(k, Binding(t))); m_bindings[k].push_back(Binding(t));
} }
BindingsMap m_bindings; BindingsMap m_bindings;

View File

@@ -129,10 +129,13 @@ std::string Help::DisplayKeys(const ActionType at)
std::string result; std::string result;
for (auto it = Bindings.begin(); it != Bindings.end(); ++it) for (auto it = Bindings.begin(); it != Bindings.end(); ++it)
{ {
if (it->second.isSingle() && it->second.action()->Type() == at) for (auto j = it->second.begin(); j != it->second.end(); ++j)
{ {
result += keyToString(it->first, &print_backspace); if (j->isSingle() && j->action()->Type() == at)
result += " "; {
result += keyToString(it->first, &print_backspace);
result += " ";
}
} }
} }
result.resize(16, ' '); result.resize(16, ' ');

View File

@@ -248,7 +248,7 @@ int main(int argc, char **argv)
auto k = Bindings.get(input); auto k = Bindings.get(input);
for (; k.first != k.second; ++k.first) for (; k.first != k.second; ++k.first)
if (k.first->second.execute()) if (k.first->execute())
break; break;
if (myScreen == myPlaylist) if (myScreen == myPlaylist)