theme editor: color editor ported to LVGL
This commit is contained in:
committed by
Raphael Coeffic
parent
1abf71efce
commit
b54e260edc
@@ -19,14 +19,15 @@
|
||||
* GNU General Public License for more details.
|
||||
*/
|
||||
#include "color_editor.h"
|
||||
#include "font.h"
|
||||
|
||||
constexpr int BAR_MARGIN = 5;
|
||||
|
||||
constexpr int BAR_TOP_MARGIN = 5;
|
||||
constexpr int BAR_HEIGHT_OFFSET = BAR_TOP_MARGIN + 25;
|
||||
|
||||
const char *RGBChars[MAX_BARS] = { "R", "G", "B" };
|
||||
const char *HSVChars[MAX_BARS] = { "H", "S", "V" };
|
||||
static const char *RGBChars[MAX_BARS] = { "R", "G", "B" };
|
||||
static const char *HSVChars[MAX_BARS] = { "H", "S", "V" };
|
||||
|
||||
// ColorTypes()
|
||||
// A ColorType implements a three bar color editor. Currently we support HSV and RGB
|
||||
@@ -37,9 +38,169 @@ enum HSV_BAR_TYPE
|
||||
BRIGHTNESS = 2
|
||||
};
|
||||
|
||||
void ColorBar::pressing(lv_event_t* e)
|
||||
{
|
||||
lv_obj_t* target = lv_event_get_target(e);
|
||||
lv_indev_t* click_source = (lv_indev_t*)lv_event_get_param(e);
|
||||
if (!click_source ||
|
||||
(lv_indev_get_type(click_source) != LV_INDEV_TYPE_POINTER))
|
||||
return;
|
||||
|
||||
HSVColorType::HSVColorType(FormGroup *window, uint32_t color) :
|
||||
ColorType(window->height() - BAR_HEIGHT_OFFSET)
|
||||
lv_area_t obj_coords;
|
||||
lv_obj_get_coords(target, &obj_coords);
|
||||
|
||||
lv_point_t point_act;
|
||||
lv_indev_get_point(click_source, &point_act);
|
||||
|
||||
lv_point_t rel_pos;
|
||||
rel_pos.x = point_act.x - obj_coords.x1;
|
||||
rel_pos.y = point_act.y - obj_coords.y1;
|
||||
|
||||
TRACE("PRESSING [%d,%d]", rel_pos.x, rel_pos.y);
|
||||
|
||||
ColorBar* bar = (ColorBar*)lv_obj_get_user_data(target);
|
||||
if (!bar) return;
|
||||
|
||||
bar->value = bar->screenToValue(rel_pos.y);
|
||||
lv_event_send(target->parent, LV_EVENT_VALUE_CHANGED, nullptr);
|
||||
}
|
||||
|
||||
void ColorBar::on_key(lv_event_t* e)
|
||||
{
|
||||
lv_obj_t* obj = lv_event_get_target(e);
|
||||
ColorBar* bar = (ColorBar*)lv_obj_get_user_data(obj);
|
||||
if (!bar) return;
|
||||
|
||||
uint32_t key = *(uint32_t*)lv_event_get_param(e);
|
||||
if (key == LV_KEY_LEFT) {
|
||||
if (bar->value > 0) {
|
||||
bar->value--;
|
||||
lv_event_send(obj->parent, LV_EVENT_VALUE_CHANGED, nullptr);
|
||||
}
|
||||
} else if (key == LV_KEY_RIGHT) {
|
||||
if (bar->value < bar->maxValue) {
|
||||
bar->value++;
|
||||
lv_event_send(obj->parent, LV_EVENT_VALUE_CHANGED, nullptr);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void ColorBar::draw_end(lv_event_t* e)
|
||||
{
|
||||
lv_obj_draw_part_dsc_t* dsc = lv_event_get_draw_part_dsc(e);
|
||||
if (dsc->type != LV_OBJ_DRAW_PART_RECTANGLE) return;
|
||||
|
||||
lv_obj_t* obj = lv_event_get_target(e);
|
||||
ColorBar* bar = (ColorBar*)lv_obj_get_user_data(obj);
|
||||
if (!bar) return;
|
||||
|
||||
lv_draw_line_dsc_t line_dsc;
|
||||
lv_draw_line_dsc_init(&line_dsc);
|
||||
|
||||
line_dsc.width = 1;
|
||||
line_dsc.opa = LV_OPA_100;
|
||||
|
||||
auto area = dsc->draw_area;
|
||||
lv_point_t p1, p2;
|
||||
p1.x = area->x1;
|
||||
p2.x = area->x2 + 1;
|
||||
|
||||
// draw background gradient
|
||||
for (auto y = area->y1; y <= area->y2; y++) {
|
||||
p1.y = y;
|
||||
p2.y = y;
|
||||
auto c = bar->getRGB(bar->screenToValue(y - area->y1));
|
||||
line_dsc.color = lv_color_make(GET_RED(c), GET_GREEN(c), GET_BLUE(c));
|
||||
lv_draw_line(dsc->draw_ctx, &line_dsc, &p1, &p2);
|
||||
}
|
||||
|
||||
// draw cursor
|
||||
lv_area_t cursor_area;
|
||||
cursor_area.x1 = area->x1 + (lv_area_get_width(area) / 2) - 5;
|
||||
cursor_area.x2 = cursor_area.x1 + 10 - 1;
|
||||
|
||||
auto pos = bar->valueToScreen(bar->value);
|
||||
cursor_area.y1 = area->y1 + pos - 5;
|
||||
cursor_area.y2 = cursor_area.y1 + 10 - 1;
|
||||
|
||||
lv_draw_rect_dsc_t cursor_dsc;
|
||||
lv_draw_rect_dsc_init(&cursor_dsc);
|
||||
|
||||
cursor_dsc.radius = LV_RADIUS_CIRCLE;
|
||||
cursor_dsc.bg_opa = LV_OPA_100;
|
||||
cursor_dsc.bg_color = makeLvColor(COLOR_THEME_PRIMARY2);
|
||||
cursor_dsc.border_opa = LV_OPA_100;
|
||||
cursor_dsc.border_color = makeLvColor(COLOR_THEME_PRIMARY1);
|
||||
cursor_dsc.border_width = 1;
|
||||
|
||||
lv_draw_rect(dsc->draw_ctx, &cursor_dsc, &cursor_area);
|
||||
}
|
||||
|
||||
ColorBar::ColorBar(Window* parent, const rect_t& r, uint32_t value,
|
||||
uint32_t maxValue, bool invert) :
|
||||
FormField(parent, r)
|
||||
{
|
||||
lv_group_add_obj((lv_group_t*)lv_group_get_default(), lvobj);
|
||||
lv_obj_add_event_cb(lvobj, ColorBar::pressing, LV_EVENT_PRESSING, nullptr);
|
||||
lv_obj_add_event_cb(lvobj, ColorBar::on_key, LV_EVENT_KEY, nullptr);
|
||||
lv_obj_add_event_cb(lvobj, ColorBar::draw_end, LV_EVENT_DRAW_PART_END, nullptr);
|
||||
|
||||
// normal
|
||||
lv_obj_set_style_border_width(lvobj, 1, 0);
|
||||
lv_obj_set_style_border_color(lvobj, makeLvColor(COLOR_THEME_PRIMARY1), 0);
|
||||
lv_obj_set_style_border_opa(lvobj, LV_OPA_100, 0);
|
||||
lv_obj_set_style_border_post(lvobj, true, 0);
|
||||
|
||||
// focused
|
||||
lv_obj_set_style_border_width(lvobj, 2, LV_STATE_FOCUSED);
|
||||
lv_obj_set_style_border_color(lvobj, makeLvColor(COLOR_THEME_FOCUS), LV_STATE_FOCUSED);
|
||||
}
|
||||
|
||||
int ColorBar::valueToScreen(int val)
|
||||
{
|
||||
int scaledValue = (((float)val / maxValue) * height());
|
||||
if (invert) scaledValue = height() - scaledValue;
|
||||
return scaledValue;
|
||||
}
|
||||
|
||||
uint32_t ColorBar::screenToValue(int pos)
|
||||
{
|
||||
// range check
|
||||
pos = min<int>(pos, height());
|
||||
pos = max<int>(pos, 0);
|
||||
|
||||
uint32_t scaledValue = (((float)pos / height()) * maxValue);
|
||||
if (invert) scaledValue = maxValue - scaledValue;
|
||||
return scaledValue;
|
||||
}
|
||||
|
||||
ColorType::ColorType(Window* parent, coord_t screenHeight) :
|
||||
screenHeight(screenHeight)
|
||||
{
|
||||
auto spacePerBar = (parent->width() / MAX_BARS);
|
||||
|
||||
int leftPos = 0;
|
||||
for ( int i=0; i < MAX_BARS; i++){
|
||||
rect_t r;
|
||||
r.x = leftPos + BAR_MARGIN;
|
||||
r.y = BAR_TOP_MARGIN;
|
||||
r.w = spacePerBar - BAR_MARGIN - 5;
|
||||
r.h = screenHeight;
|
||||
|
||||
bars[i] = new ColorBar(parent, r);
|
||||
leftPos += spacePerBar;
|
||||
}
|
||||
}
|
||||
|
||||
ColorType::~ColorType()
|
||||
{
|
||||
for ( int i=0; i < MAX_BARS; i++) {
|
||||
bars[i]->deleteLater();
|
||||
}
|
||||
};
|
||||
|
||||
HSVColorType::HSVColorType(Window* parent, uint32_t color) :
|
||||
ColorType(parent, parent->height() - BAR_HEIGHT_OFFSET)
|
||||
{
|
||||
auto r = GET_RED(color), g = GET_GREEN(color), b = GET_BLUE(color);
|
||||
float values[MAX_BARS];
|
||||
@@ -47,126 +208,86 @@ HSVColorType::HSVColorType(FormGroup *window, uint32_t color) :
|
||||
values[1] *= MAX_SATURATION; // convert the proper base
|
||||
values[2] *= MAX_BRIGHTNESS;
|
||||
|
||||
auto spacePerBar = (window->width() / MAX_BARS);
|
||||
|
||||
int leftPos = 0;
|
||||
|
||||
for (auto i = 0; i < MAX_BARS; i++) {
|
||||
barInfo[i].leftPos = leftPos + BAR_MARGIN;
|
||||
barInfo[i].barWidth = spacePerBar - BAR_MARGIN - 5;
|
||||
barInfo[i].maxValue = i == 0 ? MAX_HUE : MAX_BRIGHTNESS;
|
||||
barInfo[i].invert = i != 0;
|
||||
barInfo[i].sliding = false;
|
||||
barInfo[i].value = values[i];
|
||||
|
||||
leftPos += spacePerBar;
|
||||
bars[i]->maxValue = i == 0 ? MAX_HUE : MAX_BRIGHTNESS;
|
||||
bars[i]->invert = i != 0;
|
||||
bars[i]->value = values[i];
|
||||
}
|
||||
|
||||
// hue
|
||||
bars[0]->getRGB = [=] (int pos) {
|
||||
auto rgb = HSVtoRGB(pos, bars[1]->value, bars[2]->value);
|
||||
return rgb;
|
||||
};
|
||||
|
||||
// saturation
|
||||
bars[1]->getRGB = [=] (int pos) {
|
||||
auto rgb = HSVtoRGB(bars[0]->value, pos, bars[2]->value);
|
||||
return rgb;
|
||||
};
|
||||
|
||||
// brightness
|
||||
bars[2]->getRGB = [=] (int pos) {
|
||||
auto rgb = HSVtoRGB(bars[0]->value, bars[1]->value, pos);
|
||||
return rgb;
|
||||
};
|
||||
}
|
||||
|
||||
uint32_t HSVColorType::getRGB()
|
||||
{
|
||||
return HSVtoRGB(barInfo[0].value, barInfo[1].value, barInfo[2].value);
|
||||
return HSVtoRGB(bars[0]->value, bars[1]->value, bars[2]->value);
|
||||
}
|
||||
|
||||
void HSVColorType::drawBarValue(BitmapBuffer *dc, int bar)
|
||||
const char** HSVColorType::getLabelChars()
|
||||
{
|
||||
dc->drawText(barInfo[bar].leftPos, BAR_TOP_MARGIN + screenHeight + 9, HSVChars[bar], COLOR_THEME_PRIMARY1 | FONT(XXS));
|
||||
dc->drawText(barInfo[bar].leftPos + 10, BAR_TOP_MARGIN + screenHeight + 3, std::to_string(barInfo[bar].value).c_str(), COLOR_THEME_PRIMARY1);
|
||||
return HSVChars;
|
||||
}
|
||||
|
||||
void HSVColorType::drawBar(BitmapBuffer* dc, int bar, getRGBFromPos getRGB)
|
||||
RGBColorType::RGBColorType(Window* parent, uint32_t color) :
|
||||
ColorType(parent, parent->height() - BAR_HEIGHT_OFFSET)
|
||||
{
|
||||
int maxRange = screenHeight;
|
||||
for (auto i = 0; i < maxRange; i++) {
|
||||
auto rgb = getRGB(bar, i);
|
||||
auto r = GET_RED(rgb);
|
||||
auto g = GET_GREEN(rgb);
|
||||
auto b = GET_BLUE(rgb);
|
||||
|
||||
dc->drawSolidHorizontalLine(barInfo[bar].leftPos, i + BAR_TOP_MARGIN, barInfo[bar].barWidth, COLOR2FLAGS(RGB(r, g, b)));
|
||||
}
|
||||
|
||||
dc->drawSolidRect(barInfo[bar].leftPos, BAR_TOP_MARGIN, barInfo[bar].barWidth, screenHeight, 1, COLOR2FLAGS(BLACK));
|
||||
dc->drawFilledCircle(barInfo[bar].leftPos + (barInfo[bar].barWidth / 2), BAR_TOP_MARGIN + valueToScreen(bar, barInfo[bar].value), 5, COLOR2FLAGS(WHITE));\
|
||||
|
||||
drawBarValue(dc, bar);
|
||||
}
|
||||
|
||||
void HSVColorType::paint(BitmapBuffer *dc)
|
||||
{
|
||||
drawBar(dc, HUE, [=] (int bar, int pos) {
|
||||
int hue = screenToValue(0, pos);
|
||||
auto rgb = HSVtoRGB(hue, barInfo[1].value, barInfo[2].value);
|
||||
return rgb;
|
||||
});
|
||||
drawBar(dc, SATURATION, [=] (int bar, int pos) {
|
||||
int saturation = screenToValue(1, pos);
|
||||
auto rgb = HSVtoRGB(barInfo[0].value, saturation, barInfo[2].value);
|
||||
return rgb;
|
||||
});
|
||||
drawBar(dc, BRIGHTNESS, [=] (int bar, int pos) {
|
||||
int brightness = screenToValue(2, pos);
|
||||
auto rgb = HSVtoRGB(barInfo[0].value, barInfo[1].value, brightness);
|
||||
return rgb;
|
||||
});
|
||||
}
|
||||
|
||||
RGBColorType::RGBColorType(FormGroup *window, uint32_t color) :
|
||||
ColorType(window->height() - BAR_HEIGHT_OFFSET)
|
||||
{
|
||||
screenHeight = screenHeight;
|
||||
auto r = GET_RED(color), g = GET_GREEN(color), b = GET_BLUE(color);
|
||||
float values[MAX_BARS];
|
||||
values[0] = r; values[1] = g; values[2] = b;
|
||||
values[0] = r;
|
||||
values[1] = g;
|
||||
values[2] = b;
|
||||
|
||||
auto spacePerBar = (window->width() / MAX_BARS);
|
||||
int leftPos = 0;
|
||||
for (auto i = 0; i < MAX_BARS; i++) {
|
||||
barInfo[i].leftPos = leftPos + BAR_MARGIN;
|
||||
barInfo[i].barWidth = spacePerBar - BAR_MARGIN - 5;
|
||||
barInfo[i].maxValue = 255;
|
||||
barInfo[i].sliding = false;
|
||||
barInfo[i].value = values[i];
|
||||
barInfo[i].invert = true;
|
||||
leftPos += spacePerBar;
|
||||
bars[i]->maxValue = 255;
|
||||
bars[i]->value = values[i];
|
||||
bars[i]->invert = true;
|
||||
}
|
||||
|
||||
bars[0]->getRGB = [=](int pos) { return RGB(pos, 0, 0); };
|
||||
bars[1]->getRGB = [=](int pos) { return RGB(0, pos, 0); };
|
||||
bars[2]->getRGB = [=](int pos) { return RGB(0, 0, pos); };
|
||||
}
|
||||
|
||||
uint32_t RGBColorType::getRGB()
|
||||
{
|
||||
return RGB(barInfo[0].value, barInfo[1].value, barInfo[2].value);
|
||||
return RGB(bars[0]->value, bars[1]->value, bars[2]->value);
|
||||
}
|
||||
|
||||
void RGBColorType::drawBarValue(BitmapBuffer *dc, int bar)
|
||||
const char** RGBColorType::getLabelChars()
|
||||
{
|
||||
dc->drawText(barInfo[bar].leftPos, BAR_TOP_MARGIN + screenHeight + 9, RGBChars[bar], COLOR_THEME_PRIMARY1 | FONT(XXS));
|
||||
dc->drawText(barInfo[bar].leftPos + 10, BAR_TOP_MARGIN + screenHeight + 3, std::to_string(barInfo[bar].value).c_str(), COLOR_THEME_PRIMARY1);
|
||||
return RGBChars;
|
||||
}
|
||||
|
||||
void RGBColorType::paint(BitmapBuffer *dc)
|
||||
static lv_obj_t* create_bar_label(lv_obj_t* parent, lv_coord_t x, lv_coord_t y)
|
||||
{
|
||||
for (int bar = 0; bar < MAX_BARS; bar++) {
|
||||
for (uint32_t pos = 0; pos < screenHeight; pos++) {
|
||||
uint32_t value = screenToValue(bar, pos);
|
||||
uint32_t color;
|
||||
if (bar == 0)
|
||||
color = RGB(value, 0, 0);
|
||||
else if (bar == 1)
|
||||
color = RGB(0, value, 0);
|
||||
else
|
||||
color = RGB(0, 0, value);
|
||||
lv_obj_t* obj = lv_label_create(parent);
|
||||
lv_obj_set_pos(obj, x, y);
|
||||
lv_obj_set_style_text_color(obj, makeLvColor(COLOR_THEME_PRIMARY1), 0);
|
||||
lv_obj_set_style_text_font(obj, getFont(FONT(XXS)), 0);
|
||||
return obj;
|
||||
}
|
||||
|
||||
dc->drawSolidHorizontalLine(barInfo[bar].leftPos, pos + BAR_TOP_MARGIN, barInfo[bar].barWidth,
|
||||
COLOR2FLAGS(color));
|
||||
dc->drawSolidRect(barInfo[bar].leftPos, BAR_TOP_MARGIN, barInfo[bar].barWidth, screenHeight, 1,
|
||||
COLOR2FLAGS(BLACK));
|
||||
}
|
||||
|
||||
dc->drawFilledCircle(barInfo[bar].leftPos + (barInfo[bar].barWidth / 2), BAR_TOP_MARGIN + valueToScreen(bar, barInfo[bar].value), 5,
|
||||
COLOR2FLAGS(WHITE));
|
||||
|
||||
drawBarValue(dc, bar);
|
||||
}
|
||||
static lv_obj_t* create_bar_value_label(lv_obj_t* parent, lv_coord_t x, lv_coord_t y)
|
||||
{
|
||||
lv_obj_t* obj = lv_label_create(parent);
|
||||
lv_obj_set_pos(obj, x, y);
|
||||
lv_obj_set_style_text_color(obj, makeLvColor(COLOR_THEME_PRIMARY1), 0);
|
||||
return obj;
|
||||
}
|
||||
|
||||
/////////////////////////////////////////////////////////////////////////
|
||||
@@ -179,16 +300,21 @@ ColorEditor::ColorEditor(FormGroup *window, const rect_t rect, uint32_t color,
|
||||
_color(color)
|
||||
{
|
||||
_colorType = new HSVColorType(this, color);
|
||||
setFocusHandler([=](bool focus) {
|
||||
_focused = focus;
|
||||
});
|
||||
}
|
||||
|
||||
void ColorEditor::setNextFocusBar()
|
||||
{
|
||||
_focusBar = (_focusBar + 1) % MAX_BARS;
|
||||
// setFocus();
|
||||
invalidate();
|
||||
// bar labels
|
||||
for (int i = 0; i < MAX_BARS; i++) {
|
||||
auto bar = _colorType->bars[i];
|
||||
auto x = bar->left();
|
||||
auto y = bar->bottom();
|
||||
|
||||
barLabels[i] = create_bar_label(lvobj, x, y + 9);
|
||||
lv_label_set_text_static(barLabels[i], _colorType->getLabelChars()[i]);
|
||||
|
||||
barValLabels[i] = create_bar_value_label(lvobj, x + 10, y + 3);
|
||||
lv_label_set_text_fmt(barValLabels[i], "%d", bar->value);
|
||||
}
|
||||
|
||||
lv_obj_add_event_cb(lvobj, ColorEditor::value_changed, LV_EVENT_VALUE_CHANGED, nullptr);
|
||||
}
|
||||
|
||||
void ColorEditor::setColorEditorType(COLOR_EDITOR_TYPE colorType)
|
||||
@@ -206,113 +332,21 @@ void ColorEditor::setColorEditorType(COLOR_EDITOR_TYPE colorType)
|
||||
void ColorEditor::setRGB()
|
||||
{
|
||||
_color = _colorType->getRGB();
|
||||
invalidate();
|
||||
if (_setValue != nullptr)
|
||||
_setValue(_color);
|
||||
|
||||
// update bars & labels
|
||||
for (int i = 0; i < MAX_BARS; i++) {
|
||||
auto bar = _colorType->bars[i];
|
||||
lv_label_set_text_fmt(barValLabels[i], "%d", bar->value);
|
||||
bar->invalidate();
|
||||
}
|
||||
|
||||
if (_setValue != nullptr) _setValue(_color);
|
||||
}
|
||||
|
||||
#if defined(HARDWARE_TOUCH)
|
||||
bool ColorEditor::onTouchSlide(coord_t x, coord_t y, coord_t startX, coord_t startY, coord_t slideX, coord_t slideY)
|
||||
void ColorEditor::value_changed(lv_event_t* e)
|
||||
{
|
||||
if (touchState.event == TE_SLIDE_END) {
|
||||
onTouchEnd(0,0);
|
||||
return true;
|
||||
}
|
||||
|
||||
for (auto i = 0; i < MAX_BARS; i++) {
|
||||
if (_colorType->barInfo[i].sliding) {
|
||||
y -= BAR_TOP_MARGIN;
|
||||
auto value = _colorType->screenToValue(i, y);
|
||||
if (value != _colorType->barInfo[i].value) {
|
||||
_colorType->barInfo[i].value = value;
|
||||
setRGB();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool ColorEditor::onTouchEnd(coord_t x, coord_t y)
|
||||
{
|
||||
bool bSliding = false;
|
||||
for (auto i = 0; i < MAX_BARS; i++) {
|
||||
if (_colorType->barInfo[i].sliding) {
|
||||
bSliding = true;
|
||||
}
|
||||
_colorType->barInfo[i].sliding = false;
|
||||
}
|
||||
|
||||
if (bSliding) {
|
||||
invalidate();
|
||||
}
|
||||
|
||||
return FormGroup::onTouchEnd(x,y);
|
||||
}
|
||||
|
||||
bool ColorEditor::onTouchStart(coord_t x, coord_t y)
|
||||
{
|
||||
bool bFound = false;
|
||||
for (auto i = 0; i < MAX_BARS; i++) {
|
||||
if (y >= BAR_TOP_MARGIN && y < (coord_t)(BAR_TOP_MARGIN + _colorType->screenHeight) &&
|
||||
x >= _colorType->barInfo[i].leftPos && x < _colorType->barInfo[i].leftPos + _colorType->barInfo[i].barWidth) {
|
||||
_colorType->barInfo[i].sliding = true;
|
||||
y -= BAR_TOP_MARGIN;
|
||||
int value = _colorType->screenToValue(i, y);
|
||||
_colorType->barInfo[i].value = value;
|
||||
bFound = true;
|
||||
_focusBar = i;
|
||||
// setFocus();
|
||||
} else {
|
||||
_colorType->barInfo[i].sliding = false;
|
||||
}
|
||||
}
|
||||
if (bFound) {
|
||||
setRGB();
|
||||
return true;
|
||||
} else {
|
||||
return FormGroup::onTouchStart(x,y);
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
#if defined(HARDWARE_KEYS)
|
||||
void ColorEditor::onEvent(event_t event)
|
||||
{
|
||||
switch(event)
|
||||
{
|
||||
case EVT_ROTARY_RIGHT:
|
||||
case EVT_ROTARY_LEFT:
|
||||
{
|
||||
int direction = event == EVT_ROTARY_RIGHT ? 1 : -1;
|
||||
auto bar = &_colorType->barInfo[_focusBar];
|
||||
int newValue = (int) bar->value;
|
||||
newValue += direction;
|
||||
|
||||
newValue = min(newValue, (int)bar->maxValue);
|
||||
newValue = max(newValue, 0);
|
||||
bar->value = newValue;
|
||||
setRGB();
|
||||
onKeyPress();
|
||||
}
|
||||
break;
|
||||
default:
|
||||
FormGroup::onEvent(event);
|
||||
break;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
void ColorEditor::drawFocusBox(BitmapBuffer *dc)
|
||||
{
|
||||
auto bar = _colorType->barInfo[_focusBar];
|
||||
dc->drawSolidRect(bar.leftPos, BAR_TOP_MARGIN, bar.barWidth, _colorType->screenHeight, 2, COLOR_THEME_FOCUS);
|
||||
}
|
||||
|
||||
void ColorEditor::paint(BitmapBuffer *dc)
|
||||
{
|
||||
dc->clear(COLOR_THEME_SECONDARY3);
|
||||
_colorType->paint(dc);
|
||||
drawFocusBox(dc);
|
||||
lv_obj_t* target = lv_event_get_target(e);
|
||||
ColorEditor* edit = (ColorEditor*)lv_obj_get_user_data(target);
|
||||
if (edit) edit->setRGB();
|
||||
}
|
||||
|
||||
|
||||
@@ -28,120 +28,75 @@
|
||||
#include "listbox.h"
|
||||
|
||||
constexpr int MAX_BARS = 3;
|
||||
typedef std::function<uint32_t (int bar, int pos)> getRGBFromPos;
|
||||
typedef std::function<uint32_t (int pos)> getRGBFromPos;
|
||||
|
||||
class Bar
|
||||
{
|
||||
public:
|
||||
bool sliding = false;
|
||||
int leftPos = 0;
|
||||
int barWidth = 0;
|
||||
uint32_t maxValue = 0;
|
||||
uint32_t value = 0;
|
||||
bool invert = false;
|
||||
struct ColorBar : public FormField {
|
||||
uint32_t maxValue = 0;
|
||||
uint32_t value = 0;
|
||||
bool invert = false;
|
||||
getRGBFromPos getRGB = nullptr;
|
||||
|
||||
ColorBar(Window* parent, const rect_t& r, uint32_t value = 0,
|
||||
uint32_t maxValue = 0, bool invert = false);
|
||||
|
||||
int valueToScreen(int value);
|
||||
uint32_t screenToValue(int pos);
|
||||
|
||||
static void pressing(lv_event_t* e);
|
||||
static void on_key(lv_event_t* e);
|
||||
static void draw_end(lv_event_t* e);
|
||||
};
|
||||
|
||||
class ColorType
|
||||
struct ColorType
|
||||
{
|
||||
public:
|
||||
ColorType(coord_t screenHeight) :
|
||||
screenHeight(screenHeight)
|
||||
{
|
||||
}
|
||||
virtual ~ColorType()
|
||||
{
|
||||
};
|
||||
ColorBar* bars[MAX_BARS];
|
||||
uint32_t screenHeight;
|
||||
|
||||
virtual int valueToScreen(int bar, int value)
|
||||
{
|
||||
int scaledValue = (((float)value / barInfo[bar].maxValue) * screenHeight);
|
||||
if (barInfo[bar].invert)
|
||||
scaledValue = screenHeight - scaledValue;
|
||||
ColorType(Window* parent, coord_t screenHeight);
|
||||
virtual ~ColorType();
|
||||
|
||||
return scaledValue;
|
||||
}
|
||||
virtual uint32_t screenToValue(int bar, int pos)
|
||||
{
|
||||
// range check
|
||||
pos = min<int>(pos, screenHeight);
|
||||
pos = max<int>(pos, 0);
|
||||
|
||||
uint32_t scaledValue = (((float)pos / screenHeight) * barInfo[bar].maxValue);
|
||||
if (barInfo[bar].invert)
|
||||
scaledValue = barInfo[bar].maxValue - scaledValue;
|
||||
return scaledValue;
|
||||
}
|
||||
|
||||
Bar barInfo[MAX_BARS];
|
||||
virtual void paint(BitmapBuffer *dc) {}
|
||||
virtual uint32_t getRGB() {return 0;}
|
||||
uint32_t screenHeight;
|
||||
virtual uint32_t getRGB() = 0;
|
||||
virtual const char** getLabelChars() = 0;
|
||||
};
|
||||
|
||||
class HSVColorType : public ColorType
|
||||
{
|
||||
public:
|
||||
HSVColorType(FormGroup *window, uint32_t color);
|
||||
uint32_t getRGB() override;
|
||||
void paint(BitmapBuffer* dc) override;
|
||||
|
||||
protected:
|
||||
void drawBar(BitmapBuffer *dc, int bar, getRGBFromPos getRGB);
|
||||
void drawBarValue(BitmapBuffer *dc, int bar);
|
||||
struct HSVColorType : public ColorType {
|
||||
HSVColorType(Window* parent, uint32_t color);
|
||||
uint32_t getRGB() override;
|
||||
const char** getLabelChars() override;
|
||||
};
|
||||
|
||||
class RGBColorType : public ColorType
|
||||
{
|
||||
public:
|
||||
RGBColorType(FormGroup *window, uint32_t color);
|
||||
uint32_t getRGB() override;
|
||||
void paint(BitmapBuffer* dc) override;
|
||||
void drawBarValue(BitmapBuffer *dc, int bar);
|
||||
struct RGBColorType : public ColorType {
|
||||
RGBColorType(Window* parent, uint32_t color);
|
||||
uint32_t getRGB() override;
|
||||
const char** getLabelChars() override;
|
||||
};
|
||||
|
||||
enum COLOR_EDITOR_TYPE
|
||||
{
|
||||
RGB_COLOR_EDITOR,
|
||||
RGB_COLOR_EDITOR = 0,
|
||||
HSV_COLOR_EDITOR
|
||||
};
|
||||
|
||||
// the ColorEditor() control is a group of other controls
|
||||
class ColorEditor : public FormGroup
|
||||
{
|
||||
public:
|
||||
ColorEditor(FormGroup *window, const rect_t rect, uint32_t color, std::function<void (uint32_t rgb)> setValue = nullptr);
|
||||
public:
|
||||
ColorEditor(FormGroup* window, const rect_t rect, uint32_t color,
|
||||
std::function<void(uint32_t rgb)> setValue = nullptr);
|
||||
|
||||
#if defined(DEBUG_WINDOWS)
|
||||
std::string getName() const override
|
||||
{
|
||||
return "ColorEditor";
|
||||
}
|
||||
std::string getName() const override { return "ColorEditor"; }
|
||||
#endif
|
||||
|
||||
void setColorEditorType(COLOR_EDITOR_TYPE colorType);
|
||||
|
||||
#if defined(HARDWARE_TOUCH)
|
||||
bool onTouchSlide(coord_t x, coord_t y, coord_t startX, coord_t startY, coord_t slideX, coord_t slideY) override;
|
||||
bool onTouchEnd(coord_t x, coord_t y) override;
|
||||
bool onTouchStart(coord_t x, coord_t y) override;
|
||||
#endif
|
||||
protected:
|
||||
ColorType* _colorType = nullptr;
|
||||
lv_obj_t* barLabels[MAX_BARS];
|
||||
lv_obj_t* barValLabels[MAX_BARS];
|
||||
std::function<void(uint32_t)> _setValue;
|
||||
uint32_t _color;
|
||||
|
||||
void setNextFocusBar();
|
||||
|
||||
#if defined(HARDWARE_KEYS)
|
||||
void onEvent(event_t event) override;
|
||||
#endif
|
||||
|
||||
void paint(BitmapBuffer *dc) override;
|
||||
|
||||
protected:
|
||||
ColorType *_colorType = nullptr;
|
||||
void drawColorBox(BitmapBuffer *dc);
|
||||
void drawFocusBox(BitmapBuffer *dc);
|
||||
void setRGB();
|
||||
std::function<void (uint32_t rgb)> _setValue;
|
||||
uint32_t _color;
|
||||
int _focusBar = 0;
|
||||
bool _focused = false;
|
||||
void setRGB();
|
||||
static void value_changed(lv_event_t* e);
|
||||
};
|
||||
|
||||
|
||||
@@ -258,6 +258,7 @@ class PreviewWindow : public FormGroup
|
||||
void setColorList(std::vector<ColorEntry> colorList)
|
||||
{
|
||||
_colorList = colorList;
|
||||
invalidate();
|
||||
}
|
||||
|
||||
void checkEvents() override
|
||||
|
||||
@@ -155,8 +155,9 @@ class ColorSquare : public FormField
|
||||
void setHexStr(StaticText* hexBox, uint32_t rgb)
|
||||
{
|
||||
auto r = GET_RED(rgb), g = GET_GREEN(rgb), b = GET_BLUE(rgb);
|
||||
char hexstr[80];
|
||||
sprintf(hexstr, "%02X%02X%02X\n", (uint16_t)r, (uint16_t)g, (uint16_t)b);
|
||||
char hexstr[8];
|
||||
snprintf(hexstr, sizeof(hexstr), "%02X%02X%02X",
|
||||
(uint16_t)r, (uint16_t)g, (uint16_t)b);
|
||||
hexBox->setText(hexstr);
|
||||
}
|
||||
|
||||
@@ -170,8 +171,8 @@ public:
|
||||
_indexOfColor(indexOfColor),
|
||||
_theme(theme)
|
||||
{
|
||||
buildHead(&header);
|
||||
buildBody(&body);
|
||||
buildHead(&header);
|
||||
}
|
||||
|
||||
void setActiveColorBar(int activeTab)
|
||||
@@ -185,26 +186,6 @@ public:
|
||||
}
|
||||
}
|
||||
|
||||
#if defined(HARDWARE_KEYS)
|
||||
void onEvent(event_t event ) override
|
||||
{
|
||||
if (event == EVT_KEY_BREAK(KEY_TELEM)) {
|
||||
_colorEditor->setNextFocusBar();
|
||||
} else if (event == EVT_KEY_BREAK(KEY_PGUP) || event == EVT_KEY_BREAK(KEY_PGDN)) {
|
||||
int direction = event == EVT_KEY_BREAK(KEY_PGUP) ? -1 : 1;
|
||||
int newActiveTab = _activeTab + direction;
|
||||
if (newActiveTab < 0)
|
||||
newActiveTab = 1;
|
||||
if (newActiveTab >= (int) _tabs.size())
|
||||
newActiveTab = 0;
|
||||
|
||||
setActiveColorBar(newActiveTab);
|
||||
} else {
|
||||
Page::onEvent(event);
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
protected:
|
||||
std::function<void (uint32_t rgb)> _setValue;
|
||||
LcdColorIndex _indexOfColor;
|
||||
@@ -212,7 +193,7 @@ protected:
|
||||
TextButton *_cancelButton;
|
||||
ColorEditor *_colorEditor;
|
||||
PreviewWindow *_previewWindow;
|
||||
std::vector<PageButton *> _tabs;
|
||||
std::vector<Button *> _tabs;
|
||||
int _activeTab = 0;
|
||||
ColorSquare *_colorSquare;
|
||||
StaticText *_hexBox;
|
||||
@@ -285,18 +266,20 @@ protected:
|
||||
ThemePersistance::getColorNames()[(int)_indexOfColor], 0, COLOR_THEME_PRIMARY2 | flags);
|
||||
|
||||
// page tabs
|
||||
rect_t r = { LCD_W - (BUTTON_WIDTH + 5), 6, BUTTON_WIDTH, BUTTON_HEIGHT };
|
||||
rect_t r = { LCD_W - 2*(BUTTON_WIDTH + 5), 6, BUTTON_WIDTH, BUTTON_HEIGHT };
|
||||
_tabs.emplace_back(
|
||||
new PageButton(window, r, "RGB",
|
||||
new TextButton(window, r, "RGB",
|
||||
[=] () {
|
||||
setActiveColorBar(0);
|
||||
return 1;
|
||||
},
|
||||
0, COLOR_THEME_PRIMARY1));
|
||||
r.x -= (BUTTON_WIDTH + 5);
|
||||
r.x += (BUTTON_WIDTH + 5);
|
||||
_tabs.emplace_back(
|
||||
new PageButton(window, r, "HSV",
|
||||
new TextButton(window, r, "HSV",
|
||||
[=] () {
|
||||
setActiveColorBar(1);
|
||||
return 1;
|
||||
},
|
||||
0, COLOR_THEME_PRIMARY1));
|
||||
_tabs[1]->check(true);
|
||||
|
||||
@@ -26,51 +26,6 @@
|
||||
constexpr int BOX_MARGIN = 2;
|
||||
constexpr int MAX_BOX_WIDTH = 15;
|
||||
|
||||
class PageButton : public Window
|
||||
{
|
||||
public:
|
||||
PageButton(FormGroup *parent, const rect_t &rect, std::string text,
|
||||
std::function<void ()> setTab = nullptr,
|
||||
WindowFlags windowFlags = BUTTON_BACKGROUND | OPAQUE,
|
||||
LcdFlags textFlags = 0) :
|
||||
Window(parent, rect, windowFlags | NO_FOCUS, textFlags),
|
||||
_setTab(std::move(setTab)),
|
||||
_text(text)
|
||||
{
|
||||
}
|
||||
|
||||
#if defined(HARDWARE_TOUCH)
|
||||
bool onTouchEnd(coord_t x, coord_t y) override
|
||||
{
|
||||
if (_setTab != nullptr) {
|
||||
_setTab();
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
#endif
|
||||
|
||||
void paint(BitmapBuffer *dc) override
|
||||
{
|
||||
uint32_t textColor = _checked ? COLOR_THEME_PRIMARY2 : COLOR_THEME_PRIMARY1;
|
||||
dc->clear(_checked ? COLOR_THEME_ACTIVE : COLOR_THEME_SECONDARY2);
|
||||
|
||||
dc->drawText(rect.w / 2, 1 + (rect.h - getFontHeight(textFlags)) / 2,
|
||||
_text.c_str(), CENTERED | textColor);
|
||||
}
|
||||
|
||||
void check(bool checked)
|
||||
{
|
||||
_checked = checked;
|
||||
invalidate();
|
||||
}
|
||||
|
||||
private:
|
||||
std::function<void ()> _setTab;
|
||||
bool _checked = false;
|
||||
std::string _text;
|
||||
};
|
||||
|
||||
class ThemeColorPreview : public FormField
|
||||
{
|
||||
public:
|
||||
|
||||
Reference in New Issue
Block a user