Skip to content

Commit 3cf96ec

Browse files
committed
widgets/wrapper: support overriding implicit size
1 parent e135de9 commit 3cf96ec

File tree

7 files changed

+146
-26
lines changed

7 files changed

+146
-26
lines changed

src/widgets/ClippingWrapperRectangle.qml

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -41,6 +41,16 @@ ClippingRectangle {
4141
/// Determines if child item should be resized larger than its implicit size if
4242
/// the parent is resized larger than its implicit size. Defaults to false.
4343
property /*bool*/alias resizeChild: manager.resizeChild
44+
/// Overrides the implicit width of the wrapper.
45+
///
46+
/// Defaults to the implicit width of the content item plus its left and right margin,
47+
/// and may be reset by assigning `undefined`.
48+
property /*real*/alias implicitWidth: manager.implicitWidth
49+
/// Overrides the implicit height of the wrapper.
50+
///
51+
/// Defaults to the implicit width of the content item plus its top and bottom margin,
52+
/// and may be reset by assigning `undefined`.
53+
property /*real*/alias implicitHeight: manager.implicitHeight
4454
/// See @@WrapperManager.child for details.
4555
property alias child: manager.child
4656

src/widgets/WrapperItem.qml

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -55,6 +55,16 @@ Item {
5555
/// Determines if child item should be resized larger than its implicit size if
5656
/// the parent is resized larger than its implicit size. Defaults to false.
5757
property /*bool*/alias resizeChild: manager.resizeChild
58+
/// Overrides the implicit width of the wrapper.
59+
///
60+
/// Defaults to the implicit width of the content item plus its left and right margin,
61+
/// and may be reset by assigning `undefined`.
62+
property /*real*/alias implicitWidth: manager.implicitWidth
63+
/// Overrides the implicit height of the wrapper.
64+
///
65+
/// Defaults to the implicit width of the content item plus its top and bottom margin,
66+
/// and may be reset by assigning `undefined`.
67+
property /*real*/alias implicitHeight: manager.implicitHeight
5868
/// See @@WrapperManager.child for details.
5969
property /*Item*/alias child: manager.child
6070

src/widgets/WrapperMouseArea.qml

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -43,6 +43,16 @@ MouseArea {
4343
/// Determines if child item should be resized larger than its implicit size if
4444
/// the parent is resized larger than its implicit size. Defaults to false.
4545
property /*bool*/alias resizeChild: manager.resizeChild
46+
/// Overrides the implicit width of the wrapper.
47+
///
48+
/// Defaults to the implicit width of the content item plus its left and right margin,
49+
/// and may be reset by assigning `undefined`.
50+
property /*real*/alias implicitWidth: manager.implicitWidth
51+
/// Overrides the implicit height of the wrapper.
52+
///
53+
/// Defaults to the implicit width of the content item plus its top and bottom margin,
54+
/// and may be reset by assigning `undefined`.
55+
property /*real*/alias implicitHeight: manager.implicitHeight
4656
/// See @@WrapperManager.child for details.
4757
property /*Item*/alias child: manager.child
4858

src/widgets/WrapperRectangle.qml

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -45,6 +45,16 @@ Rectangle {
4545
/// Determines if child item should be resized larger than its implicit size if
4646
/// the parent is resized larger than its implicit size. Defaults to false.
4747
property /*bool*/alias resizeChild: manager.resizeChild
48+
/// Overrides the implicit width of the wrapper.
49+
///
50+
/// Defaults to the implicit width of the content item plus its left and right margin,
51+
/// and may be reset by assigning `undefined`.
52+
property /*real*/alias implicitWidth: manager.implicitWidth
53+
/// Overrides the implicit height of the wrapper.
54+
///
55+
/// Defaults to the implicit width of the content item plus its top and bottom margin,
56+
/// and may be reset by assigning `undefined`.
57+
property /*real*/alias implicitHeight: manager.implicitHeight
4858
/// See @@WrapperManager.child for details.
4959
property alias child: manager.child
5060

src/widgets/marginwrapper.cpp

Lines changed: 21 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@
22

33
#include <qobject.h>
44
#include <qquickitem.h>
5+
#include <qtmetamacros.h>
56

67
#include "wrapper.hpp"
78

@@ -10,22 +11,26 @@ namespace qs::widgets {
1011
MarginWrapperManager::MarginWrapperManager(QObject* parent): WrapperManager(parent) {
1112
this->bTopMargin.setBinding([this] {
1213
return this->bExtraMargin
13-
+ (this->bTopMarginSet.value() ? this->bTopMarginValue : this->bMargin);
14+
+ (this->bOverrides.value().testFlag(TopMargin) ? this->bTopMarginOverride : this->bMargin
15+
);
1416
});
1517

1618
this->bBottomMargin.setBinding([this] {
1719
return this->bExtraMargin
18-
+ (this->bBottomMarginSet.value() ? this->bBottomMarginValue : this->bMargin);
20+
+ (this->bOverrides.value().testFlag(BottomMargin) ? this->bBottomMarginOverride
21+
: this->bMargin);
1922
});
2023

2124
this->bLeftMargin.setBinding([this] {
2225
return this->bExtraMargin
23-
+ (this->bLeftMarginSet.value() ? this->bLeftMarginValue : this->bMargin);
26+
+ (this->bOverrides.value().testFlag(LeftMargin) ? this->bLeftMarginOverride
27+
: this->bMargin);
2428
});
2529

2630
this->bRightMargin.setBinding([this] {
2731
return this->bExtraMargin
28-
+ (this->bRightMarginSet.value() ? this->bRightMarginValue : this->bMargin);
32+
+ (this->bOverrides.value().testFlag(RightMargin) ? this->bRightMarginOverride
33+
: this->bMargin);
2934
});
3035

3136
this->bChildX.setBinding([this] {
@@ -63,11 +68,19 @@ MarginWrapperManager::MarginWrapperManager(QObject* parent): WrapperManager(pare
6368
});
6469

6570
this->bWrapperImplicitWidth.setBinding([this] {
66-
return this->bChildImplicitWidth.value() + this->bLeftMargin + this->bRightMargin;
71+
if (this->bOverrides.value().testFlag(ImplicitWidth)) {
72+
return this->bImplicitWidthOverride.value();
73+
} else {
74+
return this->bChildImplicitWidth.value() + this->bLeftMargin + this->bRightMargin;
75+
}
6776
});
6877

6978
this->bWrapperImplicitHeight.setBinding([this] {
70-
return this->bChildImplicitHeight.value() + this->bTopMargin + this->bBottomMargin;
79+
if (this->bOverrides.value().testFlag(ImplicitHeight)) {
80+
return this->bImplicitHeightOverride.value();
81+
} else {
82+
return this->bChildImplicitHeight.value() + this->bLeftMargin + this->bRightMargin;
83+
}
7184
});
7285
}
7386

@@ -122,10 +135,12 @@ void MarginWrapperManager::onChildImplicitHeightChanged() {
122135

123136
void MarginWrapperManager::setWrapperImplicitWidth() {
124137
if (this->mWrapper) this->mWrapper->setImplicitWidth(this->bWrapperImplicitWidth);
138+
emit this->implicitWidthChanged();
125139
}
126140

127141
void MarginWrapperManager::setWrapperImplicitHeight() {
128142
if (this->mWrapper) this->mWrapper->setImplicitHeight(this->bWrapperImplicitHeight);
143+
emit this->implicitHeightChanged();
129144
}
130145

131146
} // namespace qs::widgets

src/widgets/marginwrapper.hpp

Lines changed: 60 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
#pragma once
22

3+
#include <qflags.h>
34
#include <qobject.h>
45
#include <qproperty.h>
56
#include <qqmlintegration.h>
@@ -69,6 +70,16 @@ class MarginWrapperManager: public WrapperManager {
6970
/// Determines if child item should be resized larger than its implicit size if
7071
/// the parent is resized larger than its implicit size. Defaults to false.
7172
Q_PROPERTY(bool resizeChild READ default WRITE default BINDABLE bindableResizeChild NOTIFY resizeChildChanged FINAL);
73+
/// Overrides the implicit width of the wrapper.
74+
///
75+
/// Defaults to the implicit width of the content item plus its left and right margin,
76+
/// and may be reset by assigning `undefined`.
77+
Q_PROPERTY(qreal implicitWidth READ implicitWidth WRITE setImplicitWidth RESET resetImplicitWidth NOTIFY implicitWidthChanged FINAL);
78+
/// Overrides the implicit height of the wrapper.
79+
///
80+
/// Defaults to the implicit width of the content item plus its top and bottom margin,
81+
/// and may be reset by assigning `undefined`.
82+
Q_PROPERTY(qreal implicitHeight READ implicitHeight WRITE setImplicitHeight RESET resetImplicitHeight NOTIFY implicitHeightChanged FINAL);
7283
// clang-format on
7384
QML_ELEMENT;
7485

@@ -81,35 +92,61 @@ class MarginWrapperManager: public WrapperManager {
8192
[[nodiscard]] QBindable<qreal> bindableExtraMargin() { return &this->bExtraMargin; }
8293

8394
[[nodiscard]] qreal topMargin() const { return this->bTopMargin.value(); }
84-
void resetTopMargin() { this->bTopMarginSet = false; }
95+
void resetTopMargin() { this->bOverrides = this->bOverrides.value() & ~TopMargin; }
8596
void setTopMargin(qreal topMargin) {
86-
this->bTopMarginValue = topMargin;
87-
this->bTopMarginSet = true;
97+
this->bTopMarginOverride = topMargin;
98+
this->bOverrides = this->bOverrides.value() | TopMargin;
8899
}
89100

90101
[[nodiscard]] qreal bottomMargin() const { return this->bBottomMargin.value(); }
91-
void resetBottomMargin() { this->bBottomMarginSet = false; }
102+
void resetBottomMargin() { this->bOverrides = this->bOverrides.value() & ~BottomMargin; }
92103
void setBottomMargin(qreal bottomMargin) {
93-
this->bBottomMarginValue = bottomMargin;
94-
this->bBottomMarginSet = true;
104+
this->bBottomMarginOverride = bottomMargin;
105+
this->bOverrides = this->bOverrides.value() | BottomMargin;
95106
}
96107

97108
[[nodiscard]] qreal leftMargin() const { return this->bLeftMargin.value(); }
98-
void resetLeftMargin() { this->bLeftMarginSet = false; }
109+
void resetLeftMargin() { this->bOverrides = this->bOverrides.value() & ~LeftMargin; }
99110
void setLeftMargin(qreal leftMargin) {
100-
this->bLeftMarginValue = leftMargin;
101-
this->bLeftMarginSet = true;
111+
this->bLeftMarginOverride = leftMargin;
112+
this->bOverrides = this->bOverrides.value() | LeftMargin;
102113
}
103114

104115
[[nodiscard]] qreal rightMargin() const { return this->bRightMargin.value(); }
105-
void resetRightMargin() { this->bRightMarginSet = false; }
116+
void resetRightMargin() { this->bOverrides = this->bOverrides.value() & ~RightMargin; }
106117
void setRightMargin(qreal rightMargin) {
107-
this->bRightMarginValue = rightMargin;
108-
this->bRightMarginSet = true;
118+
this->bRightMarginOverride = rightMargin;
119+
this->bOverrides = this->bOverrides.value() | RightMargin;
109120
}
110121

111122
[[nodiscard]] QBindable<bool> bindableResizeChild() { return &this->bResizeChild; }
112123

124+
[[nodiscard]] qreal implicitWidth() const { return this->bWrapperImplicitWidth.value(); }
125+
void resetImplicitWidth() { this->bOverrides = this->bOverrides.value() & ~ImplicitWidth; }
126+
void setImplicitWidth(qreal implicitWidth) {
127+
this->bImplicitWidthOverride = implicitWidth;
128+
this->bOverrides = this->bOverrides.value() | ImplicitWidth;
129+
}
130+
131+
[[nodiscard]] qreal implicitHeight() const { return this->bWrapperImplicitHeight.value(); }
132+
void resetImplicitHeight() { this->bOverrides = this->bOverrides.value() & ~ImplicitHeight; }
133+
void setImplicitHeight(qreal implicitHeight) {
134+
this->bImplicitHeightOverride = implicitHeight;
135+
this->bOverrides = this->bOverrides.value() | ImplicitHeight;
136+
}
137+
138+
// has to be public for flag operator definitions
139+
enum OverrideFlag : quint8 {
140+
ImplicitWidth = 0b1,
141+
ImplicitHeight = 0b10,
142+
TopMargin = 0b100,
143+
BottomMargin = 0b1000,
144+
LeftMargin = 0b10000,
145+
RightMargin = 0b100000,
146+
};
147+
148+
Q_DECLARE_FLAGS(OverrideFlags, OverrideFlag);
149+
113150
signals:
114151
void marginChanged();
115152
void baseMarginChanged();
@@ -118,6 +155,8 @@ class MarginWrapperManager: public WrapperManager {
118155
void leftMarginChanged();
119156
void rightMarginChanged();
120157
void resizeChildChanged();
158+
void implicitWidthChanged();
159+
void implicitHeightChanged();
121160

122161
private slots:
123162
void onChildImplicitWidthChanged();
@@ -135,14 +174,13 @@ private slots:
135174
Q_OBJECT_BINDABLE_PROPERTY(MarginWrapperManager, qreal, bMargin, &MarginWrapperManager::marginChanged);
136175
Q_OBJECT_BINDABLE_PROPERTY(MarginWrapperManager, qreal, bExtraMargin, &MarginWrapperManager::baseMarginChanged);
137176

138-
Q_OBJECT_BINDABLE_PROPERTY(MarginWrapperManager, bool, bTopMarginSet);
139-
Q_OBJECT_BINDABLE_PROPERTY(MarginWrapperManager, bool, bBottomMarginSet);
140-
Q_OBJECT_BINDABLE_PROPERTY(MarginWrapperManager, bool, bLeftMarginSet);
141-
Q_OBJECT_BINDABLE_PROPERTY(MarginWrapperManager, bool, bRightMarginSet);
142-
Q_OBJECT_BINDABLE_PROPERTY(MarginWrapperManager, qreal, bTopMarginValue);
143-
Q_OBJECT_BINDABLE_PROPERTY(MarginWrapperManager, qreal, bBottomMarginValue);
144-
Q_OBJECT_BINDABLE_PROPERTY(MarginWrapperManager, qreal, bLeftMarginValue);
145-
Q_OBJECT_BINDABLE_PROPERTY(MarginWrapperManager, qreal, bRightMarginValue);
177+
Q_OBJECT_BINDABLE_PROPERTY(MarginWrapperManager, OverrideFlags, bOverrides);
178+
Q_OBJECT_BINDABLE_PROPERTY(MarginWrapperManager, qreal, bImplicitWidthOverride);
179+
Q_OBJECT_BINDABLE_PROPERTY(MarginWrapperManager, qreal, bImplicitHeightOverride);
180+
Q_OBJECT_BINDABLE_PROPERTY(MarginWrapperManager, qreal, bTopMarginOverride);
181+
Q_OBJECT_BINDABLE_PROPERTY(MarginWrapperManager, qreal, bBottomMarginOverride);
182+
Q_OBJECT_BINDABLE_PROPERTY(MarginWrapperManager, qreal, bLeftMarginOverride);
183+
Q_OBJECT_BINDABLE_PROPERTY(MarginWrapperManager, qreal, bRightMarginOverride);
146184

147185
// computed
148186
Q_OBJECT_BINDABLE_PROPERTY(MarginWrapperManager, qreal, bTopMargin, &MarginWrapperManager::topMarginChanged);
@@ -167,4 +205,6 @@ private slots:
167205
// clang-format on
168206
};
169207

208+
Q_DECLARE_OPERATORS_FOR_FLAGS(MarginWrapperManager::OverrideFlags);
209+
170210
} // namespace qs::widgets

src/widgets/test/manual/marginwrapper.qml

Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -28,6 +28,8 @@ FloatingWindow {
2828
bottomMargin: separateMarginsCb.checked ? bottomMarginSlider.value : undefined
2929
leftMargin: separateMarginsCb.checked ? leftMarginSlider.value : undefined
3030
rightMargin: separateMarginsCb.checked ? rightMarginSlider.value : undefined
31+
implicitWidth: parentImplicitSizeCb.checked ? parentImplicitWidthSlider.value : undefined
32+
implicitHeight: parentImplicitSizeCb.checked ? parentImplicitHeightSlider.value : undefined
3133
}
3234

3335
Rectangle {
@@ -55,6 +57,11 @@ FloatingWindow {
5557
id: separateMarginsCb
5658
text: "Individual Margins"
5759
}
60+
61+
CheckBox {
62+
id: parentImplicitSizeCb
63+
text: "Parent Implicit Size"
64+
}
5865
}
5966

6067
RowLayout {
@@ -93,6 +100,24 @@ FloatingWindow {
93100
}
94101
}
95102

103+
RowLayout {
104+
Layout.fillWidth: true
105+
106+
Label { text: "Parent Implicit Width" }
107+
Slider {
108+
id: parentImplicitWidthSlider
109+
Layout.fillWidth: true
110+
from: 0; to: 300; value: 200
111+
}
112+
113+
Label { text: "Parent Implicit Height" }
114+
Slider {
115+
id: parentImplicitHeightSlider
116+
Layout.fillWidth: true
117+
from: 0; to: 300; value: 200
118+
}
119+
}
120+
96121
RowLayout {
97122
Layout.fillWidth: true
98123

0 commit comments

Comments
 (0)