AUI Framework  master
Cross-platform module-based framework for developing C++20 desktop applications
/github/workspace/aui.views/src/AUI/View/AView.h

Wraps the addAssName function to make it easier to add ASS class names.

... _new<ALabel>("Components") << ".components_title" ...

Parameters
assNamenew ASS name
Returns
this
/*
* AUI Framework - Declarative UI toolkit for modern C++20
* Copyright (C) 2020-2024 Alex2772 and Contributors
*
* SPDX-License-Identifier: MPL-2.0
*
* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/.
*/
#pragma once
#include <chrono>
#include <functional>
#include <array>
#include <glm/glm.hpp>
#include "AUI/Common/ASmallVector.h"
#include <AUI/ASS/Property/IProperty.h>
#include <AUI/ASS/Property/ScrollbarAppearance.h>
#include "AUI/Common/ABoxFields.h"
#include "AUI/Common/ADeque.h"
#include "AUI/Common/AObject.h"
#include "AUI/Common/SharedPtr.h"
#include "AUI/Platform/ACursor.h"
#include "AUI/Platform/AInput.h"
#include "AUI/Reflect/AClass.h"
#include "AUI/Font/AFontStyle.h"
#include "AUI/Util/AFieldSignalEmitter.h"
#include "AUI/Render/ARenderContext.h"
#include "AUI/Util/IBackgroundEffect.h"
#include <AUI/ASS/PropertyListRecursive.h>
#include <AUI/Enum/AOverflow.h>
#include <AUI/Enum/Visibility.h>
#include <AUI/Enum/MouseCollisionPolicy.h>
#include <AUI/Util/ALayoutDirection.h>
#include <AUI/Action/AMenu.h>
#include <AUI/Event/AScrollEvent.h>
#include <AUI/Event/AGestureEvent.h>
#include <AUI/Event/APointerPressedEvent.h>
#include <AUI/Event/APointerReleasedEvent.h>
#include <AUI/Event/APointerMoveEvent.h>
#include <AUI/Render/ITexture.h>
#include <AUI/Render/IRenderViewToTexture.h>
#include <AUI/Enum/AFloat.h>
class AWindow;
class AAnimator;
class AAssHelper;
class API_AUI_VIEWS AView: public AObject
{
friend class AViewContainerBase;
friend class AViewContainer;
friend class IRenderViewToTexture;
private:
_<AAnimator> mAnimator;
AOverflowMask mOverflowMask = AOverflowMask::ROUNDED_RECT;
Visibility mVisibility = Visibility::VISIBLE;
_<AAssHelper> mAssHelper;
float mBorderRadius = 0;
MouseCollisionPolicy mMouseCollisionPolicy = MouseCollisionPolicy::DEFAULT;
aui::float_within_0_1 mOpacity = 1;
_<AStylesheet> mExtraStylesheet;
virtual void notifyParentEnabledStateChanged(bool enabled);
[[nodiscard]]
ALayoutDirection parentLayoutDirection() const noexcept;
bool mMouseEntered = false;
bool mBlockClicksWhenPressed = true;
protected:
AViewContainerBase* mParent = nullptr;
std::array<ass::prop::IPropertyBase*, int(ass::prop::PropertySlot::COUNT)> mAss;
ass::PropertyListRecursive mCustomStyleRule;
glm::ivec2 mPosition = { 0, 0 };
glm::ivec2 mSize = { 20, 20 };
glm::ivec2 mExpanding = {0, 0};
AOptional<glm::ivec2> mCachedMinContentSize;
bool mMarkedMinContentSizeInvalid = false;
bool mRedrawRequested = false;
glm::ivec2 mMinSize = {0, 0};
glm::ivec2 mMaxSize = {0x7fffffff, 0x7fffffff};
glm::ivec2 mFixedSize = {0, 0};
ABoxFields mMargin;
ABoxFields mPadding;
AVector<AString> mAssNames;
bool mSkipUntilLayoutUpdate = true;
bool transformGestureEventsToDesktop(const glm::ivec2& origin, const AGestureEvent& event);
void applyAssRule(const ass::PropertyList& propertyList);
void applyAssRule(const ass::PropertyListRecursive& propertyList);
virtual AMenuModel composeContextMenu();
virtual void onViewGraphSubtreeChanged();
virtual void markPixelDataInvalid(ARect<int> invalidArea);
virtual void commitStyle();
public:
AView();
~AView() override;
void redraw();
AWindowBase* getWindow() const;
virtual void drawStencilMask(ARenderContext ctx);
virtual void render(ARenderContext ctx);
virtual void postRender(ARenderContext ctx);
void popStencilIfNeeded(ARenderContext ctx);
[[nodiscard]]
const AVector<AString>& getAssNames() const noexcept {
return mAssNames;
}
[[nodiscard]]
glm::ivec2 getPosition() const noexcept
{
return mPosition;
}
[[nodiscard]]
glm::ivec2 getCenterPointInWindow() const noexcept
{
return getPositionInWindow() + getSize() / 2;
}
[[nodiscard]]
glm::ivec2 getSize() const noexcept
{
return mSize;
}
glm::ivec2 getMinSize() const noexcept {
return mMinSize;
}
void setMinSize(glm::ivec2 minSize) noexcept {
mMinSize = minSize;
}
virtual void markMinContentSizeInvalid();
void setExtraStylesheet(_<AStylesheet> extraStylesheet) {
mExtraStylesheet = std::move(extraStylesheet);
invalidateAssHelper();
}
void setExtraStylesheet(AStylesheet&& extraStylesheet);
[[nodiscard]]
const _<AStylesheet>& extraStylesheet() const noexcept {
return mExtraStylesheet;
}
AOverflow getOverflow() const
{
return mOverflow;
}
void setOverflow(AOverflow overflow)
{
mOverflow = overflow;
}
AOverflowMask getOverflowMask() const
{
return mOverflowMask;
}
void setOverflowMask(AOverflowMask overflow)
{
mOverflowMask = overflow;
}
float getBorderRadius() const {
return mBorderRadius;
}
void setBorderRadius(float radius) {
mBorderRadius = radius;
}
int getWidth() const
{
return mSize.x;
}
int getHeight() const
{
return mSize.y;
}
int getTotalOccupiedWidth() const
{
return !(mVisibility & Visibility::FLAG_CONSUME_SPACE) ? 0 : mSize.x + getTotalFieldHorizontal();
}
int getTotalOccupiedHeight() const
{
return !(mVisibility & Visibility::FLAG_CONSUME_SPACE) ? 0 : mSize.y + getTotalFieldVertical();
}
[[nodiscard]]
glm::ivec2 getMinimumSizePlusMargin() {
return getMinimumSize() + mMargin.occupiedSize();
}
[[nodiscard]]
const ABoxFields& getMargin()
{
ensureAssUpdated();
return mMargin;
}
void setMargin(const ABoxFields& margin) {
mMargin = margin;
}
virtual bool consumesClick(const glm::ivec2& pos);
[[nodiscard]]
const ABoxFields& getPadding()
{
ensureAssUpdated();
return mPadding;
}
void setPadding(const ABoxFields& padding) {
mPadding = padding;
}
virtual AString debugString() const;
[[nodiscard]]
int getTotalFieldHorizontal() const {
return mPadding.horizontal() + mMargin.horizontal();
}
[[nodiscard]]
int getTotalFieldVertical() const {
return mPadding.vertical() + mMargin.vertical();
}
[[nodiscard]]
glm::ivec2 getTotalFieldSize() const {
return { getTotalFieldHorizontal(), getTotalFieldVertical() };
}
AViewContainerBase* getParent() const
{
return mParent;
}
const AOptional<ACursor>& getCursor() const
{
return mCursor;
}
void setCursor(AOptional<ACursor> cursor);
[[nodiscard]]
virtual int getContentMinimumWidth();
[[nodiscard]]
virtual int getContentMinimumHeight();
[[nodiscard]]
glm::ivec2 getContentMinimumSize() noexcept {
if (!mCachedMinContentSize) {
glm::ivec2 minContentSize = glm::ivec2(getContentMinimumWidth(), getContentMinimumHeight());
mCachedMinContentSize = minContentSize;
return minContentSize;
}
// TODO ignore layout?
return *mCachedMinContentSize;
}
[[nodiscard]]
bool isContentMinimumSizeInvalidated() noexcept {
return !mCachedMinContentSize.hasValue();
}
bool hasFocus() const;
virtual int getMinimumWidth();
virtual int getMinimumHeight();
glm::ivec2 getMinimumSize() {
return { getMinimumWidth(), getMinimumHeight() };
}
void setMaxSize(const glm::ivec2& maxSize) {
mMaxSize = maxSize;
}
[[nodiscard]] const glm::ivec2& getMaxSize() const
{
return mMaxSize;
}
int getContentWidth() const
{
return static_cast<int>(mSize.x - mPadding.horizontal());
}
int getContentHeight() const
{
return static_cast<int>(mSize.y - mPadding.vertical());
}
[[nodiscard]]
const glm::ivec2& getExpanding() const
{
return mExpanding;
}
void setExpanding(glm::ivec2 expanding)
{
if (mExpanding == expanding) [[unlikely]] {
return;
}
mExpanding = expanding;
if (expandingChanged) emit expandingChanged(expanding);
markMinContentSizeInvalid();
}
void setExpanding(int expanding)
{
setExpanding({expanding, expanding});
}
void setExpanding()
{
setExpanding(2);
}
const _<AAnimator>& getAnimator() const {
return mAnimator;
}
void setAnimator(const _<AAnimator>& animator);
void getTransform(glm::mat4& transform) const;
[[nodiscard]]
int getExpandingHorizontal() const
{
return mExpanding.x;
}
[[nodiscard]]
int getExpandingVertical() const
{
return mExpanding.y;
}
[[nodiscard]] aui::float_within_0_1 getOpacity() const {
return mOpacity;
}
void setOpacity(aui::float_within_0_1 opacity) {
mOpacity = opacity;
}
virtual void setPosition(glm::ivec2 position);
void setSizeForced(glm::ivec2 size) {
mSize = size;
}
virtual void setSize(glm::ivec2 size);
virtual void setGeometry(int x, int y, int width, int height);
void setGeometry(const glm::ivec2& position, const glm::ivec2& size) {
setGeometry(position.x, position.y, size.x, size.y);
}
bool isBlockClicksWhenPressed() const noexcept {
return mBlockClicksWhenPressed;
}
void setBlockClicksWhenPressed(bool value) noexcept {
mBlockClicksWhenPressed = value;
}
const glm::ivec2& getFixedSize() {
return mFixedSize;
}
void setFixedSize(glm::ivec2 size) {
AUI_ASSERTX(glm::all(glm::greaterThanEqual(size, glm::ivec2(-100000))), "abnormal fixed size");
if (size == mFixedSize) [[unlikely]] {
return;
}
mFixedSize = size;
markMinContentSizeInvalid();
}
[[nodiscard]]
bool isMouseHover() const noexcept
{
return mHovered;
}
[[nodiscard]]
bool isPressed() const noexcept
{
return !mPressed.empty();
}
[[nodiscard]]
bool isPressed(APointerIndex index) const noexcept
{
return mPressed.contains(index);
}
[[nodiscard]]
bool isEnabled() const noexcept
{
return mEnabled;
}
bool isFocused() const {
return mHasFocus;
}
bool isMouseEntered() const {
return mMouseEntered;
}
Visibility getVisibility() const
{
return mVisibility;
}
Visibility getVisibilityRecursive() const;
void setVisibility(Visibility visibility) noexcept;
void setVisible(bool visible) noexcept
{
setVisibility(visible ? Visibility::VISIBLE : Visibility::INVISIBLE);
}
[[nodiscard]]
MouseCollisionPolicy getMouseCollisionPolicy() const {
return mMouseCollisionPolicy;
}
void setMouseCollisionPolicy(MouseCollisionPolicy mouseCollisionPolicy) {
mMouseCollisionPolicy = mouseCollisionPolicy;
}
void click() {
emit clickedButton(APointerIndex::button(AInput::LBUTTON));
emit clicked();
}
void pack();
void focus(bool needFocusChainUpdate = true);
virtual bool capturesFocus();
bool hasIndirectParent(const _<AView>& v);
[[nodiscard]] glm::ivec2 getPositionInWindow() const;
void addAssName(const AString& assName);
void removeAssName(const AString& assName);
inline AView& operator<<(const AString& assName) {
addAssName(assName);
return *this;
}
const _<AAssHelper>& getAssHelper() const {
return mAssHelper;
}
const ass::PropertyListRecursive& getCustomAss() const {
return mCustomStyleRule;
}
void setCustomStyle(ass::PropertyListRecursive rule);
void ensureAssUpdated();
[[nodiscard]]
_<AView> sharedPtr() {
return _cast<AView>(AObject::sharedPtr());
}
[[nodiscard]]
_weak<AView> weakPtr() {
return _weak<AView>(sharedPtr());
}
virtual bool onGesture(const glm::ivec2& origin, const AGestureEvent& event);
virtual void onMouseEnter();
virtual void onPointerMove(glm::vec2 pos, const APointerMoveEvent& event);
virtual void onMouseLeave();
virtual void onDpiChanged();
virtual void onPointerPressed(const APointerPressedEvent& event);
virtual void onPointerReleased(const APointerReleasedEvent& event);
virtual void onPointerDoubleClicked(const APointerPressedEvent& event);
virtual void onScroll(const AScrollEvent& event);
virtual void onKeyDown(AInput::Key key);
virtual void onKeyRepeat(AInput::Key key);
virtual void onKeyUp(AInput::Key key);
virtual void onFocusAcquired();
virtual void onFocusLost();
virtual void onCharEntered(char16_t c);
virtual bool handlesNonMouseNavigation();
virtual void forceUpdateLayoutRecursively();
virtual void setEnabled(bool enabled = true);
void setDisabled(bool disabled = true) {
setEnabled(!disabled);
}
void updateEnableState();
void enable()
{
setEnabled(true);
}
void disable()
{
setEnabled(false);
}
void operator+(ass::PropertyListRecursive rule) {
setCustomStyle(std::move(rule));
}
virtual void onClickPrevented();
virtual void invalidateAllStyles();
void invalidateStateStyles() {
invalidateStateStylesImpl(getMinimumSizePlusMargin());
}
virtual void invalidateAssHelper();
[[nodiscard]]
virtual bool wantsTouchscreenKeyboard();
void setSkipUntilLayoutUpdate(bool skipUntilLayoutUpdate) {
mSkipUntilLayoutUpdate = skipUntilLayoutUpdate;
}
void setFloating(AFloat f) noexcept
{
mFloating = f;
}
[[nodiscard]]
AFloat getFloating() const noexcept
{
return mFloating;
}
signals:
emits<> viewGraphSubtreeChanged;
emits<bool> hoveredState;
emits<> mouseEnter;
emits<> mouseLeave;
emits<bool> enabledState;
emits<> enabled;
emits<> disabled;
emits<APointerIndex> clickedButton;
emits<> clicked;
emits<glm::ivec2> positionChanged;
emits<glm::ivec2> sizeChanged;
emits<glm::ivec2> expandingChanged;
emits<Visibility> visibilityChanged;
emits<AInput::Key> keyPressed;
emits<AInput::Key> keyReleased;
emits<> clickedRight;
emits<> clickedRightOrLongPressed;
emits<APointerIndex> doubleClicked;
emits<> customCssPropertyChanged;
emits<bool> focusState;
emits<> focusAcquired;
emits<> focusLost;
emits<_<AView>> childFocused;
private:
AFieldSignalEmitter<bool> mHovered = AFieldSignalEmitter<bool>(hoveredState, mouseEnter, mouseLeave);
//AWatchable<bool> mFocused = AWatchable<bool>(pressedState, pressed, released);
AFieldSignalEmitter<bool> mEnabled = AFieldSignalEmitter<bool>(enabledState, enabled, disabled, true);
bool mDirectlyEnabled = true;
bool mParentEnabled = true;
AFieldSignalEmitter<bool> mHasFocus = AFieldSignalEmitter<bool>(focusState, focusAcquired, focusLost, false);
AFloat mFloating = AFloat::NONE;
struct RenderToTexture {
_unique<IRenderViewToTexture> rendererInterface;
bool drawFromTexture = true;
bool skipRedrawUntilTextureIsPresented = false;
};
AOptional<RenderToTexture> mRenderToTexture;
virtual void invalidateStateStylesImpl(glm::ivec2 prevMinimumSizePlusField);
void notifyParentChildFocused(const _<AView>& view);
};
API_AUI_VIEWS std::ostream& operator<<(std::ostream& os, const AView& view);
Definition: AAnimator.h:26
Remember, ASS is not a butt. ASS is Aui Style Sheets.
Definition: AAssHelper.h:32
Represents cursor type.
Definition: ACursor.h:27
Definition: AFieldSignalEmitter.h:51
A base object class.
Definition: AObject.h:49
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
AOptional< AInput::Key > button() const noexcept
Definition: APointerIndex.h:56
Vector-like container consisting of few elements on stack and switches to dynamic allocation vector i...
Definition: ASmallVector.h:34
Represents a Unicode character string.
Definition: AString.h:37
Definition: AStylesheet.h:21
A view that represents a set of views.
Definition: AViewContainerBase.h:68
A trivial modifiable view that represents a set of views.
Definition: AViewContainer.h:33
Base class of all UI objects.
Definition: AView.h:77
Definition: AWindowBase.h:33
Represents a window in the underlying windowing system.
Definition: AWindow.h:45
Rendering view to texture storage interface.
Definition: IRenderViewToTexture.h:26
An std::weak_ptr with AUI extensions.
Definition: SharedPtrTypes.h:177
#define emit
emits the specified signal in context of this object.
Definition: AObject.h:196
#define AUI_ASSERTX(condition, what)
Asserts that the passed condition evaluates to true. Adds extra message string.
Definition: Assert.h:74
AOverflow
Controls visibility of the overflowed contents of AView with AView::drawStencilMask.
Definition: AOverflow.h:25
@ VISIBLE
Overflowed contents are visible.
@ DEFAULT
There's no concrete input action. Let the OS decide which action is the most appropriate.
Represents a rectangle fields. Useful for margin and padding around AViews.
Definition: ABoxFields.h:21
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
Defines areas to invalidate (redraw).
Definition: IRenderViewToTexture.h:32
Definition: Click.h:51
Definition: Size.h:22
Definition: Visible.h:20
An std::weak_ptr with AUI extensions.
Definition: SharedPtrTypes.h:51
Definition: PropertyListRecursive.h:24
Definition: PropertyList.h:25
Clamps the possible values for a number to the specified range: [min;max].
Definition: values.h:452