Skip to content

Commit

Permalink
[SUTK] Implemented and tested SUTK::HPaneContainer it is now working …
Browse files Browse the repository at this point in the history
…as expected

 - with minor improvements still need to be made
  • Loading branch information
ravi688 committed Sep 10, 2024
1 parent 3f4d128 commit 8740756
Show file tree
Hide file tree
Showing 8 changed files with 174 additions and 49 deletions.
9 changes: 6 additions & 3 deletions sutk/include/sutk/AnchorRect.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -12,9 +12,9 @@ namespace SUTK
private:
Rect2Df m_rect;
Rect2Df m_constraintRect;
Container& m_childRect;
Container& m_parentRect;
AnchorRect(Container& childRect, Container& parentRect) noexcept;
Container* m_childRect;
Container* m_parentRect;
AnchorRect(Container* childRect, Container* parentRect) noexcept;

friend class Container;
// should be called by the parent container whenever its rect is resized or changes its position
Expand All @@ -24,6 +24,9 @@ namespace SUTK

Rect2Df getUnnormalizedAnchorRect() noexcept;
void recalculateConstraints() noexcept;

void setParent(Container* parent) noexcept;
void setChild(Container* child) noexcept;
public:

// getters
Expand Down
5 changes: 3 additions & 2 deletions sutk/include/sutk/Container.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -85,6 +85,7 @@ namespace SUTK
void setLayoutAttributes(const LayoutAttributes& attrs) noexcept;
bool isLayoutIgnore() const noexcept { return m_isLayoutIgnore || (!isActive()); }
void setLayoutIgnore(bool isIgnore) noexcept;
void setLayoutExpand() noexcept;

// childs getters
std::vector<Container*>& getChilds() noexcept { return getContainerList(); }
Expand All @@ -94,7 +95,7 @@ namespace SUTK
Container* getParent() { return m_parent; }
const Container* getParent() const { return m_parent; }
// parent setters
void setParent(Container* parent) noexcept;
void setParent(Container* parent, bool isInvariantPos = true) noexcept;

// rect getters
Rect2Df getRect() const { return m_rect; }
Expand Down Expand Up @@ -136,7 +137,7 @@ namespace SUTK
// addition and removal of child containers

// adds a new container as a child to this container
virtual void add(Container* container);
virtual void add(Container* container, bool isInvariantPos = true);
// removes an existing container from this container
virtual void remove(Container* container);
};
Expand Down
23 changes: 16 additions & 7 deletions sutk/include/sutk/HPaneContainer.hpp
Original file line number Diff line number Diff line change
@@ -1,26 +1,35 @@
#pragma once

#include <sutk/Container.hpp>
#include <sutk/HBoxContainer.hpp>
#include <sutk/InputEventHandlerObject.hpp>

#include <array> // for std::array

namespace SUTK
{
class RenderRectFill;
class RenderableContainer;

class HPaneContainer : public Container,
class HPaneContainer : public HBoxContainer,
public MouseClickHandlerObject,
public MouseMoveHandlerObject
{
private:
bool m_isGrabbed;
std::vector<RenderRectFill*> m_handleRects;
bool m_isHandleRect;
std::array<Container*, 3> m_grabbedHandle;
struct HandleAdjacencyData
{
Container* left;
Container* right;
};
std::vector<std::pair<RenderableContainer*, HandleAdjacencyData>> m_handleRects;
std::vector<Container*> m_externalChilds;
Vec2Df m_prevPos;
protected:
virtual void onMouseClick(MouseButton button, KeyEvent action) override;
virtual void onMouseMove(Vec2Df position) override;

virtual void onAddChild(Container* child) override;
virtual void onRemoveChild(Container* child) override;
virtual void add(Container* child, bool isInvariantPos = true) override;
virtual void remove(Container* child) override;
public:
HPaneContainer(UIDriver& driver, Container* parent = NULL) noexcept;
virtual ~HPaneContainer() noexcept = default;
Expand Down
3 changes: 2 additions & 1 deletion sutk/include/sutk/tests/HPaneTest.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -16,11 +16,12 @@ namespace SUTK
{
private:
UIDriver* m_uiDriver;
IInputDriver* m_inputDriver;
IGfxDriver* m_gfxDriver;
HPaneContainer* m_hPaneContainer;

public:
HPaneTest() : m_uiDriver(NULL), m_gfxDriver(NULL) { }
HPaneTest() : m_uiDriver(NULL), m_inputDriver(NULL), m_gfxDriver(NULL) { }

DriverInitializationData getInitializationData() override;

Expand Down
23 changes: 19 additions & 4 deletions sutk/source/AnchorRect.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@

namespace SUTK
{
AnchorRect::AnchorRect(Container& childRect, Container& parentRect) noexcept : m_childRect(childRect), m_parentRect(parentRect)
AnchorRect::AnchorRect(Container* childRect, Container* parentRect) noexcept : m_childRect(childRect), m_parentRect(parentRect)
{
// NOTE: initially the anchor rect is degenerate (width and height both is zero) and has position as { 0, 0 }

Expand All @@ -12,24 +12,39 @@ namespace SUTK

Rect2Df AnchorRect::getUnnormalizedAnchorRect() noexcept
{
Vec2Df parentSize = m_parentRect.getSize();
_com_assert(m_parentRect != NULL);
Vec2Df parentSize = m_parentRect->getSize();
// calculate unnormalized anchor rect in the parent rect's local coordinates
Rect2Df anchorRect { m_rect.getPosition() * parentSize, m_rect.getSize() * parentSize };
return anchorRect;
}

void AnchorRect::recalculateConstraints() noexcept
{
if((m_childRect == NULL) || ((m_parentRect == NULL)))
return;
Rect2Df anchorRect = getUnnormalizedAnchorRect();
// signed difference is the constraint
m_constraintRect = anchorRect - m_childRect.getRect();
m_constraintRect = anchorRect - m_childRect->getRect();
}

void AnchorRect::setParent(Container* parent) noexcept
{
m_parentRect = parent;
recalculateConstraints();
}
void AnchorRect::setChild(Container* child) noexcept
{
m_childRect = child;
recalculateConstraints();
}

void AnchorRect::onParentResize(const Rect2Df& newRect, bool isPositionChanged, bool isSizeChanged) noexcept
{
_com_assert(m_childRect != NULL);
Rect2Df anchorRect = getUnnormalizedAnchorRect();
Rect2Df newChildRect = anchorRect - m_constraintRect;
m_childRect.setRect(newChildRect);
m_childRect->setRect(newChildRect);
}

void AnchorRect::onChildResize(const Rect2Df& newRect, bool isPositionChanged, bool isSizeChanged) noexcept
Expand Down
47 changes: 33 additions & 14 deletions sutk/source/Container.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -19,10 +19,7 @@ namespace SUTK
m_isDebug(false)
{
if(parent != NULL)
{
setParentChildRelation(parent);
m_anchorRect = new AnchorRect(*this, *parent);
}
setParent(parent, false);
}

Container::~Container()
Expand All @@ -39,6 +36,9 @@ namespace SUTK
// remove this container from the list of "childs" of the (old) parent container
bool result = com::erase_first_if(m_parent->m_containers.begin(), m_parent->m_containers.end(), [this](Container*& _container) { return _container == this; });
_assert(result == true);
_com_assert(m_anchorRect != NULL);
if(parent == NULL)
m_anchorRect->setParent(NULL);
// invoke onRemoveChild callback for the parent container as a child 'this' has been removed from that
m_parent->onRemoveChild(this);
m_parent = NULL;
Expand All @@ -52,21 +52,23 @@ namespace SUTK
// add this container into the list of "childs" of the (new) parent container
parent->m_containers.push_back(this);
m_parent = parent;
if(m_anchorRect == NULL)
m_anchorRect = new AnchorRect(this, parent);
else
m_anchorRect->setParent(parent);
// invoke onAdd callback function for this container as it has now been added into another (parent) container
onAdd(this);
// invoke onAddChild callback function for the parent container as a new child 'this' has been added into that
parent->onAddChild(this);
}
}

void Container::setParent(Container* parent) noexcept
void Container::setParent(Container* parent, bool isInvariantPos) noexcept
{
// recalculate this container's rect into the local space of new parent container
Vec2Df screenCoords = getLocalCoordsToScreenCoords({ 0u, 0u });
Vec2Df localCoords = (parent != NULL) ? parent->getScreenCoordsToLocalCoords(screenCoords) : screenCoords;
setPosition(localCoords);

setParentChildRelation(parent);
if(parent != NULL)
parent->add(this, isInvariantPos);
else if(m_parent != NULL)
m_parent->remove(this);
}

bool Container::containsGlobalCoords(Vec2Df globalCoords) const noexcept
Expand Down Expand Up @@ -114,16 +116,26 @@ namespace SUTK
_assert(parent != NULL);
}

void Container::add(Container* container)
void Container::add(Container* container, bool isInvariantPos)
{
_assert(container != NULL);
container->setParent(this);
if(isInvariantPos)
{
// recalculate this container's rect into the local space of new parent container
Vec2Df screenCoords = container->getLocalCoordsToScreenCoords({ 0u, 0u });
Vec2Df localCoords = getScreenCoordsToLocalCoords(screenCoords);
container->setPosition(localCoords);
}
else
container->setPosition({ 0.0f, 0.0f });

container->setParentChildRelation(this);
}

void Container::remove(Container* container)
{
_assert(container != NULL);
container->setParent(NULL);
container->setParentChildRelation(NULL);
}

void Container::onParentResize(const Rect2Df& newRect, bool isPositionChanged, bool isSizeChanged)
Expand Down Expand Up @@ -209,4 +221,11 @@ namespace SUTK
recalculateLayoutParent();
m_isLayoutIgnore = isIgnore;
}

void Container::setLayoutExpand() noexcept
{
auto& attr = getLayoutAttributes();
attr.prefSize = attr.maxSize;
setLayoutAttributes(attr);
}
}
91 changes: 75 additions & 16 deletions sutk/source/HPaneContainer.cpp
Original file line number Diff line number Diff line change
@@ -1,42 +1,101 @@
#include <sutk/HPaneContainer.hpp>
#include <sutk/RenderRectFill.hpp>
#include <sutk/RenderableContainer.hpp>

#define HANDLE_HIGHLIGHT_COLOR Color4::grey(0.5f)
#define HANDLE_HOVER_COLOR Color4::grey(0.5f)
#define HANDLE_IDLE_COLOR Color4::grey(0.2f)
#define HANDLE_WIDTH 0.1f

namespace SUTK
{
HPaneContainer::HPaneContainer(UIDriver& driver, Container* parent) noexcept : Container(driver, parent),
HPaneContainer::HPaneContainer(UIDriver& driver, Container* parent) noexcept : HBoxContainer(driver, parent),
MouseClickHandlerObject(driver, this),
MouseMoveHandlerObject(driver, this)
MouseMoveHandlerObject(driver, this),
m_isHandleRect(false),
m_grabbedHandle({ NULL, NULL, NULL })
{
}

void HPaneContainer::onMouseClick(MouseButton button, KeyEvent action)
{
// if((m_handleRect == NULL) || (button != MouseButton::Left))
// return;

// if(action == KeyEvent::Press)
// {
// Vec2Df pos = getInputDriver().getMousePosition();
// if(m_handleRect->containsGlobalCoords(pos))
// m_isGrabbed = true;
// }
// else
// m_isGrabbed = false;
if(button != MouseButton::Left)
return;

if(action == KeyEvent::Press)
{
Vec2Df pos = getInputDriver().getMousePosition();
for(const auto &handle : m_handleRects)
{
if(handle.first->containsGlobalCoords(pos))
{
m_grabbedHandle[0] = handle.first;
m_grabbedHandle[1] = handle.second.left;
m_grabbedHandle[2] = handle.second.right;
m_prevPos = pos;
break;
}
}
}
else
m_grabbedHandle = { NULL, NULL, NULL };
}

void HPaneContainer::onMouseMove(Vec2Df position)
{
if(m_grabbedHandle[0])
{
Vec2Df pos = getInputDriver().getMousePosition();
auto disp = pos - m_prevPos;
m_prevPos = pos;

auto left = m_grabbedHandle[1];
auto middle = m_grabbedHandle[0];
auto right = m_grabbedHandle[2];

auto rect = left->getRect();
rect.extendRight(disp.x);
left->setRect(rect);

rect = middle->getRect();
rect.extendLeft(-disp.x);
rect.extendRight(disp.x);
middle->setRect(rect);

rect = right->getRect();
rect.extendLeft(-disp.x);
right->setRect(rect);
}
}

void HPaneContainer::onAddChild(Container* child)
void HPaneContainer::add(Container* child, bool isInvariantPos)
{
if(m_isHandleRect)
{
HBoxContainer::add(child, isInvariantPos);
m_isHandleRect = false;
return;
}
std::size_t externChildCount = m_externalChilds.size();
if(externChildCount > 0)
{
m_isHandleRect = true;
RenderableContainer* handleRectCont = getUIDriver().createContainer<RenderableContainer>(this);
LayoutAttributes attr = handleRectCont->getLayoutAttributes();
attr.minSize.width = HANDLE_WIDTH;
attr.prefSize.width = HANDLE_WIDTH;
handleRectCont->setLayoutAttributes(attr);
RenderRect* handleRect = getUIDriver().createRenderable<RenderRectFill>(handleRectCont);
handleRect->setColor(HANDLE_IDLE_COLOR);
_com_assert(getChilds().size() > 1);
m_handleRects.push_back({ handleRectCont, { getChilds()[getChilds().size() - 2], child } });
}
HBoxContainer::add(child, isInvariantPos);
m_externalChilds.push_back(child);
}

void HPaneContainer::onRemoveChild(Container* child)
void HPaneContainer::remove(Container* child)
{
HBoxContainer::remove(child);
bool result = com::find_erase(m_externalChilds, child);
_com_assert(result);
}
Expand Down
Loading

0 comments on commit 8740756

Please sign in to comment.