user interface screen: use flex layout

This commit is contained in:
Raphael Coeffic
2022-06-11 15:38:08 +02:00
committed by Raphael Coeffic
parent 74e535df62
commit d9c66f16f3
8 changed files with 283 additions and 151 deletions
+2
View File
@@ -31,6 +31,7 @@ set(GUI_SRC
color_editor.cpp
color_list.cpp
preview_window.cpp
file_preview.cpp
file_carosell.cpp
listbox.cpp
tabsgroup.cpp
@@ -85,6 +86,7 @@ set(GUI_SRC
view_statistics.cpp
view_text.cpp
menu_screen.cpp
screen_user_interface.cpp
screen_setup.cpp
switch_warn_dialog.cpp
LvglWrapper.cpp
+74
View File
@@ -0,0 +1,74 @@
/*
* Copyright (C) EdgeTX
*
* Based on code named
* opentx - https://github.com/opentx/opentx
* th9x - http://code.google.com/p/th9x
* er9x - http://code.google.com/p/er9x
* gruvin9x - http://code.google.com/p/gruvin9x
*
* License GPLv2: http://www.gnu.org/licenses/gpl-2.0.html
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 as
* published by the Free Software Foundation.
*
* This program 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 General Public License for more details.
*/
#include "file_preview.h"
#include "sdcard.h"
FilePreview::FilePreview(Window *parent, const rect_t &rect,
bool drawCentered) :
Window(parent, rect, NO_SCROLLBAR), _drawCentered(drawCentered)
{
}
FilePreview::~FilePreview()
{
if (bitmap != nullptr) delete bitmap;
}
void FilePreview::setFile(const char *filename)
{
if (bitmap != nullptr) delete bitmap;
bitmap = nullptr;
const char *ext = getFileExtension(filename);
if (ext && isExtensionMatching(ext, BITMAPS_EXT)) {
bitmap = BitmapBuffer::loadBitmap(filename);
} else {
bitmap = nullptr;
}
invalidate();
}
coord_t FilePreview::getBitmapWidth() const
{
if (bitmap) return bitmap->width();
return 0;
}
coord_t FilePreview::getBitmapHeight() const
{
if (bitmap) return bitmap->height();
return 0;
}
void FilePreview::paint(BitmapBuffer *dc)
{
dc->setFormat(BMP_RGB565);
coord_t y = _drawCentered ? parent->getScrollPositionY() + 2 : 2;
coord_t h = _drawCentered ? MENU_BODY_HEIGHT - 4 : rect.h;
if (bitmap != nullptr) {
coord_t bitmapHeight = min<coord_t>(h, bitmap->height());
coord_t bitmapWidth = min<coord_t>(width(), bitmap->width());
dc->drawScaledBitmap(bitmap, (width() - bitmapWidth) / 2,
_drawCentered ? y + (h - bitmapHeight) / 2 : 0,
bitmapWidth, bitmapHeight);
}
}
+11 -46
View File
@@ -24,56 +24,21 @@
class FilePreview : public Window
{
public:
FilePreview(Window *parent, const rect_t &rect, bool drawCentered = true) :
Window(parent, rect, NO_SCROLLBAR),
_drawCentered(drawCentered)
{
}
~FilePreview()
{
if (bitmap != nullptr)
delete bitmap;
}
public:
FilePreview(Window *parent, const rect_t &rect, bool drawCentered = true);
~FilePreview();
#if defined(DEBUG_WINDOWS)
std::string getName() const override
{
return "FilePreview";
}
std::string getName() const override { return "FilePreview"; }
#endif
void setFile(const char *filename)
{
if (bitmap != nullptr)
delete bitmap;
bitmap = nullptr;
void setFile(const char *filename);
coord_t getBitmapWidth() const;
coord_t getBitmapHeight() const;
const char *ext = getFileExtension(filename);
if (ext && isExtensionMatching(ext, BITMAPS_EXT)) {
bitmap = BitmapBuffer::loadBitmap(filename);
} else {
bitmap = nullptr;
}
invalidate();
}
void paint(BitmapBuffer *dc) override;
void paint(BitmapBuffer *dc) override
{
dc->setFormat(BMP_RGB565);
coord_t y = _drawCentered ? parent->getScrollPositionY() + 2 : 2;
coord_t h = _drawCentered ? MENU_BODY_HEIGHT - 4 : rect.h;
if (bitmap != nullptr) {
coord_t bitmapHeight = min<coord_t>(h, bitmap->height());
coord_t bitmapWidth = min<coord_t>(width(), bitmap->width());
dc->drawScaledBitmap(bitmap, (width() - bitmapWidth) / 2,
_drawCentered ? y + (h - bitmapHeight) / 2 : 0,
bitmapWidth, bitmapHeight);
}
}
protected:
BitmapBuffer *bitmap = nullptr;
bool _drawCentered = true;
protected:
BitmapBuffer *bitmap = nullptr;
bool _drawCentered = true;
};
-94
View File
@@ -26,8 +26,6 @@
#include "topbar.h"
#include "libopenui.h"
#include "layouts/layout_factory_impl.h"
#include "theme_manager.h"
#include "file_preview.h"
#define SET_DIRTY() storageDirty(EE_MODEL)
#define BUTTON_HEIGHT 30
@@ -254,98 +252,6 @@ class SetupWidgetsPage: public FormWindow
// }
};
ScreenUserInterfacePage::ScreenUserInterfacePage(ScreenMenu* menu):
PageTab(STR_USER_INTERFACE, ICON_THEME_SETUP),
menu(menu)
{
}
class MyFormGridLayout : public FormGridLayout
{
public:
MyFormGridLayout(int width, int top) :
FormGridLayout(width, top)
{
}
rect_t getFieldSlotEx(uint8_t count = 1, uint8_t index = 0, uint8_t number = 1) const
{
coord_t width = (this->width - labelWidth - lineMarginRight - (count - 1) * PAGE_LINE_SPACING) / count;
coord_t left = labelWidth + (width + PAGE_LINE_SPACING) * index;
return {left, currentY, width *number, PAGE_LINE_HEIGHT};
}
};
void ScreenUserInterfacePage::build(FormWindow * window)
{
MyFormGridLayout grid(LCD_W, 10);
// Top Bar
new StaticText(window, grid.getLabelSlot(), STR_TOP_BAR, 0, COLOR_THEME_PRIMARY1);
auto menu = this->menu;
auto setupTopbarWidgets = new TextButton(window, grid.getFieldSlot(), STR_SETUP_WIDGETS);
setupTopbarWidgets->setPressHandler([menu]() -> uint8_t {
new SetupTopBarWidgetsPage(menu);
return 0;
});
grid.nextLine();
grid.spacer(8);
// Theme choice
new StaticText(window, grid.getLabelSlot(), STR_THEME, 0, COLOR_THEME_PRIMARY1);
auto tp = ThemePersistance::instance();
tp->refresh();
std::vector<std::string> names = tp->getNames();
new Choice(window, grid.getFieldSlotEx(), names, 0, names.size() - 1,
[=] () {
return tp->getThemeIndex();
},
[=] (int value) {
tp->setThemeIndex(value);
tp->applyTheme(value);
tp->setDefaultTheme(value);
window->clear();
build(window);
});
bool bNarrowScreen = LCD_W < LCD_H;
if (bNarrowScreen)
grid.setLabelWidth(LCD_W);
grid.nextLine();
auto theme = tp->getCurrentTheme();
auto themeImage = theme->getThemeImageFileNames();
grid.spacer(8);
new StaticText(window, grid.getLabelSlot(), "Author", 0, COLOR_THEME_PRIMARY1 | FONT(BOLD));
grid.nextLine();
new StaticText(window, grid.getLabelSlot(), theme->getAuthor(), 0, COLOR_THEME_PRIMARY1);
grid.nextLine();
new StaticText(window, grid.getLabelSlot(), "Description", 0, COLOR_THEME_PRIMARY1 | FONT(BOLD));
grid.nextLine();
int charBreak = bNarrowScreen ? 40 : 30;
auto info = wrap(theme->getInfo(), charBreak);
rect_t r = grid.getLabelSlot();
r.h += 50;
new StaticText(window, r, info, 0, COLOR_THEME_PRIMARY1);
rect_t previewRect = bNarrowScreen ?
rect_t {0, r.h, LCD_W, window->height()} :
rect_t {LCD_W / 2 + 6, 30, LCD_W / 2 - 12, window->height()};
auto preview = new FilePreview(window, previewRect);
preview->setFile(themeImage.size() > 0 ? themeImage[0].c_str() : "");
window->setInnerHeight(grid.getWindowHeight());
}
ScreenAddPage::ScreenAddPage(ScreenMenu * menu, uint8_t pageIndex):
PageTab(),
menu(menu),
+2 -10
View File
@@ -20,19 +20,11 @@
*/
#include "menu_screen.h"
#include "screen_user_interface.h"
#include "layout.h"
#include "datastructs.h"
class ScreenUserInterfacePage: public PageTab {
public:
ScreenUserInterfacePage(ScreenMenu* menu);
void build(FormWindow * window) override;
protected:
ScreenMenu * menu;
};
class ScreenAddPage: public PageTab {
public:
ScreenAddPage(ScreenMenu * menu, uint8_t pageIndex);
@@ -0,0 +1,156 @@
/*
* Copyright (C) EdgeTX
*
* Based on code named
* opentx - https://github.com/opentx/opentx
* th9x - http://code.google.com/p/th9x
* er9x - http://code.google.com/p/er9x
* gruvin9x - http://code.google.com/p/gruvin9x
*
* License GPLv2: http://www.gnu.org/licenses/gpl-2.0.html
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 as
* published by the Free Software Foundation.
*
* This program 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 General Public License for more details.
*/
#include "screen_user_interface.h"
#include "theme_manager.h"
#include "file_preview.h"
struct ThemeDetails : public Window {
ThemeDetails(Window* parent, ThemeFile* theme) : Window(parent, rect_t{})
{
// vertical flow layout
lv_obj_set_flex_flow(lvobj, LV_FLEX_FLOW_COLUMN);
lv_obj_set_style_pad_row(lvobj, 2, LV_PART_MAIN);
// make the object fill the grid cell
lv_obj_set_style_grid_cell_x_align(lvobj, LV_GRID_ALIGN_STRETCH, 0);
// TODO: translation
new StaticText(this, rect_t{}, "Author", 0,
COLOR_THEME_PRIMARY1 | FONT(BOLD));
auto txt = new StaticText(this, rect_t{}, theme->getAuthor(), 0,
COLOR_THEME_PRIMARY1);
// labels default to LV_SIZE_CONTENT,
// which could overflow the width avail
auto obj = txt->getLvObj();
lv_obj_set_width(obj, lv_pct(100));
// TODO: translation
new StaticText(this, rect_t{}, "Description", 0,
COLOR_THEME_PRIMARY1 | FONT(BOLD));
txt = new StaticText(this, rect_t{}, theme->getInfo(), 0,
COLOR_THEME_PRIMARY1);
obj = txt->getLvObj();
lv_obj_set_width(obj, lv_pct(100));
}
};
#if LCD_W > LCD_H // landscape
// form grid
static const lv_coord_t line_col_dsc[] = {LV_GRID_FR(1), LV_GRID_FR(1),
LV_GRID_TEMPLATE_LAST};
static const lv_coord_t line_row_dsc[] = {LV_GRID_CONTENT,
LV_GRID_TEMPLATE_LAST};
// theme details grid
static const lv_coord_t* theme_col_dsc = line_col_dsc;
static const lv_coord_t* theme_row_dsc = line_row_dsc;
#else // portrait
// form grid
static const lv_coord_t line_col_dsc[] = {LV_GRID_FR(1), LV_GRID_FR(2),
LV_GRID_TEMPLATE_LAST};
static const lv_coord_t line_row_dsc[] = {LV_GRID_CONTENT,
LV_GRID_TEMPLATE_LAST};
// theme details grid
static const lv_coord_t theme_col_dsc[] = {LV_GRID_FR(1),
LV_GRID_TEMPLATE_LAST};
static const lv_coord_t theme_row_dsc[] = {LV_GRID_CONTENT, LV_GRID_CONTENT,
LV_GRID_TEMPLATE_LAST};
#endif
constexpr coord_t MAX_PREVIEW_WIDTH = (100 * LV_DPI_DEF) / 57;
constexpr coord_t MAX_PREVIEW_HEIGHT = LV_DPI_DEF;
ScreenUserInterfacePage::ScreenUserInterfacePage(ScreenMenu* menu):
PageTab(STR_USER_INTERFACE, ICON_THEME_SETUP),
menu(menu)
{
}
void ScreenUserInterfacePage::build(FormWindow* form)
{
FlexGridLayout grid(line_col_dsc, line_row_dsc);
form->setFlexLayout();
// Top Bar
auto line = form->newLine(&grid);
new StaticText(line, rect_t{}, STR_TOP_BAR, 0, COLOR_THEME_PRIMARY1);
auto menu = this->menu;
auto setupTopbarWidgets = new TextButton(line, rect_t{}, STR_SETUP_WIDGETS);
setupTopbarWidgets->setPressHandler([menu]() -> uint8_t {
new SetupTopBarWidgetsPage(menu);
return 0;
});
// Theme choice
line = form->newLine(&grid);
new StaticText(line, rect_t{}, STR_THEME, 0, COLOR_THEME_PRIMARY1);
auto tp = ThemePersistance::instance();
tp->refresh();
std::vector<std::string> names = tp->getNames();
new Choice(line, rect_t{}, names, 0, names.size() - 1,
[=] () {
return tp->getThemeIndex();
},
[=] (int value) {
tp->setThemeIndex(value);
tp->applyTheme(value);
tp->setDefaultTheme(value);
// TODO: shouldn't be necessary, would be better to send LV_EVENT_CHANGED
form->clear();
build(form);
});
auto theme = tp->getCurrentTheme();
FilePreview* preview = nullptr;
if (theme) {
FlexGridLayout theme_grid(theme_col_dsc, theme_row_dsc);
line = form->newLine(&theme_grid);
new ThemeDetails(line, theme);
auto themeImage = theme->getThemeImageFileNames();
if (themeImage.size() > 0) {
preview = new FilePreview(line, rect_t{}, false);
preview->setFile(themeImage[0].c_str());
// adjust width according to max
preview->setWidth(min(MAX_PREVIEW_WIDTH, preview->getBitmapWidth()));
preview->setHeight(min(MAX_PREVIEW_HEIGHT, preview->getBitmapHeight()));
// center within cell
auto obj = preview->getLvObj();
lv_obj_set_style_grid_cell_x_align(obj, LV_GRID_ALIGN_CENTER, 0);
}
}
form->updateSize();
}
@@ -0,0 +1,37 @@
/*
* Copyright (C) EdgeTX
*
* Based on code named
* opentx - https://github.com/opentx/opentx
* th9x - http://code.google.com/p/th9x
* er9x - http://code.google.com/p/er9x
* gruvin9x - http://code.google.com/p/gruvin9x
*
* License GPLv2: http://www.gnu.org/licenses/gpl-2.0.html
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 as
* published by the Free Software Foundation.
*
* This program 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 General Public License for more details.
*/
#pragma once
#include "tabsgroup.h"
class ScreenMenu;
class ScreenUserInterfacePage : public PageTab
{
public:
ScreenUserInterfacePage(ScreenMenu* menu);
void build(FormWindow* window) override;
protected:
ScreenMenu* menu;
};