From 2a0b3b30b63860e3c062397cf5a91e05f5e9b376 Mon Sep 17 00:00:00 2001 From: Bertrand Songis Date: Mon, 6 Apr 2020 09:16:40 +0200 Subject: [PATCH] Generic carousel added --- .../thirdparty/libopenui/src/CMakeLists.txt | 1 + .../src/thirdparty/libopenui/src/carousel.cpp | 58 +++++++++ radio/src/thirdparty/libopenui/src/carousel.h | 118 ++++++++++++++++++ 3 files changed, 177 insertions(+) create mode 100644 radio/src/thirdparty/libopenui/src/carousel.cpp create mode 100644 radio/src/thirdparty/libopenui/src/carousel.h diff --git a/radio/src/thirdparty/libopenui/src/CMakeLists.txt b/radio/src/thirdparty/libopenui/src/CMakeLists.txt index 788521440..f6712eea4 100644 --- a/radio/src/thirdparty/libopenui/src/CMakeLists.txt +++ b/radio/src/thirdparty/libopenui/src/CMakeLists.txt @@ -19,6 +19,7 @@ set(LIBOPENUI_SRC button.cpp static.cpp checkbox.cpp + carousel.cpp slider.cpp mainwindow.cpp menu.cpp diff --git a/radio/src/thirdparty/libopenui/src/carousel.cpp b/radio/src/thirdparty/libopenui/src/carousel.cpp new file mode 100644 index 000000000..108cf166d --- /dev/null +++ b/radio/src/thirdparty/libopenui/src/carousel.cpp @@ -0,0 +1,58 @@ +/* + * 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 "carousel.h" + +void CarouselWindow::update() +{ + auto first = min(selection - 2, items.size() - 5); + first = max(0, first); + coord_t lastPosition = 0; + + for (auto & item: items) { + item.front->detach(); + item.back->detach(); + } + + for (uint8_t index = first; lastPosition < width() && index < items.size(); index++) { + auto & item = items[index]; + auto window = (index == selection ? item.front : item.back); + window->attach(this); + window->setLeft(lastPosition); + window->setTop((height() - window->height()) / 2); + lastPosition += window->width() + CAROUSEL_SPACING; + } +} + +void Carousel::onEvent(event_t event) +{ + TRACE_WINDOWS("%s received event 0x%X", getWindowDebugString().c_str(), event); + + if (event == EVT_ROTARY_RIGHT) { + if (body->selection < body->items.size() - 1) + select(body->selection + 1); + } + else if (event == EVT_ROTARY_LEFT) { + if (body->selection > 0) + select(body->selection - 1); + } + else { + Window::onEvent(event); + } +} diff --git a/radio/src/thirdparty/libopenui/src/carousel.h b/radio/src/thirdparty/libopenui/src/carousel.h new file mode 100644 index 000000000..f81893430 --- /dev/null +++ b/radio/src/thirdparty/libopenui/src/carousel.h @@ -0,0 +1,118 @@ +/* + * 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. + */ + +#ifndef _CAROUSEL_H_ +#define _CAROUSEL_H_ + +#include +#include "button.h" + +constexpr coord_t CAROUSEL_SPACING = 20; + +class CarouselItem { + public: + CarouselItem(Window * front, Window * back): + front(front), + back(back) + { + } + + public: + Window * front; + Window * back; +}; + +class CarouselWindow: public Window { + friend class Carousel; + + public: + CarouselWindow(Window * parent, const rect_t & rect): + Window(parent, rect, NO_SCROLLBAR) + { + } + + void addItem(CarouselItem item) + { + items.emplace_back(item); + update(); + } + + void clear() + { + items.clear(); + Window::clear(); + } + + void select(int index, bool scroll = true) + { + selection = index; + update(); + } + + int selection = 0; + + protected: + std::vector items; + + void update(); +}; + +class Carousel: public Window { + public: + Carousel(Window * parent, const rect_t & rect): + Window(parent, rect, NO_SCROLLBAR) + { + } + +#if defined(DEBUG_WINDOWS) + std::string getName() override + { + return "Carousel"; + } +#endif + + void addItem(CarouselItem item) + { + body->addItem(std::move(item)); + } + + void clear() + { + body->clear(); + } + + void select(int index) + { + body->select(index); + previousButton->enable(index > 0); + nextButton->enable(index < (int)body->items.size() - 1); + } + + +#if defined(HARDWARE_KEYS) + void onEvent(event_t event) override; +#endif + + protected: + Button * previousButton = nullptr; + Button * nextButton = nullptr; + CarouselWindow * body = nullptr; +}; + +#endif // _CAROUSEL_H_