[EGD-2335] Added grid layout (for character selector)

This commit is contained in:
Adam Dobrowolski
2019-11-29 11:47:28 +01:00
committed by pholat
parent 52f7fa60aa
commit ea61c1ec8a
8 changed files with 198 additions and 25 deletions

View File

@@ -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!"); }

View File

@@ -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() {
}

View File

@@ -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 */

View File

@@ -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"

View 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;
}

View 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

View File

@@ -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
{

View File

@@ -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() {