tcMenu
RuntimeMenuItem.h
Go to the documentation of this file.
1 /*
2  * Copyright (c) 2018 https://www.thecoderscorner.com (Dave Cherry).
3  * This product is licensed under an Apache license, see the LICENSE file in the top-level directory.
4  */
5 
11 #ifndef _RUNTIME_MENUITEM_H_
12 #define _RUNTIME_MENUITEM_H_
13 
14 #include "MenuItems.h"
15 #include "tcUtil.h"
16 
18 #ifndef RANDOM_ID_START
19 #define RANDOM_ID_START 30000
20 #endif
21 
23 menuid_t nextRandomId();
24 
26 int textItemRenderFn(RuntimeMenuItem* item, uint8_t row, RenderFnMode mode, char* buffer, int bufferSize);
27 
29 int ipAddressRenderFn(RuntimeMenuItem* item, uint8_t row, RenderFnMode mode, char* buffer, int bufferSize);
30 
32 int backSubItemRenderFn(RuntimeMenuItem* item, uint8_t row, RenderFnMode mode, char* buffer, int bufferSize);
33 
35 int timeItemRenderFn(RuntimeMenuItem* item, uint8_t row, RenderFnMode mode, char* buffer, int bufferSize);
36 
38 int dateItemRenderFn(RuntimeMenuItem* item, uint8_t row, RenderFnMode mode, char* buffer, int bufferSize);
39 
41 int findPositionInEditorSet(char ch);
42 
46 enum MultiEditWireType : uint8_t {
67 };
68 
75 class RuntimeMenuItem : public MenuItem {
76 protected:
77  menuid_t id;
78  uint8_t itemPosition;
79  uint8_t noOfParts;
80 public:
81  RuntimeMenuItem(MenuType menuType, menuid_t id, RuntimeRenderingFn renderFn,
82  uint8_t itemPosition, uint8_t numberOfRows, MenuItem* next = nullptr);
83 
84  RuntimeMenuItem(const AnyMenuInfo* rtInfo, bool isPgm, MenuType menuType, RuntimeRenderingFn renderFn,
85  uint8_t itemPosition, uint8_t numberOfRows, MenuItem* next = nullptr);
86 
87  void copyValue(char* buffer, int bufferSize) const {
88  renderFn((RuntimeMenuItem*)this, itemPosition, RENDERFN_VALUE, buffer, bufferSize);
89  }
90 
91  void runCallback() const { renderFn((RuntimeMenuItem*)this, itemPosition, RENDERFN_INVOKE, nullptr, 0); }
92  int getRuntimeId() const { return int(id); }
93  int getRuntimeEeprom() const { return renderFn((RuntimeMenuItem*)this, itemPosition, RENDERFN_EEPROM_POS, nullptr, 0); }
94  uint8_t getNumberOfParts() const { return noOfParts; }
95  void copyRuntimeName(char* buffer, int bufferSize) const { renderFn((RuntimeMenuItem*)this, itemPosition, RENDERFN_NAME, buffer, bufferSize);}
96 
97  uint8_t getNumberOfRows() const { return noOfParts; }
98  uint8_t getItemPosition() const { return itemPosition; }
99 
100  void setNumberOfRows(uint8_t rows) {
101  noOfParts = rows;
102  setChanged(true);
104  }
105 };
106 
117 private:
118  const char* namePtr;
119 public:
127  : RuntimeMenuItem(MENUTYPE_BACK_VALUE, nextRandomId(), renderFn, 0, 1, next), namePtr(nullptr) { }
128 
137  BackMenuItem(const SubMenuInfo* info, MenuItem* next, bool infoInPgm);
138 
142  const char* getNameUnsafe() const { return namePtr; }
143 };
144 
149 class SubMenuItem : public RuntimeMenuItem {
150 private:
151  MenuItem* child;
152 public:
162  SubMenuItem(const SubMenuInfo* info, MenuItem* child, MenuItem* next = nullptr, bool infoInPgm = INFO_LOCATION_PGM)
163  : RuntimeMenuItem(info, infoInPgm, MENUTYPE_SUB_VALUE, backSubItemRenderFn, 0, 1, next) {
164  this->child = child;
165  }
166 
174  SubMenuItem(menuid_t id, RuntimeRenderingFn renderFn, MenuItem* child, MenuItem* next = nullptr)
175  : RuntimeMenuItem(MENUTYPE_SUB_VALUE, id, renderFn,
176  0, 1, next) {
177  this->child = child;
178  }
179 
183  MenuItem* getChild() const { return child; }
184  void setChild(MenuItem* firstChildItem) { this->child = firstChildItem; }
185 };
186 
187 #define LIST_PARENT_ITEM_POS 0xff
188 
199 public:
200  enum ListMode: uint8_t { CUSTOM_RENDER, RAM_ARRAY, FLASH_ARRAY };
201 private:
202  const char* const* dataArray;
203  uint8_t activeItem;
204  ListMode listMode = CUSTOM_RENDER;
205 public:
206  ListRuntimeMenuItem(const AnyMenuInfo* info, int numberOfRows, const char* const* array, ListMode listMode, MenuItem* next = nullptr, bool isPgm = INFO_LOCATION_PGM);
207  ListRuntimeMenuItem(const AnyMenuInfo* info, int numberOfRows, RuntimeRenderingFn renderFn, MenuItem* next = nullptr, bool isPgm = INFO_LOCATION_PGM);
208  ListRuntimeMenuItem(menuid_t id, int numberOfRows, RuntimeRenderingFn renderFn, MenuItem* next = nullptr);
209 
210  RuntimeMenuItem* getChildItem(int pos);
211  RuntimeMenuItem* asParent();
212  RuntimeMenuItem* asBackMenu();
213 
214  ListMode getListMode() const {return listMode;}
215  bool isActingAsParent() const { return itemPosition == LIST_PARENT_ITEM_POS; }
216  uint8_t getActiveIndex() const { return activeItem; }
217  void setActiveIndex(uint8_t idx) {
218  activeItem = idx;
219  setChanged(true);
220  }
221  const char* const* getDataArray() { return dataArray; }
222 };
223 
224 int defaultRtListCallback(RuntimeMenuItem* item, uint8_t row, RenderFnMode mode, char* buffer, int bufferSize);
225 
231 public:
232  EditableMultiPartMenuItem(MenuType type, menuid_t id, int numberOfParts, RuntimeRenderingFn renderFn, MenuItem* next = nullptr)
233  : RuntimeMenuItem(type, id, renderFn, 0, numberOfParts, next) {
234  }
235  EditableMultiPartMenuItem(const AnyMenuInfo* rtInfo, bool isPgm, MenuType type, int numberOfParts, RuntimeRenderingFn renderFn, MenuItem* next = nullptr)
236  : RuntimeMenuItem(rtInfo, isPgm, type, renderFn, 0, numberOfParts, next) {
237  }
238 
239  uint8_t beginMultiEdit();
240 
241  int changeEditBy(int amt);
242 
243  int previousPart();
244 
245  int nextPart();
246 
247  int getCurrentRange() const {
248  return renderFn((RuntimeMenuItem*)this, itemPosition, RENDERFN_GETRANGE, NULL, 0);
249  }
250 
251  void stopMultiEdit();
252 
253  int getPartValueAsInt() const {
254  return renderFn((RuntimeMenuItem*)this, itemPosition, RENDERFN_GETPART, NULL, 0);
255  }
256 
257  bool valueChanged(int newVal);
258 };
259 
260 // number of characters in the edit set.
261 #define ALLOWABLE_CHARS_ENCODER_SIZE 94
262 
269 private:
270  char* data;
271  bool passwordField;
272 public:
281  TextMenuItem(RuntimeRenderingFn customRenderFn, menuid_t id, int size, MenuItem* next = nullptr);
291  TextMenuItem(RuntimeRenderingFn customRenderFn, const char* initial, menuid_t id, int size, MenuItem* next = nullptr);
300  TextMenuItem(const AnyMenuInfo* info, const char* initial, int size, MenuItem* next = nullptr, bool isPgm = INFO_LOCATION_PGM);
301 
311  TextMenuItem(const AnyMenuInfo* info, RuntimeRenderingFn customRenderFn, const char* initial, int size, MenuItem* next = nullptr, bool isPgm = INFO_LOCATION_PGM);
312 
313  void setPasswordField(bool pwd) {
314  this->passwordField = pwd;
315  }
316 
320  bool isPasswordField() const {
321  return this->passwordField;
322  }
323 
324  ~TextMenuItem() { delete data; }
325 
327  uint8_t textLength() const { return noOfParts; }
328 
334  void setTextValue(const char* text, bool silent = false);
335 
337  const char* getTextValue() const { return data; }
338 
343  void cleanUpArray();
344 
352  bool setCharValue(uint8_t location, char val);
353 
361  bool valueChangedFromKeyboard(char keyPress);
362 private:
363  void initTextItem(const char* initialData);
364 };
365 
371 int findPositionInEditorSet(char ch);
372 
378 private:
379  uint8_t data[4];
380 public:
381  explicit IpAddressStorage(const char* address);
382  IpAddressStorage(uint8_t p1, uint8_t p2, uint8_t p3, uint8_t p4);
383  IpAddressStorage(const IpAddressStorage& other) = default;
384  IpAddressStorage& operator=(const IpAddressStorage& other) = default;
385 
386  void setPart(int part, uint8_t newValue) { data[part] = newValue; }
387  uint8_t* underlyingArray() { return data; }
388 };
389 
396 private:
397  IpAddressStorage data;
398 public:
405  IpAddressMenuItem(RuntimeRenderingFn renderFn, menuid_t id, MenuItem* next = nullptr)
406  : EditableMultiPartMenuItem(MENUTYPE_IPADDRESS, id, 4, renderFn, next), data(127, 0, 0, 1) {}
407 
415  IpAddressMenuItem(RuntimeRenderingFn renderFn, const IpAddressStorage& initialIp, menuid_t id, MenuItem* next = nullptr)
416  : EditableMultiPartMenuItem(MENUTYPE_IPADDRESS, id, 4, renderFn, next), data(initialIp) {}
417 
427  IpAddressMenuItem(const AnyMenuInfo* info, RuntimeRenderingFn renderFn, const IpAddressStorage& initialIp, MenuItem* next = nullptr, bool isPgm = INFO_LOCATION_PGM)
428  : EditableMultiPartMenuItem(info, isPgm, MENUTYPE_IPADDRESS, 4, renderFn, next), data(initialIp) {}
429 
438  IpAddressMenuItem(const AnyMenuInfo* info, const IpAddressStorage& initialIp, MenuItem* next = nullptr, bool isPgm = INFO_LOCATION_PGM)
439  : EditableMultiPartMenuItem(info, isPgm, MENUTYPE_IPADDRESS, 4, ipAddressRenderFn, next), data(initialIp) {}
440 
441  void setIpAddress(const char* source);
442 
444  void setIpAddress(uint8_t p1, uint8_t p2, uint8_t p3, uint8_t p4) {
445  data = IpAddressStorage(p1, p2, p3, p4);
446  }
447 
449  uint8_t* getIpAddress() { return data.underlyingArray(); }
450 
451  void setUnderlying(const IpAddressStorage& other);
452 
453  IpAddressStorage& getUnderlying() { return data; }
454 
456  void setIpPart(uint8_t part, uint8_t newVal);
457 };
458 
463 struct TimeStorage {
464  TimeStorage() {
465  this->hours = this->minutes = this->seconds = this->hundreds = 0;
466  }
467  TimeStorage(uint8_t hours, uint8_t minutes, uint8_t seconds = 0, uint8_t hundreds = 0) {
468  this->hours = hours;
469  this->minutes = minutes;
470  this->seconds = seconds;
471  this->hundreds = hundreds;
472  }
473  TimeStorage(const TimeStorage& other) = default;
474  TimeStorage& operator=(const TimeStorage& other) = default;
475 
476  uint8_t hours;
477  uint8_t minutes;
478  uint8_t seconds;
479  uint8_t hundreds;
480 };
481 
485 struct DateStorage {
486  uint8_t day;
487  uint8_t month;
488  uint16_t year;
489 
490  DateStorage() {
491  year = day = month = 0;
492  }
493 
494  DateStorage(int day, int month, int year) {
495  this->day = day;
496  this->month = month;
497  this->year = year;
498  }
499 
500  DateStorage(const DateStorage& other) = default;
501  DateStorage& operator=(const DateStorage& other)=default;
502 };
503 
511 private:
512  MultiEditWireType format;
513  TimeStorage data;
514 public:
515  TimeFormattedMenuItem(RuntimeRenderingFn renderFn, menuid_t id, MultiEditWireType format, MenuItem* next = nullptr);
516  TimeFormattedMenuItem(RuntimeRenderingFn renderFn, const TimeStorage& initial, menuid_t id, MultiEditWireType format, MenuItem* next = nullptr);
517  TimeFormattedMenuItem(const AnyMenuInfo* info, RuntimeRenderingFn renderFn, const TimeStorage& initial, MultiEditWireType format, MenuItem* next = nullptr, bool isPgm = INFO_LOCATION_PGM);
518  TimeFormattedMenuItem(const AnyMenuInfo* info, const TimeStorage& initial, MultiEditWireType format, MenuItem* next = nullptr, bool isPgm = INFO_LOCATION_PGM);
519 
521  TimeStorage getTime() const { return data; }
522 
524  void setTime(TimeStorage newTime) { data = newTime; }
525 
527  void setTimeFromString(const char* time);
528 
530  MultiEditWireType getFormat() const { return format; }
531 
532  TimeStorage* getUnderlyingData() {return &data;}
533 };
534 
541 public:
542  enum DateFormatOption { DD_MM_YYYY, MM_DD_YYYY, YYYY_MM_DD };
543 private:
544  DateStorage data;
545  static char separator;
546  static DateFormatOption dateFormatMode;
547 public:
548  DateFormattedMenuItem(RuntimeRenderingFn renderFn, menuid_t id, MenuItem* next = nullptr)
549  : EditableMultiPartMenuItem(MENUTYPE_DATE, id, 3, renderFn, next), data(1, 1, 2020) {}
550 
551  DateFormattedMenuItem(RuntimeRenderingFn renderFn, const DateStorage& initial, menuid_t id, MenuItem* next = nullptr)
552  : EditableMultiPartMenuItem(MENUTYPE_DATE, id, 3, renderFn, next), data(initial) {}
553 
554  DateFormattedMenuItem(const AnyMenuInfo* info, RuntimeRenderingFn renderFn, const DateStorage& initial, menuid_t /*id*/, MenuItem* next = nullptr, bool isPgm = INFO_LOCATION_PGM)
555  : EditableMultiPartMenuItem(info, isPgm, MENUTYPE_DATE, 3, renderFn, next), data(initial) {}
556 
557  DateFormattedMenuItem(const AnyMenuInfo* info, const DateStorage& initial, MenuItem* next = nullptr, bool isPgm = INFO_LOCATION_PGM)
558  : EditableMultiPartMenuItem(info, isPgm, MENUTYPE_DATE, 3, dateItemRenderFn, next), data(initial) {}
559 
564  static void setDateSeparator(char sep) {
565  separator = sep;
566  }
567 
571  static char getDateSeparator() {
572  return separator;
573  }
574 
579  static void setDateFormatStyle(DateFormatOption fmt) {
580  dateFormatMode = fmt;
581  }
582 
586  static DateFormatOption getDateFormatStyle() {
587  return dateFormatMode;
588  }
589 
590  DateStorage getDate() const { return data; }
591 
592  void setDate(DateStorage newDate) { data = newDate; }
593 
594  void setDateFromString(const char *dateText);
595 
596  DateStorage* getUnderlyingData() { return &data; }
597 };
598 
605 long parseIntUntilSeparator(const char* ptr, int& offset, size_t maxDigits=10);
606 
612 inline void invokeIfSafe(MenuCallbackFn cb, MenuItem* pItem) { if(cb && pItem) cb(pItem->getId()); }
613 
624 #define RENDERING_CALLBACK_NAME_INVOKE(fnName, parent, namepgm, eepromPosition, invoke) \
625 const char fnName##Pgm[] PROGMEM = namepgm; \
626 int fnName(RuntimeMenuItem* item, uint8_t row, RenderFnMode mode, char* buffer, int buffSize) { \
627  switch(mode) { \
628  case RENDERFN_NAME: \
629  safeProgCpy(buffer, fnName##Pgm, buffSize); \
630  return true; \
631  case RENDERFN_INVOKE: \
632  invokeIfSafe(invoke, item); \
633  return true; \
634  case RENDERFN_EEPROM_POS: \
635  return eepromPosition; \
636  default: \
637  return parent(item, row, mode, buffer, buffSize); \
638  } \
639 }
640 
651 #define RENDERING_CALLBACK_NAME_OVERRIDDEN(fnName, customFn, namepgm, eepromPosition) \
652 const char fnName##Pgm[] PROGMEM = namepgm; \
653 int fnName(RuntimeMenuItem* item, uint8_t row, RenderFnMode mode, char* buffer, int buffSize) { \
654  switch(mode) { \
655  case RENDERFN_NAME: \
656  if(customFn(item, row, mode, buffer, buffSize) == false) { \
657  safeProgCpy(buffer, fnName##Pgm, buffSize); \
658  } \
659  return true; \
660  case RENDERFN_EEPROM_POS: \
661  return eepromPosition; \
662  default: \
663  return customFn(item, row, mode, buffer, buffSize); \
664  } \
665 }
666 
667 #endif //_RUNTIME_MENUITEM_H_
In TcMenu, MenuItem storage is shared between program memory and RAM. Usually each MenuItem has assoc...
RenderFnMode
Definition: MenuItems.h:283
@ RENDERFN_EEPROM_POS
Definition: MenuItems.h:289
@ RENDERFN_INVOKE
Definition: MenuItems.h:291
@ RENDERFN_NAME
Definition: MenuItems.h:287
@ RENDERFN_GETRANGE
Definition: MenuItems.h:297
@ RENDERFN_GETPART
Definition: MenuItems.h:299
@ RENDERFN_VALUE
Definition: MenuItems.h:285
int(* RuntimeRenderingFn)(RuntimeMenuItem *item, uint8_t row, RenderFnMode mode, char *buffer, int bufferSize)
Definition: MenuItems.h:318
void(* MenuCallbackFn)(int id)
Definition: MenuItems.h:45
MenuType
Definition: MenuItems.h:238
@ MENUTYPE_IPADDRESS
Definition: MenuItems.h:269
@ MENUTYPE_DATE
Definition: MenuItems.h:273
@ MENUTYPE_SUB_VALUE
Definition: MenuItems.h:260
@ MENUTYPE_BACK_VALUE
Definition: MenuItems.h:254
Definition: MenuItems.h:51
int ipAddressRenderFn(RuntimeMenuItem *item, uint8_t row, RenderFnMode mode, char *buffer, int bufferSize)
Definition: RuntimeMenuItem.cpp:157
int dateItemRenderFn(RuntimeMenuItem *item, uint8_t row, RenderFnMode mode, char *buffer, int bufferSize)
Definition: RuntimeMenuItem.cpp:300
void invokeIfSafe(MenuCallbackFn cb, MenuItem *pItem)
Definition: RuntimeMenuItem.h:612
int findPositionInEditorSet(char ch)
Definition: RuntimeMenuItem.cpp:372
menuid_t nextRandomId()
Definition: RuntimeMenuItem.cpp:15
MultiEditWireType
Definition: RuntimeMenuItem.h:46
@ EDITMODE_TIME_24H
Definition: RuntimeMenuItem.h:52
@ EDITMODE_TIME_DURATION_HUNDREDS
Definition: RuntimeMenuItem.h:62
@ EDITMODE_PLAIN_TEXT
Definition: RuntimeMenuItem.h:48
@ EDITMODE_TIME_12H_HHMM
Definition: RuntimeMenuItem.h:66
@ EDITMODE_TIME_12H
Definition: RuntimeMenuItem.h:54
@ EDITMODE_IP_ADDRESS
Definition: RuntimeMenuItem.h:50
@ EDITMODE_TIME_HUNDREDS_24H
Definition: RuntimeMenuItem.h:56
@ EDITMODE_GREGORIAN_DATE
Definition: RuntimeMenuItem.h:58
@ EDITMODE_TIME_DURATION_SECONDS
Definition: RuntimeMenuItem.h:60
@ EDITMODE_TIME_24H_HHMM
Definition: RuntimeMenuItem.h:64
int timeItemRenderFn(RuntimeMenuItem *item, uint8_t row, RenderFnMode mode, char *buffer, int bufferSize)
Definition: RuntimeMenuItem.cpp:197
long parseIntUntilSeparator(const char *ptr, int &offset, size_t maxDigits=10)
Definition: RuntimeMenuItem.cpp:511
int textItemRenderFn(RuntimeMenuItem *item, uint8_t row, RenderFnMode mode, char *buffer, int bufferSize)
Definition: RuntimeMenuItem.cpp:383
int backSubItemRenderFn(RuntimeMenuItem *item, uint8_t row, RenderFnMode mode, char *buffer, int bufferSize)
Definition: RuntimeMenuItem.cpp:344
Definition: RuntimeMenuItem.h:116
const char * getNameUnsafe() const
Definition: RuntimeMenuItem.h:142
BackMenuItem(RuntimeRenderingFn renderFn, MenuItem *next)
Definition: RuntimeMenuItem.h:126
Definition: RuntimeMenuItem.h:540
static void setDateSeparator(char sep)
Definition: RuntimeMenuItem.h:564
static DateFormatOption getDateFormatStyle()
Definition: RuntimeMenuItem.h:586
static char getDateSeparator()
Definition: RuntimeMenuItem.h:571
static void setDateFormatStyle(DateFormatOption fmt)
Definition: RuntimeMenuItem.h:579
Definition: RuntimeMenuItem.h:230
Definition: RuntimeMenuItem.h:395
void setIpPart(uint8_t part, uint8_t newVal)
Definition: RuntimeMenuItem.cpp:495
IpAddressMenuItem(RuntimeRenderingFn renderFn, const IpAddressStorage &initialIp, menuid_t id, MenuItem *next=nullptr)
Definition: RuntimeMenuItem.h:415
IpAddressMenuItem(const AnyMenuInfo *info, const IpAddressStorage &initialIp, MenuItem *next=nullptr, bool isPgm=INFO_LOCATION_PGM)
Definition: RuntimeMenuItem.h:438
IpAddressMenuItem(const AnyMenuInfo *info, RuntimeRenderingFn renderFn, const IpAddressStorage &initialIp, MenuItem *next=nullptr, bool isPgm=INFO_LOCATION_PGM)
Definition: RuntimeMenuItem.h:427
void setIpAddress(uint8_t p1, uint8_t p2, uint8_t p3, uint8_t p4)
Definition: RuntimeMenuItem.h:444
IpAddressMenuItem(RuntimeRenderingFn renderFn, menuid_t id, MenuItem *next=nullptr)
Definition: RuntimeMenuItem.h:405
uint8_t * getIpAddress()
Definition: RuntimeMenuItem.h:449
Definition: RuntimeMenuItem.h:377
Definition: RuntimeMenuItem.h:198
Definition: MenuItems.h:329
void setChanged(bool changed)
Definition: MenuItems.cpp:112
menuid_t getId() const
Definition: MenuItems.cpp:81
const AnyMenuInfo * info
Definition: MenuItems.h:334
void setSendRemoteNeededAll()
Definition: MenuItems.cpp:30
Definition: RuntimeMenuItem.h:75
Definition: RuntimeMenuItem.h:149
MenuItem * getChild() const
Definition: RuntimeMenuItem.h:183
SubMenuItem(const SubMenuInfo *info, MenuItem *child, MenuItem *next=nullptr, bool infoInPgm=INFO_LOCATION_PGM)
Definition: RuntimeMenuItem.h:162
SubMenuItem(menuid_t id, RuntimeRenderingFn renderFn, MenuItem *child, MenuItem *next=nullptr)
Definition: RuntimeMenuItem.h:174
Definition: RuntimeMenuItem.h:268
void cleanUpArray()
Definition: RuntimeMenuItem.cpp:123
uint8_t textLength() const
Definition: RuntimeMenuItem.h:327
const char * getTextValue() const
Definition: RuntimeMenuItem.h:337
bool valueChangedFromKeyboard(char keyPress)
Definition: RuntimeMenuItem.cpp:614
bool setCharValue(uint8_t location, char val)
Definition: RuntimeMenuItem.cpp:133
TextMenuItem(RuntimeRenderingFn customRenderFn, menuid_t id, int size, MenuItem *next=nullptr)
Definition: RuntimeMenuItem.cpp:444
void setTextValue(const char *text, bool silent=false)
Definition: RuntimeMenuItem.cpp:112
bool isPasswordField() const
Definition: RuntimeMenuItem.h:320
Definition: RuntimeMenuItem.h:510
MultiEditWireType getFormat() const
Definition: RuntimeMenuItem.h:530
TimeStorage getTime() const
Definition: RuntimeMenuItem.h:521
void setTime(TimeStorage newTime)
Definition: RuntimeMenuItem.h:524
void setTimeFromString(const char *time)
Definition: RuntimeMenuItem.cpp:527
Definition: RuntimeMenuItem.h:485
Definition: RuntimeMenuItem.h:463
A series of utilities that used throughout tcMenu.