window: scrolling now only with LVGL
This commit is contained in:
committed by
Raphael Coeffic
parent
4ef479bf3f
commit
bd7e893a0b
@@ -42,13 +42,10 @@ void CarouselWindow::update()
|
|||||||
window->attach(this);
|
window->attach(this);
|
||||||
window->setLeft(lastPosition);
|
window->setLeft(lastPosition);
|
||||||
window->setTop((height() - window->height()) / 2);
|
window->setTop((height() - window->height()) / 2);
|
||||||
if (index == first)
|
|
||||||
setScrollPositionX(lastPosition);
|
|
||||||
lastPosition += window->width() + spacing;
|
lastPosition += window->width() + spacing;
|
||||||
index += 1;
|
index += 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
setInnerWidth(lastPosition);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
#if defined(HARDWARE_KEYS)
|
#if defined(HARDWARE_KEYS)
|
||||||
|
|||||||
+11
-36
@@ -66,7 +66,7 @@ FormField::FormField(Window* parent, const rect_t& rect,
|
|||||||
if (!(windowFlags & NO_FOCUS)) {
|
if (!(windowFlags & NO_FOCUS)) {
|
||||||
auto cont = dynamic_cast<FieldContainer*>(parent);
|
auto cont = dynamic_cast<FieldContainer*>(parent);
|
||||||
if (cont) {
|
if (cont) {
|
||||||
cont->addField(this, windowFlags & PUSH_FRONT);
|
cont->addField(this);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -163,18 +163,18 @@ void FormGroup::Line::construct()
|
|||||||
lv_obj_set_width(lvobj, lv_pct(100));
|
lv_obj_set_width(lvobj, lv_pct(100));
|
||||||
}
|
}
|
||||||
|
|
||||||
void FormGroup::Line::addChild(Window* window, bool front)
|
void FormGroup::Line::addChild(Window* window)
|
||||||
{
|
{
|
||||||
Window::addChild(window, front);
|
Window::addChild(window);
|
||||||
if (layout) {
|
if (layout) {
|
||||||
layout->add(window->getLvObj());
|
layout->add(window->getLvObj());
|
||||||
layout->nextCell();
|
layout->nextCell();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void FormGroup::Line::addField(FormField *field, bool front)
|
void FormGroup::Line::addField(FormField *field)
|
||||||
{
|
{
|
||||||
group->addField(field, front);
|
group->addField(field);
|
||||||
}
|
}
|
||||||
|
|
||||||
void FormGroup::Line::removeField(FormField *field)
|
void FormGroup::Line::removeField(FormField *field)
|
||||||
@@ -250,25 +250,16 @@ void FormGroup::removeField(FormField * field)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void FormGroup::addField(FormField * field, bool front)
|
void FormGroup::addField(FormField * field)
|
||||||
{
|
{
|
||||||
if (field->getWindowFlags() & FORM_DETACHED)
|
if (field->getWindowFlags() & FORM_DETACHED)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
if (front) {
|
if (last)
|
||||||
if (first)
|
link(last, field);
|
||||||
link(field, first);
|
last = field;
|
||||||
|
if (!first)
|
||||||
first = field;
|
first = field;
|
||||||
if (!last)
|
|
||||||
last = field;
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
if (last)
|
|
||||||
link(last, field);
|
|
||||||
last = field;
|
|
||||||
if (!first)
|
|
||||||
first = field;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (WRAP_FORM_FIELDS_WITHIN_PAGE) {
|
if (WRAP_FORM_FIELDS_WITHIN_PAGE) {
|
||||||
if (previous && (windowFlags & FORM_FORWARD_FOCUS)) {
|
if (previous && (windowFlags & FORM_FORWARD_FOCUS)) {
|
||||||
@@ -366,22 +357,6 @@ void FormGroup::onEvent(event_t event)
|
|||||||
{
|
{
|
||||||
TRACE_WINDOWS("%s received event 0x%X", getWindowDebugString("FormGroup").c_str(), event);
|
TRACE_WINDOWS("%s received event 0x%X", getWindowDebugString("FormGroup").c_str(), event);
|
||||||
|
|
||||||
if (event == EVT_KEY_BREAK(KEY_ENTER)) {
|
FormField::onEvent(event);
|
||||||
onKeyPress();
|
|
||||||
setFocusOnFirstVisibleField(SET_FOCUS_FIRST);
|
|
||||||
} else if (event == EVT_KEY_FIRST(KEY_EXIT) && !hasFocus() &&
|
|
||||||
!(windowFlags & FORM_FORWARD_FOCUS)) {
|
|
||||||
killEvents(event);
|
|
||||||
onKeyPress();
|
|
||||||
setFocus(SET_FOCUS_DEFAULT); // opentx - model - timers settings
|
|
||||||
} else if (event == EVT_ROTARY_RIGHT && !next) {
|
|
||||||
onKeyPress();
|
|
||||||
setFocusOnFirstVisibleField(SET_FOCUS_FIRST);
|
|
||||||
} else if (event == EVT_ROTARY_LEFT && !previous) {
|
|
||||||
onKeyPress();
|
|
||||||
setFocusOnLastVisibleField(SET_FOCUS_BACKWARD);
|
|
||||||
} else {
|
|
||||||
FormField::onEvent(event);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|||||||
+4
-25
@@ -118,7 +118,7 @@ class FormField : public Window
|
|||||||
class FieldContainer
|
class FieldContainer
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
virtual void addField(FormField *field, bool front = false) = 0;
|
virtual void addField(FormField *field) = 0;
|
||||||
virtual void removeField(FormField *field) = 0;
|
virtual void removeField(FormField *field) = 0;
|
||||||
};
|
};
|
||||||
|
|
||||||
@@ -137,8 +137,8 @@ class FormGroup : public FormField, public FieldContainer
|
|||||||
Line(Window *parent, lv_obj_t *obj, FlexGridLayout* layout, FormGroup* group);
|
Line(Window *parent, lv_obj_t *obj, FlexGridLayout* layout, FormGroup* group);
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
void addChild(Window* window, bool front = false) override;
|
void addChild(Window* window) override;
|
||||||
void addField(FormField *field, bool front = false) override;
|
void addField(FormField *field) override;
|
||||||
void removeField(FormField *field) override;
|
void removeField(FormField *field) override;
|
||||||
};
|
};
|
||||||
|
|
||||||
@@ -157,7 +157,7 @@ class FormGroup : public FormField, public FieldContainer
|
|||||||
void setFocus(uint8_t flag = SET_FOCUS_DEFAULT,
|
void setFocus(uint8_t flag = SET_FOCUS_DEFAULT,
|
||||||
Window *from = nullptr) override;
|
Window *from = nullptr) override;
|
||||||
|
|
||||||
void addField(FormField *field, bool front = false) override;
|
void addField(FormField *field) override;
|
||||||
void removeField(FormField *field) override;
|
void removeField(FormField *field) override;
|
||||||
|
|
||||||
void setFirstField(FormField *field) { first = field; }
|
void setFirstField(FormField *field) { first = field; }
|
||||||
@@ -165,27 +165,6 @@ class FormGroup : public FormField, public FieldContainer
|
|||||||
FormField *getFirstField() const { return first; }
|
FormField *getFirstField() const { return first; }
|
||||||
FormField *getLastField() const { return last; }
|
FormField *getLastField() const { return last; }
|
||||||
|
|
||||||
void setFocusOnFirstVisibleField(uint8_t flag = SET_FOCUS_DEFAULT) const
|
|
||||||
{
|
|
||||||
auto field = getFirstField();
|
|
||||||
while (field && !field->isInsideParentScrollingArea()) {
|
|
||||||
field = field->getNextField();
|
|
||||||
}
|
|
||||||
if (field) {
|
|
||||||
field->setFocus(flag);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void setFocusOnLastVisibleField(uint8_t flag = SET_FOCUS_DEFAULT) const
|
|
||||||
{
|
|
||||||
auto field = getLastField();
|
|
||||||
while (field && !field->isInsideParentScrollingArea()) {
|
|
||||||
field = field->getPreviousField();
|
|
||||||
}
|
|
||||||
if (field) {
|
|
||||||
field->setFocus(flag);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
FormField *first = nullptr;
|
FormField *first = nullptr;
|
||||||
|
|||||||
-1
@@ -267,7 +267,6 @@ void Menu::updatePosition()
|
|||||||
content->body.setHeight(bodyHeight);
|
content->body.setHeight(bodyHeight);
|
||||||
}
|
}
|
||||||
|
|
||||||
content->body.setInnerHeight(height);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void Menu::setTitle(std::string text)
|
void Menu::setTitle(std::string text)
|
||||||
|
|||||||
@@ -158,7 +158,6 @@ class MenuToolbar: public FormGroup {
|
|||||||
|
|
||||||
y += MENUS_TOOLBAR_BUTTON_WIDTH;
|
y += MENUS_TOOLBAR_BUTTON_WIDTH;
|
||||||
|
|
||||||
setInnerHeight(y);
|
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|||||||
-1
@@ -171,7 +171,6 @@ class Table: public FormField
|
|||||||
void addLine(Line * line)
|
void addLine(Line * line)
|
||||||
{
|
{
|
||||||
lines.push_back(line);
|
lines.push_back(line);
|
||||||
setInnerHeight((int)lines.size() * TABLE_LINE_HEIGHT - 2);
|
|
||||||
if (hasFocus() && selection < 0) {
|
if (hasFocus() && selection < 0) {
|
||||||
select(0, true);
|
select(0, true);
|
||||||
}
|
}
|
||||||
|
|||||||
+89
-127
@@ -22,8 +22,6 @@
|
|||||||
#include "mainwindow.h"
|
#include "mainwindow.h"
|
||||||
|
|
||||||
Window * Window::focusWindow = nullptr;
|
Window * Window::focusWindow = nullptr;
|
||||||
Window * Window::slidingWindow = nullptr;
|
|
||||||
Window * Window::capturedWindow = nullptr;
|
|
||||||
std::list<Window *> Window::trash;
|
std::list<Window *> Window::trash;
|
||||||
|
|
||||||
extern lv_obj_t *virtual_kb;
|
extern lv_obj_t *virtual_kb;
|
||||||
@@ -107,8 +105,6 @@ static void window_event_cb(lv_event_t * e)
|
|||||||
rel_pos.x = point_act.x - obj_coords.x1;
|
rel_pos.x = point_act.x - obj_coords.x1;
|
||||||
rel_pos.y = point_act.y - obj_coords.y1;
|
rel_pos.y = point_act.y - obj_coords.y1;
|
||||||
|
|
||||||
rel_pos.x += window->getScrollPositionX();
|
|
||||||
rel_pos.y += window->getScrollPositionY();
|
|
||||||
|
|
||||||
if (code == LV_EVENT_PRESSED) {
|
if (code == LV_EVENT_PRESSED) {
|
||||||
TRACE("PRESSED[%d|%d]", rel_pos.x, rel_pos.y);
|
TRACE("PRESSED[%d|%d]", rel_pos.x, rel_pos.y);
|
||||||
@@ -127,14 +123,14 @@ static void window_event_cb(lv_event_t * e)
|
|||||||
#endif
|
#endif
|
||||||
else if (code == LV_EVENT_SCROLL) {
|
else if (code == LV_EVENT_SCROLL) {
|
||||||
|
|
||||||
|
#if defined(DEBUG_WINDOWS)
|
||||||
lv_coord_t scroll_y = lv_obj_get_scroll_y(target);
|
lv_coord_t scroll_y = lv_obj_get_scroll_y(target);
|
||||||
lv_coord_t scroll_x = lv_obj_get_scroll_x(target);
|
lv_coord_t scroll_x = lv_obj_get_scroll_x(target);
|
||||||
|
|
||||||
TRACE_WINDOWS("SCROLL[x=%d;y=%d] %s", scroll_x, scroll_y,
|
TRACE_WINDOWS("SCROLL[x=%d;y=%d] %s", scroll_x, scroll_y,
|
||||||
window->getWindowDebugString().c_str());
|
window->getWindowDebugString().c_str());
|
||||||
|
#endif
|
||||||
|
|
||||||
window->setScrollPositionY(scroll_y);
|
|
||||||
window->setScrollPositionX(scroll_x);
|
|
||||||
|
|
||||||
} else if (code == LV_EVENT_FOCUSED) {
|
} else if (code == LV_EVENT_FOCUSED) {
|
||||||
if (inhibit_focus) return;
|
if (inhibit_focus) return;
|
||||||
@@ -147,10 +143,8 @@ static void window_event_cb(lv_event_t * e)
|
|||||||
|
|
||||||
Window::Window(Window *parent, const rect_t &rect, WindowFlags windowFlags,
|
Window::Window(Window *parent, const rect_t &rect, WindowFlags windowFlags,
|
||||||
LcdFlags textFlags, LvglCreate objConstruct) :
|
LcdFlags textFlags, LvglCreate objConstruct) :
|
||||||
parent(parent),
|
|
||||||
rect(rect),
|
rect(rect),
|
||||||
innerWidth(rect.w),
|
parent(parent),
|
||||||
innerHeight(rect.h),
|
|
||||||
windowFlags(windowFlags),
|
windowFlags(windowFlags),
|
||||||
textFlags(textFlags)
|
textFlags(textFlags)
|
||||||
{
|
{
|
||||||
@@ -174,7 +168,7 @@ Window::Window(Window *parent, const rect_t &rect, WindowFlags windowFlags,
|
|||||||
lv_obj_add_event_cb(lvobj, window_event_cb, LV_EVENT_ALL, this);
|
lv_obj_add_event_cb(lvobj, window_event_cb, LV_EVENT_ALL, this);
|
||||||
|
|
||||||
if (parent) {
|
if (parent) {
|
||||||
parent->addChild(this, windowFlags & PUSH_FRONT);
|
parent->addChild(this);
|
||||||
if (!(windowFlags & TRANSPARENT)) {
|
if (!(windowFlags & TRANSPARENT)) {
|
||||||
invalidate();
|
invalidate();
|
||||||
}
|
}
|
||||||
@@ -187,9 +181,9 @@ Window::Window(Window *parent, const rect_t &rect, WindowFlags windowFlags,
|
|||||||
}
|
}
|
||||||
|
|
||||||
Window::Window(Window *parent, lv_obj_t* lvobj)
|
Window::Window(Window *parent, lv_obj_t* lvobj)
|
||||||
: lvobj(lvobj),
|
: rect(nullRect),
|
||||||
parent(parent),
|
parent(parent),
|
||||||
rect(nullRect)
|
lvobj(lvobj)
|
||||||
{
|
{
|
||||||
lv_obj_set_user_data(lvobj, this);
|
lv_obj_set_user_data(lvobj, this);
|
||||||
|
|
||||||
@@ -202,7 +196,7 @@ Window::Window(Window *parent, lv_obj_t* lvobj)
|
|||||||
lv_obj_add_event_cb(lvobj, window_event_cb, LV_EVENT_ALL, this);
|
lv_obj_add_event_cb(lvobj, window_event_cb, LV_EVENT_ALL, this);
|
||||||
|
|
||||||
if (parent) {
|
if (parent) {
|
||||||
parent->addChild(this, windowFlags & PUSH_FRONT);
|
parent->addChild(this);
|
||||||
if (!(windowFlags & TRANSPARENT)) {
|
if (!(windowFlags & TRANSPARENT)) {
|
||||||
invalidate();
|
invalidate();
|
||||||
}
|
}
|
||||||
@@ -230,6 +224,65 @@ Window::~Window()
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#if defined(DEBUG_WINDOWS)
|
||||||
|
std::string Window::getName() const { return "Window"; }
|
||||||
|
|
||||||
|
std::string Window::getRectString() const
|
||||||
|
{
|
||||||
|
char result[32];
|
||||||
|
sprintf(result, "[%d, %d, %d, %d]", left(), top(), width(), height());
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
std::string Window::getIndentString() const
|
||||||
|
{
|
||||||
|
std::string result;
|
||||||
|
auto tmp = parent;
|
||||||
|
while (tmp) {
|
||||||
|
result += " ";
|
||||||
|
tmp = tmp->getParent();
|
||||||
|
}
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
std::string Window::getWindowDebugString(const char *name = nullptr) const
|
||||||
|
{
|
||||||
|
return getName() + (name ? std::string(" [") + name + "] " : " ") +
|
||||||
|
getRectString();
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
Window *Window::getFullScreenWindow()
|
||||||
|
{
|
||||||
|
if (width() == LCD_W && height() == LCD_H) return this;
|
||||||
|
if (parent) return parent->getFullScreenWindow();
|
||||||
|
return nullptr;
|
||||||
|
}
|
||||||
|
|
||||||
|
void Window::setWindowFlags(WindowFlags flags)
|
||||||
|
{
|
||||||
|
// TODO: check if LVGL flags need updating...
|
||||||
|
windowFlags = flags;
|
||||||
|
}
|
||||||
|
|
||||||
|
void Window::setTextFlags(LcdFlags flags)
|
||||||
|
{
|
||||||
|
textFlags = flags;
|
||||||
|
if (!lvobj) return;
|
||||||
|
|
||||||
|
// lv integration for colors
|
||||||
|
auto textColor = COLOR_VAL(flags);
|
||||||
|
auto r = GET_RED(textColor), g = GET_GREEN(textColor),
|
||||||
|
b = GET_BLUE(textColor);
|
||||||
|
lv_obj_set_style_text_color(lvobj, lv_color_make(r, g, b), LV_PART_MAIN);
|
||||||
|
|
||||||
|
// rco: shouldn't this be done via 'setTextFlags()' on the children?
|
||||||
|
for (uint32_t i = 0; i < lv_obj_get_child_cnt(lvobj); i++) {
|
||||||
|
auto child = lv_obj_get_child(lvobj, i);
|
||||||
|
lv_obj_set_style_text_color(child, lv_color_make(r, g, b), LV_PART_MAIN);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
void Window::attach(Window *newParent)
|
void Window::attach(Window *newParent)
|
||||||
{
|
{
|
||||||
if (parent) detach();
|
if (parent) detach();
|
||||||
@@ -279,10 +332,6 @@ void Window::deleteLater(bool detach, bool trash)
|
|||||||
|
|
||||||
void Window::clear()
|
void Window::clear()
|
||||||
{
|
{
|
||||||
scrollPositionX = 0;
|
|
||||||
scrollPositionY = 0;
|
|
||||||
innerWidth = rect.w;
|
|
||||||
innerHeight = rect.h;
|
|
||||||
deleteChildren();
|
deleteChildren();
|
||||||
if(lvobj != nullptr) {
|
if(lvobj != nullptr) {
|
||||||
lv_obj_clean(lvobj);
|
lv_obj_clean(lvobj);
|
||||||
@@ -370,71 +419,15 @@ void Window::setFocus(uint8_t flag, Window * from)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void Window::setScrollPositionX(coord_t value)
|
|
||||||
{
|
|
||||||
auto newScrollPosition = max<coord_t>(0, min<coord_t>(innerWidth - width(), value));
|
|
||||||
if (newScrollPosition != scrollPositionX) {
|
|
||||||
scrollPositionX = newScrollPosition;
|
|
||||||
invalidate();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void Window::setScrollPositionY(coord_t value)
|
|
||||||
{
|
|
||||||
auto newScrollPosition = min<coord_t>(innerHeight - height(), value);
|
|
||||||
|
|
||||||
if (newScrollPosition < 0 && innerHeight != INFINITE_HEIGHT) {
|
|
||||||
newScrollPosition = 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (newScrollPosition != scrollPositionY) {
|
|
||||||
scrollPositionY = newScrollPosition;
|
|
||||||
invalidate();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void Window::scrollTo(Window * child)
|
void Window::scrollTo(Window * child)
|
||||||
{
|
{
|
||||||
coord_t offsetX = 0;
|
|
||||||
coord_t offsetY = 0;
|
|
||||||
|
|
||||||
Window * parentWindow = child->getParent();
|
|
||||||
while (parentWindow && parentWindow != this) {
|
|
||||||
offsetX += parentWindow->left();
|
|
||||||
offsetY += parentWindow->top();
|
|
||||||
parentWindow = parentWindow->getParent();
|
|
||||||
}
|
|
||||||
|
|
||||||
const rect_t scrollRect = {
|
|
||||||
offsetX + child->left(),
|
|
||||||
offsetY + child->top(),
|
|
||||||
min(child->width(), width()),
|
|
||||||
min(child->height(), height())
|
|
||||||
};
|
|
||||||
|
|
||||||
scrollTo(scrollRect);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void Window::scrollTo(const rect_t & rect)
|
void Window::scrollTo(const rect_t & rect)
|
||||||
{
|
{
|
||||||
if (rect.top() < scrollPositionY) {
|
|
||||||
auto y =
|
|
||||||
pageHeight ? rect.top() - (rect.top() % pageHeight) : rect.top();
|
|
||||||
lv_obj_scroll_to_y(lvobj, y, LV_ANIM_OFF);
|
|
||||||
} else if (rect.bottom() > scrollPositionY + height()) {
|
|
||||||
auto y = pageHeight ? rect.top() - (rect.top() % pageHeight)
|
|
||||||
: rect.bottom() - height();
|
|
||||||
lv_obj_scroll_to_y(lvobj, y, LV_ANIM_OFF);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (rect.left() < scrollPositionX) {
|
|
||||||
auto x = pageWidth ? rect.left() - (rect.left() % pageWidth) : rect.left();
|
|
||||||
lv_obj_scroll_to_x(lvobj, x, LV_ANIM_OFF);
|
|
||||||
}
|
|
||||||
else if (rect.right() > scrollPositionX + width()) {
|
|
||||||
auto x = pageWidth ? rect.left() - (rect.left() % pageWidth) : rect.right() - width();
|
|
||||||
lv_obj_scroll_to_x(lvobj, x, LV_ANIM_OFF);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
bool Window::hasOpaqueRect(const rect_t & testRect) const
|
bool Window::hasOpaqueRect(const rect_t & testRect) const
|
||||||
@@ -495,9 +488,6 @@ void Window::fullPaint(BitmapBuffer * dc)
|
|||||||
TRACE_WINDOWS_INDENT("%s (skipped)", getWindowDebugString().c_str());
|
TRACE_WINDOWS_INDENT("%s (skipped)", getWindowDebugString().c_str());
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!(windowFlags & NO_SCROLLBAR)) {
|
|
||||||
drawVerticalScrollbar(dc);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!(windowFlags & PAINT_CHILDREN_FIRST)) {
|
if (!(windowFlags & PAINT_CHILDREN_FIRST)) {
|
||||||
paintChildren(dc, firstChild);
|
paintChildren(dc, firstChild);
|
||||||
@@ -523,17 +513,6 @@ bool Window::isChildVisible(const Window * window) const
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
void Window::setInsideParentScrollingArea()
|
|
||||||
{
|
|
||||||
Window * parent = getParent();
|
|
||||||
while (parent && parent->getWindowFlags() & FORWARD_SCROLL) {
|
|
||||||
parent = parent->parent;
|
|
||||||
}
|
|
||||||
if (parent) {
|
|
||||||
parent->scrollTo(this);
|
|
||||||
invalidate();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void Window::paintChildren(BitmapBuffer * dc, std::list<Window *>::iterator it)
|
void Window::paintChildren(BitmapBuffer * dc, std::list<Window *>::iterator it)
|
||||||
{
|
{
|
||||||
@@ -558,11 +537,11 @@ void Window::paintChildren(BitmapBuffer * dc, std::list<Window *>::iterator it)
|
|||||||
if (child_ymax <= ymin)
|
if (child_ymax <= ymin)
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
dc->setOffset(x + child->rect.x - child->scrollPositionX, y + child->rect.y - child->scrollPositionY);
|
// dc->setOffset(x + child->rect.x - child->scrollPositionX,
|
||||||
dc->setClippingRect(max(xmin, x + child->rect.left()),
|
// y + child->rect.y - child->scrollPositionY);
|
||||||
min(xmax, x + child->rect.right()),
|
dc->setClippingRect(
|
||||||
max(ymin, y + child->rect.top()),
|
max(xmin, x + child->rect.left()), min(xmax, x + child->rect.right()),
|
||||||
min(ymax, y + child->rect.bottom()));
|
max(ymin, y + child->rect.top()), min(ymax, y + child->rect.bottom()));
|
||||||
child->fullPaint(dc);
|
child->fullPaint(dc);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -636,8 +615,6 @@ bool Window::onTouchEnd(coord_t x, coord_t y)
|
|||||||
|
|
||||||
bool Window::onTouchSlide(coord_t x, coord_t y, coord_t startX, coord_t startY, coord_t slideX, coord_t slideY)
|
bool Window::onTouchSlide(coord_t x, coord_t y, coord_t startX, coord_t startY, coord_t slideX, coord_t slideY)
|
||||||
{
|
{
|
||||||
startX += getScrollPositionX();
|
|
||||||
startY += getScrollPositionY();
|
|
||||||
|
|
||||||
for (auto it = children.rbegin(); it != children.rend(); ++it) {
|
for (auto it = children.rbegin(); it != children.rend(); ++it) {
|
||||||
auto child = *it;
|
auto child = *it;
|
||||||
@@ -654,19 +631,13 @@ bool Window::onTouchSlide(coord_t x, coord_t y, coord_t startX, coord_t startY,
|
|||||||
|
|
||||||
void Window::adjustInnerHeight()
|
void Window::adjustInnerHeight()
|
||||||
{
|
{
|
||||||
coord_t bottomMax = 0;
|
|
||||||
for (auto child: children) {
|
|
||||||
bottomMax = max(bottomMax, child->rect.y + child->rect.h);
|
|
||||||
}
|
|
||||||
setInnerHeight(bottomMax);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
coord_t Window::adjustHeight()
|
coord_t Window::adjustHeight()
|
||||||
{
|
{
|
||||||
coord_t old = rect.h;
|
coord_t old = rect.h;
|
||||||
adjustInnerHeight();
|
adjustInnerHeight();
|
||||||
rect.h = innerHeight;
|
if (lvobj) lv_obj_set_style_height(lvobj, rect.h, LV_PART_MAIN);
|
||||||
lv_obj_set_style_height(getLvObj(), rect.h, LV_PART_MAIN);
|
|
||||||
return rect.h - old;
|
return rect.h - old;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -696,33 +667,24 @@ void Window::updateSize()
|
|||||||
invalidate();
|
invalidate();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void Window::addChild(Window* window)
|
||||||
|
{
|
||||||
|
auto lv_parent = lv_obj_get_parent(window->lvobj);
|
||||||
|
if (lv_parent && (lv_parent != lvobj)) {
|
||||||
|
lv_obj_set_parent(window->lvobj, lvobj);
|
||||||
|
}
|
||||||
|
|
||||||
|
children.push_back(window);
|
||||||
|
}
|
||||||
|
|
||||||
|
void Window::removeChild(Window* window)
|
||||||
|
{
|
||||||
|
children.remove(window);
|
||||||
|
if (window->lvobj != nullptr) lv_obj_set_parent(window->lvobj, nullptr);
|
||||||
|
invalidate();
|
||||||
|
}
|
||||||
|
|
||||||
void Window::invalidate(const rect_t & rect)
|
void Window::invalidate(const rect_t & rect)
|
||||||
{
|
{
|
||||||
if (lvobj) lv_obj_invalidate(lvobj);
|
if (lvobj) lv_obj_invalidate(lvobj);
|
||||||
}
|
}
|
||||||
|
|
||||||
void Window::drawVerticalScrollbar(BitmapBuffer * dc)
|
|
||||||
{
|
|
||||||
if (innerHeight > rect.h) {
|
|
||||||
coord_t yofs = divRoundClosest(rect.h * scrollPositionY, innerHeight);
|
|
||||||
coord_t yhgt = divRoundClosest(rect.h * rect.h, innerHeight);
|
|
||||||
if (yhgt < 15)
|
|
||||||
yhgt = 15;
|
|
||||||
if (yhgt + yofs > rect.h)
|
|
||||||
yhgt = rect.h - yofs;
|
|
||||||
dc->drawSolidFilledRect(rect.w - SCROLLBAR_WIDTH, scrollPositionY + yofs, SCROLLBAR_WIDTH, yhgt, COLOR_THEME_PRIMARY3);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void Window::drawHorizontalScrollbar(BitmapBuffer * dc)
|
|
||||||
{
|
|
||||||
if (innerWidth > rect.w) {
|
|
||||||
coord_t xofs = divRoundClosest(rect.w * scrollPositionX, innerWidth);
|
|
||||||
coord_t xwdth = divRoundClosest(rect.w * rect.w, innerWidth);
|
|
||||||
if (xwdth < 15)
|
|
||||||
xwdth = 15;
|
|
||||||
if (xwdth + xofs > rect.w)
|
|
||||||
xwdth = rect.w - xofs;
|
|
||||||
dc->drawSolidFilledRect(scrollPositionX + xofs, rect.h - SCROLLBAR_WIDTH, xwdth, SCROLLBAR_WIDTH, COLOR_THEME_PRIMARY3);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|||||||
+36
-230
@@ -74,105 +74,40 @@ class Window
|
|||||||
virtual ~Window();
|
virtual ~Window();
|
||||||
|
|
||||||
#if defined(DEBUG_WINDOWS)
|
#if defined(DEBUG_WINDOWS)
|
||||||
virtual std::string getName() const
|
virtual std::string getName() const;
|
||||||
{
|
std::string getRectString() const;
|
||||||
return "Window";
|
std::string getIndentString() const;
|
||||||
}
|
std::string getWindowDebugString(const char * name = nullptr) const;
|
||||||
|
|
||||||
std::string getRectString() const
|
|
||||||
{
|
|
||||||
char result[32];
|
|
||||||
sprintf(result, "[%d, %d, %d, %d]", left(), top(), width(), height());
|
|
||||||
return result;
|
|
||||||
}
|
|
||||||
|
|
||||||
std::string getIndentString() const
|
|
||||||
{
|
|
||||||
std::string result;
|
|
||||||
auto tmp = parent;
|
|
||||||
while (tmp) {
|
|
||||||
result += " ";
|
|
||||||
tmp = tmp->getParent();
|
|
||||||
}
|
|
||||||
return result;
|
|
||||||
}
|
|
||||||
|
|
||||||
std::string getWindowDebugString(const char * name = nullptr) const
|
|
||||||
{
|
|
||||||
return getName() + (name ? std::string(" [") + name + "] " : " ") + getRectString();
|
|
||||||
}
|
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
Window * getParent() const
|
Window *getParent() const { return parent; }
|
||||||
{
|
|
||||||
return parent;
|
|
||||||
}
|
|
||||||
|
|
||||||
bool isChild(Window * window) const
|
bool isChild(Window *window) const
|
||||||
{
|
{
|
||||||
return window == this || (parent && parent->isChild(window));
|
return window == this || (parent && parent->isChild(window));
|
||||||
}
|
}
|
||||||
|
|
||||||
Window *getFullScreenWindow()
|
Window *getFullScreenWindow();
|
||||||
{
|
|
||||||
if (width() == LCD_W && height() == LCD_H) return this;
|
|
||||||
if (parent) return parent->getFullScreenWindow();
|
|
||||||
return nullptr;
|
|
||||||
}
|
|
||||||
|
|
||||||
WindowFlags getWindowFlags() const
|
WindowFlags getWindowFlags() const { return windowFlags; }
|
||||||
{
|
void setWindowFlags(WindowFlags flags);
|
||||||
return windowFlags;
|
|
||||||
}
|
|
||||||
|
|
||||||
void setWindowFlags(WindowFlags flags)
|
LcdFlags getTextFlags() const { return textFlags; }
|
||||||
{
|
void setTextFlags(LcdFlags flags);
|
||||||
windowFlags = flags;
|
|
||||||
}
|
|
||||||
|
|
||||||
LcdFlags getTextFlags() const
|
typedef std::function<void()> CloseHandler;
|
||||||
{
|
void setCloseHandler(CloseHandler h) { closeHandler = std::move(h); }
|
||||||
return textFlags;
|
|
||||||
}
|
|
||||||
|
|
||||||
void setTextFlags(LcdFlags flags)
|
typedef std::function<void(bool)> FocusHandler;
|
||||||
{
|
void setFocusHandler(FocusHandler h) { focusHandler = std::move(h); }
|
||||||
textFlags = flags;
|
|
||||||
if (!lvobj) return;
|
|
||||||
|
|
||||||
// lv integration for colors
|
const std::list<Window *> getChildren() { return children; }
|
||||||
auto textColor = COLOR_VAL(flags);
|
|
||||||
auto r = GET_RED(textColor), g = GET_GREEN(textColor), b = GET_BLUE(textColor);
|
|
||||||
lv_obj_set_style_text_color(lvobj, lv_color_make(r, g, b), LV_PART_MAIN);
|
|
||||||
|
|
||||||
// rco: shouldn't this be done via 'setTextFlags()' on the children?
|
|
||||||
for (uint32_t i = 0; i < lv_obj_get_child_cnt(lvobj); i++) {
|
|
||||||
auto child = lv_obj_get_child(lvobj, i);
|
|
||||||
lv_obj_set_style_text_color(child, lv_color_make(r, g, b), LV_PART_MAIN);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void setCloseHandler(std::function<void()> handler)
|
|
||||||
{
|
|
||||||
closeHandler = std::move(handler);
|
|
||||||
}
|
|
||||||
|
|
||||||
void setFocusHandler(std::function<void(bool)> handler)
|
|
||||||
{
|
|
||||||
focusHandler = std::move(handler);
|
|
||||||
}
|
|
||||||
|
|
||||||
const std::list<Window *> getChildren()
|
|
||||||
{
|
|
||||||
return children;
|
|
||||||
}
|
|
||||||
|
|
||||||
virtual void deleteLater(bool detach = true, bool trash = true);
|
|
||||||
|
|
||||||
void clear();
|
void clear();
|
||||||
|
virtual void deleteLater(bool detach = true, bool trash = true);
|
||||||
|
|
||||||
void clearLvgl();
|
void clearLvgl();
|
||||||
|
|
||||||
void deleteChildren();
|
|
||||||
|
|
||||||
bool hasFocus() const
|
bool hasFocus() const
|
||||||
{
|
{
|
||||||
@@ -218,14 +153,7 @@ class Window
|
|||||||
void setHeight(coord_t value)
|
void setHeight(coord_t value)
|
||||||
{
|
{
|
||||||
rect.h = value;
|
rect.h = value;
|
||||||
if (lvobj != nullptr)
|
if (lvobj != nullptr) lv_obj_set_height(lvobj, rect.h);
|
||||||
lv_obj_set_height(lvobj, rect.h);
|
|
||||||
|
|
||||||
if (windowFlags & FORWARD_SCROLL)
|
|
||||||
innerHeight = value;
|
|
||||||
else if (lvobj != nullptr && innerHeight <= value) {
|
|
||||||
lv_obj_scroll_to_y(lvobj, 0, LV_ANIM_OFF);
|
|
||||||
}
|
|
||||||
invalidate();
|
invalidate();
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -278,94 +206,7 @@ class Window
|
|||||||
return rect;
|
return rect;
|
||||||
}
|
}
|
||||||
|
|
||||||
coord_t getInnerWidth() const
|
|
||||||
{
|
|
||||||
return innerWidth;
|
|
||||||
}
|
|
||||||
|
|
||||||
void setInnerWidth(coord_t w)
|
|
||||||
{
|
|
||||||
innerWidth = w;
|
|
||||||
if (width() >= w) {
|
|
||||||
scrollPositionX = 0;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void setPageWidth(coord_t w)
|
|
||||||
{
|
|
||||||
pageWidth = w;
|
|
||||||
}
|
|
||||||
|
|
||||||
void setPageHeight(coord_t h)
|
|
||||||
{
|
|
||||||
pageHeight = h;
|
|
||||||
}
|
|
||||||
|
|
||||||
uint8_t getPageCount() const
|
|
||||||
{
|
|
||||||
if (pageWidth)
|
|
||||||
return innerWidth / pageWidth;
|
|
||||||
else if (pageHeight)
|
|
||||||
return innerHeight / pageHeight;
|
|
||||||
else
|
|
||||||
return 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
uint8_t getPageIndex() const
|
|
||||||
{
|
|
||||||
if (pageWidth)
|
|
||||||
return (getScrollPositionX() + (pageWidth / 2)) / pageWidth;
|
|
||||||
else if (pageHeight)
|
|
||||||
return (getScrollPositionY() + (pageHeight / 2)) / pageHeight;
|
|
||||||
else
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
coord_t getInnerHeight() const
|
|
||||||
{
|
|
||||||
return innerHeight;
|
|
||||||
}
|
|
||||||
|
|
||||||
void setInnerHeight(coord_t h)
|
|
||||||
{
|
|
||||||
innerHeight = h;
|
|
||||||
if (windowFlags & FORWARD_SCROLL) {
|
|
||||||
rect.h = innerHeight;
|
|
||||||
parent->adjustInnerHeight();
|
|
||||||
}
|
|
||||||
else if (height() >= h) {
|
|
||||||
lv_obj_scroll_to_y(lvobj, 0, LV_ANIM_OFF);
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
coord_t maxScrollPosition = h - height();
|
|
||||||
if (scrollPositionY > maxScrollPosition) {
|
|
||||||
lv_obj_scroll_to_y(lvobj, maxScrollPosition, LV_ANIM_OFF);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
invalidate();
|
|
||||||
}
|
|
||||||
|
|
||||||
coord_t getScrollPositionX() const
|
|
||||||
{
|
|
||||||
return scrollPositionX;
|
|
||||||
}
|
|
||||||
|
|
||||||
void captureWindow(Window *window)
|
|
||||||
{
|
|
||||||
capturedWindow = window;
|
|
||||||
}
|
|
||||||
|
|
||||||
coord_t getScrollPositionY() const
|
|
||||||
{
|
|
||||||
return scrollPositionY;
|
|
||||||
}
|
|
||||||
|
|
||||||
virtual void setScrollPositionX(coord_t value);
|
|
||||||
|
|
||||||
virtual void setScrollPositionY(coord_t value);
|
|
||||||
|
|
||||||
bool isChildVisible(const Window * window) const;
|
bool isChildVisible(const Window * window) const;
|
||||||
|
|
||||||
bool isChildFullSize(const Window * window) const;
|
bool isChildFullSize(const Window * window) const;
|
||||||
|
|
||||||
bool isVisible() const
|
bool isVisible() const
|
||||||
@@ -373,17 +214,6 @@ class Window
|
|||||||
return parent && parent->isChildVisible(this);
|
return parent && parent->isChildVisible(this);
|
||||||
}
|
}
|
||||||
|
|
||||||
bool isInsideParentScrollingArea() const
|
|
||||||
{
|
|
||||||
return parent && right() >= parent->getScrollPositionX() && left() <= parent->getScrollPositionX() + parent->width();
|
|
||||||
}
|
|
||||||
|
|
||||||
void setInsideParentScrollingArea();
|
|
||||||
|
|
||||||
void drawVerticalScrollbar(BitmapBuffer * dc);
|
|
||||||
|
|
||||||
void drawHorizontalScrollbar(BitmapBuffer * dc);
|
|
||||||
|
|
||||||
virtual void onEvent(event_t event);
|
virtual void onEvent(event_t event);
|
||||||
|
|
||||||
void adjustInnerHeight();
|
void adjustInnerHeight();
|
||||||
@@ -427,57 +257,33 @@ class Window
|
|||||||
inline lv_obj_t *getLvObj() { return lvobj; }
|
inline lv_obj_t *getLvObj() { return lvobj; }
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
lv_obj_t *lvobj = nullptr;
|
static Window* focusWindow;
|
||||||
Window * parent;
|
static std::list<Window*> trash;
|
||||||
std::list<Window *> children;
|
|
||||||
rect_t rect;
|
|
||||||
coord_t innerWidth = 0;
|
|
||||||
coord_t innerHeight = 0;
|
|
||||||
coord_t pageWidth = 0;
|
|
||||||
coord_t pageHeight = 0;
|
|
||||||
coord_t scrollPositionX = 0;
|
|
||||||
coord_t scrollPositionY = 0;
|
|
||||||
WindowFlags windowFlags = 0;
|
|
||||||
LcdFlags textFlags = 0;
|
|
||||||
bool _deleted = false;
|
|
||||||
|
|
||||||
static Window * focusWindow;
|
rect_t rect;
|
||||||
static Window * slidingWindow;
|
|
||||||
static Window * capturedWindow;
|
Window* parent = nullptr;
|
||||||
static std::list<Window *> trash;
|
lv_obj_t* lvobj = nullptr;
|
||||||
|
|
||||||
|
std::list<Window *> children;
|
||||||
|
|
||||||
|
WindowFlags windowFlags = 0;
|
||||||
|
LcdFlags textFlags = 0;
|
||||||
|
|
||||||
|
bool _deleted = false;
|
||||||
|
|
||||||
std::function<void()> closeHandler;
|
std::function<void()> closeHandler;
|
||||||
std::function<void(bool)> focusHandler;
|
std::function<void(bool)> focusHandler;
|
||||||
|
|
||||||
virtual void addChild(Window * window, bool front = false)
|
void deleteChildren();
|
||||||
{
|
|
||||||
auto lv_parent = lv_obj_get_parent(window->lvobj);
|
|
||||||
if (lv_parent && (lv_parent != lvobj)) {
|
|
||||||
lv_obj_set_parent(window->lvobj, lvobj);
|
|
||||||
// not used anywhere!
|
|
||||||
if (front)
|
|
||||||
lv_obj_move_to_index(window->lvobj, 0);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (front)
|
virtual void addChild(Window * window);
|
||||||
children.push_front(window);
|
void removeChild(Window * window);
|
||||||
else
|
|
||||||
children.push_back(window);
|
|
||||||
}
|
|
||||||
|
|
||||||
void removeChild(Window * window)
|
|
||||||
{
|
|
||||||
children.remove(window);
|
|
||||||
if (window->lvobj != nullptr)
|
|
||||||
lv_obj_set_parent(window->lvobj, nullptr);
|
|
||||||
invalidate();
|
|
||||||
}
|
|
||||||
|
|
||||||
virtual void invalidate(const rect_t & rect);
|
virtual void invalidate(const rect_t & rect);
|
||||||
|
|
||||||
void paintChildren(BitmapBuffer * dc, std::list<Window *>::iterator it);
|
|
||||||
|
|
||||||
void fullPaint(BitmapBuffer * dc);
|
void fullPaint(BitmapBuffer * dc);
|
||||||
|
void paintChildren(BitmapBuffer * dc, std::list<Window *>::iterator it);
|
||||||
|
|
||||||
virtual void onFocusLost()
|
virtual void onFocusLost()
|
||||||
{
|
{
|
||||||
|
|||||||
Reference in New Issue
Block a user