228 lines
5.4 KiB
C++
228 lines
5.4 KiB
C++
#include <M5Unified.h>
|
|
#include <stdint.h>
|
|
|
|
struct rect_t
|
|
{
|
|
int x;
|
|
int y;
|
|
int w;
|
|
int h;
|
|
|
|
bool contain(int x, int y)
|
|
{
|
|
return this->x <= x && x < (this->x + this->w)
|
|
&& this->y <= y && y < (this->y + this->h);
|
|
}
|
|
bool contain(m5::Touch_Class::point_t &p) {
|
|
return contain(p.x, p.y);
|
|
}
|
|
};
|
|
|
|
class slider_t
|
|
{
|
|
public:
|
|
void setup(const rect_t &r, int min_value, int max_value, int value, uint16_t frame_color = 0xFFFF, uint16_t back_color = 0, uint16_t thumb_color = 0xFFE0) {
|
|
setupPosition(r);
|
|
setupValue(min_value, max_value, value);
|
|
setupColor(frame_color, back_color, thumb_color);
|
|
}
|
|
|
|
void setupPosition(const rect_t &r) {
|
|
_rect = r;
|
|
_vertical = r.h > r.w;
|
|
}
|
|
|
|
void setupValue(int min_value, int max_value, int value)
|
|
{
|
|
_min_value = min_value;
|
|
_max_value = max_value;
|
|
_current_value = value;
|
|
_control_value = value;
|
|
}
|
|
|
|
void setupColor(uint16_t frame_color, uint16_t back_color, uint16_t thumb_color)
|
|
{
|
|
_frame_color = frame_color;
|
|
_back_color = back_color;
|
|
_thumb_color = thumb_color;
|
|
}
|
|
|
|
void draw(LovyanGFX* gfx = &M5.Display)
|
|
{
|
|
gfx->startWrite();
|
|
draw_frame(gfx);
|
|
int pos = calc_pos(_current_value);
|
|
draw_thumb(pos, _thumb_color, gfx);
|
|
gfx->endWrite();
|
|
}
|
|
|
|
bool update(m5::touch_detail_t &td, LovyanGFX* gfx = &M5.Display)
|
|
{
|
|
_was_changed = false;
|
|
if (!_rect.contain(td.base)) return false;
|
|
|
|
if (td.wasReleased()) {
|
|
_current_value = _control_value;
|
|
}
|
|
|
|
if (td.isPressed()) {
|
|
int rw = _vertical ? _rect.h : _rect.w;
|
|
int tmp = (_current_value - _min_value) * rw / (_max_value - _min_value);
|
|
tmp += _vertical ? td.distanceY() : td.distanceX();
|
|
int v = _min_value + (_max_value - _min_value) * tmp / rw;
|
|
_was_changed = value_update(v, gfx);
|
|
return true;
|
|
}
|
|
return false;
|
|
}
|
|
|
|
int getValue(void) const { return _control_value; }
|
|
bool wasChanged(void) const { return _was_changed; }
|
|
|
|
protected:
|
|
rect_t _rect;
|
|
|
|
int _min_value;
|
|
int _max_value;
|
|
int _current_value;
|
|
int _control_value;
|
|
|
|
uint16_t _frame_color = 0xFFFF;
|
|
uint16_t _back_color = 0;
|
|
uint16_t _thumb_color = 0xFFE0;
|
|
bool _vertical = false;
|
|
bool _was_changed = false;
|
|
|
|
bool value_update(int new_value, LovyanGFX* gfx = &M5.Display)
|
|
{
|
|
int min_v = _min_value;
|
|
int max_v = _max_value;
|
|
if (min_v > max_v) {
|
|
min_v = _max_value;
|
|
max_v = _min_value;
|
|
}
|
|
new_value = new_value < min_v ? min_v : new_value > max_v ? max_v : new_value;
|
|
|
|
if (_control_value == new_value) {
|
|
return false;
|
|
}
|
|
int prev_pos = calc_pos(_control_value);
|
|
int new_pos = calc_pos(new_value);
|
|
_control_value = new_value;
|
|
|
|
if (prev_pos != new_pos) {
|
|
gfx->startWrite();
|
|
draw_thumb(prev_pos, _back_color, gfx);
|
|
draw_thumb(new_pos, _thumb_color, gfx);
|
|
gfx->endWrite();
|
|
}
|
|
return true;
|
|
}
|
|
|
|
int calc_pos(int value)
|
|
{
|
|
int diff = _max_value - _min_value;
|
|
if (diff == 0) return 0;
|
|
value -= _min_value;
|
|
int w = _vertical ? (_rect.h - _rect.w) : (_rect.w - _rect.h);
|
|
return (w * value) / diff;
|
|
}
|
|
|
|
void draw_frame(LovyanGFX* gfx = &M5.Display)
|
|
{
|
|
gfx->fillRoundRect(_rect.x+1, _rect.y+1, _rect.w-2, _rect.h-2, 2, _back_color);
|
|
gfx->drawRoundRect(_rect.x, _rect.y, _rect.w, _rect.h, 3, _frame_color);
|
|
}
|
|
|
|
void draw_thumb(int pos, uint16_t color, LovyanGFX* gfx = &M5.Display)
|
|
{
|
|
int rx = _rect.x + 1;
|
|
int ry = _rect.y + 1;
|
|
int rw;
|
|
if (_vertical) {
|
|
ry += pos;
|
|
rw = _rect.w;
|
|
} else {
|
|
rx += pos;
|
|
rw = _rect.h;
|
|
}
|
|
rw -= 2;
|
|
gfx->fillRoundRect(rx, ry, rw, rw, 3, color);
|
|
}
|
|
|
|
};
|
|
|
|
static constexpr std::size_t slider_count = 4;
|
|
static slider_t slider_list[slider_count];
|
|
|
|
void setup(void)
|
|
{
|
|
M5.begin();
|
|
|
|
int dw = M5.Display.width();
|
|
int dh = M5.Display.height();
|
|
|
|
slider_list[0].setup({ 20, dh/2 -20, dw-40, 40 }, 5, 25, 15, TFT_WHITE, TFT_BLACK, TFT_LIGHTGRAY);
|
|
slider_list[1].setup({ dw*1/4-20, 0, 40, dh/2 -40 }, 255, 0, 127, TFT_WHITE, TFT_BLACK, TFT_RED);
|
|
slider_list[2].setup({ dw*2/4-20, 0, 40, dh/2 -40 }, 255, 0, 127, TFT_WHITE, TFT_BLACK, TFT_GREEN);
|
|
slider_list[3].setup({ dw*3/4-20, 0, 40, dh/2 -40 }, 255, 0, 127, TFT_WHITE, TFT_BLACK, TFT_BLUE);
|
|
|
|
M5.Display.setEpdMode(epd_mode_t::epd_fastest);
|
|
M5.Display.setTextSize(2);
|
|
for (std::size_t i = 0; i < slider_count; ++i)
|
|
{
|
|
slider_list[i].draw();
|
|
}
|
|
}
|
|
|
|
void loop(void)
|
|
{
|
|
M5.delay(16);
|
|
|
|
M5.update();
|
|
|
|
if (0 == M5.Touch.getCount())
|
|
{
|
|
return;
|
|
}
|
|
|
|
bool changed = false;
|
|
auto t = M5.Touch.getDetail();
|
|
for (std::size_t i = 0; i < slider_count; ++i)
|
|
{
|
|
if (slider_list[i].update(t)) {
|
|
changed = true;
|
|
}
|
|
}
|
|
|
|
if (changed) {
|
|
int w = slider_list[0].getValue();
|
|
int r = slider_list[1].getValue();
|
|
int g = slider_list[2].getValue();
|
|
int b = slider_list[3].getValue();
|
|
uint32_t rgb = r << 16 | g << 8 | b;
|
|
if (slider_list[0].wasChanged())
|
|
{
|
|
M5.Display.fillRect(M5.Display.width()/2-25, M5.Display.height()*3/4-25, 51,51, TFT_BLACK);
|
|
}
|
|
M5.Display.fillCircle(M5.Display.width()/2, M5.Display.height()*3/4, w, rgb);
|
|
}
|
|
}
|
|
|
|
#if !defined ( ARDUINO ) && defined ( ESP_PLATFORM )
|
|
extern "C" {
|
|
void loopTask(void*)
|
|
{
|
|
setup();
|
|
for (;;) {
|
|
loop();
|
|
}
|
|
vTaskDelete(NULL);
|
|
}
|
|
|
|
void app_main()
|
|
{
|
|
xTaskCreatePinnedToCore(loopTask, "loopTask", 8192, NULL, 1, NULL, 1);
|
|
}
|
|
}
|
|
#endif
|