#include "cWindow.hpp" #include "../FXEngine/cGFX.hpp" #include "../UtilityEngine/cUtility.hpp" #include "cGUI.hpp" #include "cLabel.hpp" #include "cLayout.hpp" using GUIEngine::cWindow; /*static*/ const UtilityEngine::cString cWindow::sNAME = "windows"; /*static*/ GUIHelpers::Position cWindow::sPOSITION = { 0, 0 }; /*static*/ GUIHelpers::Size cWindow::sSIZE = { 0, 0 }; /*static*/ GUIHelpers::Padding cWindow::sPADDING = { 5, 5, 5, 5 }; /*static*/ GUIHelpers::RGBA cWindow::sCOLOUR = { 100, 100, 100, 255 }; /*static*/ GUIHelpers::eAlign cWindow::sALIGN = GUIHelpers::eAlign::CENTER; /*static*/ GUIHelpers::eLayout cWindow::sLAYOUT = GUIHelpers::eLayout::FILL_PARENT; /*static*/ GUIHelpers::eOrientation cWindow::sORIENTATION = GUIHelpers::eOrientation::NONE; cWindow::cWindow( cWindow* parent /*= nullptr*/, const signed int id /*= -1*/, const GUIHelpers::eOrientation& orientation /*= sORIENTATION*/, const GUIHelpers::eAlign& align /*= sALIGN*/, const GUIHelpers::eLayout& layout /*= sLAYOUT*/, const GUIHelpers::Position& pos /*= sPOSITION*/, const GUIHelpers::Size& size /*= sSIZE*/, const GUIHelpers::Padding& padding /*= sPADDING*/, const cString& name /*= sNAME*/ ) : cObject(id) { Create(parent, id, orientation, align, layout, pos, size, padding, name); } /*virtual*/ cWindow::~cWindow() { for (unsigned int i = 0; i < m_children.size(); ++i) { delete m_children[i]; m_children[i] = nullptr; } m_children.clear(); } /*virtual*/ void cWindow::Create( cWindow* parent /*= nullptr*/, const signed int id /*= -1*/, const GUIHelpers::eOrientation& orientation /*= sORIENTATION*/, const GUIHelpers::eAlign& align /*= sALIGN*/, const GUIHelpers::eLayout& layout /*= sLAYOUT*/, const GUIHelpers::Position& pos /*= sPOSITION*/, const GUIHelpers::Size& size /*= sSIZE*/, const GUIHelpers::Padding& padding /*= sPADDING*/, const cString& name /*= sNAME*/ ) { mp_parent = parent; cObject::setID(id); setOrientation(orientation); setAlign(align); setLayout(layout); setPosition(pos); setSize(size); setPadding(padding); m_name = name; } /*virtual*/ void cWindow::Display() { std::vector::iterator it; for (it = m_children.begin(); it < m_children.end(); it++) { (*it)->Display(); } DebugDisplay(); } /// Functions const bool cWindow::Inside( const MathEngine::iVector2& location ) const { bool rtn = false; if ((location.x >= m_pos.x) && (location.y >= m_pos.y)) { if ((location.x <= (m_pos.x + m_size.x)) && (location.y <= (m_pos.y + m_size.y))) rtn = true; } return rtn; } void cWindow::AddChild( cWindow* obj ) { m_children.push_back(obj); } const bool cWindow::RemoveChild( cWindow* obj ) { bool rtn = false; std::vector::iterator it; for (it = m_children.begin(); it < m_children.end(); it++) { if (obj == (*it)) { m_children.erase(it); rtn = true; //break out of the for loop break; } } return rtn; } /// Sets /*static*/ void cWindow::PositionDefault( const GUIHelpers::Position& pos ) { if (pos.x >= 0) sPOSITION = pos; } /*static*/ void cWindow::SizeDefault( const GUIHelpers::Size& size ) { if (size.x >= 0) sSIZE = size; } /*static*/ void cWindow::PaddingDefault( const GUIHelpers::Padding& pad ) { if (pad.x >= 0) sPADDING = pad; } /*static*/ void cWindow::AlignDefault( const GUIHelpers::eAlign& align ) { if (align != GUIHelpers::eAlign::DEFAULT_ALIGN) sALIGN = align; } /*static*/ void cWindow::LayoutDefault( const GUIHelpers::eLayout& layout ) { if (layout != GUIHelpers::eLayout::DEFAULT_LAYOUT) sLAYOUT = layout; } /*static*/ void cWindow::OrientationDefault( const GUIHelpers::eOrientation& orientation ) { if (orientation != GUIHelpers::eOrientation::DEFAULT_ORIENTATION) sORIENTATION = orientation; } void cWindow::setOrientation( const GUIHelpers::eOrientation& orientation /*= sORIENTATION*/ ) { if (orientation == GUIHelpers::eOrientation::DEFAULT_ORIENTATION) m_orientation = cWindow::sORIENTATION; else m_orientation = orientation; } void cWindow::setAlign( const GUIHelpers::eAlign& align /*= sALIGN*/ ) { if (align == GUIHelpers::eAlign::DEFAULT_ALIGN) m_align = cWindow::sALIGN; else m_align = align; RebuildPos(); } void cWindow::setLayout( const GUIHelpers::eLayout& layout /*= sLAYOUT*/ ) { if (layout == GUIHelpers::eLayout::DEFAULT_LAYOUT) m_layout = cWindow::sLAYOUT; else m_layout = layout; } void cWindow::setPosition( const GUIHelpers::Position& pos /*= POSITION*/ ) { if (pos.x < 0) m_pos = cWindow::sPOSITION; else m_pos = pos; } void cWindow::setSize( const GUIHelpers::Size& size /*= sSIZE*/ ) { if (size.x < 0) m_size = cWindow::sSIZE; else m_size = size; } void cWindow::setPadding( const GUIHelpers::Padding& padding /*= PADDING*/ ) { if (padding.x < 0) m_padding = cWindow::sPADDING; else m_padding = padding; } void cWindow::setContentSize( const GUIHelpers::Size& content ) { m_content = content; } void cWindow::setName( const cString& name /*= NAME*/ ) { m_name = name; } void cWindow::setParent( cWindow* parent ) { mp_parent = parent; } /// Gets const GUIHelpers::Position cWindow::getCenter( const bool pad /*= true*/ ) const { GUIHelpers::Position rtn = { 0, 0 }; rtn.x = (m_size.x / 2) + m_pos.x; rtn.y = (m_size.y / 2) + m_pos.y; if (pad == true) { rtn.x += (m_padding.x - m_padding.w); rtn.y += (m_padding.y - m_padding.z); } return rtn; } const GUIHelpers::eOrientation& cWindow::getOrientation() const { return m_orientation; } const GUIHelpers::eAlign& cWindow::getAlign() const { return m_align; } const GUIHelpers::eLayout& cWindow::getLayout() const { if (m_layout == GUIHelpers::eLayout::MATCH_PARENT) { if (mp_parent != nullptr) return mp_parent->getLayout(); } return m_layout; } const GUIHelpers::Position cWindow::getPosition( const bool pad /*= true*/ ) const { GUIHelpers::Position rtn = m_pos; if (pad == false) { rtn.x -= m_padding.x; rtn.y -= m_padding.y; } return rtn; } const GUIHelpers::Size cWindow::getSize( const bool pad /*= true*/ ) const { GUIHelpers::Size rtn = m_size; if (pad == true) { rtn.x += m_padding.x + m_padding.w; rtn.y += m_padding.y + m_padding.z; } return rtn; } const GUIHelpers::Padding& cWindow::getPadding() const { return m_padding; } const GUIHelpers::Size& cWindow::getContentSize() const { return m_content; } const cString& cWindow::getName() const { return m_name; } const GUIHelpers::Size cWindow::getChildrenSize( const cWindow* ignore /*= nullptr*/ ) { GUIHelpers::Size rtn = { 0, 0 }; std::vector::iterator it; for (it = m_children.begin(); it < m_children.end(); it++) { if ((ignore == nullptr) || ((*it) != ignore)) rtn += (*it)->getSize(); } return rtn; } cWindow* cWindow::getParent() { return mp_parent; } /*virtual*/ const GUIHelpers::eType cWindow::getType() const { return GUIHelpers::eType::CWINDOW; } /// protected /*virtual*/ void cWindow::Resize() { RebuildLayout(this->getLayout()); RePos(); } /*virtual*/ void cWindow::RebuildLayout( const GUIHelpers::eLayout& layout ) { GUIHelpers::Size mySize = { 0, 0 }; std::vector::iterator it; switch (layout) { case GUIHelpers::eLayout::MATCH_PARENT: case GUIHelpers::eLayout::FILL_PARENT: if (mp_parent != nullptr) { GUIHelpers::Position myPos = mp_parent->getPosition(false); myPos.x += m_padding.x; myPos.y += m_padding.y; mySize = mp_parent->getSize(false); if (mp_parent->getType() == GUIHelpers::eType::CLAYOUT) { if (mp_parent->getChildren().size() > 1) mySize -= mp_parent->getChildrenSize(this); if (mp_parent->getOrientation() == GUIHelpers::eOrientation::VERTICAL) mySize.x = m_size.x; if (mp_parent->getOrientation() == GUIHelpers::eOrientation::HORIZONTAL) mySize.y = m_size.y; } mySize.x -= m_padding.x + m_padding.w; mySize.y -= m_padding.y + m_padding.z; m_pos = myPos; m_size = mySize; } for (it = m_children.begin(); it < m_children.end(); it++) { (*it)->Resize(); } break; case GUIHelpers::eLayout::WRAP_CONTENT: GUIHelpers::Size size = { 0, 0 }; if (m_children.size() > 0) { for (it = m_children.begin(); it < m_children.end(); it++) { (*it)->Resize(); size = (*it)->getSize(); AddSize(size.x, size.y, mySize); } } else { if (mp_parent != nullptr) m_pos = mp_parent->getCenter(); } m_size = mySize; break; } } /*virtual*/ void cWindow::RePos() { std::vector::iterator it; for (it = m_children.begin(); it < m_children.end(); it++) { (*it)->RePos(); } if (this->getType() == GUIHelpers::eType::CLAYOUT) { GUIHelpers::Position prtCenter = getCenter(); GUIHelpers::Position ourSet = prtCenter; GUIHelpers::Size totalSize = { 0, 0 }; GUIHelpers::Position totalCenter = { 0, 0 }; for (it = m_children.begin(); it < m_children.end(); it++) { totalSize += (*it)->getSize(); } totalCenter.x = totalSize.x / 2; totalCenter.y = totalSize.y / 2; ourSet.x -= totalCenter.x; ourSet.y -= totalCenter.y; GUIHelpers::Position posSet = ourSet; GUIHelpers::Position posNext = posSet; for (it = m_children.begin(); it < m_children.end(); it++) { posSet = posNext; GUIHelpers::Padding pad = (*it)->getPadding(); GUIHelpers::Size size = (*it)->getSize(false); if (m_orientation == GUIHelpers::eOrientation::HORIZONTAL) { posSet.x += pad.x; posSet.y = (pad.y - pad.z - (size.y / 2)) + prtCenter.y; posNext = posSet; posNext.x += size.x + pad.w; //posNext.y = ourSet.y; } else { posSet.x = (pad.x - pad.w - (size.x / 2)) + prtCenter.x; posSet.y += pad.y; posNext = posSet; //posNext.x = ourSet.x; posNext.y += size.y + pad.z; } (*it)->setPosition(posSet); (*it)->RebuildPos(); } } } /*virtual*/ void cWindow::RebuildPos() { if ((mp_parent != nullptr) && (mp_parent->getOrientation() != GUIHelpers::eOrientation::NONE)) { GUIHelpers::Position prtPos = mp_parent->getPosition(); GUIHelpers::Size prtSize = mp_parent->getSize(); GUIHelpers::Position pos = this->getPosition(); GUIHelpers::Size size = this->getSize(); GUIHelpers::Padding pad = this->getPadding(); if (mp_parent->getOrientation() == GUIHelpers::eOrientation::HORIZONTAL) { switch (this->getAlign()) { default: case GUIHelpers::eAlign::CENTER: pos.y = mp_parent->getCenter().y - (this->getSize(false).y / 2); break; case GUIHelpers::eAlign::BOTTOM: pos.y = prtSize.y - size.y; break; case GUIHelpers::eAlign::TOP: pos.y = prtPos.y + pad.y; break; } } if (mp_parent->getOrientation() == GUIHelpers::eOrientation::VERTICAL) { switch (this->getAlign()) { default: case GUIHelpers::eAlign::CENTER: pos.x = mp_parent->getCenter().x - (this->getSize(false).x / 2); break; case GUIHelpers::eAlign::RIGHT: pos.x = prtSize.x - size.x; break; case GUIHelpers::eAlign::LEFT: pos.x = prtPos.x + pad.x; break; } } this->setPosition(pos); } } /*virtual*/ const GUIHelpers::RGBA& cWindow::getDebugColour() const { return GUIHelpers::WHITE; } std::vector& cWindow::getChildren() { return m_children; } /// private void cWindow::AddSize( const int x, const int y, GUIHelpers::Size& mySize ) const { int addFrom = x; int largestFrom = y; int addTo = mySize.x; int largestTo = mySize.y; if (m_orientation == GUIHelpers::eOrientation::HORIZONTAL) { addFrom = y; largestFrom = x; addTo = mySize.y; largestTo = mySize.x; } /*We do the real work here.*/ if (largestTo < largestFrom) largestTo = largestFrom; addTo += addFrom; } void cWindow::DebugDisplay() const { // Debug Level 0 display nothing // Debug Level 1 display a coloured rectangle and center pixel for each GUI element. // Debug Level 2 display the type of GUI element unsigned long int debugLvl = GUIEngine::cGUI::Inst().getDebugLevel(); if (debugLvl >= 1) { SDL_Rect rect; rect.x = m_pos.x; rect.y = m_pos.y; rect.w = m_pos.x + m_size.x; rect.h = m_pos.y + m_size.y; GUIHelpers::Position strPos = getCenter(); GUIHelpers::RGBA colour = getDebugColour(); FXEngine::cGFX::Inst().Pixel(strPos.x, strPos.y, colour); cString str = ""; str.format("X: %d Y: %d", strPos.x, strPos.y); FXEngine::cGFX::Inst().StringDefault(str, { strPos.x + 2, strPos.y + 2, 0, 0 }, colour); if (debugLvl >= 2) { SDL_Rect typePos = { 2, 2, 0, 0 }; cString type = ""; switch (getType()) { case GUIHelpers::eType::CPANEL: type = "Panel"; break; case GUIHelpers::eType::CLAYOUT: type = "Layout"; break; case GUIHelpers::eType::CLABEL: typePos = { -10, -10, 0, 0 }; type = "Label"; break; default: type = ""; } typePos.x += m_pos.x; typePos.y += m_pos.y; FXEngine::cGFX::Inst().StringDefault(type, typePos, colour); // if (debugLvl >= 3) { // GUIHelpers::Position pos = getPosPPad(); // //GUIHelpers::Size size = getSizePPad(); // SDL_Rect box{ 0, 0, 0, 0 }; // box.x += pos.x; // box.y += pos.y; // box.h += pos.y + m_size.y + m_padding.y + m_padding.z; // box.w += pos.x + m_padding.x; // // FXEngine::cGFX::Inst().Box(box, colour); // } } FXEngine::cGFX::Inst().Rectangle(rect, colour); } }