Duncan McIntyre / SimpleGUITouchScreen

Dependents:   TouchScreenGUIDemo

TouchScreenEventSource.cpp

Committer:
duncanFrance
Date:
2016-05-17
Revision:
4:0be0d6a61e90
Parent:
3:45777fe81448
Child:
5:e3084e17e8e6

File content as of revision 4:0be0d6a61e90:

#include "TouchScreenEventSource.h"
#include "EventType.h"

/**
* Implementation of TouchScreenEventSource which adds timers to detect and dispatch
* tap and double-tap events
**/

TouchScreenEventSource::TouchScreenEventSource(TouchScreen* touchScreen, GUI* gui) 
: EventSource(gui), _touchScreen(touchScreen), _state(Idle)
{
    _touchScreen->setTouchStartHandler(this, &TouchScreenEventSource::touchStartHandler);
    _touchScreen->setTouchEndHandler(this, &TouchScreenEventSource::touchEndHandler);
    _touchScreen->setTouchMoveHandler(this, &TouchScreenEventSource::touchMoveHandler);
}

void TouchScreenEventSource::touchStartHandler(TouchPosition p)
{
    if(_state == Idle) {
        // see if we get the touchEnd event before the timeout
        _state = SingleTimer;
        _timeout.attach_us(this, &TouchScreenEventSource::_timeoutHandler, TAP_TIMEOUT_MICROS);
    }
    
    Event e;
    e.screenX = p.screenX;
    e.screenY = p.screenY;
    e.type = TOUCH_START;
    _gui->queueEvent(e);
}

void TouchScreenEventSource::touchMoveHandler(TouchPosition p)
{
    
    Event e;
    e.screenX = p.screenX;
    e.screenY = p.screenY;
    e.type = TOUCH_MOVE;
    _gui->queueEvent(e);
}

void TouchScreenEventSource::touchEndHandler(TouchPosition p)
{
    // Work out what events we need before we dispatch them, so the handler doesn't interfere with any timers
    Event endEvent;
    Event tapEvent;
    bool tapped = false;
    
    // We always want to dispatch a touchEndEvent
    endEvent.screenX = p.screenX;
    endEvent.screenY = p.screenY;
    endEvent.type = TOUCH_END;
    
    tapEvent.screenX = p.screenX;
    tapEvent.screenY = p.screenY;

    // We'll want a touchTapEvent if we haven't timed out and we're looking for it
    if(_state == SingleTimer) {
        // Reset the timer to look for a double-tap
        _timeout.attach_us(this, &TouchScreenEventSource::_timeoutHandler, DOUBLE_TAP_TIMEOUT_MICROS);
        _state = DoubleTimer;
        
        tapEvent.type = TOUCH_TAP;
        tapped = true;
    } else if(_state == DoubleTimer) {
        
        _timeout.detach();
        _state = Idle;
        
        tapEvent.type = TOUCH_DOUBLE_TAP;
        tapped = true;
    }
        
    _gui->queueEvent(endEvent);
    
    if(tapped) {
        _gui->queueEvent(tapEvent);
    }
}

void TouchScreenEventSource::_timeoutHandler() {
    // Timed out waiting for whatever, so clear the state
    _state = Idle;
}