Richard Parker / EALCD

extras/EASettings.cpp

Committer:
richardparker
Date:
2010-11-01
Revision:
7:6cf21b018420
Parent:
4:f8f7f4f9c58d

File content as of revision 7:6cf21b018420:

// Copyright 2010 Richard Parker

#include "mbed.h"

#include "EASettings.h"

#include "../screen/EALCD.h"
#include "../screen/EATouch.h"
#include "../manager/EATouchManager.h"
#include "../widgets/EAButton.h"
#include "../widgets/EACompass.h"

#include "HMC6352.h"

EASettings::EASettings(EALCD& lcd, EATouch& touch, EATouchManager& manager, HMC6352& compass)
:   _lcd(lcd),
    _touch(touch),
    _manager(manager),
    _compass(compass),
    _time(NULL),
    _compassCircle(NULL),
    _launchBox(NULL),
    _returnBox(NULL),
    _touchBox(NULL),
    _dateBox(NULL),
    _compassBox(NULL),
    _nextBox(NULL),
    _prevBox(NULL),
    _incBox(NULL),
    _decBox(NULL),
    _state(EASettings::STATE_ENDED)
{
    // Actually start the RTC without this call RTC is not running.
    set_time(0);
    time_t seconds = time(NULL);
    _time = localtime(&seconds);
}

EASettings::~EASettings()
{
}

void EASettings::start()
{
    _state = EASettings::STATE_IDLE;
    _drawLaunchButton();
}

void EASettings::tick()
{
    // Do action depending on the state that in.
    switch(state())
    {
        case EASettings::STATE_COMPASS:
            _updateCompass();
        break;
    }   
}

void EASettings::actionHandler(EAHitBox* box, short x, short y)
{
    State nextState = EASettings::STATE_IDLE;

    // Disable hit boxs from previous screens.
    _disableHitBoxs();
    
    // Do action depending on the state that in.
    switch(state())
    {
        case EASettings::STATE_IDLE:
            _drawPortal();
            nextState = EASettings::STATE_PORTAL;
        break;
        case EASettings::STATE_PORTAL:
            if (box == _returnBox->hitBox())
            {
                nextState = EASettings::STATE_ENDED;
            }
            else if (box == _touchBox->hitBox())
            {
                _touch.calibrate();
                _drawPortal();
                nextState = EASettings::STATE_PORTAL;
            }
            else if (box == _dateBox->hitBox())
            {
                _drawDate();
                _state = EASettings::STATE_DATE_SECOND;
                nextState = _nextDate();                
            }
            else if (box == _compassBox->hitBox())
            {
                _drawCompass();
                nextState = EASettings::STATE_COMPASS;
            } else {
                _drawPortal();
                nextState = EASettings::STATE_PORTAL;
            }
        break;
        case EASettings::STATE_COMPASS:
            if (box == _returnBox->hitBox())
            {
                _drawPortal();
                nextState = EASettings::STATE_PORTAL;
            } else {
                _drawCompass();
                nextState = EASettings::STATE_COMPASS;
            }
        break;
        case EASettings::STATE_DATE_DAY:
        case EASettings::STATE_DATE_MONTH:
        case EASettings::STATE_DATE_YEAR:
        case EASettings::STATE_DATE_HOUR:
        case EASettings::STATE_DATE_MINUTE:
        case EASettings::STATE_DATE_SECOND:
            if (box == _returnBox->hitBox())
            {
                set_time(mktime(_time));
                _drawPortal();
                nextState = EASettings::STATE_PORTAL;
            }
            else if (box == _nextBox->hitBox())
            {
                nextState = _nextDate();
            }
            else if (box == _prevBox->hitBox())
            {
                nextState = _prevDate();
            }
            else if (box == _incBox->hitBox())
            {
                nextState = _incDate();
            }
            else if (box == _decBox->hitBox())
            {
                nextState = _decDate();
            } else {
                _drawPortal();
                nextState = EASettings::STATE_PORTAL;
            }
            _enableDateButtons();
        break;
        default:
            nextState = EASettings::STATE_ENDED;
        break;
    }
    
    _state = nextState;    
}

void EASettings::_disableHitBoxs()
{   
    if (_launchBox != NULL)
    {
        _launchBox->setEnabled(false);
    }
    
    if (_returnBox != NULL)
    {
        _returnBox->setEnabled(false);
    }

    if (_touchBox != NULL)
    {
        _touchBox->setEnabled(false);
    }

    if (_dateBox != NULL)
    {
        _dateBox->setEnabled(false);
    }
    
    if (_compassBox != NULL)
    {
        _compassBox->setEnabled(false);
    }
    
    if (_nextBox != NULL)
    {
        _nextBox->setEnabled(false);
    }

    if (_prevBox != NULL)
    {
        _prevBox->setEnabled(false);
    }

    if (_incBox != NULL)
    {
        _incBox->setEnabled(false);
    }

    if (_decBox != NULL)
    {
        _decBox->setEnabled(false);
    }
}

void EASettings::_drawLaunchButton()
{
    // Setup colours and clear screen to known background.    
    EAColor white = EAColor(0xFF, 0xFF, 0xFF);
    EAColor black = EAColor(0x00, 0x00, 0x00);

    EAFont font;
    EABrush brush = _lcd.brush();
    EAPen pen = _lcd.pen();
      
    font.load("/local/large.fnt");   
    _lcd.setFont(font);
      
    brush.setColor(black);
    _lcd.setBrush(brush);

    pen.setColor(white);
    _lcd.setPen(pen);

    // Create hit box if not already available.
    if (_launchBox == NULL)
    {
        _launchBox = new EAButton(_manager, _lcd.width()-60, _lcd.height()-60, 60, 60, "S", this);
    } else {
        _launchBox->setEnabled(true);
    }
    _launchBox->paint(_lcd);
}

void EASettings::_drawPortal()
{
    // Setup colours and clear screen to known background.    
    EAColor white = EAColor(0xFF, 0xFF, 0xFF);
    EAColor black = EAColor(0x00, 0x00, 0x00);
    
    EAFont font;
    EABrush brush = _lcd.brush();
    EAPen pen = _lcd.pen();
      
    font.load("/local/large.fnt");   
    _lcd.setFont(font);
    
    // DEBUG
    printf("Font set\r\n");

    brush.setColor(black);
    _lcd.setBrush(brush);

    pen.setColor(white);
    _lcd.setPen(pen);
    
    // Clear the screen to draw the buttons on.
    _lcd.clearScreen();

    // Draw title.
    _lcd.drawText((_lcd.width()/2)-(size()*2)+50, 10, "Settings");
   
    // Create hit box if not already available.
    if (_compassBox == NULL)
    {
        _compassBox = new EAButton(_manager, (_lcd.width()/2)-(size()*2), _lcd.height()-(size()*5), size()*4, size(), "Calibrate Compass", this);
    } else {
        _compassBox->setEnabled(true);
    }
    _compassBox->paint(_lcd);

    // Create hit box if not already available.
    if (_dateBox == NULL)
    {
        _dateBox = new EAButton(_manager, (_lcd.width()/2)-(size()*2), _lcd.height()-(size()*4), size()*4, size(), "Set Date", this);
    } else {
        _dateBox->setEnabled(true);
    }
    _dateBox->paint(_lcd);

    // Create hit box if not already available.
    if (_touchBox == NULL)
    {
        _touchBox = new EAButton(_manager, (_lcd.width()/2)-(size()*2), _lcd.height()-(size()*3), size()*4, size(), "Touch Calibration", this);
    } else {
        _touchBox->setEnabled(true);
    }
    _touchBox->paint(_lcd);  

    // Create hit box if not already available.
    if (_returnBox == NULL)
    {
        _returnBox = new EAButton(_manager, (_lcd.width()/2)-(size()*2), _lcd.height()-(size()*2), size()*4, size(), "Return...", this);
    } else {
        _returnBox->setEnabled(true);
    }
    _returnBox->paint(_lcd);
    
}

void EASettings::_updateCompass()
{
    float angle = _compass.getHeading();
    angle = (angle * PI)/180;
    
    if (_compassCircle != NULL)
    {
        _compassCircle->update(_lcd, angle);
    }
}

void EASettings::_drawCompass()
{
    // Setup colours and clear screen to known background.    
    EAColor white = EAColor(0xFF, 0xFF, 0xFF);
    EAColor black = EAColor(0x00, 0x00, 0x00);
    
    EAFont font;
    EABrush brush = _lcd.brush();
    EAPen pen = _lcd.pen();
      
    font.load("/local/large.fnt");   
    _lcd.setFont(font);

    brush.setColor(black);
    _lcd.setBrush(brush);

    pen.setColor(white);
    _lcd.setPen(pen);
    
    // Clear the screen to draw the buttons on.
    _lcd.clearScreen();

    // Draw title.
    _lcd.drawText((_lcd.width()/2)-(size()*2), 10, "Compass Calibration");

    // Create compass if not already available.
    if (_compassCircle == NULL)
    {
        _compassCircle = new EACompass((_lcd.width()/2)-(size()*1.5), (_lcd.height()/2)-(size()*1.5)-25, size()*3, 0);
    }
    _compassCircle->paint(_lcd);

    // Create hit box if not already available.
    if (_returnBox == NULL)
    {
        _returnBox = new EAButton(_manager, (_lcd.width()/2)-(size()*2), _lcd.height()-(size()*2), size()*4, size(), "Return...", this);
    } else {
        _returnBox->setEnabled(true);
    }
    _returnBox->paint(_lcd);    
}

void EASettings::_drawDate()
{
    // Setup colours and clear screen to known background.    
    EAColor white = EAColor(0xFF, 0xFF, 0xFF);
    EAColor black = EAColor(0x00, 0x00, 0x00);
    
    EAFont font;
    EABrush brush = _lcd.brush();
    EAPen pen = _lcd.pen();
      
    font.load("/local/large.fnt");   
    _lcd.setFont(font);

    brush.setColor(black);
    _lcd.setBrush(brush);

    pen.setColor(white);
    _lcd.setPen(pen);
    
    // Clear the screen to draw the buttons on.
    _lcd.clearScreen();

    // Draw title.
    _lcd.drawText((_lcd.width()/2)-(size()*2)+50, 10, "Date/Time");

    // Draw date.
    char buffer[5];
    short y = 60;
    short x = (_lcd.width()/2)-(size()*2)-25;

    // Update cached time.    
    time_t seconds = time(NULL);
    _time = localtime(&seconds);
    
    // Put the day of the month into the buffer and display.
    sprintf(buffer, "%02d", _time->tm_mday);
    _lcd.drawText(x, y, buffer);
    
    // Display spacer.
    _lcd.drawText(x+20, y, "/");  
    
    // Put the month into the buffer and display.
    sprintf(buffer, "%02d", _time->tm_mon+1);
    _lcd.drawText(x+30, y, buffer);

    // Display spacer.
    _lcd.drawText(x+50, y, "/");  
    
    // Put the month into the buffer and display.
    sprintf(buffer, "%04d", _time->tm_year+1900);
    _lcd.drawText(x+60, y, buffer);

    // Put the hour into the buffer and display.
    sprintf(buffer, "%02d", _time->tm_hour);
    _lcd.drawText(x+120, y, buffer);
    
    // Display spacer.
    _lcd.drawText(x+140, y, ":");  
    
    // Put the minute into the buffer and display.
    sprintf(buffer, "%02d", _time->tm_min);
    _lcd.drawText(x+150, y, buffer);

    // Display spacer.
    _lcd.drawText(x+170, y, ":");  
    
    // Put the minute into the buffer and display.
    sprintf(buffer, "%02d", _time->tm_sec);
    _lcd.drawText(x+180, y, buffer);

    _enableDateButtons();     
    _prevBox->paint(_lcd);
    _nextBox->paint(_lcd);
    _decBox->paint(_lcd);
    _incBox->paint(_lcd);
    _returnBox->paint(_lcd);
}

void EASettings::_enableDateButtons()
{
    // Create hit box if not already available.
    if (_prevBox == NULL)
    {
        _prevBox = new EAButton(_manager, (_lcd.width()/2)-(size()*3), _lcd.height()-(size()*3.5), size(), size(), "<", this);
    } else {
        _prevBox->setEnabled(true);
    }

    // Create hit box if not already available.
    if (_nextBox == NULL)
    {
        _nextBox = new EAButton(_manager, (_lcd.width()/2)-(size()*1.5), _lcd.height()-(size()*3.5), size(), size(), ">", this);
    } else {
        _nextBox->setEnabled(true);
    }

    // Create hit box if not already available.
    if (_decBox == NULL)
    {
        _decBox = new EAButton(_manager, (_lcd.width()/2)+(size()*0.5), _lcd.height()-(size()*3.5), size(), size(), "-", this);
    } else {
        _decBox->setEnabled(true);
    }

    // Create hit box if not already available.
    if (_incBox == NULL)
    {
        _incBox = new EAButton(_manager, (_lcd.width()/2)+(size()*2), _lcd.height()-(size()*3.5), size(), size(), "+", this);
    } else {
        _incBox->setEnabled(true);
    }

    // Create hit box if not already available.
    if (_returnBox == NULL)
    {
        _returnBox = new EAButton(_manager, (_lcd.width()/2)-(size()*2), _lcd.height()-(size()*2), size()*4, size(), "Return...", this);
    } else {
        _returnBox->setEnabled(true);
    }
}

EASettings::State EASettings::_incDate()
{    
    char buffer[5];
    short y = 60;
    short x = (_lcd.width()/2)-(size()*2)-25;
    tm oldTime = *_time;

    // Setup colours and clear screen to known background.    
    EAColor white = EAColor(0xFF, 0xFF, 0xFF);
    EAColor black = EAColor(0x00, 0x00, 0x00);

    EAFont font;    
    EABrush brush = _lcd.brush();
    EAPen pen = _lcd.pen();
      
    font.load("/local/large.fnt");   
    _lcd.setFont(font);
      
    brush.setColor(black);
    _lcd.setBrush(brush);

    pen.setColor(black);
    _lcd.setPen(pen);

    // Now clear selection box.
    switch (state())
    {
        default:
        case EASettings::STATE_DATE_DAY:
            _time->tm_mday = (int)(_time->tm_mday+1) % 32;
            if (_time->tm_mday == 0) _time->tm_mday = 1;
        break;
        case EASettings::STATE_DATE_MONTH:
            _time->tm_mon = (int)(_time->tm_mon+1) % 12;
            printf("Month: %d\r\n", _time->tm_mon);
        break;
        case EASettings::STATE_DATE_YEAR:
            _time->tm_year++;
        break;
        case EASettings::STATE_DATE_HOUR:
            _time->tm_hour = (int)(_time->tm_hour+1) % 60;
        break;
        case EASettings::STATE_DATE_MINUTE:
            _time->tm_min = (int)(_time->tm_min+1) % 60;
        break;
        case EASettings::STATE_DATE_SECOND:
            _time->tm_sec = (int)(_time->tm_sec+1) % 60;
        break;
    }
    
    // This converts to a valid value e.g. the value is too large for the month.
    time_t seconds = mktime(_time);
    printf("Time value is: %d\r\n", seconds);
    if (seconds == (time_t)-1)
    {
        printf("Bad time, not changing time...\r\n");
        *_time = oldTime;
    } else {
        _time = localtime(&seconds);
    }
    
    if (oldTime.tm_mday != _time->tm_mday)
    {
        _lcd.drawFilledRect(x, y, 20, 20);
        sprintf(buffer, "%02d", _time->tm_mday);
        pen.setColor(white);
        _lcd.setPen(pen);
        _lcd.drawText(x, y, buffer);                   
        pen.setColor(black);
        _lcd.setPen(pen);
    }
    if (oldTime.tm_mon != _time->tm_mon)
    {
        _lcd.drawFilledRect(x+30, y, 20, 20);
        sprintf(buffer, "%02d", _time->tm_mon+1);
        pen.setColor(white);
        _lcd.setPen(pen);
        _lcd.drawText(x+30, y, buffer);                   
        pen.setColor(black);
        _lcd.setPen(pen);
    }
    if (oldTime.tm_year != _time->tm_year)
    {
        _lcd.drawFilledRect(x+60, y, 40, 20);
        sprintf(buffer, "%04d", _time->tm_year+1900);
        pen.setColor(white);
        _lcd.setPen(pen);
        _lcd.drawText(x+60, y, buffer);                   
        pen.setColor(black);
        _lcd.setPen(pen);
    }
    if (oldTime.tm_hour != _time->tm_hour)
    {
        _lcd.drawFilledRect(x+120, y, 20, 20);
        sprintf(buffer, "%02d", _time->tm_hour);
        pen.setColor(white);
        _lcd.setPen(pen);
        _lcd.drawText(x+120, y, buffer);                   
        pen.setColor(black);
        _lcd.setPen(pen);
    }
    if (oldTime.tm_min != _time->tm_min)
    {
        _lcd.drawFilledRect(x+150, y, 20, 20);
        sprintf(buffer, "%02d", _time->tm_min);
        pen.setColor(white);
        _lcd.setPen(pen);
        _lcd.drawText(x+150, y, buffer);                   
        pen.setColor(black);
        _lcd.setPen(pen);
    }
    if (oldTime.tm_sec != _time->tm_sec)
    {
        _lcd.drawFilledRect(x+180, y, 20, 20);
        sprintf(buffer, "%02d", _time->tm_sec);
        pen.setColor(white);
        _lcd.setPen(pen);
        _lcd.drawText(x+180, y, buffer);                   
        pen.setColor(black);
        _lcd.setPen(pen);
    }  

    pen.setColor(white);
    _lcd.setPen(pen);

    // Now redraw selection box.
    switch (state())
    {
        default:
        case EASettings::STATE_DATE_DAY:
            _lcd.drawRect(x, y, 20, 20);
        break;
        case EASettings::STATE_DATE_MONTH:
            _lcd.drawRect(x+30, y, 20, 20);
        break;
        case EASettings::STATE_DATE_YEAR:
            _lcd.drawRect(x+60, y, 40, 20);
        break;
        case EASettings::STATE_DATE_HOUR:
            _lcd.drawRect(x+120, y, 20, 20);
        break;
        case EASettings::STATE_DATE_MINUTE:
            _lcd.drawRect(x+150, y, 20, 20);
        break;
        case EASettings::STATE_DATE_SECOND:
            _lcd.drawRect(x+180, y, 20, 20);
        break;
    }

    return state();
}

EASettings::State EASettings::_decDate()
{
    char buffer[5];
    short y = 60;
    short x = (_lcd.width()/2)-(size()*2)-25;
    tm oldTime = *_time;

    // Setup colours and clear screen to known background.    
    EAColor white = EAColor(0xFF, 0xFF, 0xFF);
    EAColor black = EAColor(0x00, 0x00, 0x00);

    EAFont font;    
    EABrush brush = _lcd.brush();
    EAPen pen = _lcd.pen();
      
    font.load("/local/large.fnt");   
    _lcd.setFont(font);
      
    brush.setColor(black);
    _lcd.setBrush(brush);

    pen.setColor(black);
    _lcd.setPen(pen);

    switch (state())
    {
        default:
        case EASettings::STATE_DATE_DAY:
            _time->tm_mday = (int)(_time->tm_mday-1) % 32;
            if (_time->tm_mday == 0) _time->tm_mday = 31;
        break;
        case EASettings::STATE_DATE_MONTH:
            _time->tm_mon = (int)(_time->tm_mon-1) % 12;
        break;
        case EASettings::STATE_DATE_YEAR:
            if (_time->tm_year > 70)
            {
                _time->tm_year--;
            }
        break;
        case EASettings::STATE_DATE_HOUR:
            _time->tm_hour = (int)(_time->tm_hour-1) % 60;
        break;
        case EASettings::STATE_DATE_MINUTE:
            _time->tm_min = (int)(_time->tm_min-1) % 60;
        break;
        case EASettings::STATE_DATE_SECOND:
            _time->tm_sec = (int)(_time->tm_sec-1) % 60;
        break;
    }
    
    // This converts to a valid value e.g. the value is too large for the month.
    time_t seconds = mktime(_time);
    printf("Time value is: %d\r\n", seconds);
    if (seconds == (time_t)-1)
    {
        printf("Bad time, not changing time...\r\n");
        *_time = oldTime;
    } else {
        _time = localtime(&seconds);
    }
    
    if (oldTime.tm_mday != _time->tm_mday)
    {
        _lcd.drawFilledRect(x, y, 20, 20);
        sprintf(buffer, "%02d", _time->tm_mday);
        pen.setColor(white);
        _lcd.setPen(pen);
        _lcd.drawText(x, y, buffer);                   
        pen.setColor(black);
        _lcd.setPen(pen);
    }
    if (oldTime.tm_mon != _time->tm_mon)
    {
        _lcd.drawFilledRect(x+30, y, 20, 20);
        sprintf(buffer, "%02d", _time->tm_mon+1);
        pen.setColor(white);
        _lcd.setPen(pen);
        _lcd.drawText(x+30, y, buffer);                   
        pen.setColor(black);
        _lcd.setPen(pen);
    }
    if (oldTime.tm_year != _time->tm_year)
    {
        _lcd.drawFilledRect(x+60, y, 40, 20);
        sprintf(buffer, "%04d", _time->tm_year+1900);
        pen.setColor(white);
        _lcd.setPen(pen);
        _lcd.drawText(x+60, y, buffer);                   
        pen.setColor(black);
        _lcd.setPen(pen);
    }
    if (oldTime.tm_hour != _time->tm_hour)
    {
        _lcd.drawFilledRect(x+120, y, 20, 20);
        sprintf(buffer, "%02d", _time->tm_hour);
        pen.setColor(white);
        _lcd.setPen(pen);
        _lcd.drawText(x+120, y, buffer);                   
        pen.setColor(black);
        _lcd.setPen(pen);
    }
    if (oldTime.tm_min != _time->tm_min)
    {
        _lcd.drawFilledRect(x+150, y, 20, 20);
        sprintf(buffer, "%02d", _time->tm_min);
        pen.setColor(white);
        _lcd.setPen(pen);
        _lcd.drawText(x+150, y, buffer);                   
        pen.setColor(black);
        _lcd.setPen(pen);
    }
    if (oldTime.tm_sec != _time->tm_sec)
    {
        _lcd.drawFilledRect(x+180, y, 20, 20);
        sprintf(buffer, "%02d", _time->tm_sec);
        pen.setColor(white);
        _lcd.setPen(pen);
        _lcd.drawText(x+180, y, buffer);                   
        pen.setColor(black);
        _lcd.setPen(pen);
    }  

    pen.setColor(white);
    _lcd.setPen(pen);

    // Now redraw selection box.
    switch (state())
    {
        default:
        case EASettings::STATE_DATE_DAY:
            _lcd.drawRect(x, y, 20, 20);
        break;
        case EASettings::STATE_DATE_MONTH:
            _lcd.drawRect(x+30, y, 20, 20);
        break;
        case EASettings::STATE_DATE_YEAR:
            _lcd.drawRect(x+60, y, 40, 20);
        break;
        case EASettings::STATE_DATE_HOUR:
            _lcd.drawRect(x+120, y, 20, 20);
        break;
        case EASettings::STATE_DATE_MINUTE:
            _lcd.drawRect(x+150, y, 20, 20);
        break;
        case EASettings::STATE_DATE_SECOND:
            _lcd.drawRect(x+180, y, 20, 20);
        break;
    }

    return state();
}

EASettings::State EASettings::_nextDate()
{
    short y = 60;
    short x = (_lcd.width()/2)-(size()*2)-25;

    EASettings::State nextState = EASettings::STATE_IDLE;

    // Setup colours and clear screen to known background.    
    EAColor white = EAColor(0xFF, 0xFF, 0xFF);
    EAColor black = EAColor(0x00, 0x00, 0x00);
    
    EABrush brush = _lcd.brush();
    EAPen pen = _lcd.pen();
      
    brush.setColor(white);
    _lcd.setBrush(brush);

    pen.setColor(black);
    _lcd.setPen(pen);

    // Now clear selection box.
    switch (state())
    {
        default:
        case EASettings::STATE_DATE_DAY:
            _lcd.drawRect(x, y, 20, 20);
        break;
        case EASettings::STATE_DATE_MONTH:
            _lcd.drawRect(x+30, y, 20, 20);
        break;
        case EASettings::STATE_DATE_YEAR:
            _lcd.drawRect(x+60, y, 40, 20);
        break;
        case EASettings::STATE_DATE_HOUR:
            _lcd.drawRect(x+120, y, 20, 20);
        break;
        case EASettings::STATE_DATE_MINUTE:
            _lcd.drawRect(x+150, y, 20, 20);
        break;
        case EASettings::STATE_DATE_SECOND:
            _lcd.drawRect(x+180, y, 20, 20);
        break;
    }

    brush.setColor(black);
    _lcd.setBrush(brush);

    pen.setColor(white);
    _lcd.setPen(pen);

    // Now draw selection box.
    switch (state())
    {
        default:
        case EASettings::STATE_DATE_DAY:
            nextState = EASettings::STATE_DATE_MONTH;
            _lcd.drawRect(x+30, y, 20, 20);
        break;
        case EASettings::STATE_DATE_MONTH:
            nextState = EASettings::STATE_DATE_YEAR;
            _lcd.drawRect(x+60, y, 40, 20);
        break;
        case EASettings::STATE_DATE_YEAR:
            nextState = EASettings::STATE_DATE_HOUR;
            _lcd.drawRect(x+120, y, 20, 20);
        break;
        case EASettings::STATE_DATE_HOUR:
            nextState = EASettings::STATE_DATE_MINUTE;
            _lcd.drawRect(x+150, y, 20, 20);
        break;
        case EASettings::STATE_DATE_MINUTE:
            nextState = EASettings::STATE_DATE_SECOND;
            _lcd.drawRect(x+180, y, 20, 20);
        break;
        case EASettings::STATE_DATE_SECOND:
            nextState = EASettings::STATE_DATE_DAY;
            _lcd.drawRect(x, y, 20, 20);
        break;
    }
    
    return nextState;
}

EASettings::State EASettings::_prevDate()
{
    short y = 60;
    short x = (_lcd.width()/2)-(size()*2)-25;

    EASettings::State prevState = EASettings::STATE_IDLE;

    // Setup colours and clear screen to known background.    
    EAColor white = EAColor(0xFF, 0xFF, 0xFF);
    EAColor black = EAColor(0x00, 0x00, 0x00);
    
    EABrush brush = _lcd.brush();
    EAPen pen = _lcd.pen();
      
    brush.setColor(white);
    _lcd.setBrush(brush);

    pen.setColor(black);
    _lcd.setPen(pen);

    // Now clear selection box.
    switch (state())
    {
        default:
        case EASettings::STATE_DATE_DAY:
            _lcd.drawRect(x, y, 20, 20);
        break;
        case EASettings::STATE_DATE_MONTH:
            _lcd.drawRect(x+30, y, 20, 20);
        break;
        case EASettings::STATE_DATE_YEAR:
            _lcd.drawRect(x+60, y, 40, 20);
        break;
        case EASettings::STATE_DATE_HOUR:
            _lcd.drawRect(x+120, y, 20, 20);
        break;
        case EASettings::STATE_DATE_MINUTE:
            _lcd.drawRect(x+150, y, 20, 20);
        break;
        case EASettings::STATE_DATE_SECOND:
            _lcd.drawRect(x+180, y, 20, 20);
        break;
    }

    brush.setColor(black);
    _lcd.setBrush(brush);

    pen.setColor(white);
    _lcd.setPen(pen);

    // Now draw selection box.
    switch (state())
    {
        default:
        case EASettings::STATE_DATE_DAY:
            prevState = EASettings::STATE_DATE_SECOND;
            _lcd.drawRect(x+180, y, 20, 20);
        break;
        case EASettings::STATE_DATE_MONTH:
            prevState = EASettings::STATE_DATE_DAY;
            _lcd.drawRect(x, y, 20, 20);
        break;
        case EASettings::STATE_DATE_YEAR:
            prevState = EASettings::STATE_DATE_MONTH;
            _lcd.drawRect(x+30, y, 20, 20);
        break;
        case EASettings::STATE_DATE_HOUR:
            prevState = EASettings::STATE_DATE_YEAR;
            _lcd.drawRect(x+60, y, 40, 20);
        break;
        case EASettings::STATE_DATE_MINUTE:
            prevState = EASettings::STATE_DATE_HOUR;
            _lcd.drawRect(x+120, y, 20, 20);
        break;
        case EASettings::STATE_DATE_SECOND:
            prevState = EASettings::STATE_DATE_MINUTE;
            _lcd.drawRect(x+150, y, 20, 20);
        break;
    }
    
    return prevState;
}