user interface screen: use flex layout
This commit is contained in:
committed by
Raphael Coeffic
parent
74e535df62
commit
d9c66f16f3
@@ -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
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
}
|
||||
@@ -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;
|
||||
};
|
||||
|
||||
@@ -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),
|
||||
|
||||
@@ -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;
|
||||
};
|
||||
Vendored
+1
-1
Submodule radio/src/thirdparty/libopenui updated: f6a19ca00b...4491bb0755
Reference in New Issue
Block a user