13 #define CONSTRAINTS_SET(property, value) \
15 auto constraints = m_Constraints.find(child); \
16 if (constraints != m_Constraints.end()) \
18 (*constraints).second.property = value; \
22 m_Constraints[child] = Constraints{}; \
23 m_Constraints[child].property = value; \
26 #define CONSTRAINTS_GET(property, defaultValue) \
28 auto constraints = m_Constraints.find(child); \
29 return (constraints != m_Constraints.end()) ? (*constraints).second.property : \
32 AnchorPane::Constraints AnchorPane::getConstraints(Component* child)
const
36 auto constraints = m_Constraints.find(child);
37 if (constraints != m_Constraints.end())
39 return (*constraints).second;
45 bool AnchorPane::hasConstraints(Component* child)
const
49 auto constraints = m_Constraints.find(child);
50 if (constraints == m_Constraints.end())
55 const Anchors& anchors = (*constraints).second.anchors;
57 return anchors.topAnchor != ANCHOR_NOT_ENABLED ||
58 anchors.rightAnchor != ANCHOR_NOT_ENABLED ||
59 anchors.bottomAnchor != ANCHOR_NOT_ENABLED ||
60 anchors.leftAnchor != ANCHOR_NOT_ENABLED;
63 void AnchorPane::setHorizontalRelativePositioning(Component* child,
bool enabled)
65 CONSTRAINTS_SET(isHorizontalRelative, enabled);
68 void AnchorPane::setVerticalRelativePositioning(Component* child,
bool enabled)
70 CONSTRAINTS_SET(isVerticalRelative, enabled);
73 bool AnchorPane::isHorizontalRelativePositioning(Component* child)
const
75 CONSTRAINTS_GET(isHorizontalRelative,
false);
78 bool AnchorPane::isVerticalRelativePositioning(Component* child)
const
80 CONSTRAINTS_GET(isVerticalRelative,
false);
83 void AnchorPane::setTopAnchor(Component* child, int32_t anchor)
85 CONSTRAINTS_SET(anchors.topAnchor, anchor);
88 void AnchorPane::setRightAnchor(Component* child, int32_t anchor)
90 CONSTRAINTS_SET(anchors.rightAnchor, anchor);
93 void AnchorPane::setBottomAnchor(Component* child, int32_t anchor)
95 CONSTRAINTS_SET(anchors.bottomAnchor, anchor);
98 void AnchorPane::setLeftAnchor(Component* child, int32_t anchor)
100 CONSTRAINTS_SET(anchors.leftAnchor, anchor);
103 int32_t AnchorPane::getTopAnchor(Component* child)
const
105 CONSTRAINTS_GET(anchors.topAnchor, ANCHOR_NOT_ENABLED);
108 int32_t AnchorPane::getRightAnchor(Component* child)
const
110 CONSTRAINTS_GET(anchors.rightAnchor, ANCHOR_NOT_ENABLED);
113 int32_t AnchorPane::getBottomAnchor(Component* child)
const
115 CONSTRAINTS_GET(anchors.bottomAnchor, ANCHOR_NOT_ENABLED);
118 int32_t AnchorPane::getLeftAnchor(Component* child)
const
120 CONSTRAINTS_GET(anchors.leftAnchor, ANCHOR_NOT_ENABLED);
123 void AnchorPane::layoutChildren()
125 Sml::Rectangle<int32_t> contentArea = getContentArea();
127 for (
auto child : m_Children)
129 Constraints constraints = getConstraints(child);
131 if (!hasConstraints(child))
133 child->setLayoutWidth(child->computePrefWidth());
134 child->setLayoutHeight(child->computePrefHeight());
139 if (isHorizontalRelativePositioning(child))
141 int32_t prefWidth = child->computePrefWidth();
142 int32_t freeWidth = contentArea.width - prefWidth;
144 child->setLayoutWidth(prefWidth);
146 int32_t totalAnchors = constraints.anchors.leftAnchor + constraints.anchors.rightAnchor;
147 int32_t leftOffset = freeWidth * (
static_cast<float>(constraints.anchors.leftAnchor) / totalAnchors);
149 child->setLayoutX(contentArea.pos.x + leftOffset);
151 else if (constraints.anchors.leftAnchor != ANCHOR_NOT_ENABLED &&
152 constraints.anchors.rightAnchor != ANCHOR_NOT_ENABLED)
154 child->setLayoutX(contentArea.pos.x + constraints.anchors.leftAnchor);
155 child->setLayoutWidth(contentArea.width -
156 constraints.anchors.leftAnchor -
157 constraints.anchors.rightAnchor);
159 else if (constraints.anchors.leftAnchor != ANCHOR_NOT_ENABLED &&
160 constraints.anchors.rightAnchor == ANCHOR_NOT_ENABLED)
162 child->setLayoutX(contentArea.pos.x + constraints.anchors.leftAnchor);
163 child->setLayoutWidth(child->computePrefWidth());
165 else if (constraints.anchors.leftAnchor == ANCHOR_NOT_ENABLED &&
166 constraints.anchors.rightAnchor != ANCHOR_NOT_ENABLED)
168 child->setLayoutWidth(child->computePrefWidth());
169 child->setLayoutX(contentArea.pos.x + contentArea.width - child->getLayoutWidth() -
170 constraints.anchors.rightAnchor);
174 child->setLayoutWidth(child->computePrefWidth());
178 if (isVerticalRelativePositioning(child))
180 int32_t prefHeight = child->computePrefHeight();
181 int32_t freeHeight = contentArea.height - prefHeight;
183 child->setLayoutHeight(prefHeight);
185 int32_t totalAnchors = constraints.anchors.topAnchor + constraints.anchors.bottomAnchor;
186 int32_t topOffset = freeHeight * (
static_cast<float>(constraints.anchors.topAnchor) / totalAnchors);
188 child->setLayoutY(contentArea.pos.y + topOffset);
190 else if (constraints.anchors.topAnchor != ANCHOR_NOT_ENABLED &&
191 constraints.anchors.bottomAnchor != ANCHOR_NOT_ENABLED)
193 child->setLayoutY(contentArea.pos.y + constraints.anchors.topAnchor);
194 child->setLayoutHeight(contentArea.height -
195 constraints.anchors.topAnchor -
196 constraints.anchors.bottomAnchor);
198 else if (constraints.anchors.topAnchor != ANCHOR_NOT_ENABLED &&
199 constraints.anchors.bottomAnchor == ANCHOR_NOT_ENABLED)
201 child->setLayoutY(contentArea.pos.y + constraints.anchors.topAnchor);
202 child->setLayoutHeight(child->computePrefHeight());
204 else if (constraints.anchors.topAnchor == ANCHOR_NOT_ENABLED &&
205 constraints.anchors.bottomAnchor != ANCHOR_NOT_ENABLED)
207 child->setLayoutHeight(child->computePrefHeight());
208 child->setLayoutY(contentArea.pos.y + contentArea.height - child->getLayoutHeight() -
209 constraints.anchors.bottomAnchor);
213 child->setLayoutHeight(child->computePrefHeight());
218 int32_t AnchorPane::computeCustomPrefWidth(int32_t height)
const
220 int32_t maxNeededWidth = 0;
221 for (
auto child : m_Children)
223 int32_t leftOffset = getLeftAnchor(child);
224 int32_t rightOffset = getRightAnchor(child);
226 if (leftOffset == ANCHOR_NOT_ENABLED && rightOffset == ANCHOR_NOT_ENABLED)
231 int32_t neededWidth = child->computePrefWidth();
232 if (!isHorizontalRelativePositioning(child))
234 if (leftOffset != ANCHOR_NOT_ENABLED) { neededWidth += leftOffset; }
235 if (rightOffset != ANCHOR_NOT_ENABLED) { neededWidth += rightOffset; }
238 if (neededWidth > maxNeededWidth)
240 maxNeededWidth = neededWidth;
244 int32_t defaultPrefWidth = Container::computeCustomPrefWidth(height);
246 return std::max(defaultPrefWidth, getInsets().left + getInsets().right + maxNeededWidth);
249 int32_t AnchorPane::computeCustomPrefHeight(int32_t width)
const
251 int32_t maxNeededHeight = 0;
252 for (
auto child : m_Children)
254 int32_t topOffset = getTopAnchor(child);
255 int32_t bottomOffset = getBottomAnchor(child);
257 if (topOffset == ANCHOR_NOT_ENABLED && bottomOffset == ANCHOR_NOT_ENABLED)
262 int32_t neededHeight = child->computePrefHeight();
263 if (!isVerticalRelativePositioning(child))
265 if (topOffset != ANCHOR_NOT_ENABLED) { neededHeight += topOffset; }
266 if (bottomOffset != ANCHOR_NOT_ENABLED) { neededHeight += bottomOffset; }
269 if (neededHeight > maxNeededHeight)
271 maxNeededHeight = neededHeight;
275 int32_t defaultPrefHeight = Container::computeCustomPrefHeight(width);
277 return std::max(defaultPrefHeight, getInsets().top + getInsets().bottom + maxNeededHeight);
281 int32_t AnchorPane::computeCustomMinWidth(int32_t height)
const
287 int32_t AnchorPane::computeCustomMinHeight(int32_t width)
const