Whats implemented so far:
-Added a Hot Keys tab under Options
-This Hot Keys tab has a button for each configurable hot key
-The configurable hot key button opens up a modal window which displays the current set hot key, you can enter a key combination and it is saved(moving the cursor off the window exits out not saving anything)
-The configured hot keys work in game
Things I still need to implement and/or look into:
-Possibly figure out a better way for adding the initial hot key to the DB(the current int/string way seems a bit messy)
-Add the logic behind the use default hot keys button
-State logic for hot keys being enabled/disabled depending on the current window
-Pretty up the UI parts(modal window, options Hot Keys tab/buttons)
-General clean up of the code
-Change the location of the actual HotKeyManger .cpp/.h files?(I created them within visual studio, in the VS filter they are under UI but it looks like they are really in a folder with .asm files)
The few questions I currently have:
Is there a way to change the text size of a GG::TextControl()? I've been looking but can only manage to find a method that tells me the size, i'd like to make the text for the current set Hot Key combination on the modal window bigger.
Is there anything major you see that I am missing from the needs to be implemented list ? Probably the most major thing I can think of is the enabling/disabling depending on the states.
Also how would you like the UI portion of this to look/be changed around? I know its not all that pretty, so far I've just been aiming to get the functionality done.
Also, when the time comes, what is the process to adding a file to the patch that isn't in the repository(HotKeyManager.cpp/.h)? When I create a patch it isn't added.
Here is the HotKeyManager code since I can't seem to get it added to the patch:
Code: Select all
// -*- C++ -*-
//HotKeyManager.h
#ifndef _HotKeyManager_h_
#define _HotKeyManager_h_
#include <../GG/GG/Base.h>
#include <GG/WndEvent.h>
#include <GG/GUI.h>
#include "../../UI/MapWnd.h"
class HotKeyManager;
/////////////////////////////////////////////
// Free Functions
/////////////////////////////////////////////
/** returns the singleton Hot Key Manager */
//HotKeyManager& GetHotKeyManager();
struct HotKeyCombination
{
HotKeyCombination(){}
HotKeyCombination(std::string hot_key_name, GG::Key key, GG::Flags<GG::ModKey> default_modkeys, boost::uint32_t key_code_point)
: m_hot_key_name(hot_key_name), m_key(key), m_default_modkeys(default_modkeys), m_key_code_point(key_code_point)
{
}
std::string m_hot_key_name;
GG::Key m_key;
GG::Flags<GG::ModKey> m_default_modkeys;
boost::uint32_t m_key_code_point;
};
/** Hot Key Manager */
class HotKeyManager
{
public:
static HotKeyManager* Instance();
void SetHotKeyAccelerator(std::string hot_key_name);
void ChangeHotKey(std::string hot_key_name, GG::Key key, GG::Flags<GG::ModKey> default_modkeys, boost::uint32_t key_code_point);
GG::GUI::AcceleratorSignalType& GetHotKeySignal(std::string hot_key_name);
void ConnectKeyboardAcceleratorSignals(MapWnd* map_window); //!< connects signals from keyboard accelerators to various GUI responses
void SetAccelerators(); //!< tells the GUI which keypress combinations to track and emit signals for when they occur
void RemoveAccelerators(); //!< tells GUI to stop emitting signals for keypresses
std::string HotKeyToString(std::string hot_key_name);
HotKeyCombination ReadHotKeyFromDB(std::string hot_key_name);
void WriteHotKeyComboToDB(HotKeyCombination hot_key_combo);
bool WaitForNextKeyPress(GG::Key key);
std::string SpecialHotKeyToString(HotKeyCombination hot_key_combo, bool only_check_modkeys);
private:
HotKeyManager();
HotKeyManager(const HotKeyManager&){};
HotKeyManager& operator=(const HotKeyManager&){};
static HotKeyManager* m_sInstance;
std::set<boost::signals::connection> m_keyboard_accelerator_signals;
MapWnd* m_map_window;
bool m_map_window_ptr_set;
};
#endif
Code: Select all
#include "HotKeyManager.h"
#include "../util/OptionsDB.h"
#include <iostream>
#include <boost/algorithm/string.hpp>
#include "../../../FreeOrion/GG/GG/Edit.h"
#include "../util/MultiplayerCommon.h"
HotKeyManager::HotKeyManager() : m_map_window_ptr_set(false)
{
}
/////////////////////////////////////////////////
// HotKeyManager //
/////////////////////////////////////////////////
// static(s)
HotKeyManager* HotKeyManager::m_sInstance = nullptr;
HotKeyManager* HotKeyManager::Instance()
{
if (!m_sInstance) // Only allow one instance of class to be generated.
m_sInstance = new HotKeyManager();
return m_sInstance;
}
void HotKeyManager::SetHotKeyAccelerator(std::string hot_key_name)
{
HotKeyCombination hot_key_combo = ReadHotKeyFromDB(hot_key_name);
GG::GUI::GetGUI()->SetAccelerator(hot_key_combo.m_key, hot_key_combo.m_default_modkeys);
}
void HotKeyManager::ChangeHotKey(std::string hot_key_name, GG::Key key, GG::Flags<GG::ModKey> default_modkeys, boost::uint32_t key_code_point)
{
HotKeyCombination hot_key_combo(hot_key_name, key, default_modkeys, key_code_point);
WriteHotKeyComboToDB(hot_key_combo);
RemoveAccelerators();
// needed for connecting signals
if (m_map_window_ptr_set)
{
SetAccelerators();
ConnectKeyboardAcceleratorSignals(m_map_window);
}
}
GG::GUI::AcceleratorSignalType& HotKeyManager::GetHotKeySignal(std::string hot_key_name)
{
HotKeyCombination hot_key_combo = ReadHotKeyFromDB(hot_key_name);
return GG::GUI::GetGUI()->AcceleratorSignal(hot_key_combo.m_key, hot_key_combo.m_default_modkeys);
}
void HotKeyManager::ConnectKeyboardAcceleratorSignals(MapWnd* map_window)
{
m_map_window = map_window;
m_map_window_ptr_set = true;
m_keyboard_accelerator_signals.insert(
GG::Connect(HotKeyManager::Instance()->GetHotKeySignal("HotKey.ReturnToMap"),
&MapWnd::ReturnToMap, map_window));
m_keyboard_accelerator_signals.insert(
GG::Connect(HotKeyManager::Instance()->GetHotKeySignal("HotKey.OpenChatWindow1"),
&MapWnd::OpenChatWindow, map_window));
m_keyboard_accelerator_signals.insert(
GG::Connect(HotKeyManager::Instance()->GetHotKeySignal("HotKey.OpenChatWindow2"),
&MapWnd::OpenChatWindow, map_window));
m_keyboard_accelerator_signals.insert(
GG::Connect(HotKeyManager::Instance()->GetHotKeySignal("HotKey.EndTurn1"),
&MapWnd::EndTurn, map_window));
m_keyboard_accelerator_signals.insert(
GG::Connect(HotKeyManager::Instance()->GetHotKeySignal("HotKey.EndTurn2"),
&MapWnd::EndTurn, map_window));
m_keyboard_accelerator_signals.insert(
GG::Connect(HotKeyManager::Instance()->GetHotKeySignal("HotKey.ToggleSitRep"),
&MapWnd::ToggleSitRep, map_window));
m_keyboard_accelerator_signals.insert(
GG::Connect(HotKeyManager::Instance()->GetHotKeySignal("HotKey.ToggleResearch"),
&MapWnd::ToggleResearch, map_window));
m_keyboard_accelerator_signals.insert(
GG::Connect(HotKeyManager::Instance()->GetHotKeySignal("HotKey.ToggleProduction"),
&MapWnd::ToggleProduction, map_window));
m_keyboard_accelerator_signals.insert(
GG::Connect(HotKeyManager::Instance()->GetHotKeySignal("HotKey.ToggleDesign"),
&MapWnd::ToggleDesign, map_window));
m_keyboard_accelerator_signals.insert(
GG::Connect(HotKeyManager::Instance()->GetHotKeySignal("HotKey.ShowMenu"),
&MapWnd::ShowMenu, map_window));
m_keyboard_accelerator_signals.insert(
GG::Connect(HotKeyManager::Instance()->GetHotKeySignal("HotKey.CloseSystemView"),
&MapWnd::CloseSystemView, map_window));
// Keys for zooming
m_keyboard_accelerator_signals.insert(
GG::Connect(HotKeyManager::Instance()->GetHotKeySignal("HotKey.KeyboardZoomIn1"),
&MapWnd::KeyboardZoomIn, map_window));
m_keyboard_accelerator_signals.insert(
GG::Connect(HotKeyManager::Instance()->GetHotKeySignal("HotKey.KeyboardZoomIn2"),
&MapWnd::KeyboardZoomIn, map_window));
m_keyboard_accelerator_signals.insert(
GG::Connect(HotKeyManager::Instance()->GetHotKeySignal("HotKey.KeyboardZoomOut1"),
&MapWnd::KeyboardZoomOut, map_window));
m_keyboard_accelerator_signals.insert(
GG::Connect(HotKeyManager::Instance()->GetHotKeySignal("HotKey.KeyboardZoomOut2"),
&MapWnd::KeyboardZoomOut, map_window));
// Keys for showing systems
m_keyboard_accelerator_signals.insert(
GG::Connect(HotKeyManager::Instance()->GetHotKeySignal("HotKey.ZoomToHomeSystem"),
&MapWnd::ZoomToHomeSystem, map_window));
m_keyboard_accelerator_signals.insert(
GG::Connect(HotKeyManager::Instance()->GetHotKeySignal("HotKey.ZoomToPrevOwnedSystem"),
&MapWnd::ZoomToPrevOwnedSystem, map_window));
m_keyboard_accelerator_signals.insert(
GG::Connect(HotKeyManager::Instance()->GetHotKeySignal("HotKey.ZoomToNextOwnedSystem"),
&MapWnd::ZoomToNextOwnedSystem, map_window));
// Keys for showing fleets
m_keyboard_accelerator_signals.insert(
GG::Connect(HotKeyManager::Instance()->GetHotKeySignal("HotKey.ZoomToPrevIdleFleet"),
&MapWnd::ZoomToPrevIdleFleet, map_window));
m_keyboard_accelerator_signals.insert(
GG::Connect(HotKeyManager::Instance()->GetHotKeySignal("HotKey.ZoomToNextIdleFleet"),
&MapWnd::ZoomToNextIdleFleet, map_window));
m_keyboard_accelerator_signals.insert(
GG::Connect(HotKeyManager::Instance()->GetHotKeySignal("HotKey.ZoomToPrevFleet"),
&MapWnd::ZoomToPrevFleet, map_window));
m_keyboard_accelerator_signals.insert(
GG::Connect(HotKeyManager::Instance()->GetHotKeySignal("HotKey.ZoomToNextFleet"),
&MapWnd::ZoomToNextFleet, map_window));
// set up the regression hotkey
}
void HotKeyManager::SetAccelerators()
{
HotKeyToString("HotKey.ReturnToMap");
SetHotKeyAccelerator("HotKey.ReturnToMap");
SetHotKeyAccelerator("HotKey.OpenChatWindow1");
SetHotKeyAccelerator("HotKey.OpenChatWindow2");
SetHotKeyAccelerator("HotKey.EndTurn1");
SetHotKeyAccelerator("HotKey.EndTurn2");
SetHotKeyAccelerator("HotKey.ToggleSitRep");
SetHotKeyAccelerator("HotKey.ToggleResearch");
SetHotKeyAccelerator("HotKey.ToggleProduction");
SetHotKeyAccelerator("HotKey.ToggleDesign");
SetHotKeyAccelerator("HotKey.ShowMenu");
SetHotKeyAccelerator("HotKey.CloseSystemView");
SetHotKeyAccelerator("HotKey.KeyboardZoomIn1");
SetHotKeyAccelerator("HotKey.KeyboardZoomIn2");
SetHotKeyAccelerator("HotKey.KeyboardZoomOut1");
SetHotKeyAccelerator("HotKey.KeyboardZoomOut2");
SetHotKeyAccelerator("HotKey.ZoomToHomeSystem");
SetHotKeyAccelerator("HotKey.ZoomToPrevOwnedSystem");
SetHotKeyAccelerator("HotKey.ZoomToNextOwnedSystem");
SetHotKeyAccelerator("HotKey.ZoomToPrevIdleFleet");
SetHotKeyAccelerator("HotKey.ZoomToNextIdleFleet");
SetHotKeyAccelerator("HotKey.ZoomToPrevFleet");
SetHotKeyAccelerator("HotKey.ZoomToNextFleet");
}
void HotKeyManager::RemoveAccelerators()
{
GG::GUI::accel_iterator i = GG::GUI::GetGUI()->accel_begin();
while (i != GG::GUI::GetGUI()->accel_end()) {
GG::GUI::GetGUI()->RemoveAccelerator(i);
i = GG::GUI::GetGUI()->accel_begin();
}
for (std::set<boost::signals::connection>::iterator it =
m_keyboard_accelerator_signals.begin();
it != m_keyboard_accelerator_signals.end();
++it) {
it->disconnect();
}
m_keyboard_accelerator_signals.clear();
}
std::string HotKeyManager::HotKeyToString(std::string hot_key_name)
{
HotKeyCombination hot_key_combo = ReadHotKeyFromDB(hot_key_name);
//std::string a = boost::lexical_cast<std::string>(hot_key_combo.m_key);
std::string full_hot_key_string;
std::string translated_code_point_key;
GG::GetTranslatedCodePoint(hot_key_combo.m_key, hot_key_combo.m_key_code_point, hot_key_combo.m_default_modkeys, translated_code_point_key);
if (translated_code_point_key == "")
full_hot_key_string = SpecialHotKeyToString(hot_key_combo, false);
else
full_hot_key_string += SpecialHotKeyToString(hot_key_combo, true) + translated_code_point_key;
std::cout << full_hot_key_string + " ";
return full_hot_key_string;
}
// arrows
// fkeys
// modkeys
// spacebar
// tab
// enter/return
// backspace
// insert/delete/home/end/pageup/pagedown
std::string HotKeyManager::SpecialHotKeyToString(HotKeyCombination hot_key_combo, bool only_check_modkeys)
{
std::string hot_key_string;
// check modkeys
GG::Flags<GG::ModKey> modkeys = hot_key_combo.m_default_modkeys;
if (modkeys & GG::MOD_KEY_CTRL) {
hot_key_string += "CTRL ";
}
if(modkeys & GG::MOD_KEY_SHIFT) {
hot_key_string += "SHIFT ";
}
if (modkeys & GG::MOD_KEY_ALT) {
hot_key_string += "ALT ";
}
if (modkeys & GG::MOD_KEY_META) {
hot_key_string += "META ";
}
if (modkeys & GG::MOD_KEY_NUM) {
hot_key_string += "NUM LOCK ";
}
if (modkeys & GG::MOD_KEY_CAPS) {
hot_key_string += "CAPS LOCK ";
}
if (modkeys & GG::MOD_KEY_MODE) {
hot_key_string += "MODE ";
}
if (!only_check_modkeys) {
switch(hot_key_combo.m_key) {
case GG::GGK_LEFT:
hot_key_string += UserString("Left_Arrow");
break;
case GG::GGK_RIGHT:
hot_key_string += UserString("Right_Arrow");
break;
case GG::GGK_UP:
hot_key_string += UserString("Up_Arrow");
break;
case GG::GGK_DOWN:
hot_key_string += UserString("Down_Arrow");
break;
case GG::GGK_F1:
hot_key_string += UserString("F1");
break;
case GG::GGK_F2:
hot_key_string += UserString("F2");
break;
case GG::GGK_F3:
hot_key_string += UserString("F3");
break;
case GG::GGK_F4:
hot_key_string += UserString("F4");
break;
case GG::GGK_F5:
hot_key_string += UserString("F5");
break;
case GG::GGK_F6:
hot_key_string += UserString("F6");
break;
case GG::GGK_F7:
hot_key_string += UserString("F7");
break;
case GG::GGK_F8:
hot_key_string += UserString("F8");
break;
case GG::GGK_F9:
hot_key_string += UserString("F9");
break;
case GG::GGK_F10:
hot_key_string += UserString("F10");
break;
case GG::GGK_F11:
hot_key_string += UserString("F11");
break;
case GG::GGK_F12:
hot_key_string += UserString("F12");
break;
case GG::GGK_SPACE:
hot_key_string += UserString("Space");
break;
case GG::GGK_TAB:
hot_key_string += UserString("Tab");
break;
case GG::GGK_KP_ENTER:
hot_key_string += UserString("Enter");
break;
case GG::GGK_RETURN:
hot_key_string += UserString("Return");
break;
case GG::GGK_BACKSPACE:
hot_key_string += UserString("Backspace");
break;
// insert/delete/home/end/pageup/pagedown
case GG::GGK_INSERT:
hot_key_string += UserString("Insert");
break;
case GG::GGK_DELETE:
hot_key_string += UserString("Delete");
break;
case GG::GGK_HOME:
hot_key_string += UserString("Home");
break;
case GG::GGK_END:
hot_key_string += UserString("End");
break;
case GG::GGK_PAGEUP:
hot_key_string += UserString("Page_Up");
break;
case GG::GGK_PAGEDOWN:
hot_key_string += UserString("Page_Down");
break;
default:
break;
}
}
return hot_key_string;
}
HotKeyCombination HotKeyManager::ReadHotKeyFromDB(std::string hot_key_name)
{
std::string db_stored_key = GetOptionsDB().Get<std::string>(hot_key_name);
std::vector<std::string> split_strings;
boost::split(split_strings, db_stored_key, boost::is_any_of(" "));
GG::Key key = (GG::Key)boost::lexical_cast<int>(split_strings.at(0));
GG::Flags<GG::ModKey> modkeys;
boost::uint32_t key_code_point;
for (unsigned int x = 1; x < split_strings.size()-1; ++x)
{
std::string cur = split_strings.at(x);
if (cur == "c") {
modkeys |= GG::MOD_KEY_CTRL;
} else if(cur == "s") {
modkeys |= GG::MOD_KEY_SHIFT;
} else if (cur == "a") {
modkeys |= GG::MOD_KEY_ALT;
} else if (cur == "m") {
modkeys |= GG::MOD_KEY_META;
} else if(cur == "num") {
modkeys |= GG::MOD_KEY_NUM;
} else if (cur == "cap") {
modkeys |= GG::MOD_KEY_CAPS;
} else if (cur == "mode") {
modkeys |= GG::MOD_KEY_MODE;
}
}
if ((split_strings.size() - 1) != 0)
key_code_point = boost::lexical_cast<boost::uint32_t>(split_strings.at(split_strings.size()-1));
else
key_code_point = 0;
HotKeyCombination db_key_combo(hot_key_name, key, modkeys, key_code_point);
return db_key_combo;
}
void HotKeyManager::WriteHotKeyComboToDB(HotKeyCombination hot_key_combo)
{
// store new keys combo
int key_int = (int) hot_key_combo.m_key;
GG::Flags<GG::ModKey> default_modkeys = hot_key_combo.m_default_modkeys;
std::string hot_key_string = boost::lexical_cast<std::string>(key_int);
if (default_modkeys & GG::MOD_KEY_CTRL) {
hot_key_string += " c";
}
if(default_modkeys & GG::MOD_KEY_SHIFT) {
hot_key_string += " s";
}
if (default_modkeys & GG::MOD_KEY_ALT) {
hot_key_string += " a";
}
if (default_modkeys & GG::MOD_KEY_META) {
hot_key_string += " m";
}
if (default_modkeys & GG::MOD_KEY_NUM) {
hot_key_string += " num";
}
if (default_modkeys & GG::MOD_KEY_CAPS) {
hot_key_string += " cap";
}
if (default_modkeys & GG::MOD_KEY_MODE) {
hot_key_string += " mode";
}
hot_key_string += " " + boost::lexical_cast<std::string>(hot_key_combo.m_key_code_point);
GetOptionsDB().Set<std::string>(hot_key_combo.m_hot_key_name, hot_key_string);
}
// fix gui
// add states
// clean up code
// cancel button
bool HotKeyManager::WaitForNextKeyPress(GG::Key key)
{
switch(key) {
case GG::GGK_NUMLOCK:
case GG::GGK_CAPSLOCK:
case GG::GGK_RSHIFT:
case GG::GGK_LSHIFT:
case GG::GGK_RCTRL:
case GG::GGK_LCTRL:
case GG::GGK_RALT:
case GG::GGK_LALT:
case GG::GGK_RMETA:
case GG::GGK_LMETA:
case GG::GGK_MODE:
return true;
break;
default:
return false;
break;
}
}