Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -36,32 +36,32 @@ struct dyn_range_capabilities {
* @tparam T element type
* @details
* <!-- aui:experimental -->
* `aui::any_view` is a dynamic range class that mimics the behavior of C++20 ranges/range-v3 using type-erased
* `aui::any_range_view` is a dynamic range class that mimics the behavior of C++20 ranges/range-v3 using type-erased
* interfaces. It allows for the creation of runtime-checked, polymorphic ranges with input iterators.
*
* Alternative implementation of `ranges::views::any_view`.
* Alternative implementation of `ranges::views::any_range_view`.
*
* The general idea is to preserve lazy nature of C++20 ranges/range-v3 and flexibility between compilation modules.
*
* Keep in mind that type erasure can lead to performance overhead due to dynamic dispatch.
*
* `aui::any_view` initialized with an lvalue reference will contain a reference to the container; thus the container
* `aui::any_range_view` initialized with an lvalue reference will contain a reference to the container; thus the container
* can be modified.
*
* <!-- aui:snippet aui.core/tests/IteratorsTest.cpp DynRange4 -->
*
* `aui::any_view` initialized with an rvalue reference will move the container into itself; thus it acquires
* `aui::any_range_view` initialized with an rvalue reference will move the container into itself; thus it acquires
* ownership.
*
* <!-- aui:snippet aui.core/tests/IteratorsTest.cpp DynRange5 -->
*
* Using `aui::any_view::iterator` acquired before modification of the referenced container may lead to undefined
* Using `aui::any_range_view::iterator` acquired before modification of the referenced container may lead to undefined
* behaviour; it all depends on the referenced container.
*
* `aui::any_view` follows the same principle as `std::function` for functors.
* `aui::any_range_view` follows the same principle as `std::function` for functors.
*/
template<typename T>
struct any_view {
struct any_range_view {
struct iterator {
using value_type = T;
using iterator_category = std::input_iterator_tag;
Expand Down Expand Up @@ -184,28 +184,28 @@ struct any_view {
}
};

template<typename Rng>
any_view(Rng&& rng): mImpl(rttify(std::forward<Rng>(rng))) {
template<ranges::input_range Rng>
any_range_view(Rng&& rng): mImpl(rttify(std::forward<Rng>(rng))) {

}

any_view(): mImpl(nullptr) {}
any_range_view(): mImpl(nullptr) {}

any_view(any_view&& rhs) noexcept = default;
any_view& operator=(any_view&& rhs) noexcept = default;
any_range_view(any_range_view&& rhs) noexcept = default;
any_range_view& operator=(any_range_view&& rhs) noexcept = default;

any_view(any_view& rhs) {
any_range_view(any_range_view& rhs) {
operator=(rhs);
}
any_view(const any_view& rhs) {
any_range_view(const any_range_view& rhs) {
operator=(rhs);
}

any_view& operator=(any_view& rhs) {
return operator=(const_cast<const any_view&>(rhs));
any_range_view& operator=(any_range_view& rhs) {
return operator=(const_cast<const any_range_view&>(rhs));
}

any_view& operator=(const any_view& rhs) {
any_range_view& operator=(const any_range_view& rhs) {
if (this == &rhs) {
return *this;
}
Expand Down Expand Up @@ -289,9 +289,9 @@ struct any_view {
}
};

static_assert(ranges::input_iterator<any_view<int>::iterator>);
static_assert(ranges::sentinel_for<any_view<int>::iterator, any_view<int>::iterator>);
static_assert(ranges::range<any_view<int>>);
static_assert(ranges::input_iterator<any_range_view<int>::iterator>);
static_assert(ranges::sentinel_for<any_range_view<int>::iterator, any_range_view<int>::iterator>);
static_assert(ranges::range<any_range_view<int>>);

}

20 changes: 10 additions & 10 deletions aui.core/tests/IteratorsTest.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,7 @@
#include <AUI/Common/AVector.h>
#include <AUI/Traits/iterators.h>
#include <array>
#include "AUI/Traits/any_view.h"
#include "AUI/Traits/any_range_view.h"

TEST(Iterators, Zip) {
std::array<int, 3> ints = { 1, 2, 3 };
Expand Down Expand Up @@ -62,24 +62,24 @@ TEST(Iterators, Reverse) {
}

TEST(Iterators, DynRange1) {
aui::any_view<int> ints = ranges::views::ints | ranges::views::take(10);
aui::any_range_view<int> ints = ranges::views::ints | ranges::views::take(10);
EXPECT_EQ(ints | ranges::to_vector, std::vector({0, 1, 2, 3, 4, 5, 6, 7, 8, 9}));
}

TEST(Iterators, DynRange2) {
aui::any_view<int> ints = ranges::views::ints | ranges::views::take(10) | ranges::views::filter([](int i) { return i % 2 == 0; });
aui::any_range_view<int> ints = ranges::views::ints | ranges::views::take(10) | ranges::views::filter([](int i) { return i % 2 == 0; });
EXPECT_EQ(ints | ranges::to_vector, std::vector({0, 2, 4, 6, 8 }));
}

TEST(Iterators, DynRange3) {
aui::any_view<int> ints = ranges::views::ints | ranges::views::take(10) | ranges::views::filter([](int i) { return i % 2 == 0; }) | ranges::to_vector;
aui::any_range_view<int> ints = ranges::views::ints | ranges::views::take(10) | ranges::views::filter([](int i) { return i % 2 == 0; }) | ranges::to_vector;
EXPECT_EQ(ints | ranges::to_vector, std::vector({0, 2, 4, 6, 8 }));
}

TEST(Iterators, DynRange4) {
/// [DynRange4]
AVector<int> elements{1,2,3};
aui::any_view<int> ints = elements;
aui::any_range_view<int> ints = elements;
EXPECT_EQ(ints | ranges::to_vector, std::vector({1, 2, 3 }));
elements << 4;
EXPECT_EQ(ints | ranges::to_vector, std::vector({1, 2, 3, 4 }));
Expand All @@ -89,7 +89,7 @@ TEST(Iterators, DynRange4) {
TEST(Iterators, DynRange5) {
/// [DynRange5]
AVector<int> elements{1,2,3};
aui::any_view<int> ints = std::move(elements);
aui::any_range_view<int> ints = std::move(elements);
EXPECT_EQ(ints | ranges::to_vector, std::vector({1, 2, 3 }));
elements << 4;
EXPECT_EQ(ints | ranges::to_vector, std::vector({1, 2, 3 }));
Expand All @@ -98,16 +98,16 @@ TEST(Iterators, DynRange5) {

TEST(Iterators, DynRangeNoCopy1) {
AVector<std::unique_ptr<int>> elements{};
aui::any_view<std::unique_ptr<int>> ints = std::move(elements);
aui::any_range_view<std::unique_ptr<int>> ints = std::move(elements);
}

TEST(Iterators, DynRangeNoCopy2) {
AVector<std::unique_ptr<int>> elements{};
aui::any_view<std::unique_ptr<int>> ints = elements;
aui::any_range_view<std::unique_ptr<int>> ints = elements;
}

TEST(Iterators, DynRangeCaps1) {
aui::any_view<int> r = ranges::views::ints;
aui::any_range_view<int> r = ranges::views::ints;
EXPECT_TRUE(r.capabilities().implementsOperatorMinusMinus);
auto it = r.begin();
EXPECT_EQ(*it, 0);
Expand All @@ -120,7 +120,7 @@ TEST(Iterators, DynRangeCaps1) {
}

TEST(Iterators, DynRangeCaps2) {
aui::any_view<int> r = ranges::views::ints | ranges::views::chunk_by([](int l, int r) { return l / 10 == r / 10; }) | ranges::views::transform([](const auto& i){ return 0; });
aui::any_range_view<int> r = ranges::views::ints | ranges::views::chunk_by([](int l, int r) { return l / 10 == r / 10; }) | ranges::views::transform([](const auto& i){ return 0; });
EXPECT_FALSE(r.capabilities().implementsOperatorMinusMinus);
auto it = r.begin();
EXPECT_EQ(*it, 0);
Expand Down
9 changes: 1 addition & 8 deletions aui.views/src/AUI/ASS/AStylesheet.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -352,13 +352,6 @@ AStylesheet::AStylesheet() {
},
/// [ARadioButton]

// ADropdownList
{
t<ADropdownList>() >> t<ALabel>(),
Expanding{},
ATextAlign::LEFT,
},

// AListView
{
{t<AListView>(), t<ATreeView>()},
Expand Down Expand Up @@ -495,6 +488,7 @@ AStylesheet::AStylesheet() {
{
t<AScrollbar>(),
Margin { 0, 0, 0, 2_px },
LayoutSpacing { 1_px },
},
{
t<AScrollbarHandle>(),
Expand All @@ -507,7 +501,6 @@ AStylesheet::AStylesheet() {

MinSize { 15_dp, 15_dp },
BackgroundSolid { 0xcccccc_rgb },
Margin {1_px, 1_px },
},
{
t<AScrollbar>::disabled() > t<AScrollbarHandle>(),
Expand Down
19 changes: 15 additions & 4 deletions aui.views/src/AUI/Devtools/DevtoolsProfilingOptions.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -37,7 +37,7 @@ _<AView> makeLink(AString text, AUrl destination) {
}

_<ALabel> header(AString title) {
return Label { std::move(title) } AUI_WITH_STYLE { FontSize{16_pt}, Padding{0}, Margin { 4_dp, 24_dp, 8_dp } };
return Label { std::move(title) } AUI_WITH_STYLE { FontSize{16_pt}, Padding{0}, Margin { 16_dp, 24_dp, 16_dp } };
}
} // namespace

Expand Down Expand Up @@ -94,7 +94,7 @@ DevtoolsProfilingOptions::DevtoolsProfilingOptions(AWindowBase* targetWindow) {
Vertical {
Slider {
.value = AUI_REACT(*scalingParams),
.onValueChanged = [scalingParams, targetWindow](aui::float_within_0_1 newValue) {
.onValueChange = [scalingParams, targetWindow](aui::float_within_0_1 newValue) {
newValue = glm::round(newValue * 6) / 6.f;
*scalingParams = newValue;
targetWindow->setScalingParams({
Expand Down Expand Up @@ -124,7 +124,7 @@ DevtoolsProfilingOptions::DevtoolsProfilingOptions(AWindowBase* targetWindow) {
AText::fromItems(
{ "In addition to your monitor DPI adjustments, changes scaling factor with AWindow::setScalingParams "
"API. In this setting, 100% takes no effect." }),
header("Typography"),
header("Layout"),
/// [fromItems]
CheckBox {
AUI_REACT(targetWindow->profiling()->showBaseline),
Expand All @@ -137,7 +137,18 @@ DevtoolsProfilingOptions::DevtoolsProfilingOptions(AWindowBase* targetWindow) {
AText::fromItems(
{ "Displays a horizontal line indicating the text baseline. When multiple text views are placed in a row, "
"their baselines should align for proper visual appearance." }),
}

CheckBox {
AUI_REACT(targetWindow->profiling()->showLayout),
[targetWindow](bool checked) {
targetWindow->profiling()->showLayout = checked;
targetWindow->redraw();
},
Label { "Show layout" },
},
AText::fromItems(
{ "Indicates expanding views and spacers" }),
}
<< ".items" AUI_WITH_STYLE {
MaxSize { 700_dp, {} },
}) });
Expand Down
8 changes: 7 additions & 1 deletion aui.views/src/AUI/Layout/AHorizontalLayout.h
Original file line number Diff line number Diff line change
Expand Up @@ -59,10 +59,16 @@ class API_AUI_VIEWS AHorizontalLayout : public ALinearLayout<> {

int getMinimumHeight() override;

/**
* @see [LayoutSpacing](ass::LayoutSpacing)
*/
void setSpacing(int spacing) override;

/**
* @see [LayoutSpacing](ass::LayoutSpacing)
*/
[[nodiscard]]
int getSpacing() const { return mSpacing; }
int getSpacing() const override { return mSpacing; }

ALayoutDirection getLayoutDirection() override;
};
6 changes: 6 additions & 0 deletions aui.views/src/AUI/Layout/ALayout.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -13,4 +13,10 @@

void ALayout::setSpacing(int spacing) {}

int ALayout::getSpacing() const {
return 0;
}

ALayoutDirection ALayout::getLayoutDirection() { return ALayoutDirection::NONE; }


9 changes: 9 additions & 0 deletions aui.views/src/AUI/Layout/ALayout.h
Original file line number Diff line number Diff line change
Expand Up @@ -389,7 +389,16 @@ class API_AUI_VIEWS ALayout : public AObject {

/**
* @brief Layout spacing.
* @see [LayoutSpacing](ass::LayoutSpacing)
* @param spacing spacing in px.
*/
virtual void setSpacing(int spacing);

/**
* @brief Layout spacing .
* @see [LayoutSpacing](ass::LayoutSpacing)
* @return spacing spacing in px.
*
*/
virtual int getSpacing() const;
};
7 changes: 6 additions & 1 deletion aui.views/src/AUI/Layout/AVerticalLayout.h
Original file line number Diff line number Diff line change
Expand Up @@ -63,8 +63,13 @@ class API_AUI_VIEWS AVerticalLayout : public ALinearLayout<> {
*/
void setSpacing(int spacing) override;

/**
* @see [LayoutSpacing](ass::LayoutSpacing)
*/
[[nodiscard]]
int getSpacing() const { return mSpacing; }
int getSpacing() const override {
return mSpacing;
}

ALayoutDirection getLayoutDirection() override;
};
6 changes: 6 additions & 0 deletions aui.views/src/AUI/Platform/AWindowBase.h
Original file line number Diff line number Diff line change
Expand Up @@ -73,6 +73,12 @@ class API_AUI_VIEWS AWindowBase: public AViewContainer {
* @brief When set to true, all rendered strings will display their baselines.
*/
AProperty<bool> showBaseline = false;


/**
* @brief When set to true, indicates expanding views and spacers.
*/
AProperty<bool> showLayout = false;
};


Expand Down
6 changes: 5 additions & 1 deletion aui.views/src/AUI/Platform/AWindows.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -51,7 +51,11 @@ void AWindow::doDrawWindow() {
APerformanceSection s("AWindow::doDrawWindow");
auto& renderer = mRenderingContext->renderer();
renderer.setWindow(this);
render({.clippingRects = { ARect<int>{ .p1 = glm::ivec2(0), .p2 = getSize() } }, .render = renderer });
render({
.clippingRects = { ARect<int> { .p1 = glm::ivec2(0), .p2 = getSize() } },
.render = renderer,
.debugLayout = profiling().hasValue() && profiling()->showLayout.raw,
});
}

void AWindow::createDevtoolsWindow() {
Expand Down
2 changes: 2 additions & 0 deletions aui.views/src/AUI/Render/ARenderContext.h
Original file line number Diff line number Diff line change
Expand Up @@ -49,6 +49,8 @@ struct API_AUI_VIEWS ARenderContext
Rectangles clippingRects;
IRenderer& render;

bool debugLayout = false;

void clip(ARect<int> clipping);

[[nodiscard]]
Expand Down
12 changes: 12 additions & 0 deletions aui.views/src/AUI/Util/Declarative/Contracts.h
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,7 @@ namespace declarative::contract {
* A helper class that allows you to declare a value that can be either a constant or a reactive expression.
*/
template <typename T>
requires aui::copy_constructible<T>
struct In {
private:
/**
Expand Down Expand Up @@ -104,6 +105,17 @@ struct In {
mImpl = Devastated {};
}

[[nodiscard]]
const T& value() const {
return std::visit(aui::lambda_overloaded {
[](const Devastated&) -> const T& {
throw AException("an attempt to get value from contract::In after bindTo");
},
[](const Constant& c) -> const T& { return c.value; },
[](const ReactiveExpression& c) -> const T& { return *c.value; },
}, mImpl);
}

private:
std::variant<Devastated, Constant, ReactiveExpression> mImpl;
};
Expand Down
4 changes: 2 additions & 2 deletions aui.views/src/AUI/View/AButton.h
Original file line number Diff line number Diff line change
Expand Up @@ -111,7 +111,7 @@ class API_AUI_VIEWS AButton : public AViewContainer {
* @details
* !!! failure "Deprecated"
*
* Left for compatibility.
* Left for compatibility with [retained UI](retained_immediate_ui.md).
*
* This setter would override any of existing content within button.
*/
Expand All @@ -125,7 +125,7 @@ class API_AUI_VIEWS AButton : public AViewContainer {
*
* !!! failure "Deprecated"
*
* Left for compatibility.
* Left for compatibility with [retained UI](retained_immediate_ui.md).
*
* This setter would override any of existing content within button.
*/
Expand Down
Loading
Loading