diff --git a/radio/src/thirdparty/libopenui/mainwindow.cpp b/radio/src/thirdparty/libopenui/mainwindow.cpp deleted file mode 100644 index de96d7fa9..000000000 --- a/radio/src/thirdparty/libopenui/mainwindow.cpp +++ /dev/null @@ -1,141 +0,0 @@ -/* - * Copyright (C) OpenTX - * - * Source: - * https://github.com/opentx/libopenui - * - * This file is a part of libopenui library. - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; either - * version 3 of the License, or (at your option) any later version. - * - * This library is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Lesser General Public License for more details. - */ - -#include "mainwindow.h" -#include "keyboard_base.h" - -#if defined(HARDWARE_TOUCH) -#include "touch.h" -#endif - -MainWindow * MainWindow::_instance = nullptr; - -#if defined(HARDWARE_TOUCH) -TouchState touchState; -Keyboard * Keyboard::activeKeyboard = nullptr; -#endif - -void MainWindow::emptyTrash() -{ - for (auto window: trash) { - delete window; - } - trash.clear(); -} - -void MainWindow::checkEvents() -{ -#if defined(HARDWARE_TOUCH) - if (touchPanelEventOccured()) { - touchPanelRead(); - } - - if (touchState.event == TE_DOWN) { - onTouchStart(touchState.x + scrollPositionX, touchState.y + scrollPositionY); - slidingWindow = nullptr; - } - else if (touchState.event == TE_UP) { - touchState.event = TE_NONE; - onTouchEnd(touchState.startX + scrollPositionX, touchState.startY + scrollPositionY); - } - else if (touchState.event == TE_SLIDE) { - if (touchState.deltaX || touchState.deltaY) { - onTouchSlide(touchState.x, touchState.y, touchState.startX, touchState.startY, touchState.deltaX, touchState.deltaY); - touchState.lastDeltaX = touchState.deltaX; - touchState.lastDeltaY = touchState.deltaY; - touchState.deltaX = 0; - touchState.deltaY = 0; - } - } - else if (touchState.event == TE_SLIDE_END && slidingWindow) { - if (touchState.lastDeltaX > SLIDE_SPEED_REDUCTION) - touchState.lastDeltaX -= SLIDE_SPEED_REDUCTION; - else if (touchState.lastDeltaX < -SLIDE_SPEED_REDUCTION) - touchState.lastDeltaX += SLIDE_SPEED_REDUCTION; - else - touchState.lastDeltaX = 0; - if (touchState.lastDeltaY > SLIDE_SPEED_REDUCTION) - touchState.lastDeltaY -= SLIDE_SPEED_REDUCTION; - else if (touchState.lastDeltaY < -SLIDE_SPEED_REDUCTION) - touchState.lastDeltaY += SLIDE_SPEED_REDUCTION; - else - touchState.lastDeltaY = 0; - - onTouchSlide(touchState.x, touchState.y, touchState.startX, touchState.startY, touchState.lastDeltaX, touchState.lastDeltaY); - slidingWindow = nullptr; - } -#endif - - Window::checkEvents(); -} - -void MainWindow::invalidate(const rect_t & rect) -{ - if (invalidatedRect.w) { - auto left = limit(0, rect.left(), invalidatedRect.left()); - auto right = limit(invalidatedRect.right(), rect.right(), LCD_W); - auto top = limit(0, rect.top(), invalidatedRect.top()); - auto bottom = limit(rect.bottom(), invalidatedRect.bottom(), LCD_H); - invalidatedRect = {left, top, right - left, bottom - top}; - } - else { - invalidatedRect = rect; - } -} - -bool MainWindow::refresh() -{ - if (invalidatedRect.w) { - if (invalidatedRect.x > 0 || invalidatedRect.y > 0 || invalidatedRect.w < LCD_W || invalidatedRect.h < LCD_H) { - TRACE_WINDOWS("Refresh rect: left=%d top=%d width=%d height=%d", invalidatedRect.left(), invalidatedRect.top(), invalidatedRect.w, invalidatedRect.h); - lcdCopy(lcd->getData(), lcdFront->getData()); - } - else { - TRACE_WINDOWS("Refresh full screen"); - } - lcd->setOffset(0, 0); - lcd->setClippingRect(invalidatedRect.left(), invalidatedRect.right(), invalidatedRect.top(), invalidatedRect.bottom()); - fullPaint(lcd); - invalidatedRect.w = 0; - return true; - } - else { - return false; - } -} - -void MainWindow::run(bool trash) -{ - auto start = ticksNow(); - - checkEvents(); - - if (trash) { - emptyTrash(); - } - - if (refresh()) { - lcdRefresh(); - } - - auto delta = ticksNow() - start; - if (delta > 10 * SYSTEM_TICKS_1MS) { - TRACE_WINDOWS("MainWindow::run took %dms", (ticksNow() - start) / SYSTEM_TICKS_1MS); - } -} diff --git a/radio/src/thirdparty/libopenui/window.cpp b/radio/src/thirdparty/libopenui/window.cpp deleted file mode 100644 index 46f5d4ce4..000000000 --- a/radio/src/thirdparty/libopenui/window.cpp +++ /dev/null @@ -1,564 +0,0 @@ -/* - * Copyright (C) OpenTX - * - * Source: - * https://github.com/opentx/libopenui - * - * This file is a part of libopenui library. - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; either - * version 3 of the License, or (at your option) any later version. - * - * This library is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Lesser General Public License for more details. - */ - -#include "window.h" -#include "touch.h" - -Window * Window::focusWindow = nullptr; -Window * Window::slidingWindow = nullptr; -Window * Window::touchedWindow = nullptr; -std::list Window::trash; - -Window::Window(Window * parent, const rect_t & rect, WindowFlags windowFlags, LcdFlags textFlags): - parent(parent), - rect(rect), - innerWidth(rect.w), - innerHeight(rect.h), - windowFlags(windowFlags), - textFlags(textFlags) -{ - if (parent) { - parent->addChild(this, windowFlags & PUSH_FRONT); - if (!(windowFlags & TRANSPARENT)) { - invalidate(); - } - } -} - -Window::~Window() -{ - TRACE_WINDOWS("Destroy %p %s", this, getWindowDebugString().c_str()); - - if (focusWindow == this) { - focusWindow = nullptr; - } - - deleteChildren(); -} - -void Window::attach(Window * newParent) -{ - if (parent) detach(); - parent = newParent; - if (newParent) newParent->addChild(this); -} - -void Window::detach() -{ - if (parent) { - parent->removeChild(this); - parent = nullptr; - } -} - -void Window::deleteLater(bool detach, bool trash) -{ - if (_deleted) - return; - - TRACE_WINDOWS("Delete %p %s", this, getWindowDebugString().c_str()); - - _deleted = true; - - if (static_cast(focusWindow) == static_cast(this)) { - focusWindow = nullptr; - } - - if (detach) - this->detach(); - else - parent = nullptr; - - deleteChildren(); - - if (closeHandler) { - closeHandler(); - } - - if (trash) { - Window::trash.push_back(this); - } -} - -void Window::clear() -{ - scrollPositionX = 0; - scrollPositionY = 0; - innerWidth = rect.w; - innerHeight = rect.h; - deleteChildren(); - invalidate(); -} - -void Window::deleteChildren() -{ - for (auto window: children) { - window->deleteLater(false); - } - children.clear(); -} - -void Window::clearFocus() -{ - if (focusWindow) { - focusWindow->onFocusLost(); - focusWindow = nullptr; - } -} - -void Window::setFocus(uint8_t flag, Window * from) -{ - if (deleted()) - return; - - TRACE_WINDOWS("%s setFocus()", getWindowDebugString().c_str()); - - if (focusWindow != this) { - // scroll before calling focusHandler so that the window can adjust the scroll position if needed - Window * parent = this->parent; - while (parent && parent->getWindowFlags() & FORWARD_SCROLL) { - parent = parent->parent; - } - if (parent) { - parent->scrollTo(this); - invalidate(); - } - - clearFocus(); - focusWindow = this; - if (focusHandler) { - focusHandler(true); - } - } -} - -void Window::setScrollPositionX(coord_t value) -{ - auto newScrollPosition = max(0, min(innerWidth - width(), value)); - if (newScrollPosition != scrollPositionX) { - scrollPositionX = newScrollPosition; - invalidate(); - } -} - -void Window::setScrollPositionY(coord_t value) -{ - auto newScrollPosition = min(innerHeight - height(), value); - - if (newScrollPosition < 0 && innerHeight != INFINITE_HEIGHT) { - newScrollPosition = 0; - } - - if (newScrollPosition != scrollPositionY) { - scrollPositionY = newScrollPosition; - invalidate(); - } -} - -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) -{ - if (rect.top() < scrollPositionY) { - setScrollPositionY(pageHeight ? rect.top() - (rect.top() % pageHeight) : rect.top() - 5); - } - else if (rect.bottom() > scrollPositionY + height() - 5) { - setScrollPositionY(pageHeight ? rect.top() - (rect.top() % pageHeight) : rect.bottom() - height() + 5); - } - - if (rect.left() < scrollPositionX) { - setScrollPositionX(pageWidth ? rect.left() - (rect.left() % pageWidth) : rect.left() - 5); - } - else if (rect.right() > scrollPositionX + width() - 5) { - setScrollPositionX(pageWidth ? rect.left() - (rect.left() % pageWidth) : rect.right() - width() + 5); - } -} - -bool Window::hasOpaqueRect(const rect_t & testRect) const -{ - if (!rect.contains(testRect)) - return false; - - if (windowFlags & OPAQUE) { - return true; - } - - rect_t relativeRect = {testRect.x - rect.x, testRect.y - rect.y, testRect.w, testRect.h}; - for (auto child: children) { - if (child->hasOpaqueRect(relativeRect)) - return true; - } - - return false; -} - -void Window::fullPaint(BitmapBuffer * dc) -{ - bool paintNeeded = true; - std::list::iterator firstChild; - - coord_t xmin, xmax, ymin, ymax; - dc->getClippingRect(xmin, xmax, ymin, ymax); - coord_t x = dc->getOffsetX(); - coord_t y = dc->getOffsetY(); - - if (windowFlags & PAINT_CHILDREN_FIRST) { - paintChildren(dc, children.begin()); - dc->setOffset(x, y); - dc->setClippingRect(xmin, xmax, ymin, ymax); - } - else { - firstChild = children.end(); - rect_t relativeRect = {xmin - x, ymin - y, xmax - xmin, ymax - ymin}; - while (firstChild != children.begin()) { - auto child = *(--firstChild); - if (child->hasOpaqueRect(relativeRect)) { - paintNeeded = false; - break; - } - } - } - - if (paintNeeded) { - TRACE_WINDOWS_INDENT("%s%s", getWindowDebugString().c_str(), hasFocus() ? " (*)" : ""); - paint(dc); -#if defined(WINDOWS_INSPECT_BORDER_COLOR) - dc->drawSolidRect(0, 0, width(), height(), 1, WINDOWS_INSPECT_BORDER_COLOR); -#endif - } - else { - TRACE_WINDOWS_INDENT("%s (skipped)", getWindowDebugString().c_str()); - } - - if (!(windowFlags & NO_SCROLLBAR)) { - drawVerticalScrollbar(dc); - } - - if (!(windowFlags & PAINT_CHILDREN_FIRST)) { - paintChildren(dc, firstChild); - } -} - -bool Window::isChildFullSize(const Window * child) const -{ - return child->top() == 0 && child->height() == height() && child->left() == 0 && child->width() == width(); -} - -bool Window::isChildVisible(const Window * window) const -{ - for (auto rit = children.rbegin(); rit != children.rend(); rit++) { - auto child = *rit; - if (child == window) { - return true; - } - if ((child->getWindowFlags() & OPAQUE) & isChildFullSize(child)) { - 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::iterator it) -{ - coord_t x = dc->getOffsetX(); - coord_t y = dc->getOffsetY(); - coord_t xmin, xmax, ymin, ymax; - dc->getClippingRect(xmin, xmax, ymin, ymax); - - for (; it != children.end(); it++) { - auto child = *it; - - coord_t child_xmin = x + child->rect.x; - if (child_xmin >= xmax) - continue; - coord_t child_ymin = y + child->rect.y; - if (child_ymin >= ymax) - continue; - coord_t child_xmax = child_xmin + child->rect.w; - if (child_xmax <= xmin) - continue; - coord_t child_ymax = child_ymin + child->rect.h; - if (child_ymax <= ymin) - continue; - - dc->setOffset(x + child->rect.x - child->scrollPositionX, y + child->rect.y - child->scrollPositionY); - dc->setClippingRect(max(xmin, x + child->rect.left()), - min(xmax, x + child->rect.right()), - max(ymin, y + child->rect.top()), - min(ymax, y + child->rect.bottom())); - child->fullPaint(dc); - } -} - -#if defined(HARDWARE_TOUCH) -coord_t Window::getSnapStep(coord_t relativeScrollPosition, coord_t pageSize) -{ - coord_t result = 0; - if (relativeScrollPosition > pageSize / 2) { - // closer to next page - result = (pageSize - relativeScrollPosition); - } - else { - // closer to previous page - result = (0 - relativeScrollPosition); - } - - // do not get too slow - if (abs(result) > 32) - result /= 2; - - return result; -} -#endif - -void Window::checkEvents() -{ - auto copy = children; - for (auto child: copy) { - if (!child->deleted()) { - child->checkEvents(); - } - } - - if (this == Window::focusWindow) { - event_t event = getWindowEvent(); - if (event) { - this->onEvent(event); - } - } - - if (windowFlags & REFRESH_ALWAYS) { - invalidate(); - } - -#if defined(HARDWARE_TOUCH) - if (touchState.event != TE_SLIDE && touchState.lastDeltaX == 0 && touchState.lastDeltaY == 0) { - if (pageWidth) { - coord_t relativeScrollPosition = getScrollPositionX() % pageWidth; - if (relativeScrollPosition) { - setScrollPositionX(getScrollPositionX() + getSnapStep(relativeScrollPosition, pageWidth)); - } - } - if (pageHeight) { - coord_t relativeScrollPosition = getScrollPositionY() % pageHeight; - if (relativeScrollPosition) { - setScrollPositionY(getScrollPositionY() + getSnapStep(relativeScrollPosition, pageHeight)); - } - } - } -#endif -} - -void Window::onEvent(event_t event) -{ - TRACE_WINDOWS("%s received event 0x%X", Window::getWindowDebugString("Window").c_str(), event); - if (parent) { - parent->onEvent(event); - } -} - -#if defined(HARDWARE_TOUCH) -bool Window::onTouchStart(coord_t x, coord_t y) -{ - for (auto it = children.rbegin(); it != children.rend(); ++it) { - auto child = *it; - if (child->rect.contains(x, y)) { - if (child->onTouchStart(x - child->rect.x + child->scrollPositionX, y - child->rect.y + child->scrollPositionY)) { - // remember the first window that processed the touch start event. We will give that window - // the opportunity to process the touchend first, and also after a slide end so the touched window - // always gets a touchEnd if it processed the touch start. - if (touchedWindow == nullptr) { - touchedWindow = child; - } - return true; - } - } - } - - return false; -} - -bool Window::forwardTouchEnd(coord_t x, coord_t y) -{ - // give the touched window the opportunity to process the touch first before it is - // forwarded: See on touchstart - if (touchedWindow != nullptr) { - auto savedTouchWindow = touchedWindow; - touchedWindow = nullptr; - // transalte x and y through the parent hierarchy - auto myParent = savedTouchWindow->parent; - while(myParent != nullptr) { - x = x - myParent->rect.x + myParent->scrollPositionX; - y = y - myParent->rect.y + myParent->scrollPositionY; - myParent = myParent->parent; - } - - if (savedTouchWindow->onTouchEnd( - x - savedTouchWindow->rect.x + savedTouchWindow->scrollPositionX, - y - savedTouchWindow->rect.y + savedTouchWindow->scrollPositionY)) { - return true; - } - } - - for (auto it = children.rbegin(); it != children.rend(); ++it) { - auto child = *it; - if (child->rect.contains(x, y)) { - if (child->onTouchEnd(x - child->rect.x + child->scrollPositionX, y - child->rect.y + child->scrollPositionY)) { - return true; - } - } - } - - return false; -} - -bool Window::onTouchEnd(coord_t x, coord_t y) -{ - return forwardTouchEnd(x, y) ? true : (windowFlags & OPAQUE); -} - -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) { - auto child = *it; - if (child->rect.contains(startX, startY)) { - if (child->onTouchSlide(x - child->rect.x, y - child->rect.y, startX - child->rect.x, startY - child->rect.y, slideX, slideY)) { - return true; - } - } - } - - if (slidingWindow && slidingWindow != this) { - return false; - } - - if (slideY && innerHeight > rect.h) { - setScrollPositionY(scrollPositionY - slideY); - slidingWindow = this; - return true; - } - - if (slideX && innerWidth > rect.w) { - setScrollPositionX(scrollPositionX - slideX); - slidingWindow = this; - return true; - } - - return false; -} -#endif - -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 old = rect.h; - adjustInnerHeight(); - rect.h = innerHeight; - return rect.h - old; -} - -void Window::moveWindowsTop(coord_t y, coord_t delta) -{ - if (getWindowFlags() & FORWARD_SCROLL) { - parent->moveWindowsTop(bottom(), delta); - } - - for (auto child: children) { - if (child->rect.y >= y) { - child->rect.y += delta; - invalidate(); - } - } -} - -void Window::invalidate(const rect_t & rect) -{ - if (isVisible()) { - parent->invalidate({this->rect.x + rect.x - parent->scrollPositionX, this->rect.y + rect.y - parent->scrollPositionY, rect.w, rect.h}); - } -} - -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); - } -} diff --git a/radio/src/thirdparty/libopenui/window.h b/radio/src/thirdparty/libopenui/window.h deleted file mode 100644 index 2b9b045e6..000000000 --- a/radio/src/thirdparty/libopenui/window.h +++ /dev/null @@ -1,451 +0,0 @@ -/* - * Copyright (C) OpenTX - * - * Source: - * https://github.com/opentx/libopenui - * - * This file is a part of libopenui library. - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; either - * version 3 of the License, or (at your option) any later version. - * - * This library is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Lesser General Public License for more details. - */ - -#pragma once - -#include -#include -#include -#include -#include -#include -#include -#include "bitmapbuffer.h" -#include "libopenui_defines.h" -#include "libopenui_helpers.h" -#include "libopenui_config.h" - -typedef uint32_t WindowFlags; - -#if !defined(_GNUC_) - #undef OPAQUE - #undef TRANSPARENT -#endif - -constexpr int INFINITE_HEIGHT = INT32_MAX; - -constexpr WindowFlags OPAQUE = 1u << 0u; -constexpr WindowFlags TRANSPARENT = 1u << 1u; -constexpr WindowFlags NO_SCROLLBAR = 1u << 2u; -constexpr WindowFlags NO_FOCUS = 1u << 3u; -constexpr WindowFlags FORWARD_SCROLL = 1u << 4u; -constexpr WindowFlags REFRESH_ALWAYS = 1u << 5u; -constexpr WindowFlags PAINT_CHILDREN_FIRST = 1u << 6u; -constexpr WindowFlags PUSH_FRONT = 1u << 7u; -constexpr WindowFlags WINDOW_FLAGS_LAST = PUSH_FRONT; - -enum SetFocusFlag -{ - SET_FOCUS_DEFAULT, - SET_FOCUS_FORWARD, - SET_FOCUS_BACKWARD, - SET_FOCUS_FIRST -}; - -class Window -{ - friend class GridLayout; - - public: - Window(Window * parent, const rect_t & rect, WindowFlags windowFlags = 0, LcdFlags textFlags = 0); - - virtual ~Window(); - -#if defined(DEBUG_WINDOWS) - virtual std::string getName() const - { - return "Window"; - } - - 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 - - Window * getParent() const - { - return parent; - } - - bool isChild(Window * window) const - { - return window == this || (parent && parent->isChild(window)); - } - - Window *getFullScreenWindow() - { - if (width() == LCD_W && height() == LCD_H) return this; - if (parent) return parent->getFullScreenWindow(); - return nullptr; - } - - WindowFlags getWindowFlags() const - { - return windowFlags; - } - - void setWindowFlags(WindowFlags flags) - { - windowFlags = flags; - } - - LcdFlags getTextFlags() const - { - return textFlags; - } - - void setTextFlags(LcdFlags flags) - { - textFlags = flags; - } - - void setCloseHandler(std::function handler) - { - closeHandler = std::move(handler); - } - - void setFocusHandler(std::function handler) - { - focusHandler = std::move(handler); - } - - const std::list getChildren() - { - return children; - } - - virtual void deleteLater(bool detach = true, bool trash = true); - - void clear(); - - void deleteChildren(); - - bool hasFocus() const - { - return focusWindow == this; - } - - static Window * getFocus() - { - return focusWindow; - } - - void scrollTo(const rect_t & rect); - - void scrollTo(Window * child); - - static void clearFocus(); - - virtual void setFocus(uint8_t flag = SET_FOCUS_DEFAULT, Window * from = nullptr); - - void setRect(rect_t value) - { - rect = value; - invalidate(); - } - - void setWidth(coord_t value) - { - rect.w = value; - invalidate(); - } - - void setWindowCentered() - { - rect.x = (parent->width() - width()) / 2; - rect.y = (parent->height() - height()) / 2; - } - - void setHeight(coord_t value) - { - rect.h = value; - if (windowFlags & FORWARD_SCROLL) - innerHeight = value; - else if (innerHeight <= value) { - setScrollPositionY(0); - } - invalidate(); - } - - void setLeft(coord_t x) - { - rect.x = x; - invalidate(); - } - - void setTop(coord_t y) - { - rect.y = y; - invalidate(); - } - - coord_t left() const - { - return rect.x; - } - - coord_t right() const - { - return rect.x + rect.w; - } - - coord_t top() const - { - return rect.y; - } - - coord_t bottom() const - { - return rect.y + rect.h; - } - - coord_t width() const - { - return rect.w; - } - - coord_t height() const - { - return rect.h; - } - - rect_t getRect() const - { - 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) { - setScrollPositionY(0); - } - else { - coord_t maxScrollPosition = h - height(); - if (scrollPositionY > maxScrollPosition) { - setScrollPositionY(maxScrollPosition); - } - } - invalidate(); - } - - coord_t getScrollPositionX() const - { - return scrollPositionX; - } - - 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 isChildFullSize(const Window * window) const; - - bool isVisible() const - { - 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); - - void adjustInnerHeight(); - - coord_t adjustHeight(); - - void moveWindowsTop(coord_t y, coord_t delta); - - void invalidate() - { - invalidate({0, 0, rect.w, rect.h}); - } - - void bringToTop() - { - attach(parent); // does a detach + attach - } - - virtual void checkEvents(); - - void attach(Window * window); - - void detach(); - - bool deleted() const - { - return _deleted; - } - - protected: - Window * parent; - std::list children; - rect_t rect; - coord_t innerWidth; - coord_t innerHeight; - coord_t pageWidth = 0; - coord_t pageHeight = 0; - coord_t scrollPositionX = 0; - coord_t scrollPositionY = 0; - WindowFlags windowFlags; - LcdFlags textFlags; - bool _deleted = false; - - static Window * focusWindow; - static Window * slidingWindow; - static Window * touchedWindow; - static std::list trash; - - std::function closeHandler; - std::function focusHandler; - - void addChild(Window * window, bool front = false) - { - if (front) - children.push_front(window); - else - children.push_back(window); - } - - void removeChild(Window * window) - { - children.remove(window); - invalidate(); - } - - virtual void invalidate(const rect_t & rect); - - void paintChildren(BitmapBuffer * dc, std::list::iterator it); - - void fullPaint(BitmapBuffer * dc); - - virtual void paint(BitmapBuffer *) - { - } - - virtual void onFocusLost() - { - TRACE_WINDOWS("%s onFocusLost()", getWindowDebugString().c_str()); - if (focusHandler) { - focusHandler(false); - } - invalidate(); - } - -#if defined(HARDWARE_TOUCH) - static coord_t getSnapStep(coord_t relativeScrollPosition, coord_t pageSize); - - virtual bool onTouchStart(coord_t x, coord_t y); - - virtual bool onTouchEnd(coord_t x, coord_t y); - - virtual bool onTouchSlide(coord_t x, coord_t y, coord_t startX, coord_t startY, coord_t slideX, coord_t slideY); -#endif - - bool forwardTouchEnd(coord_t x, coord_t y); - - bool hasOpaqueRect(const rect_t & testRect) const; -}; -