quickshell/src/widgets/marginwrapper.cpp
outfoxxed f842b84a5a
widgets/wrapper: round child position when centering
Fixes misalignment when resizeChild is false and wrapper width is odd.
2025-06-26 12:43:59 -07:00

149 lines
4.7 KiB
C++

#include "marginwrapper.hpp"
#include <cmath>
#include <qobject.h>
#include <qquickitem.h>
#include <qtmetamacros.h>
#include "wrapper.hpp"
namespace qs::widgets {
MarginWrapperManager::MarginWrapperManager(QObject* parent): WrapperManager(parent) {
this->bTopMargin.setBinding([this] {
return this->bExtraMargin
+ (this->bOverrides.value().testFlag(TopMargin) ? this->bTopMarginOverride : this->bMargin
);
});
this->bBottomMargin.setBinding([this] {
return this->bExtraMargin
+ (this->bOverrides.value().testFlag(BottomMargin) ? this->bBottomMarginOverride
: this->bMargin);
});
this->bLeftMargin.setBinding([this] {
return this->bExtraMargin
+ (this->bOverrides.value().testFlag(LeftMargin) ? this->bLeftMarginOverride
: this->bMargin);
});
this->bRightMargin.setBinding([this] {
return this->bExtraMargin
+ (this->bOverrides.value().testFlag(RightMargin) ? this->bRightMarginOverride
: this->bMargin);
});
this->bChildX.setBinding([this] {
if (this->bResizeChild) return this->bLeftMargin.value();
auto total = this->bLeftMargin + this->bRightMargin;
auto mul = total == 0 ? 0.5 : this->bLeftMargin / total;
auto margin = this->bWrapperWidth - this->bChildImplicitWidth;
return std::round(margin * mul);
});
this->bChildY.setBinding([this] {
if (this->bResizeChild) return this->bTopMargin.value();
auto total = this->bTopMargin + this->bBottomMargin;
auto mul = total == 0 ? 0.5 : this->bTopMargin / total;
auto margin = this->bWrapperHeight - this->bChildImplicitHeight;
return std::round(margin * mul);
});
this->bChildWidth.setBinding([this] {
if (this->bResizeChild) {
return this->bWrapperWidth - (this->bLeftMargin + this->bRightMargin);
} else {
return this->bChildImplicitWidth.value();
}
});
this->bChildHeight.setBinding([this] {
if (this->bResizeChild) {
return this->bWrapperHeight - (this->bTopMargin + this->bBottomMargin);
} else {
return this->bChildImplicitHeight.value();
}
});
this->bWrapperImplicitWidth.setBinding([this] {
if (this->bOverrides.value().testFlag(ImplicitWidth)) {
return this->bImplicitWidthOverride.value();
} else {
return this->bChildImplicitWidth.value() + this->bLeftMargin + this->bRightMargin;
}
});
this->bWrapperImplicitHeight.setBinding([this] {
if (this->bOverrides.value().testFlag(ImplicitHeight)) {
return this->bImplicitHeightOverride.value();
} else {
return this->bChildImplicitHeight.value() + this->bTopMargin + this->bBottomMargin;
}
});
}
void MarginWrapperManager::componentComplete() {
this->WrapperManager::componentComplete();
if (this->mWrapper) {
this->bWrapperWidth.setBinding([this] { return this->mWrapper->bindableWidth().value(); });
this->bWrapperHeight.setBinding([this] { return this->mWrapper->bindableHeight().value(); });
this->setWrapperImplicitWidth();
this->setWrapperImplicitHeight();
}
}
void MarginWrapperManager::disconnectChild() {
this->mChild->bindableX().setValue(0);
this->mChild->bindableY().setValue(0);
this->mChild->bindableWidth().setValue(0);
this->mChild->bindableHeight().setValue(0);
}
void MarginWrapperManager::connectChild() {
// QObject::disconnect in MarginWrapper handles disconnecting old item
this->mChild->bindableX().setBinding([this] { return this->bChildX.value(); });
this->mChild->bindableY().setBinding([this] { return this->bChildY.value(); });
this->mChild->bindableWidth().setBinding([this] { return this->bChildWidth.value(); });
this->mChild->bindableHeight().setBinding([this] { return this->bChildHeight.value(); });
QObject::connect(
this->mChild,
&QQuickItem::implicitWidthChanged,
this,
&MarginWrapperManager::onChildImplicitWidthChanged
);
QObject::connect(
this->mChild,
&QQuickItem::implicitHeightChanged,
this,
&MarginWrapperManager::onChildImplicitHeightChanged
);
this->onChildImplicitWidthChanged();
this->onChildImplicitHeightChanged();
}
void MarginWrapperManager::onChildImplicitWidthChanged() {
this->bChildImplicitWidth = this->mChild->implicitWidth();
}
void MarginWrapperManager::onChildImplicitHeightChanged() {
this->bChildImplicitHeight = this->mChild->implicitHeight();
}
void MarginWrapperManager::setWrapperImplicitWidth() {
if (this->mWrapper) this->mWrapper->setImplicitWidth(this->bWrapperImplicitWidth);
emit this->implicitWidthChanged();
}
void MarginWrapperManager::setWrapperImplicitHeight() {
if (this->mWrapper) this->mWrapper->setImplicitHeight(this->bWrapperImplicitHeight);
emit this->implicitHeightChanged();
}
} // namespace qs::widgets