Controls Label in flash and other fixes

This commit is contained in:
Nikola Kirov 2024-01-06 14:10:38 +02:00
parent e5f53d5118
commit 9184ae0e8b
4 changed files with 514 additions and 414 deletions

View File

@ -650,7 +650,16 @@ uint16_t ESPUIClass::addControl(
Control * ctrl = new Control(type, label, nullptr, value, color, true, parentControl);
if (auto_update_values && ctrl)
ctrl->auto_update_value = true;
return addControl(type, label, value, color, parentControl, ctrl);
return addControl(ctrl);
}
uint16_t ESPUIClass::addControl(
ControlType type, const __FlashStringHelper* label, const String& value, ControlColor color, uint16_t parentControl)
{
Control* ctrl = new Control(type, label, nullptr, value, color, true, parentControl);
if (auto_update_values && ctrl)
ctrl->auto_update_value = true;
return addControl(ctrl);
}
uint16_t ESPUIClass::addControl(ControlType type, const char* label, const String& value, ControlColor color,
@ -662,8 +671,16 @@ uint16_t ESPUIClass::addControl(ControlType type, const char* label, const Strin
return id;
}
uint16_t ESPUIClass::addControl(
ControlType type, const char* label, const String& value, ControlColor color, uint16_t parentControl, Control* control)
uint16_t ESPUIClass::addControl(ControlType type, const __FlashStringHelper* label, const String& value, ControlColor color,
uint16_t parentControl, std::function<void(Control*, int)> callback)
{
uint16_t id = addControl(type, label, value, color, parentControl);
// set the original style callback
getControl(id)->callback = callback;
return id;
}
uint16_t ESPUIClass::addControl(Control* control)
{
#ifdef ESP32
xSemaphoreTake(ControlsSemaphore, portMAX_DELAY);
@ -788,6 +805,10 @@ uint16_t ESPUIClass::button(const char* label, std::function<void(Control*, int)
return addControl(ControlType::Button, label, value, color, Control::noParent, callback);
}
uint16_t ESPUIClass::button(const __FlashStringHelper* label, const __FlashStringHelper* text, std::function<void(Control*, int)> callback, uint16_t parentControl, ControlColor color){
return addControl(ControlType::Button, label, text, color, parentControl, callback);
}
uint16_t ESPUIClass::switcher(const char* label, std::function<void(Control*, int)> callback, ControlColor color, bool startState)
{
return addControl(ControlType::Switcher, label, startState ? "1" : "0", color, Control::noParent, callback);
@ -1015,7 +1036,25 @@ void ESPUIClass::updateControlLabel(Control* control, const char* value, int cli
#endif
return;
}
control->label = value;
control->label_r = value;
control->lablel_is_in_flash = 0;
updateControl(control, clientId);
}
void ESPUIClass::updateControlLabel(Control* control, const __FlashStringHelper* value, int clientId)
{
if (!control)
{
#if defined(DEBUG_ESPUI)
if (verbosity)
{
ESPU_DBGf_P(PSTR("Error: updateControlLabel Control: There is no control with the requested ID \n"));
}
#endif
return;
}
control->label_f = value;
control->lablel_is_in_flash = 1;
updateControl(control, clientId);
}

View File

@ -132,13 +132,18 @@ public:
uint16_t addControl(ControlType type, const char* label, const String& value);
uint16_t addControl(ControlType type, const char* label, const String& value, ControlColor color);
uint16_t addControl(ControlType type, const char* label, const String& value, ControlColor color, uint16_t parentControl);
uint16_t addControl(ControlType type, const __FlashStringHelper* label, const String& value, ControlColor color, uint16_t parentControl);
uint16_t addControl(ControlType type, const char* label, const String& value, ControlColor color, uint16_t parentControl, std::function<void(Control*, int)> callback);
uint16_t addControl(ControlType type, const __FlashStringHelper * label, const String& value, ControlColor color, uint16_t parentControl, std::function<void(Control*, int)> callback);
bool removeControl(uint16_t id, bool force_rebuild_ui = false);
// create Elements
// Create Event Button
uint16_t button(const char* label, std::function<void(Control*, int)> callback, ControlColor color, const String& value = "");
uint16_t button(const __FlashStringHelper* label, const __FlashStringHelper* value,
std::function<void(Control*, int)> callback, uint16_t parentControl = Control::noParent, ControlColor color = ControlColor::Dark);
uint16_t switcher(const char* label, std::function<void(Control*, int)> callback, ControlColor color, bool startState = false); // Create Toggle Button
uint16_t pad(const char* label, std::function<void(Control*, int)> callback, ControlColor color); // Create Pad Control
uint16_t padWithCenter(const char* label, std::function<void(Control*, int)> callback, ControlColor color); // Create Pad Control with Centerbutton
@ -168,6 +173,7 @@ public:
void updateControlLabel(uint16_t control, const char * value, int clientId = -1);
void updateControlLabel(Control* control, const char * value, int clientId = -1);
void updateControlLabel(Control* control, const __FlashStringHelper* value, int clientId = -1);
void updateControl(uint16_t id, int clientId = -1);
void updateControl(Control* control, int clientId = -1);
@ -285,7 +291,7 @@ protected:
bool basicAuth = true;
uint16_t controlCount = 0;
uint16_t addControl(ControlType type, const char* label, const String& value, ControlColor color, uint16_t parentControl, Control* control);
uint16_t addControl(Control* control);
#define ClientUpdateType_t ESPUIclient::ClientUpdateType_t
void NotifyClients(ClientUpdateType_t newState);

View File

@ -1,282 +1,302 @@
#include "ESPUI.h"
static uint16_t idCounter = 0;
static const String ControlError = "*** ESPUI ERROR: Could not transfer control ***";
Control::Control(ControlType type, const char* label, std::function<void(Control*, int)> callback, const String& value,
ControlColor color, bool visible, uint16_t parentControl)
: type(type),
label(label),
callback(callback),
value(value),
color(color),
visible(visible),
wide(false),
vertical(false),
enabled(true),
auto_update_value(false),
parentControl(parentControl),
next(nullptr)
{
id = ++idCounter;
ControlChangeID = 1;
}
Control::Control(const Control& Control)
: type(Control.type),
id(Control.id),
label(Control.label),
callback(Control.callback),
value(Control.value),
color(Control.color),
visible(Control.visible),
parentControl(Control.parentControl),
next(Control.next),
ControlChangeID(Control.ControlChangeID)
{ }
void Control::SendCallback(int type)
{
if(callback)
{
callback(this, type);
}
}
void Control::DeleteControl()
{
_ToBeDeleted = true;
callback = nullptr;
}
void Control::MarshalControl(JsonObject & _item, bool refresh, uint32_t StartingOffset)
{
JsonObject & item = _item;
uint32_t length = value.length();
uint32_t maxLength = uint32_t(double(ESPUI.jsonInitialDocumentSize) * 0.75);
if((length > maxLength) || StartingOffset)
{
/*
Serial.println(String("MarshalControl:Start Fragment Processing"));
Serial.println(String("MarshalControl:id: ") + String(id));
Serial.println(String("MarshalControl:length: ") + String(length));
Serial.println(String("MarshalControl:StartingOffset: ") + String(StartingOffset));
Serial.println(String("MarshalControl:maxLength: ") + String(maxLength));
if(0 == StartingOffset)
{
Serial.println(String("MarshalControl: New control to fragement. ID: ") + String(id));
}
else
{
Serial.println(String("MarshalControl: Next fragement. ID: ") + String(id));
}
*/
// indicate that no additional controls should be sent
_item[F("type")] = uint32_t(ControlType::Fragment);
_item[F("id")] = id;
length = min((length - StartingOffset), maxLength);
// Serial.println(String("MarshalControl:Final length: ") + String(length));
_item[F("offset")] = StartingOffset;
_item[F("length")] = length;
_item[F("total")] = value.length();
item = _item.createNestedObject(F("control"));
}
item[F("id")] = id;
ControlType TempType = (ControlType::Password == type) ? ControlType::Text : type;
if(refresh)
{
item[F("type")] = uint32_t(TempType) + uint32_t(ControlType::UpdateOffset);
}
else
{
item[F("type")] = uint32_t(TempType);
}
item[F("label")] = label;
item[F ("value")] = (ControlType::Password == type) ? F ("--------") : value.substring(StartingOffset, length + StartingOffset);
item[F("visible")] = visible;
item[F("color")] = (int)color;
item[F("enabled")] = enabled;
if (!panelStyle.isEmpty()) {item[F("panelStyle")] = panelStyle;}
if (!elementStyle.isEmpty()) {item[F("elementStyle")] = elementStyle;}
if (!inputType.isEmpty()) {item[F("inputType")] = inputType;}
if (wide == true) {item[F("wide")] = true;}
if (vertical == true) {item[F("vertical")] = true;}
if (parentControl != Control::noParent)
{
item[F("parentControl")] = String(parentControl);
}
// special case for selects: to preselect an option, you have to add
// "selected" to <option>
if (ControlType::Option == type)
{
Control* ParentControl = ESPUI.getControlNoLock(parentControl);
if (nullptr == ParentControl)
{
item[F("selected")] = emptyString;
}
else if (ParentControl->value == value)
{
item[F("selected")] = F("selected");
}
else
{
item[F("selected")] = "";
}
}
}
void Control::MarshalErrorMessage(JsonObject & item)
{
item[F("id")] = id;
item[F("type")] = uint32_t(ControlType::Label);
item[F("label")] = ControlError.c_str();
item[F("value")] = ControlError;
item[F("visible")] = true;
item[F("color")] = (int)ControlColor::Carrot;
item[F("enabled")] = true;
if (parentControl != Control::noParent)
{
item[F("parentControl")] = String(parentControl);
}
}
void Control::onWsEvent(String & cmd, String& data)
{
do // once
{
// Serial.println(String(F("Control::onWsEvent")));
SetControlChangedId(ESPUI.GetNextControlChangeId());
int arg = 0;
if (cmd.equals(F("bdown")))
{
arg = B_DOWN;
}
else if (cmd.equals(F("bup")))
{
arg = B_UP;
}
else if (cmd.equals(F("pfdown")))
{
arg = P_FOR_DOWN;
}
else if (cmd.equals(F("pfup")))
{
arg = P_FOR_UP;
}
else if (cmd.equals(F("pldown")))
{
arg = P_LEFT_DOWN;
}
else if (cmd.equals(F("plup")))
{
arg = P_LEFT_UP;
}
else if (cmd.equals(F("prdown")))
{
arg = P_RIGHT_DOWN;
}
else if (cmd.equals(F("prup")))
{
arg = P_RIGHT_UP;
}
else if (cmd.equals(F("pbdown")))
{
arg = P_BACK_DOWN;
}
else if (cmd.equals(F("pbup")))
{
arg = P_BACK_UP;
}
else if (cmd.equals(F("pcdown")))
{
arg = P_CENTER_DOWN;
}
else if (cmd.equals(F("pcup")))
{
arg = P_CENTER_UP;
}
else if (cmd.equals(F("sactive")))
{
if (auto_update_value)
value = "1";
arg = S_ACTIVE;
}
else if (cmd.equals(F("sinactive")))
{
if (auto_update_value)
value = "0";
arg = S_INACTIVE;
}
else if (cmd.equals(F("slvalue")))
{
if (auto_update_value)
value = data;
arg = SL_VALUE;
}
else if (cmd.equals(F("nvalue")))
{
if (auto_update_value)
value = data;
arg = N_VALUE;
}
else if (cmd.equals(F("tvalue")))
{
if (auto_update_value)
value = data;
arg = T_VALUE;
}
else if (cmd.equals(F("tabvalue")))
{
arg = 0;
}
else if (cmd.equals(F("svalue")))
{
if (auto_update_value)
value = data;
arg = S_VALUE;
}
else if (cmd.equals(F("time")))
{
if (auto_update_value)
value = data;
arg = TM_VALUE;
}
else
{
#if defined(DEBUG_ESPUI)
if (ESPUI.verbosity)
{
Serial.println(F("Control::onWsEvent:Malformed message from the websocket"));
}
#endif
break;
}
if (!HasCallback())
{
#if defined(DEBUG_ESPUI)
if (ESPUI.verbosity)
{
Serial.println(String(F("Control::onWsEvent:No callback found for ID ")) + String(id));
}
#endif
}
else
{
// Serial.println("Control::onWsEvent:Generating callback");
SendCallback(arg);
}
} while (false);
}
#include "ESPUI.h"
static uint16_t idCounter = 0;
static const String ControlError = "*** ESPUI ERROR: Could not transfer control ***";
Control::Control(ControlType type, const char* label, std::function<void(Control*, int)> callback, const String& value,
ControlColor color, bool visible, uint16_t parentControl)
: label_r(label),
callback(callback),
next(nullptr),
value(value),
type(type),
color(color),
parentControl(parentControl),
options(CTRL_OPT_ENABLED),
ControlChangeID(1)
{
this->visible = visible;
id = ++idCounter;
}
Control::Control(ControlType type, const __FlashStringHelper* label, std::function<void(Control*, int)> callback,
const String& value, ControlColor color, bool visible, uint16_t parentControl)
: label_f(label),
callback(callback),
next(nullptr),
value(value),
type(type),
color(color),
parentControl(parentControl),
options(CTRL_OPT_ENABLED | CTRL_OPT_LABEL_IN_FLASH),
ControlChangeID(1)
{
this->visible = visible;
id = ++idCounter;
}
Control::Control(const Control& Control)
: label_r(Control.label_r),
callback(Control.callback),
next(Control.next),
value(Control.value),
type(Control.type),
color(Control.color),
id(Control.id),
parentControl(Control.parentControl),
visible(Control.visible),
ControlChangeID(Control.ControlChangeID)
{
options = Control.options;
if (lablel_is_in_flash)
label_f = Control.label_f;
}
void Control::SendCallback(int type)
{
if(callback)
{
callback(this, type);
}
}
void Control::DeleteControl()
{
_ToBeDeleted = true;
callback = nullptr;
}
void Control::MarshalControl(JsonObject & _item, bool refresh, uint32_t StartingOffset)
{
JsonObject & item = _item;
uint32_t length = value.length();
uint32_t maxLength = uint32_t(double(ESPUI.jsonInitialDocumentSize) * 0.75);
if((length > maxLength) || StartingOffset)
{
/*
Serial.println(String("MarshalControl:Start Fragment Processing"));
Serial.println(String("MarshalControl:id: ") + String(id));
Serial.println(String("MarshalControl:length: ") + String(length));
Serial.println(String("MarshalControl:StartingOffset: ") + String(StartingOffset));
Serial.println(String("MarshalControl:maxLength: ") + String(maxLength));
if(0 == StartingOffset)
{
Serial.println(String("MarshalControl: New control to fragement. ID: ") + String(id));
}
else
{
Serial.println(String("MarshalControl: Next fragement. ID: ") + String(id));
}
*/
// indicate that no additional controls should be sent
_item[F("type")] = uint32_t(ControlType::Fragment);
_item[F("id")] = id;
length = min((length - StartingOffset), maxLength);
// Serial.println(String("MarshalControl:Final length: ") + String(length));
_item[F("offset")] = StartingOffset;
_item[F("length")] = length;
_item[F("total")] = value.length();
item = _item.createNestedObject(F("control"));
}
item[F("id")] = id;
ControlType TempType = (ControlType::Password == type) ? ControlType::Text : type;
if(refresh)
{
item[F("type")] = uint32_t(TempType) + uint32_t(ControlType::UpdateOffset);
}
else
{
item[F("type")] = uint32_t(TempType);
}
if (lablel_is_in_flash)
item[F("label")] = label_f;
else
item[F("label")] = label_r;
item[F ("value")] = (ControlType::Password == type) ? F ("--------") : value.substring(StartingOffset, length + StartingOffset);
item[F("visible")] = visible;
item[F("color")] = (int)color;
item[F("enabled")] = enabled;
if (!panelStyle.isEmpty()) {item[F("panelStyle")] = panelStyle;}
if (!elementStyle.isEmpty()) {item[F("elementStyle")] = elementStyle;}
if (!inputType.isEmpty()) {item[F("inputType")] = inputType;}
if (wide == true) {item[F("wide")] = true;}
if (vertical == true) {item[F("vertical")] = true;}
if (parentControl != Control::noParent)
{
item[F("parentControl")] = String(parentControl);
}
// special case for selects: to preselect an option, you have to add
// "selected" to <option>
if (ControlType::Option == type)
{
Control* ParentControl = ESPUI.getControlNoLock(parentControl);
if (nullptr == ParentControl)
{
item[F("selected")] = emptyString;
}
else if (ParentControl->value == value)
{
item[F("selected")] = F("selected");
}
else
{
item[F("selected")] = "";
}
}
}
void Control::MarshalErrorMessage(JsonObject & item)
{
item[F("id")] = id;
item[F("type")] = uint32_t(ControlType::Label);
item[F("label")] = ControlError.c_str();
item[F("value")] = ControlError;
item[F("visible")] = true;
item[F("color")] = (int)ControlColor::Carrot;
item[F("enabled")] = true;
if (parentControl != Control::noParent)
{
item[F("parentControl")] = String(parentControl);
}
}
void Control::onWsEvent(String & cmd, String& data)
{
do // once
{
// Serial.println(String(F("Control::onWsEvent")));
SetControlChangedId(ESPUI.GetNextControlChangeId());
int arg = 0;
if (cmd.equals(F("bdown")))
{
arg = B_DOWN;
}
else if (cmd.equals(F("bup")))
{
arg = B_UP;
}
else if (cmd.equals(F("pfdown")))
{
arg = P_FOR_DOWN;
}
else if (cmd.equals(F("pfup")))
{
arg = P_FOR_UP;
}
else if (cmd.equals(F("pldown")))
{
arg = P_LEFT_DOWN;
}
else if (cmd.equals(F("plup")))
{
arg = P_LEFT_UP;
}
else if (cmd.equals(F("prdown")))
{
arg = P_RIGHT_DOWN;
}
else if (cmd.equals(F("prup")))
{
arg = P_RIGHT_UP;
}
else if (cmd.equals(F("pbdown")))
{
arg = P_BACK_DOWN;
}
else if (cmd.equals(F("pbup")))
{
arg = P_BACK_UP;
}
else if (cmd.equals(F("pcdown")))
{
arg = P_CENTER_DOWN;
}
else if (cmd.equals(F("pcup")))
{
arg = P_CENTER_UP;
}
else if (cmd.equals(F("sactive")))
{
if (auto_update_value)
value = "1";
arg = S_ACTIVE;
}
else if (cmd.equals(F("sinactive")))
{
if (auto_update_value)
value = "0";
arg = S_INACTIVE;
}
else if (cmd.equals(F("slvalue")))
{
if (auto_update_value)
value = data;
arg = SL_VALUE;
}
else if (cmd.equals(F("nvalue")))
{
if (auto_update_value)
value = data;
arg = N_VALUE;
}
else if (cmd.equals(F("tvalue")))
{
if (auto_update_value)
value = data;
arg = T_VALUE;
}
else if (cmd.equals(F("tabvalue")))
{
arg = 0;
}
else if (cmd.equals(F("svalue")))
{
if (auto_update_value)
value = data;
arg = S_VALUE;
}
else if (cmd.equals(F("time")))
{
if (auto_update_value)
value = data;
arg = TM_VALUE;
}
else
{
#if defined(DEBUG_ESPUI)
if (ESPUI.verbosity)
{
Serial.println(F("Control::onWsEvent:Malformed message from the websocket"));
}
#endif
break;
}
if (!HasCallback())
{
#if defined(DEBUG_ESPUI)
if (ESPUI.verbosity)
{
Serial.println(String(F("Control::onWsEvent:No callback found for ID ")) + String(id));
}
#endif
}
else
{
// Serial.println("Control::onWsEvent:Generating callback");
SendCallback(arg);
}
} while (false);
}

View File

@ -1,127 +1,162 @@
#pragma once
#include <Arduino.h>
#include <ArduinoJson.h>
#include <functional>
enum ControlType : uint8_t
{
// fixed Controls
Title = 0,
// updatable Controls
Pad,
PadWithCenter,
Button,
Label,
Switcher,
Slider,
Number,
Text,
Graph,
GraphPoint,
Tab,
Select,
Option,
Min,
Max,
Step,
Gauge,
Accel,
Separator,
Time,
Fragment,
Password = 99,
UpdateOffset = 100,
};
enum ControlColor : uint8_t
{
Turquoise,
Emerald,
Peterriver,
Wetasphalt,
Sunflower,
Carrot,
Alizarin,
Dark,
None = 0xFF
};
class Control
{
public:
ControlType type;
uint16_t id; // just mirroring the id here for practical reasons
const char* label;
std::function<void(Control*, int)> callback;
String value;
ControlColor color;
bool visible;
bool wide;
bool vertical;
bool enabled;
bool auto_update_value;
uint16_t parentControl;
String panelStyle;
String elementStyle;
String inputType;
Control* next;
static constexpr uint16_t noParent = 0xffff;
Control(ControlType type,
const char* label,
std::function<void(Control*, int)> callback,
const String& value,
ControlColor color,
bool visible,
uint16_t parentControl);
Control(const Control& Control);
void SendCallback(int type);
bool HasCallback() { return (nullptr != callback); }
void MarshalControl(ArduinoJson::JsonObject& item, bool refresh, uint32_t DataOffset);
void MarshalErrorMessage(ArduinoJson::JsonObject& item);
void DeleteControl();
void onWsEvent(String& cmd, String& data);
inline bool ToBeDeleted() { return _ToBeDeleted; }
inline bool NeedsSync(uint32_t lastControlChangeID) {return (false == _ToBeDeleted) && (lastControlChangeID < ControlChangeID);}
void SetControlChangedId(uint32_t value) {ControlChangeID = value;}
private:
bool _ToBeDeleted = false;
uint32_t ControlChangeID = 0;
};
#define UI_TITLE ControlType::Title
#define UI_LABEL ControlType::Label
#define UI_BUTTON ControlType::Button
#define UI_SWITCHER ControlType::Switcher
#define UI_PAD ControlType::Pad
#define UI_CPAD ControlType::Cpad
#define UI_SLIDER ControlType::Slider
#define UI_NUMBER ControlType::Number
#define UI_TEXT_INPUT ControlType::Text
#define UI_GRAPH ControlType::Graph
#define UI_ADD_GRAPH_POINT ControlType::GraphPoint
#define UPDATE_LABEL ControlType::UpdateLabel
#define UPDATE_SWITCHER ControlType::UpdateSwitcher
#define UPDATE_SLIDER ControlType::UpdateSlider
#define UPDATE_NUMBER ControlType::UpdateNumber
#define UPDATE_TEXT_INPUT ControlType::UpdateText
#define CLEAR_GRAPH ControlType::ClearGraph
// Colors
#define COLOR_TURQUOISE ControlColor::Turquoise
#define COLOR_EMERALD ControlColor::Emerald
#define COLOR_PETERRIVER ControlColor::Peterriver
#define COLOR_WETASPHALT ControlColor::Wetasphalt
#define COLOR_SUNFLOWER ControlColor::Sunflower
#define COLOR_CARROT ControlColor::Carrot
#define COLOR_ALIZARIN ControlColor::Alizarin
#define COLOR_DARK ControlColor::Dark
#define COLOR_NONE ControlColor::None
#pragma once
#include <Arduino.h>
#include <ArduinoJson.h>
#include <functional>
enum ControlType : uint8_t
{
// fixed Controls
Title = 0,
// updatable Controls
Pad,
PadWithCenter,
Button,
Label,
Switcher,
Slider,
Number,
Text,
Graph,
GraphPoint,
Tab,
Select,
Option,
Min,
Max,
Step,
Gauge,
Accel,
Separator,
Time,
Fragment,
Password = 99,
UpdateOffset = 100,
};
enum ControlColor : uint8_t
{
Turquoise,
Emerald,
Peterriver,
Wetasphalt,
Sunflower,
Carrot,
Alizarin,
Dark,
None = 0xFF
};
#define CTRL_OPT_ENABLED 0x01
#define CTRL_OPT_VISIBLE 0x02
#define CTRL_OPT_LABEL_IN_FLASH 0x04
#define CTRL_OPT_AUTO_UPDATE_VALUE 0x08
#define CTRL_OPT_WIDE 0x10
#define CTRL_OPT_VERTICAL 0x20
class Control
{
public:
static constexpr uint16_t noParent = 0xffff;
// Pointers
union
{
const char* label_r;
const __FlashStringHelper* label_f;
};
std::function<void(Control*, int)> callback;
Control* next;
// Strings
String value;
String panelStyle;
String elementStyle;
String inputType;
//enums
ControlType type;
ControlColor color;
// uint16_t
uint16_t id; // just mirroring the id here for practical reasons
uint16_t parentControl;
union
{
struct
{
uint16_t enabled : 1 ;
uint16_t visible : 1;
uint16_t lablel_is_in_flash : 1;
uint16_t auto_update_value : 1;
uint16_t wide : 1;
uint16_t vertical : 1;
};
uint16_t options;
};
Control(ControlType type,
const char* label,
std::function<void(Control*, int)> callback,
const String& value,
ControlColor color,
bool visible,
uint16_t parentControl);
Control(ControlType type,
const __FlashStringHelper* label,
std::function<void(Control*, int)> callback,
const String& value,
ControlColor color,
bool visible,
uint16_t parentControl);
Control(const Control& Control);
void SendCallback(int type);
bool HasCallback() { return (nullptr != callback); }
void MarshalControl(ArduinoJson::JsonObject& item, bool refresh, uint32_t DataOffset);
void MarshalErrorMessage(ArduinoJson::JsonObject& item);
void DeleteControl();
void onWsEvent(String& cmd, String& data);
inline bool ToBeDeleted() { return _ToBeDeleted; }
inline bool NeedsSync(uint32_t lastControlChangeID) {return (false == _ToBeDeleted) && (lastControlChangeID < ControlChangeID);}
void SetControlChangedId(uint32_t value) {ControlChangeID = value;}
private:
bool _ToBeDeleted = false;
uint32_t ControlChangeID;
};
#define UI_TITLE ControlType::Title
#define UI_LABEL ControlType::Label
#define UI_BUTTON ControlType::Button
#define UI_SWITCHER ControlType::Switcher
#define UI_PAD ControlType::Pad
#define UI_CPAD ControlType::Cpad
#define UI_SLIDER ControlType::Slider
#define UI_NUMBER ControlType::Number
#define UI_TEXT_INPUT ControlType::Text
#define UI_GRAPH ControlType::Graph
#define UI_ADD_GRAPH_POINT ControlType::GraphPoint
#define UPDATE_LABEL ControlType::UpdateLabel
#define UPDATE_SWITCHER ControlType::UpdateSwitcher
#define UPDATE_SLIDER ControlType::UpdateSlider
#define UPDATE_NUMBER ControlType::UpdateNumber
#define UPDATE_TEXT_INPUT ControlType::UpdateText
#define CLEAR_GRAPH ControlType::ClearGraph
// Colors
#define COLOR_TURQUOISE ControlColor::Turquoise
#define COLOR_EMERALD ControlColor::Emerald
#define COLOR_PETERRIVER ControlColor::Peterriver
#define COLOR_WETASPHALT ControlColor::Wetasphalt
#define COLOR_SUNFLOWER ControlColor::Sunflower
#define COLOR_CARROT ControlColor::Carrot
#define COLOR_ALIZARIN ControlColor::Alizarin
#define COLOR_DARK ControlColor::Dark
#define COLOR_NONE ControlColor::None