Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 3 additions & 1 deletion src/ui/trackerview.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -767,7 +767,9 @@ bool TrackerView::addLayoutNode(Container* container, const LayoutNode& node, si
for (const auto& row: rows) {
if (row.size()>colCount) colCount = row.size();
}
Container *w = new SimpleContainer(0,0,container->getWidth(),container->getHeight()); // TODO: itemgrid
auto w = new SimpleContainer(0,0,container->getWidth(),container->getHeight()); // TODO: itemgrid
w->setHAlign(str2itemHalign(node.getHAlignment()));
w->setVAlign(str2itemValign(node.getVAlignment()));
w->setDropShaodw(node.getDropShadow(container->getDropShadow()));
auto m = node.getMargin();
w->setMargin({m.left, m.top, m.right, m.bottom});
Expand Down
122 changes: 101 additions & 21 deletions src/uilib/container.h
Original file line number Diff line number Diff line change
@@ -1,29 +1,36 @@
#ifndef _UILIB_CONTAINER_H
#define _UILIB_CONTAINER_H
#pragma once

#include "widget.h"
#include <deque>
#include <algorithm>
#include <deque>
#include <limits>
#include "label.h" // HAlign, VAlign
#include "widget.h"

#ifndef NDEBUG
#include <typeinfo>
#include <stdio.h>
#endif


namespace Ui {

class Container : public Widget {
public:
virtual ~Container() {
virtual ~Container()
{
clearChildren();
}
virtual void addChild(Widget* child) {

virtual void addChild(Widget* child)
{
if (!child) return;
_children.push_back(child);
if (child->getHGrow()>_hGrow) _hGrow = child->getHGrow();
if (child->getVGrow()>_vGrow) _vGrow = child->getVGrow();
}
virtual void removeChild(Widget* child) {

virtual void removeChild(Widget* child)
{
if (!child) return;
if (child == _hoverChild) {
_hoverChild = nullptr;
Expand All @@ -46,7 +53,8 @@ class Container : public Widget {
return std::find(_children.begin(), _children.end(), child) != _children.end();
}

virtual void clearChildren() {
virtual void clearChildren()
{
if (_hoverChild) {
_hoverChild->onMouseLeave.emit(_hoverChild);
_hoverChild = nullptr;
Expand All @@ -56,7 +64,9 @@ class Container : public Widget {
}
_children.clear();
}
virtual void raiseChild(Widget* child) {

virtual void raiseChild(Widget* child)
{
if (!child) return;
for (auto it=_children.begin(); it!=_children.end(); it++) {
if (*it == child) {
Expand All @@ -66,7 +76,45 @@ class Container : public Widget {
}
}
}
virtual void render(Renderer renderer, int offX, int offY) override {

void render(Renderer renderer, int offX, int offY) override
{
if (_hAlign == Label::HAlign::LEFT) {
_renderOffset.left = 0;
} else {
int maxX = 0;
int minX = std::numeric_limits<int>::max();
for (const auto child : _children) {
if (child->getLeft() < minX)
minX = child->getLeft();
if (child->getLeft() + child->getWidth() > maxX)
maxX = child->getLeft() + child->getWidth();
}
if (_hAlign == Label::HAlign::RIGHT) {
_renderOffset.left = std::max(0, _size.width - (maxX - minX));
} else {
_renderOffset.left = std::max(0, (_size.width - (maxX - minX))/2);
}
}

if (_vAlign == Label::VAlign::TOP) {
_renderOffset.top = 0;
} else {
int maxY = 0;
int minY = std::numeric_limits<int>::max();
for (const auto child : _children) {
if (child->getTop() < minY)
minY = child->getTop();
if (child->getTop() + child->getHeight() > maxY)
maxY = child->getTop() + child->getHeight();
}
if (_vAlign == Label::VAlign::BOTTOM) {
_renderOffset.top = std::max(0, _size.height - (maxY - minY));
} else {
_renderOffset.top = std::max(0, (_size.height - (maxY - minY))/2);
}
}

if (_backgroundColor.a > 0) {
const auto& c = _backgroundColor;
SDL_SetRenderDrawColor(renderer, c.r, c.g, c.b, c.a);
Expand All @@ -78,38 +126,60 @@ class Container : public Widget {
SDL_RenderFillRect(renderer, &r);
}
// TODO: background image
offX += _renderOffset.left;
offY += _renderOffset.top;
for (auto& child: _children)
if (child->getVisible())
child->render(renderer, offX+_pos.left, offY+_pos.top);
}
const std::deque<Widget*> getChildren() const { return _children; }

virtual bool isHover(Widget* w) const override {
const std::deque<Widget*>& getChildren() const
{
return _children;
}

bool isHover(Widget* w) const override
{
return (w == this || (_hoverChild && _hoverChild->isHover(w)));
}

virtual bool isHit(int x, int y) const override {
bool isHit(int x, int y) const override
{
if (!_mouseInteraction)
return false;
if (_backgroundColor.a && Widget::isHit(x, y))
return true;
x -= _pos.left;
y -= _pos.top;
x -= _pos.left + _renderOffset.left;
y -= _pos.top + _renderOffset.top;
for (const auto& w: _children) {
if (w->isHit(x, y))
return true;
}
return false;
}

virtual const Widget* getHit(int x, int y) const override {
const Widget* getHit(int x, int y) const override
{
for (const auto& w: _children) {
if (w->getHit(x - w->getLeft(), y - w->getTop())) return w;
if (w->getHit(x - w->getLeft() - _renderOffset.left,
y - w->getTop() - _renderOffset.top))
return w;
}
if (Widget::isHit(x + _pos.left, y + _pos.top)) return this;
if (Widget::isHit(x + _pos.left, y + _pos.top))
return this;
return nullptr;
}

void setHAlign(const Label::HAlign hAlign)
{
_hAlign = hAlign;
}

void setVAlign(const Label::VAlign vAlign)
{
_vAlign = vAlign;
}

#ifndef NDEBUG
void dumpTree(size_t depth=0) {
printf("%s", std::string(depth, ' ').c_str());
Expand All @@ -129,11 +199,16 @@ class Container : public Widget {
protected:
std::deque<Widget*> _children;
Widget* _hoverChild = nullptr;

Position _renderOffset = {0, 0};
Label::HAlign _hAlign = Label::HAlign::LEFT;
Label::VAlign _vAlign = Label::VAlign::TOP;

Container(int x=0, int y=0, int w=0, int h=0)
: Widget(x,y,w,h)
{
onClick += { this, [this](void* s, int x, int y, int button) {
x -= _renderOffset.left;
y -= _renderOffset.top;
for (auto childIt = _children.rbegin(); childIt != _children.rend(); childIt++) {
auto& child = *childIt;
if (child->getVisible() && child->isHit(x, y)) {
Expand All @@ -142,7 +217,10 @@ class Container : public Widget {
}
}
}};

onMouseMove += { this, [this](void* s, int x, int y, unsigned buttons) {
x -= _renderOffset.left;
y -= _renderOffset.top;
auto oldHoverChild = _hoverChild;
bool match = false;
for (auto childIt = _children.rbegin(); childIt != _children.rend(); childIt++) {
Expand Down Expand Up @@ -171,20 +249,22 @@ class Container : public Widget {
if (oldHoverChild && !_hoverChild)
oldHoverChild->onMouseLeave.emit(oldHoverChild);
}};

onMouseLeave += { this, [this](void* s) {
auto oldHoverChild = _hoverChild;
if (oldHoverChild) {
_hoverChild = nullptr;
oldHoverChild->onMouseLeave.emit(oldHoverChild);
}
}};

onScroll += { this, [this](void* s, int x, int y, unsigned mod) {
x -= _renderOffset.left;
y -= _renderOffset.top;
if (_hoverChild)
_hoverChild->onScroll.emit(_hoverChild, x, y, mod);
}};
}
};

} // namespace Ui

#endif // _UILIB_CONTAINER_H
17 changes: 9 additions & 8 deletions src/uilib/simplecontainer.h
Original file line number Diff line number Diff line change
@@ -1,8 +1,8 @@
#ifndef _UILIB_SIMPLECONTAINER_H
#define _UILIB_SIMPLECONTAINER_H
#pragma once

#include "container.h"


namespace Ui {

// 1 child that spans the whole container
Expand All @@ -12,7 +12,7 @@ class SimpleContainer : public Container {
: Container(x,y,w,h)
{}

virtual void setSize(Size size) override
void setSize(Size size) override
{
if (size == _size) return;
Container::setSize(size);
Expand All @@ -30,7 +30,8 @@ class SimpleContainer : public Container {
break; // only the first child for now; TODO: only container-sized widgets?
}
}
virtual void addChild(Widget* child) override

void addChild(Widget* child) override
{
if (!child) return;
Container::addChild(child);
Expand All @@ -39,7 +40,8 @@ class SimpleContainer : public Container {
if (fireMin) onMinSizeChanged.emit(this);
if (fireMax) onMaxSizeChanged.emit(this);
}
virtual void removeChild(Widget* child) override

void removeChild(Widget* child) override
{
if (!child) return;
Container::removeChild(child);
Expand Down Expand Up @@ -74,7 +76,7 @@ class SimpleContainer : public Container {
}
return res;
}

Signal<> onMinSizeChanged; // TODO: make split between simplecontainer and container more logical
Signal<> onMaxSizeChanged;

Expand All @@ -88,6 +90,7 @@ class SimpleContainer : public Container {
if (minh>_minSize.height) _minSize.height = minh;
return (old != _minSize);
}

bool calculateMaxSize(Widget* child)
{
int maxw = child->getMaxWidth();
Expand All @@ -104,5 +107,3 @@ class SimpleContainer : public Container {
};

} // namespace

#endif // _UILIB_SIMPLECONTAINER_H
Loading