You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

124 lines
4.3 KiB

#include "uianchorlayout.h"
#include "uiwidget.h"
bool UIAnchorLayout::addAnchor(const UIWidgetPtr& anchoredWidget, AnchorPoint anchoredEdge, const AnchorLine& anchorLine)
{
UIAnchor anchor(anchoredWidget, anchoredEdge, anchorLine);
UIWidgetPtr anchorLineWidget = anchor.getAnchorLineWidget();
/*
if(!anchorLineWidget) {
logError("could not find the widget to anchor on, wrong id?");
return false;
}
*/
// we can never anchor with itself
if(anchoredWidget == anchorLineWidget) {
logError("anchoring with itself is not possible");
return false;
}
// we must never anchor to an anchor child
if(anchoredWidget && hasWidgetInAnchorTree(anchorLineWidget, anchoredWidget)) {
logError("anchors is miss configured, you must never make an anchor chains in loops");
return false;
}
// avoid duplicated anchors
for(auto it = m_anchors.begin(); it != m_anchors.end(); ++it) {
const UIAnchor& otherAnchor = *it;
if(otherAnchor.getAnchoredWidget() == anchoredWidget && otherAnchor.getAnchoredEdge() == anchoredEdge) {
m_anchors.erase(it);
break;
}
}
// setup the anchor
m_anchors.push_back(anchor);
// recalculate anchored widget layout
updateWidget(anchoredWidget);
return true;
}
void UIAnchorLayout::updateWidget(const UIWidgetPtr& widget)
{
Rect rect = widget->getGeometry();
bool verticalMoved = false;
bool horizontalMoved = false;
// FIXME: release expired anchors
for(const UIAnchor& anchor : m_anchors) {
if(anchor.getAnchoredWidget() == widget && anchor.getAnchorLineWidget()) {
int point = anchor.getAnchorLinePoint();
switch(anchor.getAnchoredEdge()) {
case AnchorHorizontalCenter:
rect.moveHorizontalCenter(point + widget->getMarginLeft() - widget->getMarginRight());
horizontalMoved = true;
break;
case AnchorLeft:
if(!horizontalMoved) {
rect.moveLeft(point + widget->getMarginLeft());
horizontalMoved = true;
} else
rect.setLeft(point + widget->getMarginLeft());
break;
case AnchorRight:
if(!horizontalMoved) {
rect.moveRight(point - widget->getMarginRight());
horizontalMoved = true;
} else
rect.setRight(point - widget->getMarginRight());
break;
case AnchorVerticalCenter:
rect.moveVerticalCenter(point + widget->getMarginTop() - widget->getMarginBottom());
verticalMoved = true;
break;
case AnchorTop:
if(!verticalMoved) {
rect.moveTop(point + widget->getMarginTop());
verticalMoved = true;
} else
rect.setTop(point + widget->getMarginTop());
break;
case AnchorBottom:
if(!verticalMoved) {
rect.moveBottom(point - widget->getMarginBottom());
verticalMoved = true;
} else
rect.setBottom(point - widget->getMarginBottom());
break;
default:
break;
}
}
}
if(rect != widget->getGeometry())
widget->setGeometry(rect);
}
void UIAnchorLayout::updateWidgetChildren(const UIWidgetPtr& parent)
{
for(const UIAnchor& anchor : m_anchors) {
if(anchor.getAnchorLineWidget() == parent) {
UIWidgetPtr child = anchor.getAnchoredWidget();
if(child)
updateWidget(child);
}
}
}
bool UIAnchorLayout::hasWidgetInAnchorTree(const UIWidgetPtr& widget, const UIWidgetPtr& treeAnchor)
{
for(const UIAnchor& anchor : m_anchors) {
if(anchor.getAnchorLineWidget() == treeAnchor) {
if(anchor.getAnchoredWidget() == widget || hasWidgetInAnchorTree(widget, anchor.getAnchoredWidget()))
return true;
}
}
return false;
}