AUI Framework  develop
Cross-platform base for C++ UI apps
Loading...
Searching...
No Matches
AViewContainerBase.h
1/*
2 * AUI Framework - Declarative UI toolkit for modern C++20
3 * Copyright (C) 2020-2024 Alex2772 and Contributors
4 *
5 * SPDX-License-Identifier: MPL-2.0
6 *
7 * This Source Code Form is subject to the terms of the Mozilla Public
8 * License, v. 2.0. If a copy of the MPL was not distributed with this
9 * file, You can obtain one at http://mozilla.org/MPL/2.0/.
10 */
11
12#pragma once
13
14#include <AUI/Views.h>
15#include <AUI/View/AView.h>
16#include "AUI/Common/SharedPtr.h"
17#include "AUI/Enum/AOverflow.h"
18#include "AUI/Util/ABitField.h"
19#include <glm/glm.hpp>
20#include "AUI/Layout/ALayout.h"
21#include "AUI/Common/AVector.h"
22#include "AUI/Render/IRenderer.h"
23#include "AUI/Render/RenderHints.h"
24#include "AUI/Render/ARenderContext.h"
25#include "glm/fwd.hpp"
26
27
28AUI_ENUM_FLAG(AViewLookupFlags) {
29 NONE = 0,
30
34 IGNORE_VISIBILITY = 0b1,
35
42 ONLY_ONE_PER_CONTAINER = 0b10,
43
50 ONLY_THAT_CONSUMES_CLICK = 0b100,
51};
52
68class API_AUI_VIEWS AViewContainerBase : public AView {
69public:
70 friend class AView;
71
73 APointerIndex pointerIndex;
74 _weak<AView> targetView;
80 };
81
82 AViewContainerBase();
83 ~AViewContainerBase() override = 0; // this class is intended to be derived; use AViewContainer for trivial
84 // container
85
86
87
88 void render(ARenderContext context) override;
89
90 void onMouseEnter() override;
91
92 void onPointerMove(glm::vec2 pos, const APointerMoveEvent& event) override;
93
94 void onMouseLeave() override;
95
96 void onDpiChanged() override;
97
98 void onClickPrevented() override;
99
100 int getContentMinimumWidth() override;
101
102 int getContentMinimumHeight() override;
103
104 void onPointerPressed(const APointerPressedEvent& event) override;
105
106 void onPointerDoubleClicked(const APointerPressedEvent& event) override;
107
108 void onPointerReleased(const APointerReleasedEvent& event) override;
109
110 void onScroll(const AScrollEvent& event) override;
111
112 bool onGesture(const glm::ivec2& origin, const AGestureEvent& event) override;
113
114 bool consumesClick(const glm::ivec2& pos) override;
115
116 void setSize(glm::ivec2 size) override;
117
118 void setEnabled(bool enabled = true) override;
119
120 auto begin() const {
121 return mViews.cbegin();
122 }
123
124 auto end() const {
125 return mViews.cend();
126 }
127
131 const AVector<_<AView>>& getViews() const {
132 return mViews;
133 }
134
135
139 [[nodiscard]]
140 const _unique<ALayout>& getLayout() const noexcept {
141 return mLayout;
142 }
143
152 [[nodiscard]]
153 virtual _<AView> getViewAt(glm::ivec2 pos, ABitField<AViewLookupFlags> flags = AViewLookupFlags::NONE) const noexcept;
154
161 [[nodiscard]]
162 _<AView> getViewAtRecursive(glm::ivec2 pos, ABitField<AViewLookupFlags> flags = AViewLookupFlags::NONE) const noexcept;
163
174 template<aui::predicate<_<AView>> Callback>
175 bool getViewAtRecursive(glm::ivec2 pos, const Callback& callback, ABitField<AViewLookupFlags> flags = AViewLookupFlags::NONE) {
176 _<AView> possibleOutput; // for case if anyone does not consumesClick
177 auto process = [&](const _<AView>& view) {
178 if (callback(view))
179 return true;
180 if (auto container = _cast<AViewContainerBase>(view)) {
181 if (container->getViewAtRecursive(pos - view->getPosition(), callback, flags)) {
182 return true;
183 }
184 }
185 return false;
186 };
187
188 for (const auto& view : aui::reverse_iterator_wrap(mViews)) {
189 auto targetPos = pos - view->getPosition();
190
191 if (targetPos.x < 0 || targetPos.y < 0 || targetPos.x >= view->getSize().x || targetPos.y >= view->getSize().y) {
192 continue;
193 }
194 if (!flags.test(AViewLookupFlags::IGNORE_VISIBILITY) && !(view->getVisibility() & Visibility::FLAG_CONSUME_CLICKS)) {
195 continue;
196 }
197
198 if (view->consumesClick(targetPos)) {
199 if (flags.test(AViewLookupFlags::IGNORE_VISIBILITY) || !!(view->getVisibility() & Visibility::FLAG_CONSUME_CLICKS)) {
200 if (process(view)) {
201 return true;
202 }
203
204 if (flags.test(AViewLookupFlags::ONLY_ONE_PER_CONTAINER)) {
205 return false;
206 }
207 }
208 } else {
209 if (possibleOutput == nullptr) {
210 possibleOutput = view;
211 }
212 }
213 }
214 if (possibleOutput) {
215 return process(possibleOutput);
216 }
217
218 return false;
219 }
220
227 template<aui::predicate<_<AView>> Callback>
228 bool visitsViewRecursive(Callback&& callback, ABitField<AViewLookupFlags> flags = AViewLookupFlags::NONE) {
229 for (auto it = mViews.rbegin(); it != mViews.rend(); ++it) {
230 auto view = *it;
231 if (flags.test(AViewLookupFlags::IGNORE_VISIBILITY) || !!(view->getVisibility() & Visibility::FLAG_CONSUME_CLICKS)) {
232 if (callback(view))
233 return true;
234 if (auto container = _cast<AViewContainerBase>(view)) {
235 if (container->visitsViewRecursive(callback, flags)) {
236 return true;
237 }
238 }
239 if (flags.test(AViewLookupFlags::ONLY_ONE_PER_CONTAINER)) {
240 break;
241 }
242 }
243 }
244 return false;
245 }
246
247
254 template<typename T>
255 _<T> getViewAtRecursiveOfType(glm::ivec2 pos, ABitField<AViewLookupFlags> flags = AViewLookupFlags::NONE) {
256 _<T> result;
257 getViewAtRecursive(pos, [&] (const _<AView>& v) { return bool(result = _cast<T>(v)); }, flags);
258 return result;
259 }
260
268 if (auto v = target.lock()) {
269 AUI_ASSERT(v->mParent == this);
270 }
271 mFocusChainTarget = std::move(target);
272 }
273
279 if (auto v = mFocusChainTarget.lock()) {
280 if (v->mParent != this) {
281 mFocusChainTarget.reset();
282 return nullptr;
283 }
284 return v;
285 }
286 return nullptr;
287 }
288
289
290 void applyGeometryToChildrenIfNecessary();
291
292 void onKeyDown(AInput::Key key) override;
293
294 void onKeyRepeat(AInput::Key key) override;
295
296 void onKeyUp(AInput::Key key) override;
297
298 void onCharEntered(char16_t c) override;
299
300 bool capturesFocus() override;
301
306 return mPointerEventsMapping;
307 }
308
309 void forceUpdateLayoutRecursively() override;
310
311 void markMinContentSizeInvalid() override;
312 void markPixelDataInvalid(ARect<int> invalidArea) override;
313
314protected:
315 AVector<_<AView>> mViews;
316 bool mWantsLayoutUpdate = true;
317 glm::ivec2 mLastLayoutUpdateSize{0, 0};
318
319 void drawView(const _<AView>& view, ARenderContext contextOfTheContainer);
320
321 template<typename Iterator>
322 void drawViews(Iterator begin, Iterator end, ARenderContext contextPassedToContainer) {
323 switch (mOverflow) {
324 case AOverflow::VISIBLE: break;
327 contextPassedToContainer.clip(ARect<int>{
328 .p1 = {0, 0},
329 .p2 = getSize(),
330 });
331 }
332
333 for (auto i = begin; i != end; ++i) {
334 drawView(*i, contextPassedToContainer);
335 }
336 }
337
338 void invalidateAllStyles() override;
339 void onViewGraphSubtreeChanged() override;
340 void invalidateAssHelper() override;
341
345 void setViews(AVector<_<AView>> views);
346
354 void addViewCustomLayout(const _<AView>& view);
355
359 void addViews(AVector<_<AView>> views);
360
364 void addView(const _<AView>& view);
365
369 void addView(size_t index, const _<AView>& view);
370
374 void removeView(const _<AView>& view);
375
379 void removeView(AView* view);
380
384 void removeView(size_t index);
385
389 void removeAllViews();
390
395 void setContents(const _<AViewContainer>& container);
396
400 void setLayout(_unique<ALayout> layout);
401
402 void renderChildren(ARenderContext contextPassedToContainer) {
403 drawViews(mViews.begin(), mViews.end(), contextPassedToContainer);
404 }
405
406 virtual void applyGeometryToChildren();
407
408signals:
413
414private:
415 _unique<ALayout> mLayout;
416 bool mSizeSet = false;
417
418
419 struct RepaintTrap {
420 bool triggered = false;
421 };
422 AOptional<RepaintTrap> mRepaintTrap;
423
424 struct ConsumesClickCache {
425 glm::ivec2 position;
426 bool value;
427 };
428
435 AOptional<ConsumesClickCache> mConsumesClickCache;
436
443 _weak<AView> mFocusChainTarget;
444
449 ASmallVector<PointerEventsMapping, 1> mPointerEventsMapping;
450
451 void notifyParentEnabledStateChanged(bool enabled) override;
452 void invalidateCaches();
453
457 _<AView> pointerEventsMapping(APointerIndex index);
458};
Bit field implementation.
Definition ABitField.h:20
Utility wrapper implementing the stack-allocated (fast) optional idiom.
Definition AOptional.h:32
Wrapper class that stores either mouse button index or finger index.
Definition APointerIndex.h:21
Vector-like container consisting of few elements on stack and switches to dynamic allocation vector i...
Definition ASmallVector.h:34
A std::vector with AUI extensions.
Definition AVector.h:39
void setFocusChainTarget(_weak< AView > target)
Set focus chain target.
Definition AViewContainerBase.h:267
bool getViewAtRecursive(glm::ivec2 pos, const Callback &callback, ABitField< AViewLookupFlags > flags=AViewLookupFlags::NONE)
Acts as AViewContainerBase::getViewAtRecursive but calls a callback instead of returning value.
Definition AViewContainerBase.h:175
emits childrenChanged
Emitted when addView(s)/removeView/setLayout was called.
Definition AViewContainerBase.h:412
const _unique< ALayout > & getLayout() const noexcept
Get layout manager of the container.
Definition AViewContainerBase.h:140
bool visitsViewRecursive(Callback &&callback, ABitField< AViewLookupFlags > flags=AViewLookupFlags::NONE)
Performs recursive view traversal.
Definition AViewContainerBase.h:228
_< AView > getViewAtRecursive(glm::ivec2 pos, ABitField< AViewLookupFlags > flags=AViewLookupFlags::NONE) const noexcept
Acts as AViewContainerBase::getViewAt but recursively (may include non-direct child).
Definition AViewContainerBase.cpp:437
_< AView > focusChainTarget()
Definition AViewContainerBase.h:278
const ASmallVector< PointerEventsMapping, 1 > & pointerEventsMapping() const noexcept
Definition AViewContainerBase.h:305
_< T > getViewAtRecursiveOfType(glm::ivec2 pos, ABitField< AViewLookupFlags > flags=AViewLookupFlags::NONE)
Acts as AViewContainerBase::getViewAtRecursive but finds a view castable to specified template type.
Definition AViewContainerBase.h:255
const AVector< _< AView > > & getViews() const
Get all views of the container.
Definition AViewContainerBase.h:131
auto enabled() const
Whether view is enabled (i.e., reacts to user).
Definition AView.h:90
virtual int getContentMinimumHeight()
Definition AView.cpp:252
virtual bool consumesClick(const glm::ivec2 &pos)
Determines whether this AView processes this click or passes it thru.
Definition AView.cpp:540
virtual bool onGesture(const glm::ivec2 &origin, const AGestureEvent &event)
Definition AView.cpp:604
virtual void invalidateAssHelper()
Resets mAssHelper.
Definition AView.cpp:291
auto size() const
Size, including content area, border and padding.
Definition AView.h:114
virtual void onPointerMove(glm::vec2 pos, const APointerMoveEvent &event)
Handles pointer hover events.
Definition AView.cpp:343
virtual void onViewGraphSubtreeChanged()
Called when direct or indirect parent has changed.
Definition AView.cpp:695
virtual void onClickPrevented()
Called on AWindowBase::preventClickOnPointerRelease.
Definition AView.cpp:680
glm::ivec2 getSize() const noexcept
Size, including content area, border and padding.
Definition AView.h:217
virtual int getContentMinimumWidth()
Definition AView.cpp:248
virtual void onPointerPressed(const APointerPressedEvent &event)
Called on pointer (mouse) released event.
Definition AView.cpp:357
virtual bool capturesFocus()
Definition AView.cpp:573
virtual void markPixelDataInvalid(ARect< int > invalidArea)
A view requests to redraw it and passes it's coords relative to this.
Definition AView.cpp:716
virtual void onPointerReleased(const APointerReleasedEvent &event)
Called on pointer (mouse) released event.
Definition AView.cpp:366
virtual void render(ARenderContext ctx)
Draws this AView. Noone should call this function except rendering routine.
Definition AView.cpp:142
virtual void invalidateAllStyles()
Invalidates all styles, causing to iterate over all rules in global and parent stylesheets.
Definition AView.cpp:179
virtual void onScroll(const AScrollEvent &event)
Definition AView.cpp:407
An std::weak_ptr with AUI extensions.
Definition SharedPtrTypes.h:178
@ HIDDEN_FROM_THIS
Like HIDDEN, but view's ASS-styled background is also affected by mask.
Definition AOverflow.h:40
@ HIDDEN
Overflowed contents are hidden. Suitable for lists with scroll.
Definition AOverflow.h:35
@ VISIBLE
Overflowed contents are visible.
Definition AOverflow.h:28
@ NONE
Definition AFloat.h:23
ASignal< Args... > emits
A signal declaration.
Definition ASignal.h:348
#define AUI_ASSERT(condition)
Asserts that the passed condition evaluates to true.
Definition Assert.h:55
Pointing method move event.
Definition APointerMoveEvent.h:21
Pointing method press event.
Definition APointerPressedEvent.h:21
Pointing method press event.
Definition APointerReleasedEvent.h:19
Axis aligned 2D rectangle.
Definition ARect.h:24
Render context passed to AView::render.
Definition ARenderContext.h:43
Pointing method scroll event.
Definition AScrollEvent.h:20
Definition AViewContainerBase.h:72
bool isBlockClicksWhenPressed
true if the view or any child (direct or indirect) of the view blocks clicks when pressed
Definition AViewContainerBase.h:79
An std::weak_ptr with AUI extensions.
Definition SharedPtrTypes.h:51
Definition iterators.h:34