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-2025 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;
   79        bool isBlockClicksWhenPressed = true;
   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;
  325            case AOverflow::HIDDEN:
  326            case AOverflow::HIDDEN_FROM_THIS:
  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
  375
  379    void removeView(const _<AView>& view);
  380
  384    void removeView(AView* view);
  385
  389    void removeView(size_t index);
  390
  394    void removeAllViews();
  395
  400    void setContents(const _<AViewContainer>& container);
  401
  405    void setLayout(_unique<ALayout> layout);
  406
  407    void renderChildren(ARenderContext contextPassedToContainer) {
  408        drawViews(mViews.begin(), mViews.end(), contextPassedToContainer);
  409    }
  410
  411    virtual void applyGeometryToChildren();
  412
  413signals:
  418
  419private:
  420    _unique<ALayout> mLayout;
  421    bool mSizeSet = false;
  422
  423
  424    struct RepaintTrap {
  425        bool triggered = false;
  426    };
  427    AOptional<RepaintTrap> mRepaintTrap;
  428
  429    struct ConsumesClickCache {
  430        glm::ivec2 position;
  431        bool value;
  432    };
  433
  440    AOptional<ConsumesClickCache> mConsumesClickCache;
  441
  448    _weak<AView> mFocusChainTarget;
  449
  454    ASmallVector<PointerEventsMapping, 1> mPointerEventsMapping;
  455
  456    void notifyParentEnabledStateChanged(bool enabled) override;
  457    void invalidateCaches();
  458
  462    _<AView> pointerEventsMapping(APointerIndex index);
  463};
Bit field implementation.
Definition ABitField.h:20
Utility wrapper implementing the stack-allocated (fast) optional idiom.
Definition AOptional.h:33
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 addViewCustomLayout(const _< AView > &view)
Adds view to container without exposing it to the layout manager.
void setFocusChainTarget(_weak< AView > target)
Set focus chain target.
Definition AViewContainerBase.h:267
void setViews(AVector< _< AView > > views)
Replace views.
void invalidateAssHelper() override
Resets mAssHelper.
void removeView(size_t index)
Remove view from the container at specified index.
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
void setLayout(_unique< ALayout > layout)
Set new layout manager for this AViewContainerBase. DESTROYS OLD LAYOUT MANAGER WITH ITS VIEWS!...
emits childrenChanged
Emitted when addView(s)/removeView/setLayout was called.
Definition AViewContainerBase.h:417
void removeView(AView *view)
Remove view from the container.
void onViewGraphSubtreeChanged() override
Called when direct or indirect parent has changed.
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
void addView(size_t index, const _< AView > &view)
Add view at specific index to the container.
void onPointerPressed(const APointerPressedEvent &event) override
Called on pointer (mouse) released event.
_< AView > getViewAtRecursive(glm::ivec2 pos, ABitField< AViewLookupFlags > flags=AViewLookupFlags::NONE) const noexcept
Acts as AViewContainerBase::getViewAt but recursively (may include non-direct child).
bool onGesture(const glm::ivec2 &origin, const AGestureEvent &event) override
int getContentMinimumWidth() override
void addViews(AVector< _< AView > > views)
Add all views from vector.
_< AView > focusChainTarget()
Definition AViewContainerBase.h:278
void onPointerMove(glm::vec2 pos, const APointerMoveEvent &event) override
Handles pointer hover events.
void removeAllViews()
Remove all views from container.
void removeView(const _< AView > &view)
Remove view from the container.
void markPixelDataInvalid(ARect< int > invalidArea) override
A view requests to redraw it and passes it's coords relative to this.
void addView(const _< AView > &view)
Add view to the container.
void onClickPrevented() override
Called on AWindowBase::preventClickOnPointerRelease.
const ASmallVector< PointerEventsMapping, 1 > & pointerEventsMapping() const noexcept
Definition AViewContainerBase.h:305
bool consumesClick(const glm::ivec2 &pos) override
Determines whether this AView processes this click or passes it thru.
void onPointerReleased(const APointerReleasedEvent &event) override
Called on pointer (mouse) released event.
void onScroll(const AScrollEvent &event) override
void removeViews(aui::range< AVector< _< AView > >::iterator > views)
Remove views from the container.
bool capturesFocus() override
void setContents(const _< AViewContainer > &container)
Moves (like via std::move) all children and layout of the specified container to this container.
void invalidateAllStyles() override
Invalidates all styles, causing to iterate over all rules in global and parent stylesheets.
_< 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
virtual _< AView > getViewAt(glm::ivec2 pos, ABitField< AViewLookupFlags > flags=AViewLookupFlags::NONE) const noexcept
Finds first direct child view under position.
const AVector< _< AView > > & getViews() const
Get all views of the container.
Definition AViewContainerBase.h:131
int getContentMinimumHeight() override
void render(ARenderContext context) override
Draws this AView. Noone should call this function except rendering routine.
auto enabled() const
Whether view is enabled (i.e., reacts to user).
Definition AView.h:90
auto size() const
Size, including content area, border and padding.
Definition AView.h:114
glm::ivec2 getSize() const noexcept
Size, including content area, border and padding.
Definition AView.h:217
An std::weak_ptr with AUI extensions.
Definition SharedPtrTypes.h:179
@ 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
#define AUI_ENUM_FLAG(name)
Make a bitfield-style enum class.
Definition AEnumerate.h:227
ASignal< Args... > emits
A signal declaration.
Definition ASignal.h:572
#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:52
Definition iterators.h:50
Definition iterators.h:34