neoGFX
Cross-platform C++ app/game engine
Loading...
Searching...
No Matches
layout_item.hpp
Go to the documentation of this file.
1// layout_item.hpp
2/*
3 neogfx C++ App/Game Engine
4 Copyright (c) 2018, 2020 Leigh Johnston. All Rights Reserved.
5
6 This program is free software: you can redistribute it and / or modify
7 it under the terms of the GNU General Public License as published by
8 the Free Software Foundation, either version 3 of the License, or
9 (at your option) any later version.
10
11 This program is distributed in the hope that it will be useful,
12 but WITHOUT ANY WARRANTY; without even the implied warranty of
13 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 GNU General Public License for more details.
15
16 You should have received a copy of the GNU General Public License
17 along with this program. If not, see <http://www.gnu.org/licenses/>.
18*/
19
20#pragma once
21
22#include <neogfx/neogfx.hpp>
27
28namespace neogfx
29{
30 template <typename Base>
31 class layout_item : public anchorable<reference_counted<Base>>
32 {
35 // events
36 public:
37 define_event(AnchorUpdated, anchor_updated, i_anchor&)
38 // types
39 public:
40 typedef i_layout_item abstract_type;
41 private:
43 // construction
44 public:
46 {
47 }
49 {
50 base_type::set_destroying();
51 }
52 // implementation
53 public:
54 const i_string& id() const final
55 {
56 return iId;
57 }
58 void set_id(const i_string& aId) final
59 {
60 iId = aId;
61 }
62 public:
63 bool is_cache() const final
64 {
65 return false;
66 }
67 public:
68 bool is_layout() const final
69 {
70 return std::is_base_of_v<i_layout, self_type>;
71 }
72 const i_layout& as_layout() const final
73 {
74 if constexpr (std::is_base_of_v<i_layout, self_type>)
75 return static_cast<const i_layout&>(*this);
76 else
77 throw not_a_layout();
78 }
80 {
81 if constexpr (std::is_base_of_v<i_layout, self_type>)
82 return static_cast<i_layout&>(*this);
83 else
84 throw not_a_layout();
85 }
86 bool is_spacer() const final
87 {
88 return std::is_base_of_v<i_spacer, self_type>;
89 }
90 const i_spacer& as_spacer() const final
91 {
92 if constexpr (std::is_base_of_v<i_spacer, self_type>)
93 return static_cast<const i_spacer&>(*this);
94 else
95 throw not_a_spacer();
96 }
97 i_spacer& as_spacer() final
98 {
99 if constexpr (std::is_base_of_v<i_spacer, self_type>)
100 return static_cast<i_spacer&>(*this);
101 else
102 throw not_a_spacer();
103 }
104 bool is_widget() const override
105 {
106 return std::is_base_of_v<i_widget, self_type>;
107 }
108 const i_widget& as_widget() const override
109 {
110 if constexpr (std::is_base_of_v<i_widget, self_type>)
111 return static_cast<const i_widget&>(*this);
112 else
113 throw not_a_widget();
114 }
115 i_widget& as_widget() override
116 {
117 if constexpr (std::is_base_of_v<i_widget, self_type>)
118 return static_cast<i_widget&>(*this);
119 else
120 throw not_a_widget();
121 }
122 public:
123 bool has_parent_layout_item() const final
124 {
125 auto& self = as_layout_item();
126 if (self.has_parent_layout() && self.same_parent_widget_as(self.parent_layout()))
127 return true;
128 else if (self.is_layout() && self.has_parent_widget())
129 return true;
130 else if (self.is_widget() && self.as_widget().has_parent())
131 return true;
132 return false;
133 }
135 {
136 auto& self = as_layout_item();
137 if (self.has_parent_layout() && self.same_parent_widget_as(self.parent_layout()))
138 return self.parent_layout();
139 else if (self.is_layout() && self.has_parent_widget())
140 return self.parent_widget();
141 else if (self.is_widget() && self.as_widget().has_parent())
142 return self.as_widget().parent();
143 throw no_parent_layout_item();
144 }
146 {
147 return const_cast<i_layout_item&>(to_const(*this).parent_layout_item());
148 }
149 public:
150 bool has_layout_manager() const final
151 {
152 auto& self = as_layout_item();
153 if (!self.has_parent_widget())
154 return false;
155 const i_widget* w = &self.parent_widget();
156 if (w->is_managing_layout())
157 return true;
158 while (w->has_parent())
159 {
160 w = &w->parent();
161 if (w->is_managing_layout())
162 return true;
163 };
164 return false;
165 }
166 const i_widget& layout_manager() const final
167 {
168 auto& self = as_layout_item();
169 const i_widget* w = &self.parent_widget();
170 if (w->is_managing_layout())
171 return *w;
172 while (w->has_parent())
173 {
174 w = &w->parent();
175 if (w->is_managing_layout())
176 return *w;
177 };
178 throw no_layout_manager();
179 }
181 {
182 return const_cast<i_widget&>(to_const(*this).layout_manager());
183 }
184 public:
185 void update_layout(bool aDeferLayout = true, bool aAncestors = false) final
186 {
187 auto& self = as_layout_item();
188 if (self.has_parent_layout_item())
189 {
190 if (!self.is_widget() ||
191 (self.as_widget().has_parent_layout() && !self.as_widget().is_managing_layout()) || aAncestors)
192 self.parent_layout_item().update_layout(aDeferLayout, aAncestors);
193 }
194
195#ifdef NEOGFX_DEBUG
196 if (debug::layoutItem == this)
197 service<debug::logger>() << neolib::logger::severity::Debug << "layout_item::update_layout(" << aDeferLayout << ", " << aAncestors << ")" << endl;
198#endif // NEOGFX_DEBUG
199
200 if (self.is_widget() && (!aDeferLayout || self.as_widget().can_defer_layout()))
201 self.as_widget().layout_items(aDeferLayout);
202 else if (self.is_layout())
203 self.as_layout().invalidate(aDeferLayout);
204 }
205 public:
206 point origin() const final
207 {
208 if (!iOrigin)
209 {
210 auto& self = as_layout_item();
211 if (!self.is_widget())
212 {
214 iOrigin = parent_layout_item().origin();
215 else
216 iOrigin = point{};
217 }
218 else
219 {
220 if (!self.as_widget().is_root() || self.as_widget().root().is_nested())
221 {
222 if (self.as_widget().has_parent())
223 iOrigin = self.as_widget().position() + self.as_widget().parent().origin();
224 else
225 iOrigin = self.as_widget().position();
226 }
227 else
228 iOrigin = point{};
229 }
230 }
231 return *iOrigin;
232 }
233 void reset_origin() const final
234 {
235 iOrigin = invalid;
236 }
237 point position() const final
238 {
239 auto& self = as_layout_item();
240 return (self.has_parent_layout_item() ? self.parent_layout_item().transformation(true) : mat33::identity()) *
241 units_converter{ *this }.from_device_units(!Anchor_Position.active() ?
242 static_cast<point>(Position) : static_cast<point>(Position) + Anchor_Position.evaluate_constraints() - unconstrained_origin());
243 }
244 size extents() const final
245 {
246 auto& self = as_layout_item();
247 return (self.has_parent_layout_item() ? self.parent_layout_item().transformation(true) : mat33::identity()) *
248 units_converter{ *this }.from_device_units(!Anchor_Size.active() ?
249 static_cast<size>(Size) : Anchor_Size.evaluate_constraints());
250 }
251 protected:
252 void set_position(const point& aPosition) override
253 {
254 reset_origin();
255 if (Position != units_converter{ *this }.to_device_units(aPosition))
256 Position.assign(units_converter{ *this }.to_device_units(aPosition), false);
257 }
258 void set_extents(const size& aExtents) override
259 {
260 if (Size != units_converter{ *this }.to_device_units(aExtents))
261 Size.assign(units_converter{ *this }.to_device_units(aExtents), false);
262 }
263 public:
264 bool has_size_policy() const noexcept override
265 {
266 return SizePolicy != std::nullopt;
267 }
268 neogfx::size_policy size_policy() const override
269 {
270#ifdef NEOGFX_DEBUG
271 if (debug::layoutItem == this)
272 service<debug::logger>() << neolib::logger::severity::Debug << typeid(*this).name() << "::size_policy()" << endl;
273#endif // NEOGFX_DEBUG
274 if (SizePolicy != std::nullopt)
275 return *SizePolicy;
276 else if (has_fixed_size())
278 else
280 }
281 using i_geometry::set_size_policy;
282 void set_size_policy(const optional_size_policy& aSizePolicy, bool aUpdateLayout = true) override
283 {
284 if (SizePolicy != aSizePolicy)
285 {
286#ifdef NEOGFX_DEBUG
287 if (debug::layoutItem == this)
288 service<debug::logger>() << neolib::logger::severity::Debug << typeid(*this).name() << "::set_size_policy(" << aSizePolicy << ", " << aUpdateLayout << ")" << endl;
289#endif // NEOGFX_DEBUG
290 SizePolicy = aSizePolicy;
291 if (aUpdateLayout)
293 }
294 }
295 bool has_weight() const noexcept override
296 {
297 return Weight != std::nullopt;
298 }
299 size weight() const override
300 {
301 if (has_weight())
302 return *Weight;
303 return size{ 1.0 };
304 }
305 void set_weight(optional_size const& aWeight, bool aUpdateLayout = true) override
306 {
307 if (Weight != aWeight)
308 {
309#ifdef NEOGFX_DEBUG
310 if (debug::layoutItem == this)
311 service<debug::logger>() << neolib::logger::severity::Debug << typeid(*this).name() << "::set_weight(" << aWeight << ", " << aUpdateLayout << ")" << endl;
312#endif // NEOGFX_DEBUG
313 Weight.assign(aWeight, aUpdateLayout);
314 if (aUpdateLayout)
316 }
317 }
318 bool has_ideal_size() const noexcept override
319 {
320 return IdealSize != std::nullopt;
321 }
322 bool is_ideal_size_constrained() const noexcept override
323 {
324 return Anchor_IdealSize.active();
325 }
326 size ideal_size(optional_size const& aAvailableSpace = {}) const override
327 {
328 size result;
329 if (has_ideal_size())
330 result = units_converter{ *this }.from_device_units(*IdealSize);
331 else if (Anchor_IdealSize.active())
332 result = units_converter{ *this }.from_device_units(Anchor_IdealSize.evaluate_constraints(aAvailableSpace));
333 else
334 {
335 scoped_query_ideal_size sqis;
336 result = minimum_size(aAvailableSpace);
337 }
338#ifdef NEOGFX_DEBUG
339 if (debug::layoutItem == this)
340 service<debug::logger>() << neolib::logger::severity::Debug << typeid(*this).name() << "::ideal_size(" << aAvailableSpace << ") --> " << result << endl;
341#endif // NEOGFX_DEBUG
342 return result;
343 }
344 void set_ideal_size(optional_size const& aIdealSize, bool aUpdateLayout = true) override
345 {
346 optional_size newIdealSize = (aIdealSize != std::nullopt ? units_converter{ *this }.to_device_units(*aIdealSize) : optional_size{});
347 if (IdealSize != newIdealSize)
348 {
349#ifdef NEOGFX_DEBUG
350 if (debug::layoutItem == this)
351 service<debug::logger>() << neolib::logger::severity::Debug << typeid(*this).name() << "::set_ideal_size(" << aIdealSize << ", " << aUpdateLayout << ")" << endl;
352#endif // NEOGFX_DEBUG
353 IdealSize.assign(newIdealSize, aUpdateLayout);
354 if (aUpdateLayout)
356 }
357 }
358 bool has_minimum_size() const noexcept override
359 {
360 return MinimumSize != std::nullopt;
361 }
362 bool is_minimum_size_constrained() const noexcept override
363 {
364 return Anchor_MinimumSize.active();
365 }
366 size minimum_size(optional_size const& aAvailableSpace = {}) const override
367 {
368 size result;
369 if (has_minimum_size())
370 result = units_converter{ *this }.from_device_units(*MinimumSize);
371 else if (Anchor_MinimumSize.active())
372 result = units_converter{ *this }.from_device_units(Anchor_MinimumSize.evaluate_constraints(aAvailableSpace));
373 else
374 result = {};
375#ifdef NEOGFX_DEBUG
376 if (debug::layoutItem == this)
377 service<debug::logger>() << neolib::logger::severity::Debug << typeid(*this).name() << "::minimum_size(" << aAvailableSpace << ") --> " << result << endl;
378#endif // NEOGFX_DEBUG
379 return result;
380 }
381 void set_minimum_size(optional_size const& aMinimumSize, bool aUpdateLayout = true) override
382 {
383 optional_size newMinimumSize = (aMinimumSize != std::nullopt ? units_converter{ *this }.to_device_units(*aMinimumSize) : optional_size{});
384 if (MinimumSize != newMinimumSize)
385 {
386#ifdef NEOGFX_DEBUG
387 if (debug::layoutItem == this)
388 service<debug::logger>() << neolib::logger::severity::Debug << typeid(*this).name() << "::set_minimum_size(" << aMinimumSize << ", " << aUpdateLayout << ")" << endl;
389#endif // NEOGFX_DEBUG
390 MinimumSize.assign(newMinimumSize, aUpdateLayout);
391 if (aUpdateLayout)
393 }
394 }
395 bool has_maximum_size() const noexcept override
396 {
397 return MaximumSize != std::nullopt;
398 }
399 bool is_maximum_size_constrained() const noexcept override
400 {
401 return Anchor_MaximumSize.active();
402 }
403 size maximum_size(optional_size const& aAvailableSpace = {}) const override
404 {
405 size result;
406 if (has_maximum_size())
407 result = units_converter{ *this }.from_device_units(*MaximumSize);
408 else if (Anchor_MaximumSize.active())
409 result = units_converter{ *this }.from_device_units(Anchor_MaximumSize.evaluate_constraints(aAvailableSpace));
410 else
411 result = size::max_size();
412 return result;
413 }
414 void set_maximum_size(optional_size const& aMaximumSize, bool aUpdateLayout = true) override
415 {
416 optional_size newMaximumSize = (aMaximumSize != std::nullopt ? units_converter{ *this }.to_device_units(*aMaximumSize) : optional_size{});
417 if (MaximumSize != newMaximumSize)
418 {
419#ifdef NEOGFX_DEBUG
420 if (debug::layoutItem == this)
421 service<debug::logger>() << neolib::logger::severity::Debug << typeid(*this).name() << "::set_maximum_size(" << aMaximumSize << ", " << aUpdateLayout << ")" << endl;
422#endif // NEOGFX_DEBUG
423 MaximumSize.assign(newMaximumSize, aUpdateLayout);
424 if (aUpdateLayout)
426 }
427 }
428 bool has_fixed_size() const noexcept override
429 {
430 return FixedSize != std::nullopt;
431 }
432 size fixed_size(optional_size const& aAvailableSpace = {}) const override
433 {
434 if (has_fixed_size())
436 return minimum_size(aAvailableSpace);
437 }
438 void set_fixed_size(optional_size const& aFixedSize, bool aUpdateLayout = true)
439 {
440 optional_size newFixedSize = (aFixedSize != std::nullopt ? units_converter{ *this }.to_device_units(*aFixedSize) : optional_size{});
441 if (FixedSize != newFixedSize)
442 {
443#ifdef NEOGFX_DEBUG
444 if (debug::layoutItem == this)
445 service<debug::logger>() << neolib::logger::severity::Debug << typeid(*this).name() << "::set_fixed_size(" << aFixedSize << ", " << aUpdateLayout << ")" << endl;
446#endif // NEOGFX_DEBUG
447 FixedSize.assign(newFixedSize, aUpdateLayout);
448 if (aUpdateLayout)
450 }
451 }
452 bool has_transformation() const noexcept override
453 {
454 return Transformation != std::nullopt;
455 }
456 mat33 const& transformation(bool aCombineAncestorTransformations = false) const override
457 {
458 if (!aCombineAncestorTransformations)
459 {
460 if (has_transformation())
461 return *Transformation;
462 return mat33::identity();
463 }
464 else
465 {
467 {
469 }
471 }
472 }
473 void set_transformation(optional_mat33 const& aTransformation, bool aUpdateLayout = true) override
474 {
475 optional_mat33 newTransformation = (aTransformation != std::nullopt ? *aTransformation : optional_mat33{});
476 if (Transformation != newTransformation)
477 {
478#ifdef NEOGFX_DEBUG
479 if (debug::layoutItem == this)
480 service<debug::logger>() << neolib::logger::severity::Debug << typeid(*this).name() << "::set_transformation(" << aTransformation << ", " << aUpdateLayout << ")" << endl;
481#endif // NEOGFX_DEBUG
482 Transformation.assign(newTransformation, aUpdateLayout);
484 if (aUpdateLayout)
486 }
487 }
488 public:
489 bool has_margin() const noexcept override
490 {
491 return Margin != std::nullopt;
492 }
493 neogfx::margin margin() const override
494 {
495 return Margin != std::nullopt ? *Margin : neogfx::margin{};
496 }
497 void set_margin(optional_margin const& aMargin, bool aUpdateLayout = true) override
498 {
499 auto newMargin = (aMargin != std::nullopt ? units_converter{ *this }.to_device_units(*aMargin) : optional_margin{});
500 if (Margin != newMargin)
501 {
502 Margin = newMargin;
503 if (aUpdateLayout)
505 }
506 }
507 bool has_border() const noexcept override
508 {
509 return Border != std::nullopt;
510 }
511 neogfx::border border() const override
512 {
513 return Border != std::nullopt ? *Border : neogfx::border{};
514 }
515 void set_border(optional_border const& aBorder, bool aUpdateLayout = true) override
516 {
517 auto newBorder = (aBorder != std::nullopt ? units_converter{ *this }.to_device_units(*aBorder) : optional_border{});
518 if (Border != newBorder)
519 {
520 Border = newBorder;
521 if (aUpdateLayout)
523 }
524 }
525 bool has_padding() const noexcept override
526 {
527 return Padding != std::nullopt;
528 }
529 neogfx::padding padding() const override
530 {
531 return Padding != std::nullopt ? *Padding : neogfx::padding{};
532 }
533 void set_padding(optional_padding const& aPadding, bool aUpdateLayout = true) override
534 {
535 auto newPadding = (aPadding != std::nullopt ? units_converter{ *this }.to_device_units(*aPadding) : optional_padding{});
536 if (Padding != newPadding)
537 {
538 Padding = newPadding;
539 if (aUpdateLayout)
541 }
542 }
543 protected:
545 {
546 auto& self = as_layout_item();
547 if (!self.is_widget())
548 {
550 return parent_layout_item().origin();
551 else
552 return {};
553 }
554 else
555 {
556 if (!self.as_widget().is_root() || self.as_widget().root().is_nested())
557 {
558 if (self.as_widget().has_parent())
559 return self.as_widget().unconstrained_position() + self.as_widget().parent().origin();
560 else
561 return self.as_widget().unconstrained_position();
562 }
563 else
564 return {};
565 }
566 }
568 {
569 return Position;
570 }
571 public:
573 {
574 iCombinedTransformation = invalid;
575
576 auto& self = as_layout_item();
577 if (self.is_layout())
578 {
579 auto& layout = self.as_layout();
580 for (layout_item_index itemIndex = 0; itemIndex < layout.count(); ++itemIndex)
581 {
582 auto& item = layout.item_at(itemIndex);
584 }
585 }
586 else if (self.is_widget())
587 {
588 auto& widget = self.as_widget();
589 for (auto& child : widget.children())
590 {
592 }
593 if (widget.has_layout())
595 }
596 }
597 void fix_weightings(bool aRecalculate = true) override
598 {
599#ifdef NEOGFX_DEBUG
600 if (debug::layoutItem == this)
601 service<debug::logger>() << neolib::logger::severity::Debug << typeid(*this).name() << "::fix_weightings(): " << endl;
602#endif // NEOGFX_DEBUG
603 auto& self = as_layout_item();
604 auto& layout = (self.is_layout() ? self.as_layout() : self.as_widget().layout());
605 for (layout_item_index itemIndex = 0; itemIndex < layout.count(); ++itemIndex)
606 {
607 auto& item = layout.item_at(itemIndex);
608 if (!item.visible())
609 continue;
610 if (aRecalculate || !item.has_weight())
611 item.set_weight(calculate_relative_weight(layout, item), false);
612 }
613#ifdef NEOGFX_DEBUG
614 if (debug::layoutItem == this)
615 {
616 service<debug::logger>() << neolib::logger::severity::Debug << typeid(*this).name() << "::fix_weightings: weightings: ";
617 bool first = true;
618 for (layout_item_index itemIndex = 0; itemIndex < layout.count(); ++itemIndex)
619 {
620 auto& item = layout.item_at(itemIndex);
621 if (!item.visible())
622 continue;
623 if (!first)
624 service<debug::logger>() << neolib::logger::severity::Debug << ", ";
625 first = false;
626 service<debug::logger>() << neolib::logger::severity::Debug << item.weight();
627 }
628 service<debug::logger>() << neolib::logger::severity::Debug << endl;
629 service<debug::logger>() << neolib::logger::severity::Debug << typeid(*this).name() << "::fix_weightings() done" << endl;
630 }
631#endif // NEOGFX_DEBUG
632 }
633 protected:
634 void layout_item_enabled(i_layout_item& aItem) override
635 {
636 }
638 {
639 }
640 public:
641 i_anchor& anchor_to(i_anchorable& aRhs, i_string const& aLhsAnchor, anchor_constraint_function aLhsFunction, i_string const& aRhsAnchor, anchor_constraint_function aRhsFunction) override
642 {
643 auto& lhsAnchor = base_type::anchor_to(aRhs, aLhsAnchor, aLhsFunction, aRhsAnchor, aRhsFunction);
644 AnchorUpdated.trigger(lhsAnchor);
645 update_layout(true, true);
646 return lhsAnchor;
647 }
648 private:
649 i_layout_item const& as_layout_item() const
650 {
651 return *this;
652 }
653 i_layout_item& as_layout_item()
654 {
655 return *this;
656 }
657 // properties / anchors
658 public:
659 // todo: declare_property
660 define_property(property_category::soft_geometry, point, Position, position)
661 define_property(property_category::soft_geometry, size, Size, extents)
662 define_property(property_category::hard_geometry, optional_margin, Margin, margin)
663 define_property(property_category::hard_geometry, optional_border, Border, border)
664 define_property(property_category::hard_geometry, optional_padding, Padding, padding)
665 define_property(property_category::hard_geometry, optional_size_policy, SizePolicy, size_policy)
666 define_property(property_category::hard_geometry, optional_size, Weight, weight)
667 define_property(property_category::hard_geometry, optional_size, IdealSize, ideal_size)
668 define_property(property_category::hard_geometry, optional_size, MinimumSize, minimum_size)
669 define_property(property_category::hard_geometry, optional_size, MaximumSize, maximum_size)
670 define_property(property_category::hard_geometry, optional_size, FixedSize, fixed_size)
671 define_property(property_category::hard_geometry, optional_mat33, Transformation, transformation)
672 // todo: declare_anchor
674 define_anchor(Size)
675 define_anchor(Padding)
676 define_anchor(IdealSize)
677 define_anchor(MinimumSize)
678 define_anchor(MaximumSize)
679 private:
680 string iId;
681 mutable cache<point> iOrigin;
682 mutable cache<mat33> iCombinedTransformation;
683 };
684}
#define define_anchor(name)
Definition anchor.hpp:232
#define define_anchor_ex(name, calculator_override)
Definition anchor.hpp:233
static constexpr basic_size max_size()
virtual const i_widget & as_widget() const =0
virtual const i_widget & parent_widget() const =0
virtual void invalidate_combined_transformation()=0
virtual bool has_parent() const =0
virtual const i_widget & as_widget() const=0
virtual const i_widget & parent() const =0
virtual bool is_managing_layout() const =0
size fixed_size(optional_size const &aAvailableSpace={}) const override
bool has_parent_layout_item() const final
void set_weight(optional_size const &aWeight, bool aUpdateLayout=true) override
bool is_spacer() const final
void set_minimum_size(optional_size const &aMinimumSize, bool aUpdateLayout=true) override
void set_fixed_size(optional_size const &aFixedSize, bool aUpdateLayout=true)
void layout_item_enabled(i_layout_item &aItem) override
i_widget & as_widget() override
bool has_maximum_size() const noexcept override
bool has_padding() const noexcept override
bool has_minimum_size() const noexcept override
define_property(property_category::soft_geometry, point, Position, position) define_property(property_category cache< point > iOrigin
neogfx::margin margin() const override
neogfx::border border() const override
bool is_maximum_size_constrained() const noexcept override
void set_border(optional_border const &aBorder, bool aUpdateLayout=true) override
bool is_layout() const final
point origin() const final
const i_layout_item & parent_layout_item() const final
void reset_origin() const final
void update_layout(bool aDeferLayout=true, bool aAncestors=false) final
void set_padding(optional_padding const &aPadding, bool aUpdateLayout=true) override
bool has_border() const noexcept override
size maximum_size(optional_size const &aAvailableSpace={}) const override
const i_widget & layout_manager() const final
void invalidate_combined_transformation() override
mat33 const & transformation(bool aCombineAncestorTransformations=false) const override
const i_layout & as_layout() const final
bool is_cache() const final
void set_position(const point &aPosition) override
bool is_widget() const override
size minimum_size(optional_size const &aAvailableSpace={}) const override
bool is_minimum_size_constrained() const noexcept override
void set_extents(const size &aExtents) override
bool has_margin() const noexcept override
void set_transformation(optional_mat33 const &aTransformation, bool aUpdateLayout=true) override
i_layout & as_layout() final
bool has_fixed_size() const noexcept override
point unconstrained_position() const override
void set_size_policy(const optional_size_policy &aSizePolicy, bool aUpdateLayout=true) override
bool has_weight() const noexcept override
const i_widget & as_widget() const override
bool has_ideal_size() const noexcept override
point unconstrained_origin() const override
i_spacer & as_spacer() final
bool has_transformation() const noexcept override
neogfx::size_policy size_policy() const override
point position() const final
void fix_weightings(bool aRecalculate=true) override
size ideal_size(optional_size const &aAvailableSpace={}) const override
const i_spacer & as_spacer() const final
i_widget & layout_manager() final
size weight() const override
void set_margin(optional_margin const &aMargin, bool aUpdateLayout=true) override
bool has_size_policy() const noexcept override
size extents() const final
void set_maximum_size(optional_size const &aMaximumSize, bool aUpdateLayout=true) override
void layout_item_disabled(i_layout_item &aItem) override
void set_id(const i_string &aId) final
neogfx::padding padding() const override
bool has_layout_manager() const final
i_anchor & anchor_to(i_anchorable &aRhs, i_string const &aLhsAnchor, anchor_constraint_function aLhsFunction, i_string const &aRhsAnchor, anchor_constraint_function aRhsFunction) override
void set_ideal_size(optional_size const &aIdealSize, bool aUpdateLayout=true) override
const i_string & id() const final
i_layout_item & parent_layout_item() final
bool is_ideal_size_constrained() const noexcept override
cache< mat33 > iCombinedTransformation
const i_layout_item & item_at(layout_item_index aIndex) const override
layout_item_index count() const override
vector2 to_device_units(const vector2 &aValue) const
vector2 from_device_units(const vector2 &aValue) const
const widget_list & children() const override
Definition widget.ipp:389
const i_layout & layout() const override
Definition widget.ipp:611
bool has_layout() const override
Definition widget.ipp:573
optional< margin > optional_margin
anchor_constraint_function
Definition i_anchor.hpp:31
optional< padding > optional_padding
uint32_t layout_item_index
Definition i_layout.hpp:35
size calculate_relative_weight(const i_layout &aLayout, const i_layout_item &aItem)
Definition i_layout.hpp:392
optional< size > optional_size
optional< border > optional_border
basic_point< coordinate > point
basic_size< coordinate > size
const endl_t endl
Definition i_logger.hpp:77
matrix33 mat33
optional< mat33 > optional_mat33
#define meta_object(...)
Definition i_object.hpp:28
#define define_event(name, declName,...)
Definition event.hpp:200
#define define_property(category, type, name, calculator,...)
Definition property.hpp:536