mirror of
https://github.com/s00500/ESPUI.git
synced 2025-06-14 02:30:41 +00:00
Support for dynamic custom inline styling.
Adds two functions in ESPUI.h: setPanelStyle() setElementStyle() These allow for custom inline CSS styles to be applied to the panel and to the specific UI element repectively. For example: ``` char stylecol1[30] sprintf(stylecol1, "background-color: #%06X;", (unsigned int) random(0x0, 0xFFFFFF)); ESPUI.setPanelStyle(switch1, stylecol1); ``` This will set the panel of the given control to a random hex colour. This is supported by both the initial UI message, and by control update messages, so you can change these styles dynamically in response to other events. setElementStyle() is not perfect. Because CSS inline styles can only style one specific DOM element, for controls made up of multiple elements (like the "pad") this is limited. I have tried to make an appropriate choice for each supported control.
This commit is contained in:
@ -757,6 +757,10 @@ void ESPUIClass::updateControl(Control* control, int clientId)
|
||||
root["id"] = control->id;
|
||||
root["visible"] = control->visible;
|
||||
root["color"] = (int)control->color;
|
||||
if (control->panelStyle != 0)
|
||||
root["panelStyle"] = control->panelStyle;
|
||||
if (control->elementStyle != 0)
|
||||
root["elementStyle"] = control->elementStyle;
|
||||
serializeJson(document, json);
|
||||
|
||||
#if defined(DEBUG_ESPUI)
|
||||
@ -797,6 +801,26 @@ void ESPUIClass::updateControl(Control* control, int clientId)
|
||||
}
|
||||
}
|
||||
|
||||
void ESPUIClass::setPanelStyle(uint16_t id, String style, int clientId)
|
||||
{
|
||||
Control* control = getControl(id);
|
||||
if (control)
|
||||
{
|
||||
control->panelStyle = style;
|
||||
updateControl(control, clientId);
|
||||
}
|
||||
}
|
||||
|
||||
void ESPUIClass::setElementStyle(uint16_t id, String style, int clientId)
|
||||
{
|
||||
Control* control = getControl(id);
|
||||
if (control)
|
||||
{
|
||||
control->elementStyle = style;
|
||||
updateControl(control, clientId);
|
||||
}
|
||||
}
|
||||
|
||||
void ESPUIClass::updateControl(uint16_t id, int clientId)
|
||||
{
|
||||
Control* control = getControl(id);
|
||||
@ -947,7 +971,8 @@ Initially this function used to send the control element data individually.
|
||||
Due to a change in the ESPAsyncWebserver library this had top be changed to be
|
||||
sent as one blob at the beginning. Therefore a new type is used as well
|
||||
*/
|
||||
void ESPUIClass::jsonDom(AsyncWebSocketClient* client) {
|
||||
void ESPUIClass::jsonDom(AsyncWebSocketClient* client)
|
||||
{
|
||||
|
||||
DynamicJsonDocument document(jsonInitialDocumentSize);
|
||||
document["type"] = (int)UI_INITIAL_GUI;
|
||||
@ -960,37 +985,43 @@ void ESPUIClass::jsonDom(AsyncWebSocketClient* client) {
|
||||
titleItem["type"] = (int)UI_TITLE;
|
||||
titleItem["label"] = ui_title;
|
||||
|
||||
while(1) {
|
||||
while (1)
|
||||
{
|
||||
control = prepareJSONChunk(client, control, &items);
|
||||
|
||||
String json;
|
||||
serializeJson(document, json);
|
||||
#if defined(DEBUG_ESPUI)
|
||||
if (this->verbosity >= Verbosity::VerboseJSON) {
|
||||
#if defined(DEBUG_ESPUI)
|
||||
if (this->verbosity >= Verbosity::VerboseJSON)
|
||||
{
|
||||
Serial.println("Sending elements --------->");
|
||||
Serial.println(json);
|
||||
}
|
||||
#endif
|
||||
if (client != nullptr) client->text(json);
|
||||
else this->ws->textAll(json);
|
||||
#endif
|
||||
if (client != nullptr)
|
||||
client->text(json);
|
||||
else
|
||||
this->ws->textAll(json);
|
||||
|
||||
if(control == nullptr) break;
|
||||
if (control == nullptr)
|
||||
break;
|
||||
|
||||
document.clear();
|
||||
items.clear();
|
||||
document["type"] = (int) UI_EXTEND_GUI;
|
||||
document["type"] = (int)UI_EXTEND_GUI;
|
||||
items = document.createNestedArray("controls");
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/* Prepare a chunk of elements as a single JSON string. If the allowed number of elements is greater than the total number
|
||||
this will represent the entire UI and this function will return null. If a control pointer is returned then the limit
|
||||
was reached, the currently serialised must be sent, and then processing resumed to send the next chunk. */
|
||||
Control *ESPUIClass::prepareJSONChunk(AsyncWebSocketClient* client, Control* control, JsonArray *items) {
|
||||
/* Prepare a chunk of elements as a single JSON string. If the allowed number of elements is greater than the total
|
||||
number this will represent the entire UI and this function will return null. If a control pointer is returned then the
|
||||
limit was reached, the currently serialised must be sent, and then processing resumed to send the next chunk. */
|
||||
Control* ESPUIClass::prepareJSONChunk(AsyncWebSocketClient* client, Control* control, JsonArray* items)
|
||||
{
|
||||
int elementcount = 0;
|
||||
|
||||
while (control != nullptr && elementcount < 10) {
|
||||
while (control != nullptr && elementcount < 10)
|
||||
{
|
||||
JsonObject item = items->createNestedObject();
|
||||
|
||||
item["id"] = String(control->id);
|
||||
@ -999,18 +1030,26 @@ Control *ESPUIClass::prepareJSONChunk(AsyncWebSocketClient* client, Control* con
|
||||
item["value"] = String(control->value);
|
||||
item["color"] = (int)control->color;
|
||||
item["visible"] = (int)control->visible;
|
||||
if (control->panelStyle != 0)
|
||||
item["panelStyle"] = String(control->panelStyle);
|
||||
if (control->elementStyle != 0)
|
||||
item["elementStyle"] = String(control->elementStyle);
|
||||
|
||||
if (control->parentControl != Control::noParent) {
|
||||
if (control->parentControl != Control::noParent)
|
||||
{
|
||||
item["parentControl"] = String(control->parentControl);
|
||||
}
|
||||
|
||||
// special case for selects: to preselect an option, you have to add
|
||||
// "selected" to <option>
|
||||
if (control->type == ControlType::Option) {
|
||||
if (ESPUI.getControl(control->parentControl)->value == control->value) {
|
||||
if (control->type == ControlType::Option)
|
||||
{
|
||||
if (ESPUI.getControl(control->parentControl)->value == control->value)
|
||||
{
|
||||
item["selected"] = "selected";
|
||||
}
|
||||
else {
|
||||
else
|
||||
{
|
||||
item["selected"] = "";
|
||||
}
|
||||
}
|
||||
|
@ -138,6 +138,8 @@ public:
|
||||
ControlColor color;
|
||||
bool visible;
|
||||
uint16_t parentControl;
|
||||
String panelStyle;
|
||||
String elementStyle;
|
||||
Control* next;
|
||||
|
||||
static constexpr uint16_t noParent = 0xffff;
|
||||
@ -281,6 +283,9 @@ public:
|
||||
void clearGraph(uint16_t id, int clientId = -1);
|
||||
void addGraphPoint(uint16_t id, int nValue, int clientId = -1);
|
||||
|
||||
void setPanelStyle(uint16_t id, String style, int clientId = -1);
|
||||
void setElementStyle(uint16_t id, String style, int clientId = -1);
|
||||
|
||||
// Variables
|
||||
const char* ui_title = "ESPUI"; // Store UI Title and Header Name
|
||||
Control* controls = nullptr;
|
||||
|
File diff suppressed because one or more lines are too long
Reference in New Issue
Block a user