mirror of
https://github.com/mudita/MuditaOS.git
synced 2026-07-29 01:08:43 -04:00
[EGD-2335] Added grid layout (for character selector)
This commit is contained in:
@@ -7,6 +7,7 @@
|
||||
#include <Style.hpp>
|
||||
#include <functional>
|
||||
#include <memory>
|
||||
#include <GridLayout.hpp>
|
||||
|
||||
namespace gui
|
||||
{
|
||||
@@ -30,8 +31,29 @@ UiTestWindow::UiTestWindow(app::Application *app) : AppWindow(app, "TEST_UI")
|
||||
application->refreshWindow(gui::RefreshModes::GUI_REFRESH_FAST);
|
||||
bottomBar->getText(BottomBar::Side::CENTER);
|
||||
}));
|
||||
text->setVisible(false);
|
||||
auto box = new GridLayout(0, title->offset_h(), style::window_width, bottomBar->offset_h() - title->offset_h(), {90,90} );
|
||||
for(auto schar : gui::special_chars) {
|
||||
auto el = new gui::Label(box, 0, 0, 80, 80);
|
||||
style::window::decorate(el);
|
||||
el->setAlignement( gui::Alignment(gui::Alignment::ALIGN_HORIZONTAL_CENTER, gui::Alignment::ALIGN_VERTICAL_CENTER));
|
||||
el->setText(std::string(1,schar));
|
||||
el->setFont(style::window::font::medium);
|
||||
el->activatedCallback = [=](Item& it) {
|
||||
LOG_INFO("handled %s", el->getText().c_str()); return true;
|
||||
};
|
||||
// on click -> send onInput event with mapped & special keypress (...)
|
||||
// better - read special_keys_keymap and handle accordingly ... to be done
|
||||
}
|
||||
box->setVisible(true);
|
||||
box->setNavigation(nullptr,nullptr);
|
||||
/// TODO do not resize on each addWidget .. just once :(
|
||||
/// TODO shouldn't be needed here
|
||||
/// TODO add widget -> put widget in it's position
|
||||
box->resizeItems();
|
||||
addWidget(box);
|
||||
// TODO TODO attach(cb - show special characters, && input somehow)
|
||||
setFocusItem(text);
|
||||
setFocusItem(box->getNavigationItem());
|
||||
}
|
||||
|
||||
void UiTestWindow::rebuild() { LOG_INFO("Only if I have to!"); }
|
||||
|
||||
@@ -16,9 +16,6 @@ BoxLayout::BoxLayout( Item* parent, const uint32_t& x, const uint32_t& y, const
|
||||
Rect ( parent, x, y, w, h ){
|
||||
}
|
||||
|
||||
BoxLayout::~BoxLayout() {
|
||||
}
|
||||
|
||||
void BoxLayout::resizeItems() {
|
||||
}
|
||||
|
||||
|
||||
@@ -28,7 +28,7 @@ protected:
|
||||
public:
|
||||
BoxLayout();
|
||||
BoxLayout( Item* parent, const uint32_t& x, const uint32_t& y, const uint32_t& w, const uint32_t& h);
|
||||
~BoxLayout();
|
||||
virtual ~BoxLayout() = default;
|
||||
|
||||
//virtual methods from Item
|
||||
void setPosition( const short& x, const short& y ) override;
|
||||
@@ -44,7 +44,7 @@ protected:
|
||||
public:
|
||||
HBox();
|
||||
HBox( Item* parent, const uint32_t& x, const uint32_t& y, const uint32_t& w, const uint32_t& h);
|
||||
~HBox() {};
|
||||
virtual ~HBox() = default;
|
||||
};
|
||||
|
||||
class VBox : public BoxLayout {
|
||||
@@ -52,7 +52,7 @@ public:
|
||||
void resizeItems() override;
|
||||
VBox();
|
||||
VBox( Item* parent, const uint32_t& x, const uint32_t& y, const uint32_t& w, const uint32_t& h);
|
||||
~VBox() {};
|
||||
virtual ~VBox() = default;
|
||||
};
|
||||
|
||||
} /* namespace gui */
|
||||
|
||||
@@ -20,6 +20,7 @@ target_sources( ${PROJECT_NAME}
|
||||
"${CMAKE_CURRENT_LIST_DIR}/Text.cpp"
|
||||
"${CMAKE_CURRENT_LIST_DIR}/Style.cpp"
|
||||
"${CMAKE_CURRENT_LIST_DIR}/InputMode.cpp"
|
||||
"${CMAKE_CURRENT_LIST_DIR}/GridLayout.cpp"
|
||||
PUBLIC
|
||||
"${CMAKE_CURRENT_LIST_DIR}/Alignment.hpp"
|
||||
"${CMAKE_CURRENT_LIST_DIR}/BottomBar.hpp"
|
||||
|
||||
110
module-gui/gui/widgets/GridLayout.cpp
Normal file
110
module-gui/gui/widgets/GridLayout.cpp
Normal file
@@ -0,0 +1,110 @@
|
||||
#include "GridLayout.hpp"
|
||||
#include <log/log.hpp>
|
||||
#include "Style.hpp"
|
||||
|
||||
using namespace gui;
|
||||
|
||||
GridLayout::GridLayout(Item *parent, const uint32_t &x, const uint32_t &y, const uint32_t &w, const uint32_t &h, GridSize grid)
|
||||
: BoxLayout(parent, x, y, w, h), grid(grid)
|
||||
{
|
||||
setPenWidth(style::window::default_border_no_focus_w);
|
||||
setPenFocusWidth(style::window::default_border_focucs_w);
|
||||
}
|
||||
|
||||
void GridLayout::resizeItems()
|
||||
{
|
||||
|
||||
if( grid.x == 0 || grid.y == 0 ) {
|
||||
LOG_ERROR("Grid == 0 - abort");
|
||||
return;
|
||||
}
|
||||
uint32_t el_in_x = widgetArea.w / grid.x;
|
||||
uint32_t el_in_y = widgetArea.h / grid.y;
|
||||
uint32_t strech_x = 0;
|
||||
uint32_t strech_y = 0;
|
||||
uint32_t max_elements = el_in_x * el_in_y;
|
||||
|
||||
if (children.size() > max_elements)
|
||||
{
|
||||
LOG_ERROR("More children than possible to show");
|
||||
}
|
||||
if (strech) {
|
||||
strech_x = (widgetArea.w - grid.x*el_in_x )/el_in_x;
|
||||
strech_y = (widgetArea.h - grid.y*el_in_y )/el_in_y;
|
||||
}
|
||||
|
||||
int i = 0;
|
||||
int row = 0;
|
||||
int col = 0;
|
||||
for (auto it = children.begin(); it != children.end() && i <= max_elements; ++it, ++i)
|
||||
{
|
||||
// check if element will fit in
|
||||
if ((*it)->widgetArea.w > grid.x || (*it)->widgetArea.h > grid.y)
|
||||
{
|
||||
LOG_ERROR("Element %d too big", i);
|
||||
}
|
||||
// set position
|
||||
(*it)->setPosition(col * grid.x + strech_x, row * grid.y + strech_y);
|
||||
// shift row/col
|
||||
++col;
|
||||
if (col == el_in_y)
|
||||
{
|
||||
col = 0;
|
||||
++row;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// TODO commomize - move loop to lambda
|
||||
void GridLayout::setNavigation(Item *previous, Item *next)
|
||||
{
|
||||
uint32_t el_in_x = widgetArea.w / grid.x;
|
||||
uint32_t el_in_y = widgetArea.h / grid.y;
|
||||
uint32_t max_elements = el_in_x * el_in_y;
|
||||
int i = 0;
|
||||
int row = 0;
|
||||
int col = 0;
|
||||
if (children.size() == 0)
|
||||
{
|
||||
LOG_ERROR("No children to set navigation");
|
||||
}
|
||||
for (auto it = children.begin(); it != children.end() && i < max_elements; ++it, ++i)
|
||||
{
|
||||
if (i != 0)
|
||||
{
|
||||
(*it)->setNavigationItem(NavigationDirection::LEFT, *std::prev(it));
|
||||
}
|
||||
if (col + 1 % el_in_x != 0 && i + 1 < children.size())
|
||||
{
|
||||
LOG_INFO("Set next navigation for item %d", i);
|
||||
(*it)->setNavigationItem(NavigationDirection::RIGHT, *std::next(it));
|
||||
}
|
||||
if (row != 0)
|
||||
{
|
||||
(*it)->setNavigationItem(NavigationDirection::UP, *std::prev(it, el_in_x));
|
||||
}
|
||||
if (row + 1 % el_in_y != 0 && i + el_in_x < children.size())
|
||||
{
|
||||
(*it)->setNavigationItem(NavigationDirection::DOWN, *std::next(it, el_in_x));
|
||||
}
|
||||
|
||||
++col;
|
||||
if (col == el_in_y)
|
||||
{
|
||||
col = 0;
|
||||
++row;
|
||||
}
|
||||
}
|
||||
// TODO
|
||||
// children.front()->setNavigationItem(NavigationDirection::UP | NavigationDirection::LEFT, previous);
|
||||
// auto last_element = (*std::next(children.begin(), max_elements < children.size() ? max_elements - 1 : children.size()));
|
||||
// last_element->setNavigationItem(NavigationDirection::DOWN | NavigationDirection::RIGHT, next);
|
||||
}
|
||||
|
||||
bool GridLayout::onFocus(bool state)
|
||||
{
|
||||
if(children.size()) {
|
||||
children.front()->setFocus(state);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
40
module-gui/gui/widgets/GridLayout.hpp
Normal file
40
module-gui/gui/widgets/GridLayout.hpp
Normal file
@@ -0,0 +1,40 @@
|
||||
#pragma once
|
||||
|
||||
#include "BoxLayout.hpp"
|
||||
|
||||
namespace gui
|
||||
{
|
||||
|
||||
class GridLayout : public BoxLayout
|
||||
{
|
||||
protected:
|
||||
|
||||
struct GridSize {
|
||||
uint32_t x = 0;
|
||||
uint32_t y = 0;
|
||||
} grid;
|
||||
|
||||
public:
|
||||
// one defined
|
||||
GridLayout(Item *parent, const uint32_t &x, const uint32_t &y, const uint32_t &w, const uint32_t &h, GridSize grid);
|
||||
// derived
|
||||
GridLayout(const uint32_t &x, const uint32_t &y, const uint32_t &w, const uint32_t &h, GridSize grid) : GridLayout(nullptr, x,y,w,h, grid) {}
|
||||
GridLayout() : GridLayout(0,0,0,0,{0,0}) {}
|
||||
virtual ~GridLayout() = default;
|
||||
// shall strech elements on resize?
|
||||
bool strech = true;
|
||||
virtual void resizeItems() override;
|
||||
|
||||
// virtual methods from Item - use from parent
|
||||
// void setPosition(const short &x, const short &y) override;
|
||||
// void setSize(const short &w, const short &h) override;
|
||||
// bool addWidget(gui::Item *item) override;
|
||||
// bool removeWidget(Item *item) override;
|
||||
// std::list<DrawCommand *> buildDrawList() override;
|
||||
/// set internal navigation and previous/next item to show when reached the end
|
||||
void setNavigation(Item* previous, Item* next);
|
||||
Item* getNavigationItem() { return children.size()?*children.begin():nullptr; }
|
||||
virtual bool onFocus(bool state) override;
|
||||
};
|
||||
|
||||
}; // namespace gui
|
||||
@@ -4,6 +4,12 @@
|
||||
#include <list>
|
||||
#include <utf8/UTF8.hpp>
|
||||
|
||||
// TODO read from keymap file ...
|
||||
namespace gui
|
||||
{
|
||||
inline const std::vector<char> special_chars = {'.', ',', '_', ':', ';', ')', '(', '?', '!', '/', '*', '+'};
|
||||
}
|
||||
|
||||
/// this widget has one goal - nicelly change input parsing which is done in application in it's widgets
|
||||
class InputMode
|
||||
{
|
||||
|
||||
@@ -23,25 +23,22 @@ Rect::Rect() :
|
||||
corners{RectangleCornerFlags::GUI_RECT_ALL_CORNERS} {
|
||||
}
|
||||
|
||||
Rect::Rect( Item* parent, const uint32_t& x, const uint32_t& y, const uint32_t& w, const uint32_t& h) :
|
||||
borderColor(Color(0,0)),
|
||||
fillColor(Color(15,15)),
|
||||
penWidth{1},
|
||||
penFocusWidth{1},
|
||||
filled{false},
|
||||
edges{RectangleEdgeFlags::GUI_RECT_ALL_EDGES},
|
||||
flatEdges{ RectangleFlatFlags::GUI_RECT_FLAT_NO_FLAT},
|
||||
corners{RectangleCornerFlags::GUI_RECT_ALL_CORNERS} {
|
||||
Rect::Rect(Item *parent, const uint32_t &x, const uint32_t &y, const uint32_t &w, const uint32_t &h)
|
||||
: borderColor(Color(0, 0)), fillColor(Color(15, 15)), penWidth{1}, penFocusWidth{1}, filled{false}, edges{RectangleEdgeFlags::GUI_RECT_ALL_EDGES},
|
||||
flatEdges{RectangleFlatFlags::GUI_RECT_FLAT_NO_FLAT}, corners{RectangleCornerFlags::GUI_RECT_ALL_CORNERS}
|
||||
{
|
||||
|
||||
widgetArea.x = 0;
|
||||
widgetArea.y = 0;
|
||||
widgetArea.w = 0;
|
||||
widgetArea.h = 0;
|
||||
this->parent = parent;
|
||||
parent->addWidget(this);
|
||||
|
||||
setPosition(x, y);
|
||||
setSize(w, h);
|
||||
widgetArea.x = 0;
|
||||
widgetArea.y = 0;
|
||||
widgetArea.w = 0;
|
||||
widgetArea.h = 0;
|
||||
this->parent = parent;
|
||||
if (parent)
|
||||
{
|
||||
parent->addWidget(this);
|
||||
}
|
||||
setPosition(x, y);
|
||||
setSize(w, h);
|
||||
}
|
||||
|
||||
Rect::~Rect() {
|
||||
|
||||
Reference in New Issue
Block a user