Important changes to repositories hosted on mbed.com
Mbed hosted mercurial repositories are deprecated and are due to be permanently deleted in July 2026.
To keep a copy of this software download the repository Zip archive or clone locally using Mercurial.
It is also possible to export all your personal repositories from the account settings page.
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; }