menu tabs header now uses lvgl buttons and supports scrolling. buttons are slightly wider now
This commit is contained in:
committed by
Raphael Coeffic
parent
f79c313d85
commit
c29ec6edfe
@@ -33,6 +33,29 @@
|
||||
|
||||
#include <algorithm>
|
||||
|
||||
TabCarouselButton::TabCarouselButton(Window* parent, const rect_t& rect, std::vector<PageTab *>& tabs, uint8_t index,
|
||||
std::function<uint8_t(void)> pressHandler,
|
||||
WindowFlags flags) :
|
||||
Button(parent, rect, std::move(pressHandler), flags), tabs(tabs), index(index)
|
||||
{
|
||||
}
|
||||
|
||||
void TabCarouselButton::paint(BitmapBuffer * dc)
|
||||
{
|
||||
if(checked()) {
|
||||
OpenTxTheme::instance()->drawCurrentMenuBackground(dc);
|
||||
}
|
||||
|
||||
dc->drawBitmap(2, 7, theme->getIcon(tabs[index]->getIcon(), checked() ? STATE_PRESSED : STATE_DEFAULT));
|
||||
}
|
||||
|
||||
void TabCarouselButton::check(bool checked)
|
||||
{
|
||||
Button::check(checked);
|
||||
if(checked) {
|
||||
lv_obj_move_foreground(lvobj);
|
||||
}
|
||||
}
|
||||
|
||||
TabsGroupHeader::TabsGroupHeader(TabsGroup* parent, uint8_t icon) :
|
||||
FormGroup(parent, {0, 0, LCD_W, MENU_BODY_TOP}, NO_FOCUS | OPAQUE),
|
||||
@@ -59,57 +82,54 @@ void TabsGroupHeader::paint(BitmapBuffer* dc)
|
||||
|
||||
TabsCarousel::TabsCarousel(Window* parent, TabsGroup* menu) :
|
||||
Window(parent,
|
||||
{MENU_HEADER_BUTTONS_LEFT, 0, LCD_W - MENU_HEADER_BUTTONS_LEFT,
|
||||
{MENU_HEADER_BUTTONS_LEFT, 0, DATETIME_SEPARATOR_X - MENU_HEADER_BUTTONS_LEFT,
|
||||
MENU_HEADER_HEIGHT + 10},
|
||||
NO_FOCUS | TRANSPARENT),
|
||||
NO_FOCUS | TRANSPARENT ),
|
||||
menu(menu)
|
||||
{
|
||||
}
|
||||
|
||||
void TabsCarousel::updateInnerWidth()
|
||||
void TabsCarousel::update()
|
||||
{
|
||||
while(buttons.size() < menu->tabs.size())
|
||||
{
|
||||
int index = buttons.size();
|
||||
rect_t btnCoords = {(int)(index * (MENU_HEADER_BUTTON_WIDTH + 2)), 0, (int)(MENU_HEADER_BUTTON_WIDTH + 3), int(MENU_TITLE_TOP + 5)};
|
||||
buttons.emplace_back(new TabCarouselButton(this, btnCoords, menu->tabs, index,
|
||||
[&, index](){
|
||||
menu->setCurrentTab(index);
|
||||
setCurrentIndex(index);
|
||||
|
||||
for(auto &b: buttons)
|
||||
b->check(false);
|
||||
|
||||
buttons[index]->check(true);
|
||||
return true;
|
||||
}
|
||||
, TRANSPARENT | NO_FOCUS));
|
||||
if(index == 0)
|
||||
buttons[index]->check(true);
|
||||
}
|
||||
while(buttons.size() > menu->tabs.size())
|
||||
{
|
||||
delete *buttons.end();
|
||||
buttons.pop_back();
|
||||
}
|
||||
}
|
||||
|
||||
void TabsCarousel::setCurrentIndex(uint8_t index)
|
||||
{
|
||||
if(buttons.size() <= index)
|
||||
return;
|
||||
buttons[currentIndex]->check(false);
|
||||
currentIndex = index;
|
||||
buttons[currentIndex]->check(true);
|
||||
}
|
||||
|
||||
void TabsCarousel::paint(BitmapBuffer * dc)
|
||||
{
|
||||
OpenTxTheme::instance()->drawPageHeader(dc, menu->tabs, currentIndex);
|
||||
}
|
||||
|
||||
#if defined(HARDWARE_TOUCH)
|
||||
bool TabsCarousel::onTouchStart(coord_t x, coord_t y)
|
||||
{
|
||||
if(sliding)
|
||||
sliding = false;
|
||||
|
||||
return Window::onTouchStart(x,y);
|
||||
}
|
||||
|
||||
bool TabsCarousel::onTouchEnd(coord_t x, coord_t y)
|
||||
{
|
||||
if(sliding)
|
||||
return true;
|
||||
|
||||
unsigned index = (x - padding_left) / MENU_HEADER_BUTTON_WIDTH;
|
||||
|
||||
if (index >= menu->tabs.size()) {
|
||||
return false;
|
||||
}
|
||||
|
||||
menu->setCurrentTab(index);
|
||||
setCurrentIndex(index);
|
||||
return true;
|
||||
}
|
||||
|
||||
bool TabsCarousel::onTouchSlide(coord_t x, coord_t y, coord_t startX, coord_t startY, coord_t slideX, coord_t slideY)
|
||||
{
|
||||
sliding = true;
|
||||
|
||||
Window::onTouchSlide(x,y,startX,startY,slideX,slideY);
|
||||
|
||||
return true;
|
||||
}
|
||||
#endif
|
||||
|
||||
TabsGroup::TabsGroup(uint8_t icon):
|
||||
Window(MainWindow::instance(), { 0, 0, LCD_W, LCD_H }, OPAQUE),
|
||||
header(this, icon),
|
||||
@@ -147,7 +167,7 @@ void TabsGroup::addTab(PageTab * page)
|
||||
if (!currentTab) {
|
||||
setCurrentTab(0);
|
||||
}
|
||||
header.carousel.updateInnerWidth();
|
||||
header.carousel.update();
|
||||
invalidate();
|
||||
}
|
||||
|
||||
@@ -169,7 +189,7 @@ void TabsGroup::removeTab(unsigned index)
|
||||
setCurrentTab(max<unsigned>(0, index - 1));
|
||||
}
|
||||
tabs.erase(tabs.begin() + index);
|
||||
header.carousel.updateInnerWidth();
|
||||
header.carousel.update();
|
||||
invalidate();
|
||||
}
|
||||
|
||||
@@ -180,7 +200,7 @@ void TabsGroup::removeAllTabs()
|
||||
}
|
||||
tabs.clear();
|
||||
currentTab = nullptr;
|
||||
header.carousel.updateInnerWidth();
|
||||
header.carousel.update();
|
||||
}
|
||||
|
||||
void TabsGroup::setVisibleTab(PageTab* tab)
|
||||
|
||||
@@ -76,6 +76,29 @@ class PageTab {
|
||||
std::function<void()> onSetVisible;
|
||||
};
|
||||
|
||||
class TabCarouselButton: public Button
|
||||
{
|
||||
public:
|
||||
TabCarouselButton(Window* parent, const rect_t& rect, std::vector<PageTab *>& tabs, uint8_t index,
|
||||
std::function<uint8_t(void)> pressHandler,
|
||||
WindowFlags flags = 0);
|
||||
|
||||
#if defined(DEBUG_WINDOWS)
|
||||
std::string getName() const override
|
||||
{
|
||||
return "TabCarouselButton(" + std::to_string(icon) + ")";
|
||||
}
|
||||
#endif
|
||||
|
||||
void paint(BitmapBuffer * dc);
|
||||
|
||||
void check(bool checked = true);
|
||||
|
||||
protected:
|
||||
std::vector<PageTab *> tabs;
|
||||
uint8_t index;
|
||||
};
|
||||
|
||||
class TabsCarousel: public Window {
|
||||
public:
|
||||
TabsCarousel(Window * parent, TabsGroup * menu);
|
||||
@@ -87,27 +110,19 @@ class TabsCarousel: public Window {
|
||||
}
|
||||
#endif
|
||||
|
||||
inline void setCurrentIndex(uint8_t index)
|
||||
{
|
||||
currentIndex = index;
|
||||
}
|
||||
void setCurrentIndex(uint8_t index);
|
||||
|
||||
inline uint8_t getCurrentIndex()
|
||||
{
|
||||
return currentIndex;
|
||||
}
|
||||
|
||||
void updateInnerWidth();
|
||||
void update();
|
||||
|
||||
void paint(BitmapBuffer * dc) override;
|
||||
|
||||
#if defined(HARDWARE_TOUCH)
|
||||
bool onTouchStart(coord_t x, coord_t y) override;
|
||||
bool onTouchEnd(coord_t x, coord_t y) override;
|
||||
bool onTouchSlide(coord_t x, coord_t y, coord_t startX, coord_t startY, coord_t slideX, coord_t slideY) override;
|
||||
#endif
|
||||
|
||||
protected:
|
||||
std::vector<TabCarouselButton*> buttons;
|
||||
constexpr static uint8_t padding_left = 3;
|
||||
TabsGroup * menu;
|
||||
uint8_t currentIndex = 0;
|
||||
|
||||
@@ -102,8 +102,7 @@ class OpenTxTheme: public Theme
|
||||
virtual void drawPageHeaderBackground(BitmapBuffer *dc, uint8_t icon,
|
||||
const char *title) const = 0;
|
||||
|
||||
virtual void drawPageHeader(BitmapBuffer *dc, std::vector<PageTab *> &tabs,
|
||||
uint8_t currentIndex) const = 0;
|
||||
virtual void drawCurrentMenuBackground(BitmapBuffer *dc) const = 0;
|
||||
|
||||
// virtual void drawMessageBox(const char * title, const char * text, const
|
||||
// char * action, uint32_t flags) const override;
|
||||
|
||||
@@ -365,19 +365,10 @@ class Theme480: public OpenTxTheme
|
||||
return state == STATE_DEFAULT ? menuIconNormal[index] : menuIconSelected[index];
|
||||
}
|
||||
|
||||
void drawPageHeader(BitmapBuffer *dc, std::vector<PageTab *> &tabs,
|
||||
uint8_t currentIndex) const override
|
||||
void drawCurrentMenuBackground(BitmapBuffer *dc) const override
|
||||
{
|
||||
for (unsigned index = 0; index < tabs.size(); index++) {
|
||||
if (index != currentIndex) {
|
||||
dc->drawBitmap(index * MENU_HEADER_BUTTON_WIDTH + 2, 7,
|
||||
menuIconNormal[tabs[index]->getIcon()]);
|
||||
}
|
||||
}
|
||||
dc->drawBitmap(currentIndex * MENU_HEADER_BUTTON_WIDTH, 0,
|
||||
dc->drawBitmap(0, 0,
|
||||
currentMenuBackground);
|
||||
dc->drawBitmap(currentIndex * MENU_HEADER_BUTTON_WIDTH + 2, 7,
|
||||
menuIconSelected[tabs[currentIndex]->getIcon()]);
|
||||
}
|
||||
|
||||
void drawMenuDatetime(BitmapBuffer * dc) const
|
||||
|
||||
@@ -366,25 +366,18 @@ class FlyskyTheme: public OpenTxTheme
|
||||
return state == STATE_DEFAULT ? menuIconNormal[index] : menuIconSelected[index];
|
||||
}
|
||||
|
||||
void drawPageHeader(BitmapBuffer *dc, std::vector<PageTab *> &tabs,
|
||||
uint8_t currentIndex) const override
|
||||
void drawCurrentMenuBackground(BitmapBuffer *dc) const override
|
||||
{
|
||||
uint8_t padding_left = 4;
|
||||
|
||||
dc->drawSolidFilledRect(0, 0, 4, MENU_HEADER_BUTTON_WIDTH,
|
||||
COLOR_THEME_FOCUS);
|
||||
for (unsigned i = 0; i < tabs.size(); i++) {
|
||||
dc->drawBitmap(
|
||||
padding_left + i * MENU_HEADER_BUTTON_WIDTH, 0,
|
||||
theme->getIcon(tabs[i]->getIcon(),
|
||||
currentIndex == i ? STATE_PRESSED : STATE_DEFAULT));
|
||||
}
|
||||
// coord_t x = padding_left + MENU_HEADER_BUTTON_WIDTH * tabs.size();
|
||||
// coord_t w = width() - x;
|
||||
// if (w > 0) {
|
||||
// dc->drawSolidFilledRect(x, 0, w, MENU_HEADER_BUTTON_WIDTH,
|
||||
// COLOR_THEME_FOCUS);
|
||||
// }
|
||||
// uint8_t padding_left = 4;
|
||||
//
|
||||
// dc->drawSolidFilledRect(0, 0, 4, MENU_HEADER_BUTTON_WIDTH,
|
||||
// COLOR_THEME_FOCUS);
|
||||
// for (unsigned i = 0; i < tabs.size(); i++) {
|
||||
// dc->drawBitmap(
|
||||
// padding_left + i * MENU_HEADER_BUTTON_WIDTH, 0,
|
||||
// theme->getIcon(tabs[i]->getIcon(),
|
||||
// currentIndex == i ? STATE_PRESSED : STATE_DEFAULT));
|
||||
// }
|
||||
}
|
||||
|
||||
void drawMenuDatetime(BitmapBuffer * dc) const
|
||||
|
||||
Reference in New Issue
Block a user