Compare commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
0ec1e34a96 | ||
|
|
f49d3cd3e1 | ||
|
|
36cdd67f23 | ||
|
|
87c5d75040 | ||
|
|
e81531a8e5 | ||
|
|
3ba1ff5b59 | ||
|
|
962926333f | ||
|
|
9750951dfd | ||
|
|
12209f9789 | ||
|
|
69868c1b31 | ||
|
|
c9666792df | ||
|
|
2240517cc2 | ||
|
|
0488de5d32 |
@@ -0,0 +1,9 @@
|
|||||||
|
# ESLabsCurses
|
||||||
|
Library for curses like interfaces on embedded displays.
|
||||||
|
|
||||||
|
Right now its only for my [CDashDisplay](https://github.com/ESilva15/CDashDisplay)
|
||||||
|
project, so it probably doesn't work that good on other projects.
|
||||||
|
|
||||||
|
# TO-DO
|
||||||
|
- Start suing `Arduino_Canvas` for drawable elements. I think it uses double buffering¿
|
||||||
|
Need to explore that.
|
||||||
+42
-7
@@ -1,11 +1,39 @@
|
|||||||
#include "UIBar.h"
|
#include "UIBar.h"
|
||||||
|
#include "UIComponent.h"
|
||||||
#include "UIDrawing.h"
|
#include "UIDrawing.h"
|
||||||
|
#include <cstdint>
|
||||||
|
#include <stdio.h>
|
||||||
|
|
||||||
UIBar::UIBar(Arduino_GFX *d, UIDimensions dims, UIDecorations *decor,
|
UIBar::UIBar() {
|
||||||
|
this->type = BAR;
|
||||||
|
};
|
||||||
|
|
||||||
|
UIBar::UIBar(Arduino_GFX *d, UIDimensions dims, UIDecorations decor,
|
||||||
char *title)
|
char *title)
|
||||||
: UIElement(d, dims, decor, title) {}
|
: UIElement(d, dims, decor, title) {
|
||||||
|
this->type = BAR;
|
||||||
|
}
|
||||||
|
|
||||||
void UIBar::Update(char *v) {
|
UIBar::~UIBar() {
|
||||||
|
// height taking the rule into account
|
||||||
|
// NOTE: need to clean this all up the 7s and 2 and whatever
|
||||||
|
int16_t charWidth = CHR_WIDTH(this->decor.textSize);
|
||||||
|
int16_t textHeight = 8 * this->decor.textSize;
|
||||||
|
int16_t totalHeight = this->dims.height + 7 + 2 + textHeight;
|
||||||
|
int16_t totalX = this->dims.x - (charWidth / 2);
|
||||||
|
int16_t totalWidth = this->dims.width + charWidth;
|
||||||
|
|
||||||
|
|
||||||
|
this->display->fillRect(
|
||||||
|
totalX,
|
||||||
|
this->dims.y,
|
||||||
|
totalWidth,
|
||||||
|
totalHeight,
|
||||||
|
this->decor.bgColor
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
void UIBar::Update(const char *v, bool forceRedraw) {
|
||||||
unsigned long time = millis();
|
unsigned long time = millis();
|
||||||
if ((time - this->lastUpdate) <= this->refreshRate) {
|
if ((time - this->lastUpdate) <= this->refreshRate) {
|
||||||
return;
|
return;
|
||||||
@@ -14,7 +42,7 @@ void UIBar::Update(char *v) {
|
|||||||
// Conver the string to an integer
|
// Conver the string to an integer
|
||||||
uint32_t newVal = atoi(v);
|
uint32_t newVal = atoi(v);
|
||||||
|
|
||||||
if (this->value == newVal) {
|
if ((this->value == newVal) && !forceRedraw) {
|
||||||
// If the value hasn't changed we do not need to re-render
|
// If the value hasn't changed we do not need to re-render
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
@@ -66,7 +94,7 @@ void UIBar::renderBlank() {
|
|||||||
this->display->print("!RANGE");
|
this->display->print("!RANGE");
|
||||||
}
|
}
|
||||||
|
|
||||||
void UIBar::Box() {
|
void UIBar::drawBox() {
|
||||||
// If the range was not set, we cannot draw our ruler
|
// If the range was not set, we cannot draw our ruler
|
||||||
if (this->range <= 0) {
|
if (this->range <= 0) {
|
||||||
this->renderBlank();
|
this->renderBlank();
|
||||||
@@ -93,12 +121,19 @@ void UIBar::Box() {
|
|||||||
this->display->setTextColor(RED);
|
this->display->setTextColor(RED);
|
||||||
this->display->drawFastVLine(x, this->dims.y + this->dims.height, 7, RED);
|
this->display->drawFastVLine(x, this->dims.y + this->dims.height, 7, RED);
|
||||||
|
|
||||||
|
// NOTE: this may fill here due to insuficcient memory?
|
||||||
char legend[5];
|
char legend[5];
|
||||||
sprintf(legend, "%d", k);
|
sprintf(legend, "%d", k);
|
||||||
this->display->setCursor(x - (CHR_WIDTH(this->decor->textSize) / 2),
|
this->display->setCursor(x - (CHR_WIDTH(this->decor.textSize) / 2),
|
||||||
this->dims.y + this->dims.height + 7 + 2);
|
this->dims.y + this->dims.height + 7 + 2);
|
||||||
this->display->setTextColor(WHITE);
|
this->display->setTextColor(WHITE);
|
||||||
this->display->setTextSize(this->decor->textSize);
|
this->display->setTextSize(this->decor.textSize);
|
||||||
this->display->print(legend);
|
this->display->print(legend);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void UIBar::Redraw() {
|
||||||
|
char val[8];
|
||||||
|
sprintf(val, "%d", this->value);
|
||||||
|
this->Update(val, true);
|
||||||
|
}
|
||||||
|
|||||||
+7
-3
@@ -2,6 +2,7 @@
|
|||||||
#define _UI_BAR
|
#define _UI_BAR
|
||||||
|
|
||||||
#include "UIComponent.h"
|
#include "UIComponent.h"
|
||||||
|
#include "values.h"
|
||||||
|
|
||||||
struct UIBar : UIElement {
|
struct UIBar : UIElement {
|
||||||
// This might be the only when where its more efficient to have the data
|
// This might be the only when where its more efficient to have the data
|
||||||
@@ -9,12 +10,15 @@ struct UIBar : UIElement {
|
|||||||
uint32_t value = 0; // current tach value
|
uint32_t value = 0; // current tach value
|
||||||
uint8_t range = 0; // define the tach range, ie: 8 for 8000rpm
|
uint8_t range = 0; // define the tach range, ie: 8 for 8000rpm
|
||||||
|
|
||||||
UIBar(Arduino_GFX *d, UIDimensions dims, UIDecorations *decor, char *title);
|
UIBar();
|
||||||
|
~UIBar() override;
|
||||||
|
UIBar(Arduino_GFX *d, UIDimensions dims, UIDecorations decor, char *title);
|
||||||
|
|
||||||
void Update(char *val);
|
void Update(const char *val, bool forceRedraw) override;
|
||||||
|
void Redraw() override;
|
||||||
void DrawBar(uint32_t *oldValue, uint32_t *newValue);
|
void DrawBar(uint32_t *oldValue, uint32_t *newValue);
|
||||||
void renderBlank();
|
void renderBlank();
|
||||||
void Box();
|
void drawBox();
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|||||||
@@ -0,0 +1,19 @@
|
|||||||
|
#include "UIBase.h"
|
||||||
|
#include "HardwareSerial.h"
|
||||||
|
#include "UIComponent.h"
|
||||||
|
#include <Arduino_GFX.h>
|
||||||
|
|
||||||
|
UIBase::UIBase() : UIElement(nullptr, {0, 0, 0, 0}, UIDecorations(), (char *)"") {
|
||||||
|
this->type = STRING;
|
||||||
|
memset(this->value, 0, this->bufferSize);
|
||||||
|
}
|
||||||
|
|
||||||
|
UIBase::UIBase(Arduino_GFX *d, UIDimensions dims, UIDecorations decor,
|
||||||
|
char *title)
|
||||||
|
: UIElement(d, dims, decor, title) {
|
||||||
|
this->type = BASE;
|
||||||
|
memset(this->value, 0, this->bufferSize);
|
||||||
|
}
|
||||||
|
|
||||||
|
void UIBase::Update(const char* data, bool forceRedraw) {}
|
||||||
|
void UIBase::Redraw() {}
|
||||||
@@ -0,0 +1,17 @@
|
|||||||
|
#ifndef __UI_BASE__
|
||||||
|
#define __UI_BASE__
|
||||||
|
|
||||||
|
#include "UIComponent.h"
|
||||||
|
|
||||||
|
// Representation of single line strings
|
||||||
|
struct UIBase : UIElement {
|
||||||
|
static const std::size_t bufferSize = 64;
|
||||||
|
char value[bufferSize];
|
||||||
|
|
||||||
|
UIBase();
|
||||||
|
UIBase(Arduino_GFX *d, UIDimensions dims, UIDecorations decor, char *title);
|
||||||
|
void Update(const char *value, bool forceRedraw) override;
|
||||||
|
void Redraw() override;
|
||||||
|
};
|
||||||
|
|
||||||
|
#endif
|
||||||
+83
-18
@@ -1,22 +1,35 @@
|
|||||||
#include "UIComponent.h"
|
#include "UIComponent.h"
|
||||||
|
#include "values.h"
|
||||||
|
#include "logger.h"
|
||||||
|
#include "windowPool.h"
|
||||||
// #include "u8g2.h"
|
// #include "u8g2.h"
|
||||||
#include "Arduino.h"
|
#include "Arduino.h"
|
||||||
#include "HardwareSerial.h"
|
#include "HardwareSerial.h"
|
||||||
#include "UIDrawing.h"
|
#include "UIDrawing.h"
|
||||||
// #include <U8g2lib.h>
|
// #include <U8g2lib.h>
|
||||||
|
#include <cstdarg>
|
||||||
#include <cstdint>
|
#include <cstdint>
|
||||||
|
#include <cstring>
|
||||||
|
|
||||||
#define DEBUG 1
|
#define DEBUG 1
|
||||||
|
|
||||||
UIElement::UIElement(Arduino_GFX *d, UIDimensions dims, UIDecorations *decor,
|
UIElement::UIElement()
|
||||||
char *title)
|
: display(nullptr), dims(UIDimensions(0, 0, 0, 0)), decor(UIDecorations()) {}
|
||||||
: display(d), dims(dims), decor(decor), title(title) {}
|
|
||||||
|
|
||||||
UIDimensions::UIDimensions(uint16_t x, uint16_t y, uint16_t w, uint16_t h)
|
UIElement::UIElement(Arduino_GFX *d, UIDimensions dims, UIDecorations decor,
|
||||||
: x(x), y(y), width(w), height(h) {}
|
char *title)
|
||||||
|
: display(d), dims(dims), decor(decor) {
|
||||||
|
strncpy(this->title, title, MAX_TITLE_LEN);
|
||||||
|
}
|
||||||
|
|
||||||
|
UIElement::~UIElement() {
|
||||||
|
// Destruction involves redrawing over the "old" area
|
||||||
|
fillRect(this->dims.x, this->dims.y, this->dims.width, this->dims.height,
|
||||||
|
this->decor.bgColor, this->display);
|
||||||
|
}
|
||||||
|
|
||||||
int16_t UIElement::getContentAreaX0() {
|
int16_t UIElement::getContentAreaX0() {
|
||||||
if (this->decor->hasBorder) {
|
if (this->decor.hasBorder) {
|
||||||
return this->dims.x + DEFAULT_BORDER_THICKNESS + DEFAULT_MARGIN;
|
return this->dims.x + DEFAULT_BORDER_THICKNESS + DEFAULT_MARGIN;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -24,7 +37,7 @@ int16_t UIElement::getContentAreaX0() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
int16_t UIElement::getContentAreaY0() {
|
int16_t UIElement::getContentAreaY0() {
|
||||||
if (this->decor->hasBorder) {
|
if (this->decor.hasBorder) {
|
||||||
return this->dims.y + this->getTitleAreaHeight() +
|
return this->dims.y + this->getTitleAreaHeight() +
|
||||||
DEFAULT_TITLE_CONTENT_SPACING;
|
DEFAULT_TITLE_CONTENT_SPACING;
|
||||||
}
|
}
|
||||||
@@ -51,7 +64,7 @@ uint16_t UIElement::getTitleAreaHeight() {
|
|||||||
int16_t x = 0, y = 0;
|
int16_t x = 0, y = 0;
|
||||||
uint16_t w = 0, h = 0;
|
uint16_t w = 0, h = 0;
|
||||||
|
|
||||||
this->display->setTextSize(this->decor->titleSize);
|
this->display->setTextSize(this->decor.titleSize);
|
||||||
this->display->getTextBounds((const char *)this->title, 0, 0, &x, &y, &w, &h);
|
this->display->getTextBounds((const char *)this->title, 0, 0, &x, &y, &w, &h);
|
||||||
|
|
||||||
return h;
|
return h;
|
||||||
@@ -61,12 +74,31 @@ uint16_t UIElement::getTitleAreaWidth() {
|
|||||||
int16_t x = 0, y = 0;
|
int16_t x = 0, y = 0;
|
||||||
uint16_t w = 0, h = 0;
|
uint16_t w = 0, h = 0;
|
||||||
|
|
||||||
this->display->setTextSize(this->decor->titleSize);
|
this->display->setTextSize(this->decor.titleSize);
|
||||||
this->display->getTextBounds((const char *)this->title, 0, 0, &x, &y, &w, &h);
|
this->display->getTextBounds((const char *)this->title, 0, 0, &x, &y, &w, &h);
|
||||||
|
|
||||||
return w;
|
return w;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void UIElement::SetTitle(char* format, ...) {
|
||||||
|
va_list args;
|
||||||
|
va_start(args, format);
|
||||||
|
vsnprintf(this->title, MAX_TITLE_LEN, format, args);
|
||||||
|
va_end(args);
|
||||||
|
}
|
||||||
|
|
||||||
|
void UIElement::SetUIDecorations(UIDecorations decor) {
|
||||||
|
this->decor = decor;
|
||||||
|
}
|
||||||
|
|
||||||
|
void UIElement::SetUIDimensions(UIDimensions dims) {
|
||||||
|
this->dims = dims;
|
||||||
|
}
|
||||||
|
|
||||||
|
void UIElement::SetDisplay(Arduino_GFX *d) {
|
||||||
|
this->display = d;
|
||||||
|
}
|
||||||
|
|
||||||
void UIElement::replaceString(char *oldVal, char *newVal) {
|
void UIElement::replaceString(char *oldVal, char *newVal) {
|
||||||
size_t newValLen = strlen(newVal);
|
size_t newValLen = strlen(newVal);
|
||||||
size_t oldValLen = strlen(oldVal);
|
size_t oldValLen = strlen(oldVal);
|
||||||
@@ -76,33 +108,66 @@ void UIElement::replaceString(char *oldVal, char *newVal) {
|
|||||||
int16_t y0 = this->getContentAreaY0(); // <- Crashes here
|
int16_t y0 = this->getContentAreaY0(); // <- Crashes here
|
||||||
// Before here
|
// Before here
|
||||||
|
|
||||||
this->display->setTextSize(this->decor->textSize);
|
this->display->setTextSize(this->decor.textSize);
|
||||||
|
|
||||||
// If the new value is shorter, delete the extra in advance
|
// If the new value is shorter, delete the extra in advance
|
||||||
if (oldValLen > newValLen) {
|
if (oldValLen > newValLen) {
|
||||||
// If the old value is longer than the new value, we have to delete the
|
// If the old value is longer than the new value, we have to delete the
|
||||||
// extra of the old value, which is whatever starts at the new value len
|
// extra of the old value, which is whatever starts at the new value len
|
||||||
for (size_t start = newValLen; start < oldValLen; start++) {
|
for (std::size_t start = newValLen; start < oldValLen; start++) {
|
||||||
this->display->setCursor(x0 + start * (CHR_WIDTH(this->decor->textSize)),
|
this->display->setCursor(x0 + start * (CHR_WIDTH(this->decor.textSize)),
|
||||||
y0);
|
y0);
|
||||||
this->display->setTextColor(this->decor->bgColor);
|
this->display->setTextColor(this->decor.bgColor);
|
||||||
this->display->print(oldVal[start]);
|
this->display->print(oldVal[start]);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
for (size_t k = 0; k < newValLen; k++) {
|
for (std::size_t k = 0; k < newValLen; k++) {
|
||||||
if (k <= oldValLen) {
|
if (k <= oldValLen) {
|
||||||
if (oldVal[k] != newVal[k]) {
|
if (oldVal[k] != newVal[k]) {
|
||||||
this->display->setCursor(x0 + k * (CHR_WIDTH(this->decor->textSize)),
|
this->display->setCursor(x0 + k * (CHR_WIDTH(this->decor.textSize)),
|
||||||
y0 + 0);
|
y0 + 0);
|
||||||
this->display->setTextColor(this->decor->bgColor);
|
this->display->setTextColor(this->decor.bgColor);
|
||||||
this->display->print(oldVal[k]);
|
this->display->print(oldVal[k]);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
this->display->setCursor(x0 + k * (CHR_WIDTH(this->decor->textSize)),
|
this->display->setCursor(x0 + k * (CHR_WIDTH(this->decor.textSize)),
|
||||||
y0 + 0);
|
y0 + 0);
|
||||||
this->display->setTextColor(this->decor->fgColor);
|
this->display->setTextColor(this->decor.fgColor);
|
||||||
this->display->print(newVal[k]);
|
this->display->print(newVal[k]);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
int16_t UIElement::AddChild(ComponentType t) {
|
||||||
|
if (childrenCount >= MAX_CHILDREN) {
|
||||||
|
LOG_ERROR(F("Failed to add child: childrenCount exceeds MAX_CHILDREN\r\n"));
|
||||||
|
LOG_ERROR(F(" %d >= %d\r\n"), childrenCount, MAX_CHILDREN);
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
int16_t newElem = WindowPool::Allocate(t);
|
||||||
|
if (newElem < 0) {
|
||||||
|
LOG_ERROR(F("Failed to allocate new component\r\n"));
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
LOG_DEBUG(F("Successfully allocated component: %d\r\n"), newElem);
|
||||||
|
|
||||||
|
this->children[this->curChildIndex] = newElem;
|
||||||
|
this->childrenCount++;
|
||||||
|
this->curChildIndex++;
|
||||||
|
|
||||||
|
return newElem;
|
||||||
|
}
|
||||||
|
|
||||||
|
void UIElement::RemoveChild(int16_t childId) {
|
||||||
|
WindowPool::Deallocate(childId);
|
||||||
|
}
|
||||||
|
|
||||||
|
UIElement* UIElement::GetChild(int16_t childID) {
|
||||||
|
return WindowPool::GetHandle(childID);
|
||||||
|
}
|
||||||
|
|
||||||
|
std::uint8_t UIElement::ChildrenCount() {
|
||||||
|
return this->childrenCount;
|
||||||
|
}
|
||||||
|
|||||||
+34
-17
@@ -1,33 +1,40 @@
|
|||||||
#ifndef __UI_COMPONENT
|
#ifndef __UI_COMPONENT__
|
||||||
#define __UI_COMPONENT
|
#define __UI_COMPONENT__
|
||||||
|
|
||||||
#include "Arduino_GFX.h"
|
#include "Arduino_GFX.h"
|
||||||
|
#include "values.h"
|
||||||
#include "UIDecorations.h"
|
#include "UIDecorations.h"
|
||||||
|
#include "UIDimensions.h"
|
||||||
|
#include <cstdint>
|
||||||
#include <stdint.h>
|
#include <stdint.h>
|
||||||
|
|
||||||
enum ComponentType {
|
class UIElement {
|
||||||
STRING,
|
private:
|
||||||
TABLE,
|
uint8_t childrenCount = 0;
|
||||||
};
|
int8_t curChildIndex = -1; // Start at -1, have no children
|
||||||
|
|
||||||
struct UIDimensions {
|
public:
|
||||||
uint16_t x = 0, y = 0;
|
|
||||||
uint16_t width = 0, height = 0;
|
|
||||||
|
|
||||||
UIDimensions(uint16_t x, uint16_t y, uint16_t w, uint16_t h);
|
|
||||||
};
|
|
||||||
|
|
||||||
struct UIElement {
|
|
||||||
Arduino_GFX *display;
|
Arduino_GFX *display;
|
||||||
UIDimensions dims;
|
UIDimensions dims;
|
||||||
UIDecorations *decor;
|
UIDecorations decor;
|
||||||
char *title;
|
char title[MAX_TITLE_LEN];
|
||||||
uint64_t lastUpdate = 0;
|
uint64_t lastUpdate = 0;
|
||||||
uint16_t refreshRate = 0;
|
uint16_t refreshRate = 0;
|
||||||
ComponentType type;
|
ComponentType type;
|
||||||
|
|
||||||
UIElement(Arduino_GFX *d, UIDimensions dims, UIDecorations *decor,
|
UIElement();
|
||||||
|
UIElement(Arduino_GFX *d, UIDimensions dims, UIDecorations decor,
|
||||||
char *Title);
|
char *Title);
|
||||||
|
virtual ~UIElement();
|
||||||
|
|
||||||
|
// Children
|
||||||
|
int16_t children[MAX_CHILDREN];
|
||||||
|
|
||||||
|
// Children Handling
|
||||||
|
int16_t AddChild(ComponentType t);
|
||||||
|
void RemoveChild(int16_t childID);
|
||||||
|
UIElement* GetChild(int16_t childID);
|
||||||
|
uint8_t ChildrenCount();
|
||||||
|
|
||||||
// Getters
|
// Getters
|
||||||
int16_t getContentAreaX0();
|
int16_t getContentAreaX0();
|
||||||
@@ -39,6 +46,12 @@ struct UIElement {
|
|||||||
uint16_t getTitleAreaHeight();
|
uint16_t getTitleAreaHeight();
|
||||||
uint16_t getTitleAreaWidth();
|
uint16_t getTitleAreaWidth();
|
||||||
|
|
||||||
|
// Setters
|
||||||
|
void SetTitle(char* format, ...);
|
||||||
|
void SetUIDecorations(UIDecorations decor);
|
||||||
|
void SetUIDimensions(UIDimensions dims);
|
||||||
|
void SetDisplay(Arduino_GFX *d);
|
||||||
|
|
||||||
// Positioning
|
// Positioning
|
||||||
void horizontalCenter(UIElement *reference);
|
void horizontalCenter(UIElement *reference);
|
||||||
void verticalCenter(UIElement *reference);
|
void verticalCenter(UIElement *reference);
|
||||||
@@ -50,6 +63,10 @@ struct UIElement {
|
|||||||
void drawBox();
|
void drawBox();
|
||||||
void noBox();
|
void noBox();
|
||||||
void replaceString(char *oldVal, char *newVal);
|
void replaceString(char *oldVal, char *newVal);
|
||||||
|
|
||||||
|
// Viewing - more like actual rendering data
|
||||||
|
virtual void Update(const char *data, bool forceRedraw) = 0;
|
||||||
|
virtual void Redraw() = 0;
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|||||||
@@ -1,6 +1,21 @@
|
|||||||
#include "UIDecorations.h"
|
#include "UIDecorations.h"
|
||||||
|
|
||||||
|
namespace Curses {
|
||||||
|
};
|
||||||
|
|
||||||
UIDecorations::UIDecorations() {}
|
UIDecorations::UIDecorations() {}
|
||||||
UIDecorations::UIDecorations(uint16_t bg, uint16_t fg, uint16_t title,
|
UIDecorations::UIDecorations(uint16_t bg, uint16_t fg, uint16_t title,
|
||||||
uint16_t border, uint8_t titleSize,
|
uint16_t border, uint8_t titleSize,
|
||||||
uint8_t textSize) {}
|
uint8_t textSize) {}
|
||||||
|
|
||||||
|
UIDecorations& UIDecorations::operator=(const UIDecorations& other) {
|
||||||
|
this->textSize = other.textSize;
|
||||||
|
this->titleSize = other.titleSize;
|
||||||
|
this->titleColor = other.titleColor;
|
||||||
|
this->borderColor = other.borderColor;
|
||||||
|
this->bgColor = other.bgColor;
|
||||||
|
this->fgColor = other.fgColor;
|
||||||
|
this->hasBorder = other.hasBorder;
|
||||||
|
|
||||||
|
return *this;
|
||||||
|
}
|
||||||
|
|||||||
+9
-4
@@ -2,17 +2,22 @@
|
|||||||
#define __UI_DECORATIONS
|
#define __UI_DECORATIONS
|
||||||
|
|
||||||
#include "UIDrawing.h"
|
#include "UIDrawing.h"
|
||||||
|
#include <cstdint>
|
||||||
#include <stdint.h>
|
#include <stdint.h>
|
||||||
|
|
||||||
struct UIDecorations {
|
struct UIDecorations {
|
||||||
bool hasBorder = true;
|
uint16_t bgColor = MAIN_BG_COLOR;
|
||||||
uint16_t bgColor = MAIN_BG_COLOR, fgColor = MAIN_FG_COLOR;
|
uint16_t fgColor = MAIN_FG_COLOR;
|
||||||
uint16_t titleColor = MAIN_FG_COLOR, borderColor = RED;
|
uint16_t titleColor = MAIN_FG_COLOR;
|
||||||
uint8_t titleSize = 2, textSize = 4;
|
uint16_t borderColor = RED;
|
||||||
|
uint8_t titleSize = 2;
|
||||||
|
uint8_t textSize = 4;
|
||||||
|
uint8_t hasBorder = true;
|
||||||
|
|
||||||
UIDecorations();
|
UIDecorations();
|
||||||
UIDecorations(uint16_t bg, uint16_t fg, uint16_t title, uint16_t border,
|
UIDecorations(uint16_t bg, uint16_t fg, uint16_t title, uint16_t border,
|
||||||
uint8_t titleSize, uint8_t textSize);
|
uint8_t titleSize, uint8_t textSize);
|
||||||
|
UIDecorations& operator=(const UIDecorations& other);
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|||||||
@@ -0,0 +1,15 @@
|
|||||||
|
#include "UIDimensions.h"
|
||||||
|
|
||||||
|
UIDimensions::UIDimensions() : x(0), y(0), width(0), height(0) {}
|
||||||
|
|
||||||
|
UIDimensions::UIDimensions(uint16_t x, uint16_t y, uint16_t w, uint16_t h)
|
||||||
|
: x(x), y(y), width(w), height(h) {}
|
||||||
|
|
||||||
|
UIDimensions& UIDimensions::operator=(const UIDimensions& other) {
|
||||||
|
this->x = other.x;
|
||||||
|
this->y = other.y;
|
||||||
|
this->width = other.width;
|
||||||
|
this->height = other.height;
|
||||||
|
|
||||||
|
return *this;
|
||||||
|
}
|
||||||
@@ -0,0 +1,18 @@
|
|||||||
|
#ifndef __UI_DIMENSIONS__
|
||||||
|
#define __UI_DIMENSIONS__
|
||||||
|
|
||||||
|
#include <cstdint>
|
||||||
|
#include <stdint.h>
|
||||||
|
|
||||||
|
struct UIDimensions {
|
||||||
|
uint16_t x = 0;
|
||||||
|
uint16_t y = 0;
|
||||||
|
uint16_t width = 0;
|
||||||
|
uint16_t height = 0;
|
||||||
|
|
||||||
|
UIDimensions();
|
||||||
|
UIDimensions(uint16_t x, uint16_t y, uint16_t w, uint16_t h);
|
||||||
|
UIDimensions& operator=(const UIDimensions& other);
|
||||||
|
};
|
||||||
|
|
||||||
|
#endif
|
||||||
+10
-3
@@ -51,11 +51,11 @@ void UIElement::placeLeft(UIElement *ref) {
|
|||||||
|
|
||||||
void UIElement::drawBox() {
|
void UIElement::drawBox() {
|
||||||
// This is the border rectangle
|
// This is the border rectangle
|
||||||
if (this->decor->hasBorder) {
|
if (this->decor.hasBorder) {
|
||||||
for (int k = 0; k < DEFAULT_BORDER_THICKNESS; k++) {
|
for (int k = 0; k < DEFAULT_BORDER_THICKNESS; k++) {
|
||||||
this->display->drawRect(
|
this->display->drawRect(
|
||||||
this->dims.x + k, this->dims.y + k, this->dims.width - (k * 2),
|
this->dims.x + k, this->dims.y + k, this->dims.width - (k * 2),
|
||||||
this->dims.height - (k * 2), this->decor->borderColor);
|
this->dims.height - (k * 2), this->decor.borderColor);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -88,7 +88,7 @@ void UIElement::drawBox() {
|
|||||||
this->display->drawRect(x, y, w, h, BLUE);
|
this->display->drawRect(x, y, w, h, BLUE);
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
if (this->decor->hasBorder) {
|
if (this->decor.hasBorder) {
|
||||||
// Remove the border line behind the title
|
// Remove the border line behind the title
|
||||||
this->display->fillRect(titleTopLeftX - DEFAULT_MARGIN, this->dims.y,
|
this->display->fillRect(titleTopLeftX - DEFAULT_MARGIN, this->dims.y,
|
||||||
titleAreaWidth + DEFAULT_MARGIN,
|
titleAreaWidth + DEFAULT_MARGIN,
|
||||||
@@ -99,9 +99,16 @@ void UIElement::drawBox() {
|
|||||||
this->display->print(this->title);
|
this->display->print(this->title);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
#ifdef DEBUG
|
#ifdef DEBUG
|
||||||
// Element bounds
|
// Element bounds
|
||||||
this->display->drawRect(this->dims.x, this->dims.y, this->dims.width,
|
this->display->drawRect(this->dims.x, this->dims.y, this->dims.width,
|
||||||
this->dims.height, PURPLE);
|
this->dims.height, PURPLE);
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void fillRect(int16_t x, int16_t y, int16_t w, int16_t h,
|
||||||
|
uint16_t colour, Arduino_GFX *display) {
|
||||||
|
// TODO: should we have a separate place to do all the drawing?
|
||||||
|
display->fillRect(x, y, w, h, colour);
|
||||||
|
}
|
||||||
|
|||||||
@@ -2,6 +2,7 @@
|
|||||||
#define __CURSES_UI_VISUALS
|
#define __CURSES_UI_VISUALS
|
||||||
|
|
||||||
#include <Arduino_GFX.h>
|
#include <Arduino_GFX.h>
|
||||||
|
#include <cstdint>
|
||||||
|
|
||||||
#define RIGHT 0
|
#define RIGHT 0
|
||||||
#define INVERTED 1
|
#define INVERTED 1
|
||||||
@@ -21,5 +22,7 @@
|
|||||||
|
|
||||||
uint16_t calculateHeight(int16_t titleSize, int16_t textSize, int16_t nLines);
|
uint16_t calculateHeight(int16_t titleSize, int16_t textSize, int16_t nLines);
|
||||||
uint16_t calculateWidth(int16_t textSize, int16_t nChars);
|
uint16_t calculateWidth(int16_t textSize, int16_t nChars);
|
||||||
|
void fillRect(int16_t x, int16_t y, int16_t w, int16_t h,
|
||||||
|
uint16_t colour, Arduino_GFX *display);
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|||||||
@@ -0,0 +1,30 @@
|
|||||||
|
#include "UIScreen.h"
|
||||||
|
#include "windowPool.h"
|
||||||
|
#include "UIComponent.h"
|
||||||
|
#include "UIDecorations.h"
|
||||||
|
#include "UIDimensions.h"
|
||||||
|
|
||||||
|
Curses::Screen::Screen(Arduino_GFX *d, UIDimensions dims,
|
||||||
|
UIDecorations decor)
|
||||||
|
: display(d), dims(dims), decor(decor) {
|
||||||
|
}
|
||||||
|
|
||||||
|
void Curses::Screen::Setup(const char* title) {
|
||||||
|
// This should always return the first available component
|
||||||
|
this->mainWindowID = WindowPool::Allocate(BASE);
|
||||||
|
if (this->mainWindowID != 0) {
|
||||||
|
// Something wrong happened
|
||||||
|
Serial2.print("Unexpected ID for main window: ");
|
||||||
|
Serial2.println(this->mainWindowID);
|
||||||
|
for (;;) {
|
||||||
|
delay(1000);
|
||||||
|
Serial2.println("Program interrupted due to setup failure");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
this->mainWindowHandle = WindowPool::GetHandle(this->mainWindowID);
|
||||||
|
this->mainWindowHandle->SetDisplay(this->display);
|
||||||
|
this->mainWindowHandle->SetTitle((char*)"%s [%2d]", title, this->mainWindowID);
|
||||||
|
this->mainWindowHandle->SetUIDecorations(this->decor);
|
||||||
|
this->mainWindowHandle->SetUIDimensions(this->dims);
|
||||||
|
}
|
||||||
@@ -0,0 +1,24 @@
|
|||||||
|
#ifndef __UI_SCREEN__
|
||||||
|
#define __UI_SCREEN__
|
||||||
|
|
||||||
|
#include "UIComponent.h"
|
||||||
|
#include "UIDecorations.h"
|
||||||
|
#include "UIDimensions.h"
|
||||||
|
|
||||||
|
namespace Curses {
|
||||||
|
// Entrypoint for our UI. We will have a single screen and this screen can
|
||||||
|
// have some windows and whatnot
|
||||||
|
class Screen {
|
||||||
|
public:
|
||||||
|
UIDimensions dims;
|
||||||
|
UIDecorations decor;
|
||||||
|
Arduino_GFX *display;
|
||||||
|
|
||||||
|
int16_t mainWindowID;
|
||||||
|
UIElement* mainWindowHandle;
|
||||||
|
Screen(Arduino_GFX *d, UIDimensions dims, UIDecorations decor);
|
||||||
|
void Setup(const char* title);
|
||||||
|
};
|
||||||
|
}; // namespace Curses
|
||||||
|
|
||||||
|
#endif
|
||||||
+8
-4
@@ -3,19 +3,19 @@
|
|||||||
#include "UIComponent.h"
|
#include "UIComponent.h"
|
||||||
#include <Arduino_GFX.h>
|
#include <Arduino_GFX.h>
|
||||||
|
|
||||||
UIString::UIString() : UIElement(nullptr, {0, 0, 0, 0}, nullptr, (char *)"") {
|
UIString::UIString() : UIElement(nullptr, {0, 0, 0, 0}, UIDecorations(), (char *)"") {
|
||||||
this->type = STRING;
|
this->type = STRING;
|
||||||
memset(this->value, 0, this->bufferSize);
|
memset(this->value, 0, this->bufferSize);
|
||||||
}
|
}
|
||||||
|
|
||||||
UIString::UIString(Arduino_GFX *d, UIDimensions dims, UIDecorations *decor,
|
UIString::UIString(Arduino_GFX *d, UIDimensions dims, UIDecorations decor,
|
||||||
char *title)
|
char *title)
|
||||||
: UIElement(d, dims, decor, title) {
|
: UIElement(d, dims, decor, title) {
|
||||||
this->type = STRING;
|
this->type = STRING;
|
||||||
memset(this->value, 0, this->bufferSize);
|
memset(this->value, 0, this->bufferSize);
|
||||||
}
|
}
|
||||||
|
|
||||||
void UIString::Update(const char *v) {
|
void UIString::Update(const char *v, bool forceRedraw) {
|
||||||
uint64_t time = millis();
|
uint64_t time = millis();
|
||||||
if ((time - this->lastUpdate) <= this->refreshRate) {
|
if ((time - this->lastUpdate) <= this->refreshRate) {
|
||||||
return;
|
return;
|
||||||
@@ -28,7 +28,7 @@ void UIString::Update(const char *v) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// If the value hasn't changed we do not need to re-render
|
// If the value hasn't changed we do not need to re-render
|
||||||
if (strcmp(this->value, v) == 0) {
|
if ((strcmp(this->value, v) == 0) && !forceRedraw) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -46,3 +46,7 @@ void UIString::Update(const char *v) {
|
|||||||
replaceString(oldVal, newVal);
|
replaceString(oldVal, newVal);
|
||||||
strncpy(this->value, v, this->bufferSize);
|
strncpy(this->value, v, this->bufferSize);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void UIString::Redraw() {
|
||||||
|
this->Update(this->value, true);
|
||||||
|
}
|
||||||
|
|||||||
+6
-5
@@ -1,17 +1,18 @@
|
|||||||
#ifndef __UI_STRING
|
#ifndef __UI_STRING__
|
||||||
#define __UI_STRING
|
#define __UI_STRING__
|
||||||
|
|
||||||
#include "UIComponent.h"
|
#include "UIComponent.h"
|
||||||
|
|
||||||
// Representation of single line strings
|
// Representation of single line strings
|
||||||
struct UIString : UIElement {
|
struct UIString : UIElement {
|
||||||
static const size_t bufferSize = 64;
|
static const std::size_t bufferSize = 64;
|
||||||
char value[bufferSize];
|
char value[bufferSize];
|
||||||
|
|
||||||
UIString();
|
UIString();
|
||||||
UIString(Arduino_GFX *d, UIDimensions dims, UIDecorations *decor,
|
UIString(Arduino_GFX *d, UIDimensions dims, UIDecorations decor,
|
||||||
char *title);
|
char *title);
|
||||||
void Update(const char *value);
|
void Update(const char *value, bool forceRedraw) override;
|
||||||
|
void Redraw() override;
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|||||||
+16
-12
@@ -6,7 +6,8 @@
|
|||||||
|
|
||||||
#define DEBUG
|
#define DEBUG
|
||||||
|
|
||||||
UITable::UITable(Arduino_GFX *gfx, UIDimensions dims, UIDecorations *decor,
|
UITable::UITable() {};
|
||||||
|
UITable::UITable(Arduino_GFX *gfx, UIDimensions dims, UIDecorations decor,
|
||||||
int nRows, int nCols, int *colWidths, char *title)
|
int nRows, int nCols, int *colWidths, char *title)
|
||||||
: UIElement(gfx, dims, decor, title) {
|
: UIElement(gfx, dims, decor, title) {
|
||||||
this->type = TABLE;
|
this->type = TABLE;
|
||||||
@@ -16,18 +17,18 @@ UITable::UITable(Arduino_GFX *gfx, UIDimensions dims, UIDecorations *decor,
|
|||||||
this->colWidths = colWidths;
|
this->colWidths = colWidths;
|
||||||
|
|
||||||
// Default decoration for every cell
|
// Default decoration for every cell
|
||||||
this->decor->textSize = 2;
|
this->decor.textSize = 2;
|
||||||
|
|
||||||
for (int k = 0; k < ROWS * COLUMNS; k++) {
|
for (int k = 0; k < ROWS * COLUMNS; k++) {
|
||||||
UIDecorations *cellDecor = new UIDecorations();
|
UIDecorations cellDecor = UIDecorations();
|
||||||
cellDecor->textSize = this->decor->textSize;
|
cellDecor.textSize = this->decor.textSize;
|
||||||
|
|
||||||
UIDimensions dims = {0, 0, 0, 0};
|
UIDimensions dims = {0, 0, 0, 0};
|
||||||
|
|
||||||
this->tableData[k] = new UIString(display, dims, cellDecor, (char *)"");
|
this->tableData[k] = new UIString(display, dims, cellDecor, (char *)"");
|
||||||
}
|
}
|
||||||
|
|
||||||
int cellH = CHR_HEIGHT(this->decor->textSize) + CELL_MARGIN;
|
int cellH = CHR_HEIGHT(this->decor.textSize) + CELL_MARGIN;
|
||||||
|
|
||||||
// Initialize the table dimensions
|
// Initialize the table dimensions
|
||||||
//// Calculate the height
|
//// Calculate the height
|
||||||
@@ -37,7 +38,7 @@ UITable::UITable(Arduino_GFX *gfx, UIDimensions dims, UIDecorations *decor,
|
|||||||
//// Calculate the width
|
//// Calculate the width
|
||||||
for (int c = 0; c < this->nColumns; c++) {
|
for (int c = 0; c < this->nColumns; c++) {
|
||||||
this->dims.width +=
|
this->dims.width +=
|
||||||
(CHR_WIDTH(this->decor->textSize) + CELL_MARGIN) * this->colWidths[c];
|
(CHR_WIDTH(this->decor.textSize) + CELL_MARGIN) * this->colWidths[c];
|
||||||
}
|
}
|
||||||
this->dims.width += (DEFAULT_BORDER_THICKNESS + DEFAULT_MARGIN) * 2;
|
this->dims.width += (DEFAULT_BORDER_THICKNESS + DEFAULT_MARGIN) * 2;
|
||||||
}
|
}
|
||||||
@@ -52,7 +53,7 @@ uint16_t UITable::getContentAreaHeight() {
|
|||||||
* I recon its dynamic enough for now
|
* I recon its dynamic enough for now
|
||||||
*/
|
*/
|
||||||
void UITable::setup() {
|
void UITable::setup() {
|
||||||
int cellH = CHR_HEIGHT(this->decor->textSize) + CELL_MARGIN;
|
int cellH = CHR_HEIGHT(this->decor.textSize) + CELL_MARGIN;
|
||||||
|
|
||||||
// Initialize the cells
|
// Initialize the cells
|
||||||
uint16_t yOffset = this->getContentAreaY0();
|
uint16_t yOffset = this->getContentAreaY0();
|
||||||
@@ -60,23 +61,26 @@ void UITable::setup() {
|
|||||||
int16_t xOffset = this->getContentAreaX0();
|
int16_t xOffset = this->getContentAreaX0();
|
||||||
for (int c = 0; c < COLUMNS; c++) {
|
for (int c = 0; c < COLUMNS; c++) {
|
||||||
this->tableData[r * COLUMNS + c]->refreshRate = this->refreshRate;
|
this->tableData[r * COLUMNS + c]->refreshRate = this->refreshRate;
|
||||||
this->tableData[r * COLUMNS + c]->decor->textSize = this->decor->textSize;
|
this->tableData[r * COLUMNS + c]->decor.textSize = this->decor.textSize;
|
||||||
this->tableData[r * COLUMNS + c]->decor->hasBorder = false;
|
this->tableData[r * COLUMNS + c]->decor.hasBorder = false;
|
||||||
this->tableData[r * COLUMNS + c]->dims.x = xOffset + CELL_MARGIN;
|
this->tableData[r * COLUMNS + c]->dims.x = xOffset + CELL_MARGIN;
|
||||||
this->tableData[r * COLUMNS + c]->dims.y = (cellH * r) + yOffset;
|
this->tableData[r * COLUMNS + c]->dims.y = (cellH * r) + yOffset;
|
||||||
this->tableData[r * COLUMNS + c]->dims.height = cellH;
|
this->tableData[r * COLUMNS + c]->dims.height = cellH;
|
||||||
this->tableData[r * COLUMNS + c]->dims.width =
|
this->tableData[r * COLUMNS + c]->dims.width =
|
||||||
this->colWidths[c] * (CHR_WIDTH(this->decor->textSize) + CELL_MARGIN);
|
this->colWidths[c] * (CHR_WIDTH(this->decor.textSize) + CELL_MARGIN);
|
||||||
memset(this->tableData[r * COLUMNS + c]->value, 0,
|
memset(this->tableData[r * COLUMNS + c]->value, 0,
|
||||||
this->tableData[r * COLUMNS + c]->bufferSize);
|
this->tableData[r * COLUMNS + c]->bufferSize);
|
||||||
|
|
||||||
xOffset +=
|
xOffset +=
|
||||||
this->colWidths[c] * (CHR_WIDTH(this->decor->textSize) + CELL_MARGIN);
|
this->colWidths[c] * (CHR_WIDTH(this->decor.textSize) + CELL_MARGIN);
|
||||||
|
|
||||||
#ifdef DEBUG
|
#ifdef DEBUG
|
||||||
this->tableData[r * COLUMNS + c]->drawBox();
|
this->tableData[r * COLUMNS + c]->drawBox();
|
||||||
this->tableData[r * COLUMNS + c]->Update("---");
|
this->tableData[r * COLUMNS + c]->Update("---", false);
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void UITable::Update(const char* data, bool forceRedraw) {}
|
||||||
|
void UITable::Redraw() {}
|
||||||
|
|||||||
+6
-1
@@ -18,7 +18,8 @@ struct UITable : UIElement {
|
|||||||
int *colWidths;
|
int *colWidths;
|
||||||
UIString **tableData;
|
UIString **tableData;
|
||||||
|
|
||||||
UITable(Arduino_GFX *gfx, UIDimensions dims, UIDecorations *decor, int nR,
|
UITable();
|
||||||
|
UITable(Arduino_GFX *gfx, UIDimensions dims, UIDecorations decor, int nR,
|
||||||
int nC, int *cWidth, char *t);
|
int nC, int *cWidth, char *t);
|
||||||
|
|
||||||
// void Update(StandingLine standings[5]);
|
// void Update(StandingLine standings[5]);
|
||||||
@@ -26,6 +27,10 @@ struct UITable : UIElement {
|
|||||||
|
|
||||||
// Getters
|
// Getters
|
||||||
uint16_t getContentAreaHeight();
|
uint16_t getContentAreaHeight();
|
||||||
|
|
||||||
|
// Rendering
|
||||||
|
void Update(const char* data, bool forceRedraw) override;
|
||||||
|
void Redraw() override;
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|||||||
@@ -0,0 +1,15 @@
|
|||||||
|
#ifndef __VALUES__
|
||||||
|
#define __VALUES__
|
||||||
|
|
||||||
|
#define MAX_WINDOWS 512
|
||||||
|
#define MAX_CHILDREN 32
|
||||||
|
#define MAX_TITLE_LEN 32
|
||||||
|
|
||||||
|
enum ComponentType {
|
||||||
|
BASE,
|
||||||
|
BAR,
|
||||||
|
STRING,
|
||||||
|
TABLE,
|
||||||
|
};
|
||||||
|
|
||||||
|
#endif
|
||||||
@@ -0,0 +1,102 @@
|
|||||||
|
#include "windowPool.h"
|
||||||
|
#include "logger.h"
|
||||||
|
#include "UIComponent.h"
|
||||||
|
#include "UIBar.h"
|
||||||
|
#include "UIString.h"
|
||||||
|
#include "UIBase.h"
|
||||||
|
#include "UITable.h"
|
||||||
|
#include "values.h"
|
||||||
|
#include "logger.h"
|
||||||
|
|
||||||
|
namespace WindowPool {
|
||||||
|
WindowEntry pool[MAX_WINDOWS];
|
||||||
|
bool inUse[MAX_WINDOWS] = {false};
|
||||||
|
|
||||||
|
static inline int16_t getNextIndex() {
|
||||||
|
for (int k = 0; k < MAX_WINDOWS; k++) {
|
||||||
|
if (!inUse[k]) {
|
||||||
|
return k;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
int16_t Allocate(ComponentType t) {
|
||||||
|
int16_t nextIndex = getNextIndex();
|
||||||
|
if (nextIndex < 0) {
|
||||||
|
LOG_ERROR(F("Failed to allocate comp: poolIndex exceeds MAX_WINDOWS\r\n"));
|
||||||
|
LOG_ERROR(F(" %d >= %d\r\n"), nextIndex, MAX_WINDOWS);
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
pool[nextIndex].type = t;
|
||||||
|
|
||||||
|
switch(pool[nextIndex].type) {
|
||||||
|
case BAR:
|
||||||
|
LOG_DEBUG(F("PRE allocing\r\n"));
|
||||||
|
pool[nextIndex].bar = new UIBar();
|
||||||
|
LOG_DEBUG(F("POST allocing type: \r\n"), pool[nextIndex].type);
|
||||||
|
break;
|
||||||
|
case STRING:
|
||||||
|
pool[nextIndex].str = new UIString();
|
||||||
|
break;
|
||||||
|
case TABLE:
|
||||||
|
pool[nextIndex].table = new UITable();
|
||||||
|
break;
|
||||||
|
case BASE:
|
||||||
|
pool[nextIndex].base = new UIBase();
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Mark it as in use
|
||||||
|
inUse[nextIndex] = true;
|
||||||
|
|
||||||
|
return nextIndex;
|
||||||
|
}
|
||||||
|
|
||||||
|
void Deallocate(int16_t id) {
|
||||||
|
// NOTE: I don't think we need this since it calls the destructor...
|
||||||
|
switch(pool[id].type) {
|
||||||
|
case BAR:
|
||||||
|
delete pool[id].str;
|
||||||
|
break;
|
||||||
|
case STRING:
|
||||||
|
delete pool[id].str;
|
||||||
|
break;
|
||||||
|
case TABLE:
|
||||||
|
break;
|
||||||
|
case BASE:
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
inUse[id] = false;
|
||||||
|
}
|
||||||
|
|
||||||
|
UIElement* GetHandle(int16_t id) {
|
||||||
|
switch(pool[id].type) {
|
||||||
|
case BAR:
|
||||||
|
return pool[id].bar;
|
||||||
|
break;
|
||||||
|
case STRING:
|
||||||
|
return pool[id].str;
|
||||||
|
break;
|
||||||
|
case TABLE:
|
||||||
|
return pool[id].table;
|
||||||
|
break;
|
||||||
|
case BASE:
|
||||||
|
return pool[id].base;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
return nullptr;
|
||||||
|
}
|
||||||
|
|
||||||
|
void PrintInUse() {
|
||||||
|
for (int k = 0; k < MAX_WINDOWS; k++) {
|
||||||
|
if (inUse[k]) {
|
||||||
|
LOG_TRACE(F("Window in use: %d : %d\n"), k, inUse[k]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,39 @@
|
|||||||
|
#ifndef __WINDOW_POOL__
|
||||||
|
#define __WINDOW_POOL__
|
||||||
|
|
||||||
|
#include <cstdint>
|
||||||
|
#include <stdint.h>
|
||||||
|
#include "values.h"
|
||||||
|
|
||||||
|
struct UIElement;
|
||||||
|
struct UIString;
|
||||||
|
struct UIBar;
|
||||||
|
struct UITable;
|
||||||
|
struct UIBase;
|
||||||
|
|
||||||
|
namespace WindowPool {
|
||||||
|
struct WindowEntry {
|
||||||
|
ComponentType type;
|
||||||
|
// Well I did this like this but I recon we can use polymorphism instead
|
||||||
|
union {
|
||||||
|
UIBase* base;
|
||||||
|
UIString* str;
|
||||||
|
UIBar* bar;
|
||||||
|
UITable* table;
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
|
extern WindowEntry pool[MAX_WINDOWS];
|
||||||
|
extern bool inUse[MAX_WINDOWS];
|
||||||
|
|
||||||
|
int16_t Allocate(ComponentType t);
|
||||||
|
// I will finish this later on, still have to figure out how to properly
|
||||||
|
// destroy the UIComponent
|
||||||
|
void Deallocate(int16_t childID);
|
||||||
|
UIElement* GetHandle(int16_t index);
|
||||||
|
|
||||||
|
// Debugging
|
||||||
|
void PrintInUse();
|
||||||
|
};
|
||||||
|
|
||||||
|
#endif
|
||||||
Reference in New Issue
Block a user