/* * Item.cpp * * Created on: 4 mar 2019 * Author: robert */ #include #include #include #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 Item::buildDrawList() { std::list commands; for( auto& widget : children ) { std::list 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 */