mirror of
https://github.com/mudita/MuditaOS.git
synced 2026-07-04 13:17:08 -04:00
* elements which possibly depended on this depend now on `visibility` of element added * changed everywhere returns on addWidget * checked layouts (vertical, horizontal, pagedbox, gridlayout)
220 lines
5.0 KiB
C++
220 lines
5.0 KiB
C++
/*
|
|
* Item.cpp
|
|
*
|
|
* Created on: 4 mar 2019
|
|
* Author: robert
|
|
*/
|
|
|
|
#include <list>
|
|
#include <algorithm>
|
|
#include <cstring>
|
|
#include "Navigation.hpp"
|
|
#include "Item.hpp"
|
|
#include "BoundingBox.hpp"
|
|
|
|
namespace gui {
|
|
|
|
Item::Item() :
|
|
focus {false},
|
|
type {ItemType::ITEM},
|
|
parent{nullptr},
|
|
radius{0},
|
|
visible{true},
|
|
verticalPolicy{ LayoutVerticalPolicy::LAYOUT_POLICY_VERTICAL_EXPAND },
|
|
horizontalPolicy { LayoutHorizontalPolicy::LAYOUT_POLICY_HORIZONTAL_EXPAND },
|
|
navigationDirections{ nullptr } {
|
|
|
|
focusChangedCallback = [](Item&){ return false;};
|
|
activatedCallback = [](Item&){ return false;};
|
|
inputCallback = [](Item&, const InputEvent& inputEvent){ return false;};
|
|
dimensionChangedCallback = [](Item&, void* data){ return false;};
|
|
contentCallback = [=](Item&){ if( parent != nullptr ) return parent->onContent(); return false;};
|
|
}
|
|
|
|
Item::~Item() {
|
|
for( auto& widget : children )
|
|
delete widget;
|
|
|
|
if( navigationDirections )
|
|
delete navigationDirections;
|
|
}
|
|
|
|
void Item::addWidget(Item *item)
|
|
{
|
|
if (item == nullptr)
|
|
return;
|
|
if (item->parent)
|
|
{
|
|
item->parent->removeWidget(item);
|
|
}
|
|
item->parent = this;
|
|
children.push_back(item);
|
|
|
|
item->updateDrawArea();
|
|
}
|
|
|
|
bool Item::removeWidget( Item* item ) {
|
|
if(item == nullptr) return false;
|
|
if (item == focusItem)
|
|
{
|
|
focusItem = nullptr;
|
|
}
|
|
|
|
auto fi = std::find( children.begin(), children.end(), item );
|
|
if( fi != children.end() ) {
|
|
children.erase(fi);
|
|
return true;
|
|
}
|
|
return false;
|
|
}
|
|
|
|
void Item::setVisible( bool value ) {
|
|
visible = value;
|
|
}
|
|
|
|
std::list<DrawCommand*> Item::buildDrawList() {
|
|
|
|
std::list<DrawCommand*> commands;
|
|
|
|
for( auto& widget : children ) {
|
|
std::list<DrawCommand*> widgetCommands = widget->buildDrawList();
|
|
if( !widgetCommands.empty() )
|
|
commands.insert( commands.end(), widgetCommands.begin(), widgetCommands.end() );
|
|
}
|
|
|
|
return commands;
|
|
}
|
|
|
|
void Item::setPosition( const short& x, const short& y ) {
|
|
|
|
BoundingBox oldArea = widgetArea;
|
|
widgetArea.x = x;
|
|
widgetArea.y = y;
|
|
updateDrawArea();
|
|
|
|
onDimensionChanged(oldArea, widgetArea);
|
|
}
|
|
|
|
void Item::setX(const uint32_t x)
|
|
{
|
|
BoundingBox oldArea = widgetArea;
|
|
widgetArea.x = x;
|
|
updateDrawArea();
|
|
|
|
onDimensionChanged(oldArea, widgetArea);
|
|
}
|
|
|
|
void Item::setY(const uint32_t y)
|
|
{
|
|
BoundingBox oldArea = widgetArea;
|
|
widgetArea.y = y;
|
|
updateDrawArea();
|
|
|
|
onDimensionChanged(oldArea, widgetArea);
|
|
}
|
|
|
|
void Item::setSize(const unsigned short w, const unsigned short h)
|
|
{
|
|
BoundingBox oldArea = widgetArea;
|
|
widgetArea.w = w;
|
|
widgetArea.h = h;
|
|
widgetMaxArea.sum(widgetArea);
|
|
updateDrawArea();
|
|
|
|
onDimensionChanged(oldArea, widgetArea);
|
|
}
|
|
|
|
void Item::setBoundingBox(const BoundingBox &new_box)
|
|
{
|
|
BoundingBox oldArea = widgetArea;
|
|
widgetArea = new_box;
|
|
updateDrawArea();
|
|
onDimensionChanged(oldArea, widgetArea);
|
|
}
|
|
|
|
void Item::setRadius( int value ) {
|
|
if( value < 0 )
|
|
value = 0;
|
|
radius = value;
|
|
}
|
|
|
|
void Item::updateDrawArea() {
|
|
Item* parentItem = parent;
|
|
|
|
BoundingBox result = widgetArea;
|
|
|
|
//iterate up to top widget in hierarchy
|
|
while( parentItem != nullptr ) {
|
|
|
|
result.x += parentItem->widgetArea.x;
|
|
result.y += parentItem->widgetArea.y;
|
|
BoundingBox newResult;
|
|
if( BoundingBox::intersect(parentItem->widgetArea, result, newResult) == false ) {
|
|
result.clear();
|
|
break;
|
|
}
|
|
result = newResult;
|
|
|
|
parentItem = parentItem->parent;
|
|
}
|
|
|
|
drawArea = result;
|
|
|
|
for( gui::Item* it : children )
|
|
it->updateDrawArea();
|
|
}
|
|
|
|
Item* Item::getNavigationItem( NavigationDirection direction ) {
|
|
if( navigationDirections != nullptr ) {
|
|
return navigationDirections->getDirectionItem(direction);
|
|
}
|
|
return nullptr;
|
|
}
|
|
|
|
void Item::setNavigationItem( gui::NavigationDirection direction, Item* item ) {
|
|
if( navigationDirections == nullptr )
|
|
navigationDirections = new Navigation();
|
|
navigationDirections->setDirectionItem(direction, item);
|
|
}
|
|
|
|
bool Item::handleNavigation(const InputEvent inputEvent)
|
|
{
|
|
gui::Item *newFocusItem = nullptr;
|
|
if ((focusItem != nullptr) && (inputEvent.state == InputEvent::State::keyReleasedShort))
|
|
{
|
|
if (itemNavigation && itemNavigation(inputEvent))
|
|
{
|
|
return true;
|
|
}
|
|
switch (inputEvent.keyCode)
|
|
{
|
|
case gui::KeyCode::KEY_LEFT:
|
|
newFocusItem = focusItem->getNavigationItem(gui::NavigationDirection::LEFT);
|
|
break;
|
|
case gui::KeyCode::KEY_RIGHT:
|
|
newFocusItem = focusItem->getNavigationItem(gui::NavigationDirection::RIGHT);
|
|
break;
|
|
case gui::KeyCode::KEY_UP:
|
|
newFocusItem = focusItem->getNavigationItem(gui::NavigationDirection::UP);
|
|
break;
|
|
case gui::KeyCode::KEY_DOWN:
|
|
newFocusItem = focusItem->getNavigationItem(gui::NavigationDirection::DOWN);
|
|
break;
|
|
case gui::KeyCode::KEY_ENTER:
|
|
if (focusItem != nullptr)
|
|
return focusItem->onActivated(nullptr);
|
|
break;
|
|
default:
|
|
break;
|
|
}
|
|
}
|
|
if (newFocusItem != nullptr)
|
|
{
|
|
setFocusItem(newFocusItem);
|
|
return true;
|
|
}
|
|
return false;
|
|
}
|
|
|
|
} /* namespace gui */
|