wesnoth/hotkeys.cpp
Dave White 5fd5346808 Allow resolution to be configurable in preferences file...
...using xresolution and yresolution options
2003-09-18 12:47:17 +00:00

184 lines
4.4 KiB
C++

/* $Id$ */
/*
Copyright (C) 2003 by David White <davidnwhite@optusnet.com.au>
Part of the Battle for Wesnoth Project http://wesnoth.whitevine.net
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY.
See the COPYING file for more details.
*/
#include "config.hpp"
#include "hotkeys.hpp"
#include "language.hpp"
#include "menu.hpp"
#include "playlevel.hpp"
#include "preferences.hpp"
#include <algorithm>
#include <cstdlib>
#include <map>
namespace {
HOTKEY_COMMAND string_to_command(const std::string& str)
{
static std::map<std::string,HOTKEY_COMMAND> m;
if(m.empty()) {
typedef std::pair<std::string,HOTKEY_COMMAND> val;
m.insert(val("cycle",HOTKEY_CYCLE_UNITS));
m.insert(val("endunitturn",HOTKEY_END_UNIT_TURN));
m.insert(val("leader",HOTKEY_LEADER));
m.insert(val("undo",HOTKEY_UNDO));
m.insert(val("redo",HOTKEY_REDO));
m.insert(val("zoomin",HOTKEY_ZOOM_IN));
m.insert(val("zoomout",HOTKEY_ZOOM_OUT));
m.insert(val("zoomdefault",HOTKEY_ZOOM_DEFAULT));
m.insert(val("fullscreen",HOTKEY_FULLSCREEN));
m.insert(val("accelerated",HOTKEY_ACCELERATED));
m.insert(val("resistance",HOTKEY_ATTACK_RESISTANCE));
m.insert(val("terraintable",HOTKEY_TERRAIN_TABLE));
}
const std::map<std::string,HOTKEY_COMMAND>::const_iterator i = m.find(str);
if(i == m.end())
return HOTKEY_NULL;
else
return i->second;
}
struct hotkey {
explicit hotkey(config& cfg);
HOTKEY_COMMAND action;
int keycode;
bool alt, ctrl, shift;
mutable bool lastres;
};
hotkey::hotkey(config& cfg) : lastres(false)
{
std::map<std::string,std::string>& m = cfg.values;
action = string_to_command(m["command"]);
keycode = m["key"].empty() ? 0 : m["key"][0];
alt = (m["alt"] == "yes");
ctrl = (m["ctrl"] == "yes");
shift = (m["shift"] == "yes");
}
bool operator==(const hotkey& a, const hotkey& b)
{
return a.keycode == b.keycode && a.alt == b.alt &&
a.ctrl == b.ctrl && a.shift == b.shift;
}
bool operator!=(const hotkey& a, const hotkey& b)
{
return !(a == b);
}
std::vector<hotkey> hotkeys;
}
struct hotkey_pressed {
hotkey_pressed(CKey& key);
bool operator()(const hotkey& hk) const;
private:
const bool shift_, ctrl_, alt_;
CKey& key_;
};
hotkey_pressed::hotkey_pressed(CKey& key) :
shift_(key[SDLK_LSHIFT] || key[SDLK_RSHIFT]),
ctrl_(key[SDLK_LCTRL] || key[SDLK_RCTRL]),
alt_(key[SDLK_LALT] || key[SDLK_RALT]), key_(key) {}
bool hotkey_pressed::operator()(const hotkey& hk) const
{
const bool res = shift_ == hk.shift && ctrl_ == hk.ctrl &&
alt_ == hk.alt && key_[hk.keycode];
//for zoom in and zoom out, allow it to happen multiple consecutive times
if(hk.action == HOTKEY_ZOOM_IN || hk.action == HOTKEY_ZOOM_OUT) {
hk.lastres = false;
return res;
}
//don't let it return true on multiple consecutive occurrences
if(hk.lastres) {
hk.lastres = res;
return false;
} else {
hk.lastres = res;
return res;
}
}
void add_hotkey(config& cfg)
{
const hotkey new_hotkey(cfg);
const std::vector<hotkey>::iterator i =
std::find(hotkeys.begin(),hotkeys.end(),new_hotkey);
if(i != hotkeys.end()) {
*i = new_hotkey;
} else {
hotkeys.push_back(new_hotkey);
}
}
void add_hotkeys(config& cfg)
{
std::vector<config*>& children = cfg.children["hotkey"];
for(std::vector<config*>::iterator i = children.begin();
i != children.end(); ++i) {
add_hotkey(**i);
}
}
HOTKEY_COMMAND check_keys(display& disp)
{
const double zoom_amount = 5.0;
CKey key;
if(key[KEY_ESCAPE]) {
const int res = gui::show_dialog(disp,NULL,"",
string_table["quit_message"],gui::YES_NO);
if(res == 0) {
throw end_level_exception(QUIT);
}
}
const std::vector<hotkey>::iterator i =
std::find_if(hotkeys.begin(),hotkeys.end(),hotkey_pressed(key));
if(i == hotkeys.end())
return HOTKEY_NULL;
switch(i->action) {
case HOTKEY_ZOOM_IN:
disp.zoom(zoom_amount);
break;
case HOTKEY_ZOOM_OUT:
disp.zoom(-zoom_amount);
break;
case HOTKEY_ZOOM_DEFAULT:
disp.default_zoom();
break;
case HOTKEY_FULLSCREEN:
preferences::set_fullscreen(!preferences::fullscreen());
break;
case HOTKEY_ACCELERATED:
preferences::set_turbo(!preferences::turbo());
break;
default:
return i->action;
}
return HOTKEY_NULL;
}