ArduinoLibs
 All Classes Files Functions Variables Typedefs Enumerations Enumerator Friends Groups Pages
TimeField.cpp
1 /*
2  * Copyright (C) 2012 Southern Storm Software, Pty Ltd.
3  *
4  * Permission is hereby granted, free of charge, to any person obtaining a
5  * copy of this software and associated documentation files (the "Software"),
6  * to deal in the Software without restriction, including without limitation
7  * the rights to use, copy, modify, merge, publish, distribute, sublicense,
8  * and/or sell copies of the Software, and to permit persons to whom the
9  * Software is furnished to do so, subject to the following conditions:
10  *
11  * The above copyright notice and this permission notice shall be included
12  * in all copies or substantial portions of the Software.
13  *
14  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
15  * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
16  * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
17  * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
18  * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
19  * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
20  * DEALINGS IN THE SOFTWARE.
21  */
22 
23 #include "TimeField.h"
24 
65 #define EDIT_HOUR 0
66 #define EDIT_MINUTE_TENS 1
67 #define EDIT_MINUTE 2
68 #define EDIT_SECOND_TENS 3
69 #define EDIT_SECOND 4
70 
82 TimeField::TimeField(const String &label)
83  : Field(label)
84  , _value(0)
85  , _maxHours(24)
86  , _printLen(0)
87  , _readOnly(false)
88  , editField(EDIT_HOUR)
89 {
90 }
91 
105 TimeField::TimeField(Form &form, const String &label, int maxHours, bool readOnly)
106  : Field(form, label)
107  , _value(0)
108  , _maxHours(maxHours)
109  , _printLen(0)
110  , _readOnly(readOnly)
111  , editField(EDIT_HOUR)
112 {
113 }
114 
115 int TimeField::dispatch(int event)
116 {
117  unsigned long newValue;
118  if (_readOnly)
119  return -1;
120  if (event == LCD_BUTTON_UP) {
121  newValue = _value;
122  if (editField == EDIT_HOUR) {
123  newValue += 60 * 60;
124  } else if (editField == EDIT_MINUTE_TENS) {
125  if (((newValue / 60) % 60) >= 50)
126  newValue -= 50 * 60;
127  else
128  newValue += 10 * 60;
129  } else if (editField == EDIT_MINUTE) {
130  if (((newValue / 60) % 60) == 59)
131  newValue -= 59 * 60;
132  else
133  newValue += 60;
134  } else if (editField == EDIT_SECOND_TENS) {
135  if ((newValue % 60) >= 50)
136  newValue -= 50;
137  else
138  newValue += 10;
139  } else {
140  if ((newValue % 60) == 59)
141  newValue -= 59;
142  else
143  newValue += 1;
144  }
145  setValue(newValue);
146  return FORM_CHANGED;
147  } else if (event == LCD_BUTTON_DOWN) {
148  newValue = _value;
149  if (editField == EDIT_HOUR) {
150  if (newValue < 60 * 60)
151  newValue += ((unsigned long)(_maxHours - 1)) * 60 * 60;
152  else
153  newValue -= 60 * 60;
154  } else if (editField == EDIT_MINUTE_TENS) {
155  if (((newValue / 60) % 60) < 10)
156  newValue += 50 * 60;
157  else
158  newValue -= 10 * 60;
159  } else if (editField == EDIT_MINUTE) {
160  if (((newValue / 60) % 60) == 0)
161  newValue += 59 * 60;
162  else
163  newValue -= 60;
164  } else if (editField == EDIT_SECOND_TENS) {
165  if ((newValue % 60) < 10)
166  newValue += 50;
167  else
168  newValue -= 10;
169  } else {
170  if ((newValue % 60) == 0)
171  newValue += 59;
172  else
173  newValue -= 1;
174  }
175  setValue(newValue);
176  return FORM_CHANGED;
177  } else if (event == LCD_BUTTON_LEFT) {
178  if (editField != EDIT_HOUR) {
179  --editField;
180  printTime();
181  return 0;
182  }
183  } else if (event == LCD_BUTTON_RIGHT) {
184  if (editField != EDIT_SECOND) {
185  ++editField;
186  printTime();
187  return 0;
188  }
189  }
190  return -1;
191 }
192 
193 void TimeField::enterField(bool reverse)
194 {
195  Field::enterField(reverse);
196  if (reverse)
197  editField = EDIT_SECOND;
198  else
199  editField = EDIT_HOUR;
200  printTime();
201  if (!_readOnly)
202  lcd()->cursor();
203 }
204 
206 {
207  if (!_readOnly)
208  lcd()->noCursor();
210 }
211 
227 void TimeField::setValue(unsigned long value)
228 {
229  unsigned long maxSecs = ((unsigned long)_maxHours) * 60 * 60;
230  value %= maxSecs;
231  if (value != _value) {
232  _value = value;
233  if (isCurrent())
234  printTime();
235  }
236 }
237 
268 void TimeField::setReadOnly(bool value)
269 {
270  if (_readOnly != value) {
271  _readOnly = value;
272  printTime();
273  if (isCurrent()) {
274  if (value)
275  lcd()->cursor();
276  else
277  lcd()->noCursor();
278  }
279  }
280 }
281 
282 void TimeField::printTime()
283 {
284  lcd()->setCursor(0, 1);
285  int col = printField(_value / (60 * 60));
286  int hourCol = col - 1;
287  lcd()->write(':');
288  ++col;
289  col += printField((_value / 60) % 60);
290  int minuteCol = col - 1;
291  lcd()->write(':');
292  ++col;
293  col += printField(_value % 60);
294  int secondCol = col - 1;
295  int tempCol = col;
296  while (tempCol++ < _printLen)
297  lcd()->write(' ');
298  _printLen = col;
299  if (!_readOnly) {
300  if (editField == EDIT_HOUR)
301  lcd()->setCursor(hourCol, 1);
302  else if (editField == EDIT_MINUTE_TENS)
303  lcd()->setCursor(minuteCol - 1, 1);
304  else if (editField == EDIT_MINUTE)
305  lcd()->setCursor(minuteCol, 1);
306  else if (editField == EDIT_SECOND_TENS)
307  lcd()->setCursor(secondCol - 1, 1);
308  else
309  lcd()->setCursor(secondCol, 1);
310  }
311 }
312 
313 int TimeField::printField(unsigned long value)
314 {
315  if (value < 100) {
316  lcd()->write('0' + (int)(value / 10));
317  lcd()->write('0' + (int)(value % 10));
318  return 2;
319  }
320  unsigned long divisor = 100;
321  while ((value / divisor) >= 10)
322  divisor *= 10;
323  int digits = 0;
324  while (divisor > 0) {
325  lcd()->write('0' + (int)((value / divisor) % 10));
326  divisor /= 10;
327  ++digits;
328  }
329  return digits;
330 }
unsigned long value() const
Returns the current value of this time field, in seconds.
Definition: TimeField.h:41
void setReadOnly(bool value)
Sets the read-only state of this field to value.
Definition: TimeField.cpp:268
Manages a single data input/output field within a Form.
Definition: Field.h:28
Manager for a form containing data input/output fields.
Definition: Form.h:32
virtual void enterField(bool reverse)
Enters the field due to form navigation.
Definition: Field.cpp:116
LiquidCrystal * lcd() const
Returns the LCD that this field is being drawn on.
Definition: Field.h:47
int dispatch(int event)
Dispatches event via this field.
Definition: TimeField.cpp:115
virtual void exitField()
Exits the field due to form navigation.
Definition: Field.cpp:129
void enterField(bool reverse)
Enters the field due to form navigation.
Definition: TimeField.cpp:193
TimeField(const String &label)
Constructs a new time field with a specific label.
Definition: TimeField.cpp:82
bool isCurrent() const
Returns true if this field is the currently-displayed field in its owning form; false otherwise...
Definition: Field.cpp:169
void exitField()
Exits the field due to form navigation.
Definition: TimeField.cpp:205
void setValue(unsigned long value)
Sets the value of this time field, in seconds.
Definition: TimeField.cpp:227