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 #define RANDOM_ID_START 50000
19 
21 menuid_t nextRandomId();
22 
24 int textItemRenderFn(RuntimeMenuItem* item, uint8_t row, RenderFnMode mode, char* buffer, int bufferSize);
25 
27 int ipAddressRenderFn(RuntimeMenuItem* item, uint8_t row, RenderFnMode mode, char* buffer, int bufferSize);
28 
30 int backSubItemRenderFn(RuntimeMenuItem* item, uint8_t row, RenderFnMode mode, char* buffer, int bufferSize);
31 
33 int timeItemRenderFn(RuntimeMenuItem* item, uint8_t row, RenderFnMode mode, char* buffer, int bufferSize);
34 
36 int dateItemRenderFn(RuntimeMenuItem* item, uint8_t row, RenderFnMode mode, char* buffer, int bufferSize);
37 
39 int findPositionInEditorSet(char ch);
40 
44 enum MultiEditWireType : uint8_t {
65 };
66 
73 class RuntimeMenuItem : public MenuItem {
74 protected:
75  menuid_t id;
76  uint8_t itemPosition;
77  uint8_t noOfParts;
78 public:
79  RuntimeMenuItem(MenuType menuType, menuid_t id, RuntimeRenderingFn renderFn,
80  uint8_t itemPosition, uint8_t numberOfRows, MenuItem* next = nullptr);
81 
82  RuntimeMenuItem(const AnyMenuInfo* rtInfo, bool isPgm, MenuType menuType, RuntimeRenderingFn renderFn,
83  uint8_t itemPosition, uint8_t numberOfRows, MenuItem* next = nullptr);
84 
85  void copyValue(char* buffer, int bufferSize) const {
86  renderFn((RuntimeMenuItem*)this, itemPosition, RENDERFN_VALUE, buffer, bufferSize);
87  }
88 
89  void runCallback() const { renderFn((RuntimeMenuItem*)this, itemPosition, RENDERFN_INVOKE, nullptr, 0); }
90  int getRuntimeId() const { return int(id); }
91  int getRuntimeEeprom() const { return renderFn((RuntimeMenuItem*)this, itemPosition, RENDERFN_EEPROM_POS, nullptr, 0); }
92  uint8_t getNumberOfParts() const { return noOfParts; }
93  void copyRuntimeName(char* buffer, int bufferSize) const { renderFn((RuntimeMenuItem*)this, itemPosition, RENDERFN_NAME, buffer, bufferSize);}
94 
95  uint8_t getNumberOfRows() const { return noOfParts; }
96  uint8_t getItemPosition() const { return itemPosition; }
97 
98  void setNumberOfRows(uint8_t rows) {
99  noOfParts = rows;
100  setChanged(true);
102  }
103 };
104 
115 private:
116  const char* namePtr;
117 public:
125  : RuntimeMenuItem(MENUTYPE_BACK_VALUE, nextRandomId(), renderFn, 0, 1, next), namePtr(nullptr) { }
126 
135  BackMenuItem(const SubMenuInfo* info, MenuItem* next, bool infoInPgm);
136 
140  const char* getNameUnsafe() const { return namePtr; }
141 };
142 
147 class SubMenuItem : public RuntimeMenuItem {
148 private:
149  MenuItem* child;
150 public:
160  SubMenuItem(const SubMenuInfo* info, MenuItem* child, MenuItem* next = nullptr, bool infoInPgm = INFO_LOCATION_PGM)
161  : RuntimeMenuItem(info, infoInPgm, MENUTYPE_SUB_VALUE, backSubItemRenderFn, 0, 1, next) {
162  this->child = child;
163  }
164 
172  SubMenuItem(menuid_t id, RuntimeRenderingFn renderFn, MenuItem* child, MenuItem* next = nullptr)
173  : RuntimeMenuItem(MENUTYPE_SUB_VALUE, id, renderFn,
174  0, 1, next) {
175  this->child = child;
176  }
177 
181  MenuItem* getChild() const { return child; }
182  void setChild(MenuItem* firstChildItem) { this->child = firstChildItem; }
183 };
184 
185 #define LIST_PARENT_ITEM_POS 0xff
186 
197 public:
198  enum ListMode: uint8_t { CUSTOM_RENDER, RAM_ARRAY, FLASH_ARRAY };
199 private:
200  const char* const* dataArray;
201  uint8_t activeItem;
202  ListMode listMode = CUSTOM_RENDER;
203 public:
204  ListRuntimeMenuItem(const AnyMenuInfo* info, int numberOfRows, const char* const* array, ListMode listMode, MenuItem* next = nullptr, bool isPgm = INFO_LOCATION_PGM);
205  ListRuntimeMenuItem(const AnyMenuInfo* info, int numberOfRows, RuntimeRenderingFn renderFn, MenuItem* next = nullptr, bool isPgm = INFO_LOCATION_PGM);
206  ListRuntimeMenuItem(menuid_t id, int numberOfRows, RuntimeRenderingFn renderFn, MenuItem* next = nullptr);
207 
208  RuntimeMenuItem* getChildItem(int pos);
209  RuntimeMenuItem* asParent();
210  RuntimeMenuItem* asBackMenu();
211 
212  ListMode getListMode() const {return listMode;}
213  bool isActingAsParent() const { return itemPosition == LIST_PARENT_ITEM_POS; }
214  uint8_t getActiveIndex() const { return activeItem; }
215  void setActiveIndex(uint8_t idx) {
216  activeItem = idx;
217  setChanged(true);
218  }
219  const char* const* getDataArray() { return dataArray; }
220 };
221 
222 int defaultRtListCallback(RuntimeMenuItem* item, uint8_t row, RenderFnMode mode, char* buffer, int bufferSize);
223 
229 public:
230  EditableMultiPartMenuItem(MenuType type, menuid_t id, int numberOfParts, RuntimeRenderingFn renderFn, MenuItem* next = nullptr)
231  : RuntimeMenuItem(type, id, renderFn, 0, numberOfParts, next) {
232  }
233  EditableMultiPartMenuItem(const AnyMenuInfo* rtInfo, bool isPgm, MenuType type, int numberOfParts, RuntimeRenderingFn renderFn, MenuItem* next = nullptr)
234  : RuntimeMenuItem(rtInfo, isPgm, type, renderFn, 0, numberOfParts, next) {
235  }
236 
237  uint8_t beginMultiEdit();
238 
239  int changeEditBy(int amt);
240 
241  int previousPart();
242 
243  int nextPart();
244 
245  int getCurrentRange() const {
246  return renderFn((RuntimeMenuItem*)this, itemPosition, RENDERFN_GETRANGE, NULL, 0);
247  }
248 
249  void stopMultiEdit();
250 
251  int getPartValueAsInt() const {
252  return renderFn((RuntimeMenuItem*)this, itemPosition, RENDERFN_GETPART, NULL, 0);
253  }
254 
255  bool valueChanged(int newVal);
256 };
257 
258 // number of characters in the edit set.
259 #define ALLOWABLE_CHARS_ENCODER_SIZE 94
260 
267 private:
268  char* data;
269  bool passwordField;
270 public:
279  TextMenuItem(RuntimeRenderingFn customRenderFn, menuid_t id, int size, MenuItem* next = nullptr);
289  TextMenuItem(RuntimeRenderingFn customRenderFn, const char* initial, menuid_t id, int size, MenuItem* next = nullptr);
298  TextMenuItem(const AnyMenuInfo* info, const char* initial, int size, MenuItem* next = nullptr, bool isPgm = INFO_LOCATION_PGM);
299 
309  TextMenuItem(const AnyMenuInfo* info, RuntimeRenderingFn customRenderFn, const char* initial, int size, MenuItem* next = nullptr, bool isPgm = INFO_LOCATION_PGM);
310 
311  void setPasswordField(bool pwd) {
312  this->passwordField = pwd;
313  }
314 
318  bool isPasswordField() const {
319  return this->passwordField;
320  }
321 
322  ~TextMenuItem() { delete data; }
323 
325  uint8_t textLength() const { return noOfParts; }
326 
332  void setTextValue(const char* text, bool silent = false);
333 
335  const char* getTextValue() const { return data; }
336 
341  void cleanUpArray();
342 
350  bool setCharValue(uint8_t location, char val);
351 
359  bool valueChangedFromKeyboard(char keyPress);
360 private:
361  void initTextItem(const char* initialData);
362 };
363 
369 int findPositionInEditorSet(char ch);
370 
376 private:
377  uint8_t data[4];
378 public:
379  explicit IpAddressStorage(const char* address);
380  IpAddressStorage(uint8_t p1, uint8_t p2, uint8_t p3, uint8_t p4);
381  IpAddressStorage(const IpAddressStorage& other) = default;
382  IpAddressStorage& operator=(const IpAddressStorage& other) = default;
383 
384  void setPart(int part, uint8_t newValue) { data[part] = newValue; }
385  uint8_t* underlyingArray() { return data; }
386 };
387 
394 private:
395  IpAddressStorage data;
396 public:
403  IpAddressMenuItem(RuntimeRenderingFn renderFn, menuid_t id, MenuItem* next = nullptr)
404  : EditableMultiPartMenuItem(MENUTYPE_IPADDRESS, id, 4, renderFn, next), data(127, 0, 0, 1) {}
405 
413  IpAddressMenuItem(RuntimeRenderingFn renderFn, const IpAddressStorage& initialIp, menuid_t id, MenuItem* next = nullptr)
414  : EditableMultiPartMenuItem(MENUTYPE_IPADDRESS, id, 4, renderFn, next), data(initialIp) {}
415 
425  IpAddressMenuItem(const AnyMenuInfo* info, RuntimeRenderingFn renderFn, const IpAddressStorage& initialIp, MenuItem* next = nullptr, bool isPgm = INFO_LOCATION_PGM)
426  : EditableMultiPartMenuItem(info, isPgm, MENUTYPE_IPADDRESS, 4, renderFn, next), data(initialIp) {}
427 
436  IpAddressMenuItem(const AnyMenuInfo* info, const IpAddressStorage& initialIp, MenuItem* next = nullptr, bool isPgm = INFO_LOCATION_PGM)
437  : EditableMultiPartMenuItem(info, isPgm, MENUTYPE_IPADDRESS, 4, ipAddressRenderFn, next), data(initialIp) {}
438 
439  void setIpAddress(const char* source);
440 
442  void setIpAddress(uint8_t p1, uint8_t p2, uint8_t p3, uint8_t p4) {
443  data = IpAddressStorage(p1, p2, p3, p4);
444  }
445 
447  uint8_t* getIpAddress() { return data.underlyingArray(); }
448 
449  void setUnderlying(const IpAddressStorage& other);
450 
451  IpAddressStorage& getUnderlying() { return data; }
452 
454  void setIpPart(uint8_t part, uint8_t newVal);
455 };
456 
461 struct TimeStorage {
462  TimeStorage() {
463  this->hours = this->minutes = this->seconds = this->hundreds = 0;
464  }
465  TimeStorage(uint8_t hours, uint8_t minutes, uint8_t seconds = 0, uint8_t hundreds = 0) {
466  this->hours = hours;
467  this->minutes = minutes;
468  this->seconds = seconds;
469  this->hundreds = hundreds;
470  }
471  TimeStorage(const TimeStorage& other) = default;
472  TimeStorage& operator=(const TimeStorage& other) = default;
473 
474  uint8_t hours;
475  uint8_t minutes;
476  uint8_t seconds;
477  uint8_t hundreds;
478 };
479 
483 struct DateStorage {
484  uint8_t day;
485  uint8_t month;
486  uint16_t year;
487 
488  DateStorage() {
489  year = day = month = 0;
490  }
491 
492  DateStorage(int day, int month, int year) {
493  this->day = day;
494  this->month = month;
495  this->year = year;
496  }
497 
498  DateStorage(const DateStorage& other) = default;
499  DateStorage& operator=(const DateStorage& other)=default;
500 };
501 
509 private:
510  MultiEditWireType format;
511  TimeStorage data;
512 public:
513  TimeFormattedMenuItem(RuntimeRenderingFn renderFn, menuid_t id, MultiEditWireType format, MenuItem* next = nullptr);
514  TimeFormattedMenuItem(RuntimeRenderingFn renderFn, const TimeStorage& initial, menuid_t id, MultiEditWireType format, MenuItem* next = nullptr);
515  TimeFormattedMenuItem(const AnyMenuInfo* info, RuntimeRenderingFn renderFn, const TimeStorage& initial, MultiEditWireType format, MenuItem* next = nullptr, bool isPgm = INFO_LOCATION_PGM);
516  TimeFormattedMenuItem(const AnyMenuInfo* info, const TimeStorage& initial, MultiEditWireType format, MenuItem* next = nullptr, bool isPgm = INFO_LOCATION_PGM);
517 
519  TimeStorage getTime() const { return data; }
520 
522  void setTime(TimeStorage newTime) { data = newTime; }
523 
525  void setTimeFromString(const char* time);
526 
528  MultiEditWireType getFormat() const { return format; }
529 
530  TimeStorage* getUnderlyingData() {return &data;}
531 };
532 
539 public:
540  enum DateFormatOption { DD_MM_YYYY, MM_DD_YYYY, YYYY_MM_DD };
541 private:
542  DateStorage data;
543  static char separator;
544  static DateFormatOption dateFormatMode;
545 public:
546  DateFormattedMenuItem(RuntimeRenderingFn renderFn, menuid_t id, MenuItem* next = nullptr)
547  : EditableMultiPartMenuItem(MENUTYPE_DATE, id, 3, renderFn, next), data(1, 1, 2020) {}
548 
549  DateFormattedMenuItem(RuntimeRenderingFn renderFn, const DateStorage& initial, menuid_t id, MenuItem* next = nullptr)
550  : EditableMultiPartMenuItem(MENUTYPE_DATE, id, 3, renderFn, next), data(initial) {}
551 
552  DateFormattedMenuItem(const AnyMenuInfo* info, RuntimeRenderingFn renderFn, const DateStorage& initial, menuid_t /*id*/, MenuItem* next = nullptr, bool isPgm = INFO_LOCATION_PGM)
553  : EditableMultiPartMenuItem(info, isPgm, MENUTYPE_DATE, 3, renderFn, next), data(initial) {}
554 
555  DateFormattedMenuItem(const AnyMenuInfo* info, const DateStorage& initial, MenuItem* next = nullptr, bool isPgm = INFO_LOCATION_PGM)
556  : EditableMultiPartMenuItem(info, isPgm, MENUTYPE_DATE, 3, dateItemRenderFn, next), data(initial) {}
557 
562  static void setDateSeparator(char sep) {
563  separator = sep;
564  }
565 
569  static char getDateSeparator() {
570  return separator;
571  }
572 
577  static void setDateFormatStyle(DateFormatOption fmt) {
578  dateFormatMode = fmt;
579  }
580 
584  static DateFormatOption getDateFormatStyle() {
585  return dateFormatMode;
586  }
587 
588  DateStorage getDate() const { return data; }
589 
590  void setDate(DateStorage newDate) { data = newDate; }
591 
592  void setDateFromString(const char *dateText);
593 
594  DateStorage* getUnderlyingData() { return &data; }
595 };
596 
603 long parseIntUntilSeparator(const char* ptr, int& offset, size_t maxDigits=10);
604 
610 inline void invokeIfSafe(MenuCallbackFn cb, MenuItem* pItem) { if(cb && pItem) cb(pItem->getId()); }
611 
622 #define RENDERING_CALLBACK_NAME_INVOKE(fnName, parent, namepgm, eepromPosition, invoke) \
623 const char fnName##Pgm[] PROGMEM = namepgm; \
624 int fnName(RuntimeMenuItem* item, uint8_t row, RenderFnMode mode, char* buffer, int buffSize) { \
625  switch(mode) { \
626  case RENDERFN_NAME: \
627  safeProgCpy(buffer, fnName##Pgm, buffSize); \
628  return true; \
629  case RENDERFN_INVOKE: \
630  invokeIfSafe(invoke, item); \
631  return true; \
632  case RENDERFN_EEPROM_POS: \
633  return eepromPosition; \
634  default: \
635  return parent(item, row, mode, buffer, buffSize); \
636  } \
637 }
638 
649 #define RENDERING_CALLBACK_NAME_OVERRIDDEN(fnName, customFn, namepgm, eepromPosition) \
650 const char fnName##Pgm[] PROGMEM = namepgm; \
651 int fnName(RuntimeMenuItem* item, uint8_t row, RenderFnMode mode, char* buffer, int buffSize) { \
652  switch(mode) { \
653  case RENDERFN_NAME: \
654  if(customFn(item, row, mode, buffer, buffSize) == false) { \
655  safeProgCpy(buffer, fnName##Pgm, buffSize); \
656  } \
657  return true; \
658  case RENDERFN_EEPROM_POS: \
659  return eepromPosition; \
660  default: \
661  return customFn(item, row, mode, buffer, buffSize); \
662  } \
663 }
664 
665 #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:610
int findPositionInEditorSet(char ch)
Definition: RuntimeMenuItem.cpp:372
menuid_t nextRandomId()
Definition: RuntimeMenuItem.cpp:15
MultiEditWireType
Definition: RuntimeMenuItem.h:44
@ EDITMODE_TIME_24H
Definition: RuntimeMenuItem.h:50
@ EDITMODE_TIME_DURATION_HUNDREDS
Definition: RuntimeMenuItem.h:60
@ EDITMODE_PLAIN_TEXT
Definition: RuntimeMenuItem.h:46
@ EDITMODE_TIME_12H_HHMM
Definition: RuntimeMenuItem.h:64
@ EDITMODE_TIME_12H
Definition: RuntimeMenuItem.h:52
@ EDITMODE_IP_ADDRESS
Definition: RuntimeMenuItem.h:48
@ EDITMODE_TIME_HUNDREDS_24H
Definition: RuntimeMenuItem.h:54
@ EDITMODE_GREGORIAN_DATE
Definition: RuntimeMenuItem.h:56
@ EDITMODE_TIME_DURATION_SECONDS
Definition: RuntimeMenuItem.h:58
@ EDITMODE_TIME_24H_HHMM
Definition: RuntimeMenuItem.h:62
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:114
const char * getNameUnsafe() const
Definition: RuntimeMenuItem.h:140
BackMenuItem(RuntimeRenderingFn renderFn, MenuItem *next)
Definition: RuntimeMenuItem.h:124
Definition: RuntimeMenuItem.h:538
static void setDateSeparator(char sep)
Definition: RuntimeMenuItem.h:562
static DateFormatOption getDateFormatStyle()
Definition: RuntimeMenuItem.h:584
static char getDateSeparator()
Definition: RuntimeMenuItem.h:569
static void setDateFormatStyle(DateFormatOption fmt)
Definition: RuntimeMenuItem.h:577
Definition: RuntimeMenuItem.h:228
Definition: RuntimeMenuItem.h:393
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:413
IpAddressMenuItem(const AnyMenuInfo *info, const IpAddressStorage &initialIp, MenuItem *next=nullptr, bool isPgm=INFO_LOCATION_PGM)
Definition: RuntimeMenuItem.h:436
IpAddressMenuItem(const AnyMenuInfo *info, RuntimeRenderingFn renderFn, const IpAddressStorage &initialIp, MenuItem *next=nullptr, bool isPgm=INFO_LOCATION_PGM)
Definition: RuntimeMenuItem.h:425
void setIpAddress(uint8_t p1, uint8_t p2, uint8_t p3, uint8_t p4)
Definition: RuntimeMenuItem.h:442
IpAddressMenuItem(RuntimeRenderingFn renderFn, menuid_t id, MenuItem *next=nullptr)
Definition: RuntimeMenuItem.h:403
uint8_t * getIpAddress()
Definition: RuntimeMenuItem.h:447
Definition: RuntimeMenuItem.h:375
Definition: RuntimeMenuItem.h:196
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:73
Definition: RuntimeMenuItem.h:147
MenuItem * getChild() const
Definition: RuntimeMenuItem.h:181
SubMenuItem(const SubMenuInfo *info, MenuItem *child, MenuItem *next=nullptr, bool infoInPgm=INFO_LOCATION_PGM)
Definition: RuntimeMenuItem.h:160
SubMenuItem(menuid_t id, RuntimeRenderingFn renderFn, MenuItem *child, MenuItem *next=nullptr)
Definition: RuntimeMenuItem.h:172
Definition: RuntimeMenuItem.h:266
void cleanUpArray()
Definition: RuntimeMenuItem.cpp:123
uint8_t textLength() const
Definition: RuntimeMenuItem.h:325
const char * getTextValue() const
Definition: RuntimeMenuItem.h:335
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:318
Definition: RuntimeMenuItem.h:508
MultiEditWireType getFormat() const
Definition: RuntimeMenuItem.h:528
TimeStorage getTime() const
Definition: RuntimeMenuItem.h:519
void setTime(TimeStorage newTime)
Definition: RuntimeMenuItem.h:522
void setTimeFromString(const char *time)
Definition: RuntimeMenuItem.cpp:527
Definition: RuntimeMenuItem.h:483
Definition: RuntimeMenuItem.h:461
A series of utilities that used throughout tcMenu.