Keybord Bindings

Programmers discuss here anything related to FreeOrion programming. Primarily for the developers to discuss.

Moderator: Committer

Message
Author
User avatar
strooka
Space Kraken
Posts: 165
Joined: Tue Jun 23, 2009 5:34 pm
Location: Bielefeld, Germany

Re: Keybord Bindings

#31 Post by strooka »

ok, guys, here is the solution.

saving to file doesnt still work although i use options db.

Code: Select all

// -*- C++ -*-
//by strooka
#ifndef _HotKeyManager_h_
#define _HotKeyManager_h_

#include <../GG/GG/Base.h>
#include <../GG/GG/GUI.h>
#include <../GG/GG/SignalsAndSlots.h>


#include "CUIWnd.h"
#include "CUIControls.h"
#include "../util/OptionsDB.h"

#include <map>


typedef boost::signal< bool() >                          SignalType;
typedef boost::shared_ptr<SignalType>                    SignalPointerType;

/////////////////////////////////////////////
// Free Functions
/////////////////////////////////////////////
namespace HKM {

std::string KeyString(GG::Key key, GG::Flags<GG::ModKey> mod_keys ); //!< computes Key input

GG::Key KeyFromString(const std::string& str); //!< computes string input for a Key

std::pair< GG::Key, GG::Flags<GG::ModKey> > UserString(const std::string& str); //!< computes user input

class HotKey 
{
public:
    HotKey( const std::string& str, const std::string& option_name = "NO_NAME_SET" );
    HotKey( GG::Key key, const std::string& option_name = "NO_NAME_SET" );
    HotKey( GG::Key key = GG::GGK_UNKNOWN, GG::Flags<GG::ModKey> mod_keys = GG::Flags<GG::ModKey>(),  const std::string& option_name = "NO_NAME_SET" );

    friend std::ostream& operator<<(std::ostream& os, const HotKey& hotkey);
    friend std::istream& operator>>(std::istream& is, HotKey& hotkey);

    void SetKey( std::pair< GG::Key, GG::Flags<GG::ModKey> > Pair );

    bool GetCtrl() const { return m_mod_keys & (GG::MOD_KEY_CTRL); }//!< Is CTRL key pressed to activate hotkey? 
    bool GetAlt() const { return m_mod_keys & (GG::MOD_KEY_ALT); } //!< ALT key?
    bool GetShift() const { return m_mod_keys & (GG::MOD_KEY_LSHIFT | GG::MOD_KEY_RSHIFT); } //!< SHIFT key?
    bool GetMeta() const { return m_mod_keys & (GG::MOD_KEY_META); } //!< META key?

    GG::Key GetKey() const { return m_key; }
    GG::Flags<GG::ModKey> GetModKeys() const { return m_mod_keys; }

    static bool IsModKey(GG::Key key) {
        if( key == (GG::GGK_RSHIFT || GG::GGK_LSHIFT || GG::GGK_RCTRL || GG::GGK_LCTRL || GG::GGK_LALT || GG::GGK_RALT || GG::GGK_LMETA || GG::GGK_RMETA) )
            return true;
        else
            return false;
    }

    boost::signals::connection& GetConnection();
    SignalPointerType GetWindowSignal() { return m_p_window_signal; }

    void UpdateConnection(GG::Key last_key = GG::GGK_UNKNOWN, GG::Flags<GG::ModKey> last_mod_keys = GG::Flags<GG::ModKey>());

    void SetOptionName(std::string str) { m_option_name = str; }
    std::string GetOptionName() { return m_option_name; }
private:
    GG::Key m_key; //!< GG code for key that was pressed
    GG::Flags<GG::ModKey> m_mod_keys;
    std::string m_option_name;
    SignalPointerType m_p_window_signal;
    boost::signals::connection m_connection;
};


class HKEdit : public CUIEdit
{
public:
    /** \name Structors */ //@{
    HKEdit(GG::X x, GG::Y y, GG::X w, const std::string& str, const std::string& option_name, const boost::shared_ptr<GG::Font>& font = boost::shared_ptr<GG::Font>(),
            GG::Clr border_color = ClientUI::CtrlBorderColor(), GG::Clr text_color = ClientUI::TextColor(),
            GG::Clr interior = ClientUI::CtrlColor(), GG::Flags<GG::WndFlag> flags = GG::INTERACTIVE); ///< basic ctor
    //@}

    /** \name Mutators */ //@{
    virtual void LButtonDown(const GG::Pt& pt, GG::Flags<GG::ModKey> mod_keys);
    //@}
private:
    const std::string m_option_name;
};


class KeyInputDialog : public CUIWnd
{
public:
    KeyInputDialog();

    virtual void KeyPress(GG::Key key, boost::uint32_t key_code_point, GG::Flags<GG::ModKey> mod_keys);

    const std::pair< GG::Key, GG::Flags<GG::ModKey> > Result() const { return m_result; }

private:
    std::pair< GG::Key, GG::Flags<GG::ModKey> > m_result;

    static const GG::X WND_WIDTH;
    static const int CONTROL_MARGIN;
};


//can be used to implement a state machine
class HotKeyManager
{
public:
    HotKeyManager();

    static HotKeyManager* s_HotKeyManager;
private:
    
    friend HotKeyManager& GetHotKeyManager();
};

}

/** returns the single instance of the class */
HKM::HotKeyManager& GetHotKeyManager();

namespace HKM {

template <class T>
struct Connect {
    Connect(const std::string option_name, bool (T::*slot)(), T* pWnd) {
        //update/initialize hotkey contents from db
        HotKey hotkey = GetOptionsDB().Get<HotKey>(option_name);
        //set signal this connection won't be altered
        GG::Connect( *hotkey.GetWindowSignal(), slot, pWnd );
        //set connection
        hotkey.UpdateConnection();
        GetOptionsDB().Set<HotKey>(option_name, hotkey);
    }
};

}

#endif // _HotKeyManager_h_

you add commands through:

Code: Select all

        db.Add("UI.HotKey.MapWnd.ReturnToMap", "Return to map", HKM::HotKey(GG::GGK_ESCAPE,"UI.HotKey.MapWnd.ReturnToMap"),       Validator<HKM::HotKey>());

and connect via:

Code: Select all

    HKM::Connect<MapWnd>("UI.HotKey.MapWnd.ReturnToMap",      &MapWnd::ReturnToMap, this);

i have replaced all commands in map wnd so you can try it out.

in options wnd, you add an key option:

Code: Select all

    BeginPage(UserString("Key Bindings"));
    BeginSection(UserString("Map Window"));

    KeyOption("UI.HotKey.MapWnd.ReturnToMap",      "Return To Map");

i think you ll give me an entry on the developers list for this 8)
Attachments
HotKeyManager.tar.gz
the final files
(58.22 KiB) Downloaded 64 times

User avatar
Geoff the Medio
Programming, Design, Admin
Posts: 13603
Joined: Wed Oct 08, 2003 1:33 am
Location: Munich

Re: Keybord Bindings

#32 Post by Geoff the Medio »

saving to file doesnt still work although i use options db.
It's very hard to follow the actual or intended flow of events in your code. I've been going over it for probably an hour now, and I'm not sure what will happen when or if connections will be made in the right order, or if everything will get set up the same depending on whether it's being default created or recreated later.

Regardless, while I'm not sure what the cause of this problem is, it needs to be fixed.

The doubling of the option name in the HotKey object creation and again in the surrounding db.Add commands in MapWnd.cpp suggests unnecessary duplication, and shouldn't be necessary.

The UserString function needs to be renamed to avoid confusion with the existing UserString function which gets the human-readable text from the stringtable entry name, and also to make its name and purpose much clearer... "UserString" doesn't tell me anything about converting text to a key + mod key combination.

Numerous instances of hard-coded human-readable text need to be replaced with stringtable entry references.

This code probably isn't doing what you think it is:

Code: Select all

if( key == (GG::GGK_RSHIFT || GG::GGK_LSHIFT || GG::GGK_RCTRL || GG::GGK_LCTRL || GG::GGK_LALT || GG::GGK_RALT || GG::GGK_LMETA || GG::GGK_RMETA) )
GG::Key values are not bitset flags, so essentially you're checking if key equals true, which will evaulate to true for any legitimate keypress (except GGK_UNKNOWN which = 0).

Same issue with

Code: Select all

key == (GG::GGK_RSHIFT || GG::GGK_LSHIFT)
Why do you have class HotKeyManager? It doesn't seem to have any purpose.

SetOptionName takes its parameter by value, but it should be by const reference.

WND_WIDTH and CONTROL_MARGIN don't need to be, so shouldn't be, part of class KeyInputDialog. Just define them in an anonymous namespace in the same source file.

The HotKey class definition needs commenting.

You get programming credit when a (non trivial) chunk of your code is committed. This isn't committable, yet.

User avatar
strooka
Space Kraken
Posts: 165
Joined: Tue Jun 23, 2009 5:34 pm
Location: Bielefeld, Germany

Re: Keybord Bindings

#33 Post by strooka »

All is fixed except the Save load Bug.
I suggest it are the Stream Operators, maybe because the Option Name in the isstream Operator wont Be Set?

User avatar
Geoff the Medio
Programming, Design, Admin
Posts: 13603
Joined: Wed Oct 08, 2003 1:33 am
Location: Munich

Re: Keybord Bindings

#34 Post by Geoff the Medio »

strooka wrote:All is fixed except the Save load Bug.
What do you mean by that?
I suggest it are the Stream Operators, maybe because the Option Name in the isstream Operator wont Be Set?
I don't know... I'm not sure what the order of things is for hotkeys created by adding options or connecting, or what happens to the loaded up hotkey object after it's created. The conceptual model for how you've set things up makes it hard to follow how all this is supposed to or actually does happen... Your hotkey struct contains a signal that has to be connected to the command-implementation, with various updates and setting of values in the process, but the hotkey also being stored (partly) as data and restored and then somehow / in theory being reconnected automatically makes it hard to follow what's going on. You also retreive and store by value hotkey structs when setting things up, and then these will go out of scope, possibly losing some of the state that was just set, but I'm not sure, due to the complexity of the hotkey struct.

I've suggested making HotKey just store the modkey and keypress, and make a separate object / class / struct to track or store or represent commands and store the signals and connections from them, in part to keep this stuff separate and understandable, and to simplify the storage and retreival process of the bound hotkeys, which would then be fully represented by their stored textual representation of keypress + modkeys.

User avatar
strooka
Space Kraken
Posts: 165
Joined: Tue Jun 23, 2009 5:34 pm
Location: Bielefeld, Germany

Re: Keybord Bindings

#35 Post by strooka »

here is the latest update.

i have to debug it though...
What do you mean by that?
i mean there is a bug while saving or loading the hotkey to disk.
I've suggested making HotKey just store the modkey and keypress, and make a separate object / class / struct to track or store or represent commands and store the signals and connections from them, in part to keep this stuff separate and understandable, and to simplify the storage and retreival process of the bound hotkeys, which would then be fully represented by their stored textual representation of keypress + modkeys.
i've put so much work in it now, i don't want to throw it all away.
i will comment it all so that it will be understandable.

the key is, that there is a signal stored that connects to a window handler function.
and a connection is made to the keyboard that connects to the function call operator of the signal.
when a handled key is pressed the function call operator of the signal will be called, calling the handler function.
resetting of the connection to the keyboard sets the key input of the keyboard anew.
also there need not be a signal connected to a function if there is no window object, there will be just a empty function call operator executed.
Attachments
HotKeyManager.tar.gz
the newest files
(100.84 KiB) Downloaded 58 times

User avatar
strooka
Space Kraken
Posts: 165
Joined: Tue Jun 23, 2009 5:34 pm
Location: Bielefeld, Germany

THE SOLUTION

#36 Post by strooka »

the solution! :mrgreen:

the name of the option was not saved and it must be stored in the hotkey, too.
with this code, all issues will be done, hotkeys will be saved and loaded.
note that on MapWnd i have disabled the handling of the numpad disabling/enabling.
this could be implemented in the hotkeymanager class.
Attachments
HotKeyManager.tar.gz
the final files. add them to the project and you will be able to change hotkeys
(101.82 KiB) Downloaded 61 times

User avatar
strooka
Space Kraken
Posts: 165
Joined: Tue Jun 23, 2009 5:34 pm
Location: Bielefeld, Germany

Re: Keybord Bindings

#37 Post by strooka »

In this version of HotKeyManager , the RequestRegressionTestDump function is enabled and disabling/enabling of AlphaNum Keys is enabled. MapWnd and HotKeyManager is updated.
Attachments
HotKeyManager.tar.gz
all done?
(102.15 KiB) Downloaded 57 times

User avatar
Geoff the Medio
Programming, Design, Admin
Posts: 13603
Joined: Wed Oct 08, 2003 1:33 am
Location: Munich

Re: Keybord Bindings

#38 Post by Geoff the Medio »

strooka wrote:...enabled and disabling/enabling of AlphaNum Keys is enabled.
Sounds good.

Can you add a way to enable / disable hotkeys depending which screen the UI is on (eg. turn off zooming the map when not looking at the map)? This should not require hard-coding a function to enable / disable specific keys (like the alphanumeric keys) or commands, and should be configurable by telling the HKM what mode the UI is in, or by specifying a string label for each command and then telling the HKM to enable / disable commands based on what labels they do / don't have.

Also, for free functions like RegressionTestDump, why do you need to specify a Wnd class template parameter when connecting the signal to the function?

Also, will things work properly if you delete and recreate the object whose member functions various keypresses have been bound to?

User avatar
strooka
Space Kraken
Posts: 165
Joined: Tue Jun 23, 2009 5:34 pm
Location: Bielefeld, Germany

Re: Keybord Bindings

#39 Post by strooka »

Geoff the Medio wrote:
strooka wrote:...enabled and disabling/enabling of AlphaNum Keys is enabled.
Sounds good.

Can you add a way to enable / disable hotkeys depending which screen the UI is on (eg. turn off zooming the map when not looking at the map)? This should not require hard-coding a function to enable / disable specific keys (like the alphanumeric keys) or commands, and should be configurable by telling the HKM what mode the UI is in, or by specifying a string label for each command and then telling the HKM to enable / disable commands based on what labels they do / don't have.
No. I have tried it, but this would afford a function either not tracking the objects stored in the options db or get them by group out of the options db, not by name.
Also, for free functions like RegressionTestDump, why do you need to specify a Wnd class template parameter when connecting the signal to the function?
there is a Connect function for theese functions implemented, not taking a pointer.
Also, will things work properly if you delete and recreate the object whose member functions various keypresses have been bound to?
i do'nt know it should be this must be done in beta testing the hkm.

User avatar
Geoff the Medio
Programming, Design, Admin
Posts: 13603
Joined: Wed Oct 08, 2003 1:33 am
Location: Munich

Re: Keybord Bindings

#40 Post by Geoff the Medio »

strooka wrote:
Can you add a way to enable / disable hotkeys depending which screen the UI is on?
No. I have tried it, but this would afford a function either not tracking the objects stored in the options db or get them by group out of the options db, not by name.
I don't really follow your explanation ("this would afford a function" ?), but there should be some way to do enable/disable hotkeys as externally-configurable groups, even if it's not the first thing you thought to try. Configurable hotkeys aren't of much use if all hotkeys have to be enabled all the time...
Also, for free functions like RegressionTestDump, why do you need to specify a Wnd class template parameter when connecting the signal to the function?
there is a Connect function for theese functions implemented, not taking a pointer.
I realize that, but it doesn't answer my question: Why does that function need to take a template parameter? If there's no pointer to take, there should be no need to have a template based on the type of a pointer.

User avatar
strooka
Space Kraken
Posts: 165
Joined: Tue Jun 23, 2009 5:34 pm
Location: Bielefeld, Germany

Re: Keybord Bindings

#41 Post by strooka »

Maybe i could Store à Vector of String hotkey names for every window in hotkeymanager.
I could use it for extracting the approitate hotkeys from optios db.

There is no use of the Template Parameter exept that i can define à Second connect function within the Same context with other Parameters.

Maybe i should disconnect the Signals and connections in the hotkey destructor?
As i tried out with it there was an Error. But in an actual Version it is gone. Should Be.

User avatar
strooka
Space Kraken
Posts: 165
Joined: Tue Jun 23, 2009 5:34 pm
Location: Bielefeld, Germany

Re: Keybord Bindings

#42 Post by strooka »

here is a version of the hotkeymanager that implements disabling/enabling keys based on which window you are.
many thgings are hardcoded like the disable/enable functions which have to be rewritten for every wnd the hokey manager is implemented.

but it isnt much work, cause you can simply copy nearly all of the stuff.

as i implemented a destructor for the hotkeys the program didnt work anymore. so i suggest all is well done.
Attachments
HotKeyManager.tar.gz
hotkeymanager with state machine
(102.83 KiB) Downloaded 47 times

User avatar
Geoff the Medio
Programming, Design, Admin
Posts: 13603
Joined: Wed Oct 08, 2003 1:33 am
Location: Munich

Re: Keybord Bindings

#43 Post by Geoff the Medio »

strooka wrote:as i implemented a destructor for the hotkeys the program didnt work anymore. so i suggest all is well done.
Could you rephrase that? It reads like you're saying your code doesn't work, so you're done...?

User avatar
strooka
Space Kraken
Posts: 165
Joined: Tue Jun 23, 2009 5:34 pm
Location: Bielefeld, Germany

Re: Keybord Bindings

#44 Post by strooka »

i mean as i implemented a destructor in the HotKey class, that disconnected the signal and the connection, i couldn't make any key input anymore when running the program.

tell me pllz for which windows i shall implement the hotkeymanager, too.

User avatar
strooka
Space Kraken
Posts: 165
Joined: Tue Jun 23, 2009 5:34 pm
Location: Bielefeld, Germany

Re: Keybord Bindings

#45 Post by strooka »

geoff, the pointer to the window, given in the hotkeymanager::connect functions is needed by gg. the only thing i could change is that enabling/disabling of the hotkeys.

Post Reply