KeyboardManager: a class to manage the polling of a switch-matrix keyboard

Dependents:   KeyboardTest

kbd_mgr/LongKeyPressMonitor.h

Committer:
osmeest
Date:
2011-02-03
Revision:
3:1310c57aca77

File content as of revision 3:1310c57aca77:

#ifndef LONG_KEY_PRESS_MONITOR_H_
#define LONG_KEY_PRESS_MONITOR_H_

#include <kbd_mgr/KeyPressEventServer.h>
#include <set>

#include "mbed.h"

namespace kbd_mgr {

/**
 * @brief A key press event handler that detects long key presses and report them as specified.
 * This class offers two specific reactions for long key presses. Either a specific long key press is reported
 * or the key press event is auto repeated. The timing for both kind of reactions can be specified independently.
 * The monitor reacts on key code, not on mapped key char. If a mapped key char is present in the event, it is retained
 * in the generated key press events.
 */
class LongKeyPressMonitor : public KeyPressEventServer, public KeyPressEventHandler {
public:
    LongKeyPressMonitor() : 
        repeatKeys_(), repeatInitTime_(0), repeatDelay_(0), longPressKeys_(), longPressTime_(0),
        state(Idle), keyDownCount(0), timer()
    { }
    
    class AutoRepeatSetupProxy {
    public:
        AutoRepeatSetupProxy(LongKeyPressMonitor *monitor) : monitor_(monitor) { }
        AutoRepeatSetupProxy& operator()(int key) { this->monitor_->addAutoRepeatKey(key, key); return *this; }
        AutoRepeatSetupProxy& operator()(int firstKey, int lastKey) { this->monitor_->addAutoRepeatKey(firstKey, lastKey); return *this; }
        
    private:
        LongKeyPressMonitor *monitor_;
    };
    
    friend class AutoRepeatSetupProxy;
    
    /**
     * @brief Sets up auto-repeat keys.
     * This method takes the timing parameters. It returns a special class that allows specifying the keys
     * between brackets. Eg: 
     *  - monitor.autoRepeat(0.3, 0.1)(1)(2)(4,8)
     *    Sets up auto repeat after 300ms, every 100ms for keys 1, 2 and 4 to 8.
     */
    AutoRepeatSetupProxy autoRepeat(float initTime, float delay); 
    
    
    class LongPressSetupProxy {
    public:
        LongPressSetupProxy(LongKeyPressMonitor *monitor) : monitor_(monitor) { }
        LongPressSetupProxy& operator()(int key) { this->monitor_->addLongPressKey(key, key); return *this; }
        LongPressSetupProxy& operator()(int firstKey, int lastKey) { this->monitor_->addLongPressKey(firstKey, lastKey); return *this; }
        
    private:
        LongKeyPressMonitor *monitor_;
    };
    
    friend class LongPressSetupProxy;
    
    /**
     * @brief Sets up long key press keys.
     * This method takes the timing parameters. It returns a special class that allows specifying the keys
     * between brackets. Eg: 
     *  - monitor.longKeyPress(0.5)(3)(12,14)
     *    Sets up report of long key press after 500ms for keys 3 and 12 to 14.
     */
    LongPressSetupProxy longKeyPress(float longPressTime);
    
    /**
     * @brief KeyPressEventHandler interface
     */
    virtual void handleKeyPress(const KeyEvent &keypress);
    
private:
    void addAutoRepeatKey(int firstKey, int lastKey);
    bool isAutoRepeatKey(int key) const { return this->repeatKeys_.find(key) != this->repeatKeys_.end(); }
    void addLongPressKey(int firstKey, int lastKey);
    bool isLongPressKey(int key) const { return this->longPressKeys_.find(key) != this->longPressKeys_.end(); }
    
    void handleKeyDown(const KeyEvent &keypress);
    void handleFirstKeyDown(const KeyEvent &keypress);
    void handleOtherKeyDown(const KeyEvent &keypress);
    void handleKeyUp(const KeyEvent &keypress);
    void handleLastKeyUp(const KeyEvent &keypress);

    void handleTimer();
    void handleRepeatTimer();
    void handleLongPressTimer();
    
    typedef std::set<int> KeySet;
    
    KeySet repeatKeys_;
    float repeatInitTime_;
    float repeatDelay_;
    
    KeySet longPressKeys_;
    float longPressTime_;
    
    enum State {
        Idle,
        RepeatInitWait,
        Repeating,
        LongPressWait,
        LongPressReported,
        Invalid
    };
    
    State state;
    KeyEvent keypress;
    int keyDownCount;
    Timeout timer;
};

} // kbd_mgr

#endif // LONG_KEY_PRESS_MONITOR_H_