Widgets: Improve BoxLayout
This commit is contained in:
parent
f1cd5ad048
commit
3712b641f8
|
|
@ -48,8 +48,8 @@ namespace Nz
|
||||||
|
|
||||||
void EnableBackground(bool enable);
|
void EnableBackground(bool enable);
|
||||||
|
|
||||||
template<typename F> void ForEachWidgetChild(F iterator);
|
template<typename F> void ForEachWidgetChild(F&& iterator, bool onlyVisible = true);
|
||||||
template<typename F> void ForEachWidgetChild(F iterator) const;
|
template<typename F> void ForEachWidgetChild(F&& iterator, bool onlyVisible = true) const;
|
||||||
|
|
||||||
//virtual BaseWidget* Clone() const = 0;
|
//virtual BaseWidget* Clone() const = 0;
|
||||||
|
|
||||||
|
|
@ -74,6 +74,7 @@ namespace Nz
|
||||||
|
|
||||||
inline Vector2f GetSize() const;
|
inline Vector2f GetSize() const;
|
||||||
const std::shared_ptr<WidgetTheme>& GetTheme() const;
|
const std::shared_ptr<WidgetTheme>& GetTheme() const;
|
||||||
|
inline std::size_t GetVisibleWidgetChildCount() const;
|
||||||
inline float GetWidth() const;
|
inline float GetWidth() const;
|
||||||
inline std::size_t GetWidgetChildCount() const;
|
inline std::size_t GetWidgetChildCount() const;
|
||||||
|
|
||||||
|
|
@ -108,6 +109,8 @@ namespace Nz
|
||||||
BaseWidget& operator=(const BaseWidget&) = delete;
|
BaseWidget& operator=(const BaseWidget&) = delete;
|
||||||
BaseWidget& operator=(BaseWidget&&) = delete;
|
BaseWidget& operator=(BaseWidget&&) = delete;
|
||||||
|
|
||||||
|
NazaraSignal(OnWidgetResized, const BaseWidget* /*widget*/, const Vector2f& /*size*/);
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
virtual void Layout();
|
virtual void Layout();
|
||||||
|
|
||||||
|
|
@ -125,6 +128,10 @@ namespace Nz
|
||||||
virtual bool IsFocusable() const;
|
virtual bool IsFocusable() const;
|
||||||
inline bool IsInside(float x, float y) const;
|
inline bool IsInside(float x, float y) const;
|
||||||
|
|
||||||
|
virtual void OnChildAdded(const BaseWidget* child);
|
||||||
|
virtual void OnChildPreferredSizeUpdated(const BaseWidget* child);
|
||||||
|
virtual void OnChildVisibilityUpdated(const BaseWidget* child);
|
||||||
|
virtual void OnChildRemoved(const BaseWidget* child);
|
||||||
virtual void OnFocusLost();
|
virtual void OnFocusLost();
|
||||||
virtual void OnFocusReceived();
|
virtual void OnFocusReceived();
|
||||||
virtual bool OnKeyPressed(const WindowEvent::KeyEvent& key);
|
virtual bool OnKeyPressed(const WindowEvent::KeyEvent& key);
|
||||||
|
|
@ -135,8 +142,8 @@ namespace Nz
|
||||||
virtual bool OnMouseButtonPress(int x, int y, Mouse::Button button);
|
virtual bool OnMouseButtonPress(int x, int y, Mouse::Button button);
|
||||||
virtual bool OnMouseButtonRelease(int x, int y, Mouse::Button button);
|
virtual bool OnMouseButtonRelease(int x, int y, Mouse::Button button);
|
||||||
virtual bool OnMouseButtonTriplePress(int x, int y, Mouse::Button button);
|
virtual bool OnMouseButtonTriplePress(int x, int y, Mouse::Button button);
|
||||||
virtual bool OnMouseWheelMoved(int x, int y, float delta);
|
|
||||||
virtual void OnMouseExit();
|
virtual void OnMouseExit();
|
||||||
|
virtual bool OnMouseWheelMoved(int x, int y, float delta);
|
||||||
virtual void OnRenderLayerUpdated(int baseRenderLayer);
|
virtual void OnRenderLayerUpdated(int baseRenderLayer);
|
||||||
virtual void OnParentResized(const Vector2f& newSize);
|
virtual void OnParentResized(const Vector2f& newSize);
|
||||||
virtual bool OnTextEntered(char32_t character, bool repeated);
|
virtual bool OnTextEntered(char32_t character, bool repeated);
|
||||||
|
|
@ -173,7 +180,7 @@ namespace Nz
|
||||||
std::shared_ptr<Sprite> m_backgroundSprite;
|
std::shared_ptr<Sprite> m_backgroundSprite;
|
||||||
std::shared_ptr<WidgetTheme> m_theme;
|
std::shared_ptr<WidgetTheme> m_theme;
|
||||||
std::vector<WidgetEntity> m_entities;
|
std::vector<WidgetEntity> m_entities;
|
||||||
std::vector<std::unique_ptr<BaseWidget>> m_children;
|
std::vector<std::unique_ptr<BaseWidget>> m_widgetChilds;
|
||||||
entt::registry* m_registry;
|
entt::registry* m_registry;
|
||||||
Canvas* m_canvas;
|
Canvas* m_canvas;
|
||||||
Color m_backgroundColor;
|
Color m_backgroundColor;
|
||||||
|
|
@ -183,7 +190,7 @@ namespace Nz
|
||||||
Vector2f m_minimumSize;
|
Vector2f m_minimumSize;
|
||||||
Vector2f m_preferredSize;
|
Vector2f m_preferredSize;
|
||||||
Vector2f m_size;
|
Vector2f m_size;
|
||||||
BaseWidget* m_widgetParent;
|
BaseWidget* m_parentWidget;
|
||||||
bool m_visible;
|
bool m_visible;
|
||||||
int m_baseRenderLayer;
|
int m_baseRenderLayer;
|
||||||
int m_renderLayerCount;
|
int m_renderLayerCount;
|
||||||
|
|
|
||||||
|
|
@ -21,7 +21,7 @@ namespace Nz
|
||||||
m_minimumSize(0.f),
|
m_minimumSize(0.f),
|
||||||
m_preferredSize(-1),
|
m_preferredSize(-1),
|
||||||
m_size(50.f, 50.f),
|
m_size(50.f, 50.f),
|
||||||
m_widgetParent(nullptr),
|
m_parentWidget(nullptr),
|
||||||
m_visible(true),
|
m_visible(true),
|
||||||
m_baseRenderLayer(0),
|
m_baseRenderLayer(0),
|
||||||
m_renderLayerCount(1)
|
m_renderLayerCount(1)
|
||||||
|
|
@ -44,32 +44,33 @@ namespace Nz
|
||||||
widget->SetBaseRenderLayer(m_baseRenderLayer + m_renderLayerCount);
|
widget->SetBaseRenderLayer(m_baseRenderLayer + m_renderLayerCount);
|
||||||
widget->Show(widget->IsVisible() && m_visible);
|
widget->Show(widget->IsVisible() && m_visible);
|
||||||
|
|
||||||
m_children.emplace_back(std::move(widget));
|
m_widgetChilds.emplace_back(std::move(widget));
|
||||||
|
OnChildAdded(m_widgetChilds.back().get());
|
||||||
}
|
}
|
||||||
|
|
||||||
inline void BaseWidget::Center()
|
inline void BaseWidget::Center()
|
||||||
{
|
{
|
||||||
NazaraAssert(m_widgetParent, "Widget has no parent");
|
NazaraAssert(m_parentWidget, "Widget has no parent");
|
||||||
|
|
||||||
Vector2f parentSize = m_widgetParent->GetSize();
|
Vector2f parentSize = m_parentWidget->GetSize();
|
||||||
Vector2f mySize = GetSize();
|
Vector2f mySize = GetSize();
|
||||||
SetPosition((parentSize.x - mySize.x) / 2.f, (parentSize.y - mySize.y) / 2.f);
|
SetPosition((parentSize.x - mySize.x) / 2.f, (parentSize.y - mySize.y) / 2.f);
|
||||||
}
|
}
|
||||||
|
|
||||||
inline void BaseWidget::CenterHorizontal()
|
inline void BaseWidget::CenterHorizontal()
|
||||||
{
|
{
|
||||||
NazaraAssert(m_widgetParent, "Widget has no parent");
|
NazaraAssert(m_parentWidget, "Widget has no parent");
|
||||||
|
|
||||||
Vector2f parentSize = m_widgetParent->GetSize();
|
Vector2f parentSize = m_parentWidget->GetSize();
|
||||||
Vector2f mySize = GetSize();
|
Vector2f mySize = GetSize();
|
||||||
SetPosition((parentSize.x - mySize.x) / 2.f, GetPosition(CoordSys::Local).y);
|
SetPosition((parentSize.x - mySize.x) / 2.f, GetPosition(CoordSys::Local).y);
|
||||||
}
|
}
|
||||||
|
|
||||||
inline void BaseWidget::CenterVertical()
|
inline void BaseWidget::CenterVertical()
|
||||||
{
|
{
|
||||||
NazaraAssert(m_widgetParent, "Widget has no parent");
|
NazaraAssert(m_parentWidget, "Widget has no parent");
|
||||||
|
|
||||||
Vector2f parentSize = m_widgetParent->GetSize();
|
Vector2f parentSize = m_parentWidget->GetSize();
|
||||||
Vector2f mySize = GetSize();
|
Vector2f mySize = GetSize();
|
||||||
SetPosition(GetPosition(CoordSys::Local).x, (parentSize.y - mySize.y) / 2.f);
|
SetPosition(GetPosition(CoordSys::Local).x, (parentSize.y - mySize.y) / 2.f);
|
||||||
}
|
}
|
||||||
|
|
@ -80,17 +81,27 @@ namespace Nz
|
||||||
}
|
}
|
||||||
|
|
||||||
template<typename F>
|
template<typename F>
|
||||||
inline void BaseWidget::ForEachWidgetChild(F iterator)
|
void BaseWidget::ForEachWidgetChild(F&& iterator, bool onlyVisible)
|
||||||
{
|
{
|
||||||
for (const auto& child : m_children)
|
for (const auto& child : m_widgetChilds)
|
||||||
|
{
|
||||||
|
if (onlyVisible && !child->IsVisible())
|
||||||
|
continue;
|
||||||
|
|
||||||
iterator(child.get());
|
iterator(child.get());
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
template<typename F>
|
template<typename F>
|
||||||
inline void BaseWidget::ForEachWidgetChild(F iterator) const
|
void BaseWidget::ForEachWidgetChild(F&& iterator, bool onlyVisible) const
|
||||||
{
|
{
|
||||||
for (const auto& child : m_children)
|
for (const auto& child : m_widgetChilds)
|
||||||
iterator(static_cast<const BaseWidget*>(child.get()));
|
{
|
||||||
|
if (onlyVisible && !child->IsVisible())
|
||||||
|
continue;
|
||||||
|
|
||||||
|
iterator(child.get());
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
inline const Color& BaseWidget::GetBackgroundColor() const
|
inline const Color& BaseWidget::GetBackgroundColor() const
|
||||||
|
|
@ -173,6 +184,15 @@ namespace Nz
|
||||||
return m_theme;
|
return m_theme;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
inline std::size_t BaseWidget::GetVisibleWidgetChildCount() const
|
||||||
|
{
|
||||||
|
std::size_t visibleChild = 0;
|
||||||
|
for (const auto& child : m_widgetChilds)
|
||||||
|
visibleChild += (child->IsVisible()) ? 1 : 0;
|
||||||
|
|
||||||
|
return visibleChild;
|
||||||
|
}
|
||||||
|
|
||||||
inline float BaseWidget::GetWidth() const
|
inline float BaseWidget::GetWidth() const
|
||||||
{
|
{
|
||||||
return m_size.x;
|
return m_size.x;
|
||||||
|
|
@ -180,7 +200,7 @@ namespace Nz
|
||||||
|
|
||||||
inline std::size_t BaseWidget::GetWidgetChildCount() const
|
inline std::size_t BaseWidget::GetWidgetChildCount() const
|
||||||
{
|
{
|
||||||
return m_children.size();
|
return m_widgetChilds.size();
|
||||||
}
|
}
|
||||||
|
|
||||||
inline void BaseWidget::Hide()
|
inline void BaseWidget::Hide()
|
||||||
|
|
@ -227,7 +247,8 @@ namespace Nz
|
||||||
|
|
||||||
inline void BaseWidget::SetMaximumSize(const Vector2f& maximumSize)
|
inline void BaseWidget::SetMaximumSize(const Vector2f& maximumSize)
|
||||||
{
|
{
|
||||||
m_maximumSize = maximumSize;
|
m_maximumSize.x = std::max(m_minimumSize.x, maximumSize.x);
|
||||||
|
m_maximumSize.y = std::max(m_minimumSize.y, maximumSize.y);
|
||||||
|
|
||||||
Vector2f size = GetSize();
|
Vector2f size = GetSize();
|
||||||
if (size.x > m_maximumSize.x || size.y > m_maximumSize.y)
|
if (size.x > m_maximumSize.x || size.y > m_maximumSize.y)
|
||||||
|
|
@ -252,7 +273,8 @@ namespace Nz
|
||||||
|
|
||||||
inline void BaseWidget::SetMinimumSize(const Vector2f& minimumSize)
|
inline void BaseWidget::SetMinimumSize(const Vector2f& minimumSize)
|
||||||
{
|
{
|
||||||
m_minimumSize = minimumSize;
|
m_minimumSize.x = std::min(minimumSize.x, m_maximumSize.x);
|
||||||
|
m_minimumSize.y = std::min(minimumSize.y, m_maximumSize.y);
|
||||||
|
|
||||||
Vector2f size = GetSize();
|
Vector2f size = GetSize();
|
||||||
if (size.x < m_minimumSize.x || size.y < m_minimumSize.y)
|
if (size.x < m_minimumSize.x || size.y < m_minimumSize.y)
|
||||||
|
|
@ -294,16 +316,20 @@ namespace Nz
|
||||||
|
|
||||||
OnRenderLayerUpdated(GetBaseRenderLayer());
|
OnRenderLayerUpdated(GetBaseRenderLayer());
|
||||||
|
|
||||||
for (const auto& widgetPtr : m_children)
|
for (const auto& widgetPtr : m_widgetChilds)
|
||||||
widgetPtr->SetBaseRenderLayer(m_baseRenderLayer + m_renderLayerCount);
|
widgetPtr->SetBaseRenderLayer(m_baseRenderLayer + m_renderLayerCount);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
inline void BaseWidget::SetPreferredSize(const Vector2f& preferredSize)
|
inline void BaseWidget::SetPreferredSize(const Vector2f& preferredSize)
|
||||||
|
{
|
||||||
|
if (m_preferredSize != preferredSize)
|
||||||
{
|
{
|
||||||
m_preferredSize = preferredSize;
|
m_preferredSize = preferredSize;
|
||||||
|
|
||||||
//Resize(m_preferredSize);
|
if (m_parentWidget)
|
||||||
|
m_parentWidget->OnChildPreferredSizeUpdated(this);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
inline void BaseWidget::SetRenderLayerCount(int renderLayerCount)
|
inline void BaseWidget::SetRenderLayerCount(int renderLayerCount)
|
||||||
|
|
@ -311,7 +337,7 @@ namespace Nz
|
||||||
if (m_renderLayerCount != renderLayerCount)
|
if (m_renderLayerCount != renderLayerCount)
|
||||||
{
|
{
|
||||||
m_renderLayerCount = renderLayerCount;
|
m_renderLayerCount = renderLayerCount;
|
||||||
for (const auto& widgetPtr : m_children)
|
for (const auto& widgetPtr : m_widgetChilds)
|
||||||
widgetPtr->SetBaseRenderLayer(m_baseRenderLayer + m_renderLayerCount);
|
widgetPtr->SetBaseRenderLayer(m_baseRenderLayer + m_renderLayerCount);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -323,7 +349,7 @@ namespace Nz
|
||||||
|
|
||||||
inline void BaseWidget::NotifyParentResized(const Vector2f& newSize)
|
inline void BaseWidget::NotifyParentResized(const Vector2f& newSize)
|
||||||
{
|
{
|
||||||
for (const auto& widgetPtr : m_children)
|
for (const auto& widgetPtr : m_widgetChilds)
|
||||||
widgetPtr->OnParentResized(newSize);
|
widgetPtr->OnParentResized(newSize);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -334,3 +360,4 @@ namespace Nz
|
||||||
}
|
}
|
||||||
|
|
||||||
#include <Nazara/Widgets/DebugOff.hpp>
|
#include <Nazara/Widgets/DebugOff.hpp>
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -27,6 +27,13 @@ namespace Nz
|
||||||
BoxLayout& operator=(BoxLayout&&) = delete;
|
BoxLayout& operator=(BoxLayout&&) = delete;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
void OnChildAdded(const BaseWidget* child) override;
|
||||||
|
void OnChildPreferredSizeUpdated(const BaseWidget* child) override;
|
||||||
|
void OnChildVisibilityUpdated(const BaseWidget* child) override;
|
||||||
|
void OnChildRemoved(const BaseWidget* child) override;
|
||||||
|
|
||||||
|
void RecomputePreferredSize();
|
||||||
|
|
||||||
struct State;
|
struct State;
|
||||||
|
|
||||||
std::unique_ptr<State> m_state;
|
std::unique_ptr<State> m_state;
|
||||||
|
|
|
||||||
|
|
@ -11,8 +11,10 @@ namespace Nz
|
||||||
{
|
{
|
||||||
enum class BoxLayoutOrientation
|
enum class BoxLayoutOrientation
|
||||||
{
|
{
|
||||||
Horizontal,
|
BottomToTop,
|
||||||
Vertical
|
LeftToRight,
|
||||||
|
RightToLeft,
|
||||||
|
TopToBottom
|
||||||
};
|
};
|
||||||
|
|
||||||
enum class CheckboxState
|
enum class CheckboxState
|
||||||
|
|
|
||||||
|
|
@ -134,9 +134,9 @@ namespace Nz
|
||||||
AbstractTextDrawer& textDrawer = GetTextDrawer();
|
AbstractTextDrawer& textDrawer = GetTextDrawer();
|
||||||
|
|
||||||
textDrawer.SetMaxLineWidth(GetWidth());
|
textDrawer.SetMaxLineWidth(GetWidth());
|
||||||
UpdateTextSprite();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
UpdateTextSprite();
|
||||||
RefreshCursor();
|
RefreshCursor();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -630,9 +630,17 @@ namespace Nz
|
||||||
|
|
||||||
void AbstractTextAreaWidget::UpdateTextSprite()
|
void AbstractTextAreaWidget::UpdateTextSprite()
|
||||||
{
|
{
|
||||||
m_textSprite->Update(GetTextDrawer());
|
const AbstractTextDrawer& textDrawer = GetTextDrawer();
|
||||||
|
m_textSprite->Update(textDrawer);
|
||||||
|
|
||||||
|
float preferredHeight = 0.f;
|
||||||
|
std::size_t lineCount = textDrawer.GetLineCount();
|
||||||
|
for (std::size_t i = 0; i < lineCount; ++i)
|
||||||
|
preferredHeight += textDrawer.GetLine(i).bounds.height;
|
||||||
|
|
||||||
|
SetPreferredSize({ -1.f, preferredHeight + s_textAreaPaddingHeight * 2.f });
|
||||||
|
|
||||||
Vector2f textSize = Vector2f(m_textSprite->GetAABB().GetLengths());
|
Vector2f textSize = Vector2f(m_textSprite->GetAABB().GetLengths());
|
||||||
SetPreferredSize(textSize);
|
|
||||||
|
|
||||||
auto& textNode = GetRegistry().get<NodeComponent>(m_textEntity);
|
auto& textNode = GetRegistry().get<NodeComponent>(m_textEntity);
|
||||||
textNode.SetPosition(s_textAreaPaddingWidth, GetHeight() - s_textAreaPaddingHeight - textSize.y);
|
textNode.SetPosition(s_textAreaPaddingWidth, GetHeight() - s_textAreaPaddingHeight - textSize.y);
|
||||||
|
|
|
||||||
|
|
@ -34,7 +34,7 @@ namespace Nz
|
||||||
NazaraAssert(parent->GetCanvas(), "Parent has no canvas");
|
NazaraAssert(parent->GetCanvas(), "Parent has no canvas");
|
||||||
|
|
||||||
m_canvas = parent->GetCanvas();
|
m_canvas = parent->GetCanvas();
|
||||||
m_widgetParent = parent;
|
m_parentWidget = parent;
|
||||||
m_registry = &m_canvas->GetRegistry();
|
m_registry = &m_canvas->GetRegistry();
|
||||||
|
|
||||||
RegisterToCanvas();
|
RegisterToCanvas();
|
||||||
|
|
@ -75,7 +75,7 @@ namespace Nz
|
||||||
{
|
{
|
||||||
NazaraAssert(this != m_canvas, "Canvas cannot be destroyed by calling Destroy()");
|
NazaraAssert(this != m_canvas, "Canvas cannot be destroyed by calling Destroy()");
|
||||||
|
|
||||||
m_widgetParent->DestroyChild(this); //< This does delete us
|
m_parentWidget->DestroyChild(this); //< This does delete us
|
||||||
}
|
}
|
||||||
|
|
||||||
/*!
|
/*!
|
||||||
|
|
@ -110,7 +110,7 @@ namespace Nz
|
||||||
|
|
||||||
OnRenderLayerUpdated(GetBaseRenderLayer());
|
OnRenderLayerUpdated(GetBaseRenderLayer());
|
||||||
|
|
||||||
for (const auto& widgetPtr : m_children)
|
for (const auto& widgetPtr : m_widgetChilds)
|
||||||
widgetPtr->SetBaseRenderLayer(m_baseRenderLayer + m_renderLayerCount);
|
widgetPtr->SetBaseRenderLayer(m_baseRenderLayer + m_renderLayerCount);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -128,14 +128,15 @@ namespace Nz
|
||||||
|
|
||||||
std::unique_ptr<BaseWidget> BaseWidget::ReleaseFromParent()
|
std::unique_ptr<BaseWidget> BaseWidget::ReleaseFromParent()
|
||||||
{
|
{
|
||||||
if (!m_widgetParent)
|
if (!m_parentWidget)
|
||||||
return {};
|
return {};
|
||||||
|
|
||||||
auto it = std::find_if(m_widgetParent->m_children.begin(), m_widgetParent->m_children.end(), [&](const std::unique_ptr<BaseWidget>& widgetPtr) { return widgetPtr.get() == this; });
|
auto it = std::find_if(m_parentWidget->m_widgetChilds.begin(), m_parentWidget->m_widgetChilds.end(), [&](const std::unique_ptr<BaseWidget>& widgetPtr) { return widgetPtr.get() == this; });
|
||||||
assert(it != m_widgetParent->m_children.end());
|
assert(it != m_parentWidget->m_widgetChilds.end());
|
||||||
|
|
||||||
std::unique_ptr<BaseWidget> ownerPtr = std::move(*it);
|
std::unique_ptr<BaseWidget> ownerPtr = std::move(*it);
|
||||||
m_widgetParent->m_children.erase(it);
|
m_parentWidget->m_widgetChilds.erase(it);
|
||||||
|
m_parentWidget->OnChildRemoved(this);
|
||||||
|
|
||||||
return ownerPtr;
|
return ownerPtr;
|
||||||
}
|
}
|
||||||
|
|
@ -151,6 +152,8 @@ namespace Nz
|
||||||
m_size = newSize;
|
m_size = newSize;
|
||||||
|
|
||||||
Layout();
|
Layout();
|
||||||
|
|
||||||
|
OnWidgetResized(this, newSize);
|
||||||
}
|
}
|
||||||
|
|
||||||
void BaseWidget::SetBackgroundColor(const Color& color)
|
void BaseWidget::SetBackgroundColor(const Color& color)
|
||||||
|
|
@ -183,7 +186,7 @@ namespace Nz
|
||||||
m_renderingRect = renderingRect;
|
m_renderingRect = renderingRect;
|
||||||
|
|
||||||
UpdatePositionAndSize();
|
UpdatePositionAndSize();
|
||||||
for (const auto& widgetPtr : m_children)
|
for (const auto& widgetPtr : m_widgetChilds)
|
||||||
widgetPtr->UpdatePositionAndSize();
|
widgetPtr->UpdatePositionAndSize();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -206,6 +209,9 @@ namespace Nz
|
||||||
}
|
}
|
||||||
|
|
||||||
ShowChildren(show);
|
ShowChildren(show);
|
||||||
|
|
||||||
|
if (m_parentWidget)
|
||||||
|
m_parentWidget->OnChildVisibilityUpdated(this);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -262,6 +268,22 @@ namespace Nz
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void BaseWidget::OnChildAdded(const BaseWidget* /*child*/)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
void BaseWidget::OnChildPreferredSizeUpdated(const BaseWidget* /*child*/)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
void BaseWidget::OnChildVisibilityUpdated(const BaseWidget* /*child*/)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
void BaseWidget::OnChildRemoved(const BaseWidget* /*child*/)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
void BaseWidget::OnFocusLost()
|
void BaseWidget::OnFocusLost()
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
@ -309,15 +331,15 @@ namespace Nz
|
||||||
return OnMouseButtonPress(x, y, button);
|
return OnMouseButtonPress(x, y, button);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void BaseWidget::OnMouseExit()
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
bool BaseWidget::OnMouseWheelMoved(int /*x*/, int /*y*/, float /*delta*/)
|
bool BaseWidget::OnMouseWheelMoved(int /*x*/, int /*y*/, float /*delta*/)
|
||||||
{
|
{
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
void BaseWidget::OnMouseExit()
|
|
||||||
{
|
|
||||||
}
|
|
||||||
|
|
||||||
void BaseWidget::OnRenderLayerUpdated(int /*firstRenderLayer*/)
|
void BaseWidget::OnRenderLayerUpdated(int /*firstRenderLayer*/)
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
@ -338,25 +360,25 @@ namespace Nz
|
||||||
|
|
||||||
void BaseWidget::ShowChildren(bool show)
|
void BaseWidget::ShowChildren(bool show)
|
||||||
{
|
{
|
||||||
for (const auto& widgetPtr : m_children)
|
for (const auto& widgetPtr : m_widgetChilds)
|
||||||
widgetPtr->Show(show);
|
widgetPtr->Show(show);
|
||||||
}
|
}
|
||||||
|
|
||||||
void BaseWidget::DestroyChild(BaseWidget* widget)
|
void BaseWidget::DestroyChild(BaseWidget* widget)
|
||||||
{
|
{
|
||||||
auto it = std::find_if(m_children.begin(), m_children.end(), [widget] (const std::unique_ptr<BaseWidget>& widgetPtr) -> bool
|
auto it = std::find_if(m_widgetChilds.begin(), m_widgetChilds.end(), [widget] (const std::unique_ptr<BaseWidget>& widgetPtr) -> bool
|
||||||
{
|
{
|
||||||
return widgetPtr.get() == widget;
|
return widgetPtr.get() == widget;
|
||||||
});
|
});
|
||||||
|
|
||||||
NazaraAssert(it != m_children.end(), "Child widget not found in parent");
|
NazaraAssert(it != m_widgetChilds.end(), "Child widget not found in parent");
|
||||||
|
|
||||||
m_children.erase(it);
|
m_widgetChilds.erase(it);
|
||||||
}
|
}
|
||||||
|
|
||||||
void BaseWidget::DestroyChildren()
|
void BaseWidget::DestroyChildren()
|
||||||
{
|
{
|
||||||
m_children.clear();
|
m_widgetChilds.clear();
|
||||||
}
|
}
|
||||||
|
|
||||||
void BaseWidget::RegisterToCanvas()
|
void BaseWidget::RegisterToCanvas()
|
||||||
|
|
@ -375,7 +397,7 @@ namespace Nz
|
||||||
NazaraAssert(oldCanvas == newCanvas, "Transferring a widget between canvas is not yet supported");
|
NazaraAssert(oldCanvas == newCanvas, "Transferring a widget between canvas is not yet supported");
|
||||||
|
|
||||||
Node::SetParent(widget);
|
Node::SetParent(widget);
|
||||||
m_widgetParent = widget;
|
m_parentWidget = widget;
|
||||||
|
|
||||||
Layout();
|
Layout();
|
||||||
}
|
}
|
||||||
|
|
@ -396,9 +418,9 @@ namespace Nz
|
||||||
|
|
||||||
Rectf scissorRect = GetScissorRect();
|
Rectf scissorRect = GetScissorRect();
|
||||||
|
|
||||||
if (m_widgetParent)
|
if (m_parentWidget)
|
||||||
{
|
{
|
||||||
Rectf parentScissorRect = m_widgetParent->GetScissorRect();
|
Rectf parentScissorRect = m_parentWidget->GetScissorRect();
|
||||||
|
|
||||||
if (!scissorRect.Intersect(parentScissorRect, &scissorRect))
|
if (!scissorRect.Intersect(parentScissorRect, &scissorRect))
|
||||||
scissorRect = parentScissorRect;
|
scissorRect = parentScissorRect;
|
||||||
|
|
|
||||||
|
|
@ -33,20 +33,25 @@ namespace Nz
|
||||||
BaseWidget::Layout();
|
BaseWidget::Layout();
|
||||||
|
|
||||||
std::size_t axis;
|
std::size_t axis;
|
||||||
|
bool reversed;
|
||||||
|
|
||||||
switch (m_orientation)
|
switch (m_orientation)
|
||||||
{
|
{
|
||||||
case BoxLayoutOrientation::Horizontal:
|
case BoxLayoutOrientation::LeftToRight:
|
||||||
|
case BoxLayoutOrientation::RightToLeft:
|
||||||
axis = 0; //< x
|
axis = 0; //< x
|
||||||
|
reversed = (m_orientation == BoxLayoutOrientation::RightToLeft);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case BoxLayoutOrientation::Vertical:
|
case BoxLayoutOrientation::BottomToTop:
|
||||||
|
case BoxLayoutOrientation::TopToBottom:
|
||||||
axis = 1; //< y
|
axis = 1; //< y
|
||||||
|
reversed = (m_orientation == BoxLayoutOrientation::TopToBottom);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
//TODO: Keep solver state when widgets don't change
|
//TODO: Keep solver state when widgets don't change
|
||||||
std::size_t widgetChildCount = GetWidgetChildCount();
|
std::size_t widgetChildCount = GetVisibleWidgetChildCount();
|
||||||
if (widgetChildCount == 0)
|
if (widgetChildCount == 0)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
|
|
@ -58,27 +63,36 @@ namespace Nz
|
||||||
kiwi::Expression sizeSum;
|
kiwi::Expression sizeSum;
|
||||||
|
|
||||||
Nz::Vector2f layoutSize = GetSize();
|
Nz::Vector2f layoutSize = GetSize();
|
||||||
float availableSpace = layoutSize[axis] - m_spacing * (widgetChildCount - 1);
|
float maxLayoutSize = layoutSize[axis];
|
||||||
float perfectSpacePerWidget = availableSpace / widgetChildCount;
|
float availableSpace = maxLayoutSize - m_spacing * (widgetChildCount - 1);
|
||||||
|
|
||||||
// Handle size
|
// Handle size
|
||||||
ForEachWidgetChild([&](BaseWidget* child)
|
ForEachWidgetChild([&](BaseWidget* child)
|
||||||
{
|
{
|
||||||
if (!child->IsVisible())
|
|
||||||
return;
|
|
||||||
|
|
||||||
float maximumSize = child->GetMaximumSize()[axis];
|
float maximumSize = child->GetMaximumSize()[axis];
|
||||||
float minimumSize = child->GetMinimumSize()[axis];
|
float minimumSize = child->GetMinimumSize()[axis];
|
||||||
|
float preferredSize = child->GetPreferredSize()[axis];
|
||||||
|
|
||||||
m_state->sizeVar.emplace_back();
|
m_state->sizeVar.emplace_back();
|
||||||
auto& sizeVar = m_state->sizeVar.back();
|
auto& sizeVar = m_state->sizeVar.back();
|
||||||
|
|
||||||
m_state->solver.addConstraint({ (sizeVar >= minimumSize) | kiwi::strength::required });
|
m_state->solver.addConstraint({ (sizeVar >= minimumSize) | kiwi::strength::required });
|
||||||
|
|
||||||
if (maximumSize < std::numeric_limits<float>::infinity())
|
if (maximumSize < std::numeric_limits<float>::infinity() && maximumSize <= minimumSize)
|
||||||
m_state->solver.addConstraint({ (sizeVar <= maximumSize) | kiwi::strength::required });
|
m_state->solver.addConstraint({ (sizeVar <= maximumSize) | kiwi::strength::required });
|
||||||
|
|
||||||
m_state->solver.addConstraint({ (sizeVar >= perfectSpacePerWidget) | kiwi::strength::medium });
|
if (preferredSize > 0.f)
|
||||||
|
{
|
||||||
|
m_state->solver.addConstraint({ (sizeVar >= preferredSize) | kiwi::strength::medium });
|
||||||
|
m_state->solver.addConstraint({ (sizeVar >= maxLayoutSize) | kiwi::strength::weak });
|
||||||
|
}
|
||||||
|
else if (maximumSize < std::numeric_limits<float>::infinity() && maximumSize <= minimumSize)
|
||||||
|
{
|
||||||
|
m_state->solver.addConstraint({ (sizeVar >= maximumSize) | kiwi::strength::medium });
|
||||||
|
m_state->solver.addConstraint({ (sizeVar >= maxLayoutSize) | kiwi::strength::weak });
|
||||||
|
}
|
||||||
|
else
|
||||||
|
m_state->solver.addConstraint({ (sizeVar >= maxLayoutSize) | kiwi::strength::medium });
|
||||||
|
|
||||||
sizeSum = sizeSum + sizeVar;
|
sizeSum = sizeSum + sizeVar;
|
||||||
});
|
});
|
||||||
|
|
@ -98,11 +112,8 @@ namespace Nz
|
||||||
|
|
||||||
ForEachWidgetChild([&](BaseWidget* child)
|
ForEachWidgetChild([&](BaseWidget* child)
|
||||||
{
|
{
|
||||||
if (!child->IsVisible())
|
|
||||||
return;
|
|
||||||
|
|
||||||
Nz::Vector2f newSize = layoutSize;
|
Nz::Vector2f newSize = layoutSize;
|
||||||
newSize[axis] = SafeCast<float>(m_state->sizeVar[varIndex].value());
|
newSize[axis] = static_cast<float>(m_state->sizeVar[varIndex].value());
|
||||||
|
|
||||||
child->Resize(newSize);
|
child->Resize(newSize);
|
||||||
remainingSize -= newSize[axis];
|
remainingSize -= newSize[axis];
|
||||||
|
|
@ -113,21 +124,81 @@ namespace Nz
|
||||||
float spacing = m_spacing + remainingSize / (widgetChildCount - 1);
|
float spacing = m_spacing + remainingSize / (widgetChildCount - 1);
|
||||||
|
|
||||||
// Handle position
|
// Handle position
|
||||||
float cursor = 0.f;
|
float cursor = (reversed) ? layoutSize[axis] : 0.f;
|
||||||
bool first = true;
|
|
||||||
ForEachWidgetChild([&](BaseWidget* child)
|
ForEachWidgetChild([&](BaseWidget* child)
|
||||||
{
|
{
|
||||||
if (first)
|
if (reversed)
|
||||||
first = false;
|
cursor -= child->GetSize()[axis];
|
||||||
else
|
|
||||||
cursor += spacing;
|
|
||||||
|
|
||||||
Nz::Vector2f position = Nz::Vector2f(0.f, 0.f);
|
Nz::Vector2f position(0.f, 0.f);
|
||||||
position[axis] = cursor;
|
position[axis] = cursor ;
|
||||||
|
|
||||||
child->SetPosition(position);
|
child->SetPosition(position);
|
||||||
|
|
||||||
cursor += child->GetSize()[axis];
|
if (reversed)
|
||||||
|
cursor -= spacing;
|
||||||
|
else
|
||||||
|
cursor += child->GetSize()[axis] + spacing;
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void BoxLayout::OnChildAdded(const BaseWidget* /*child*/)
|
||||||
|
{
|
||||||
|
RecomputePreferredSize();
|
||||||
|
Layout();
|
||||||
|
}
|
||||||
|
|
||||||
|
void BoxLayout::OnChildPreferredSizeUpdated(const BaseWidget* /*child*/)
|
||||||
|
{
|
||||||
|
Layout();
|
||||||
|
}
|
||||||
|
|
||||||
|
void BoxLayout::OnChildVisibilityUpdated(const BaseWidget* /*child*/)
|
||||||
|
{
|
||||||
|
RecomputePreferredSize();
|
||||||
|
Layout();
|
||||||
|
}
|
||||||
|
|
||||||
|
void BoxLayout::OnChildRemoved(const BaseWidget* /*child*/)
|
||||||
|
{
|
||||||
|
RecomputePreferredSize();
|
||||||
|
Layout();
|
||||||
|
}
|
||||||
|
|
||||||
|
void BoxLayout::RecomputePreferredSize()
|
||||||
|
{
|
||||||
|
std::size_t axis;
|
||||||
|
std::size_t otherAxis;
|
||||||
|
switch (m_orientation)
|
||||||
|
{
|
||||||
|
case BoxLayoutOrientation::LeftToRight:
|
||||||
|
case BoxLayoutOrientation::RightToLeft:
|
||||||
|
axis = 0;
|
||||||
|
otherAxis = 1;
|
||||||
|
break;
|
||||||
|
|
||||||
|
case BoxLayoutOrientation::BottomToTop:
|
||||||
|
case BoxLayoutOrientation::TopToBottom:
|
||||||
|
axis = 1;
|
||||||
|
otherAxis = 0;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
float childCount = 0.f;
|
||||||
|
|
||||||
|
Vector2f preferredSize;
|
||||||
|
ForEachWidgetChild([&](const BaseWidget* child)
|
||||||
|
{
|
||||||
|
const Vector2f& childPreferredSize = child->GetPreferredSize();
|
||||||
|
preferredSize[axis] += childPreferredSize[axis];
|
||||||
|
preferredSize[otherAxis] = std::max(preferredSize[otherAxis], childPreferredSize[otherAxis]);
|
||||||
|
|
||||||
|
childCount += 1.f;
|
||||||
|
});
|
||||||
|
|
||||||
|
if (childCount > 1.f)
|
||||||
|
preferredSize[axis] += m_spacing * (childCount - 1.f);
|
||||||
|
|
||||||
|
SetPreferredSize(preferredSize);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -23,7 +23,7 @@ namespace Nz
|
||||||
|
|
||||||
Vector2f size(drawer.GetBounds().GetLengths());
|
Vector2f size(drawer.GetBounds().GetLengths());
|
||||||
SetMinimumSize(size);
|
SetMinimumSize(size);
|
||||||
SetPreferredSize(size + Vector2f(20.f, 10.f));
|
SetPreferredSize(size + Vector2f(20.f, 10.f)); //< corner size (TODO: Retrieve them from theme)
|
||||||
|
|
||||||
Layout();
|
Layout();
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -20,7 +20,7 @@ namespace Nz
|
||||||
{
|
{
|
||||||
m_canvas = this;
|
m_canvas = this;
|
||||||
BaseWidget::m_registry = &m_registry;
|
BaseWidget::m_registry = &m_registry;
|
||||||
m_widgetParent = nullptr;
|
m_parentWidget = nullptr;
|
||||||
|
|
||||||
SetBaseRenderLayer(initialRenderLayer);
|
SetBaseRenderLayer(initialRenderLayer);
|
||||||
|
|
||||||
|
|
@ -99,10 +99,10 @@ namespace Nz
|
||||||
if (functor(targetWidget))
|
if (functor(targetWidget))
|
||||||
return;
|
return;
|
||||||
|
|
||||||
if (!targetWidget.widget->m_widgetParent)
|
if (!targetWidget.widget->m_parentWidget)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
widgetIndex = targetWidget.widget->m_widgetParent->m_canvasIndex;
|
widgetIndex = targetWidget.widget->m_parentWidget->m_canvasIndex;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -27,7 +27,7 @@ namespace Nz
|
||||||
|
|
||||||
Vector2f size(drawer.GetBounds().GetLengths());
|
Vector2f size(drawer.GetBounds().GetLengths());
|
||||||
SetMinimumSize(size);
|
SetMinimumSize(size);
|
||||||
SetPreferredSize(size + Vector2f(20.f, 10.f));
|
SetPreferredSize(size);
|
||||||
|
|
||||||
Layout();
|
Layout();
|
||||||
}
|
}
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue