Skip to content
Merged
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
16 changes: 14 additions & 2 deletions aui.views/src/AUI/Platform/win32/AClipboardImpl.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -19,10 +19,22 @@

#include <Windows.h>

static constexpr auto LOG_TAG = "AClipboard";

void AClipboard::copyToClipboard(const AString& text) {
const size_t len = text.length() * 2 + 2;
const auto converted = text.toUtf16();
size_t len = (converted.length() + 1 /* null terminator included */) * sizeof(wchar_t);
HGLOBAL hMem = GlobalAlloc(GMEM_MOVEABLE, len);
memcpy(GlobalLock(hMem), text.data(), len);
if (hMem == nullptr) {
ALogger::err(LOG_TAG) << "copyToClipboard: GlobalAlloc failed";
return;
}
auto globalLock = GlobalLock(hMem);
if (globalLock == nullptr) {
ALogger::err(LOG_TAG) << "copyToClipboard: GlobalLock failed";
return;
}
memcpy(globalLock, converted.data(), len);
GlobalUnlock(hMem);
OpenClipboard(nullptr);
EmptyClipboard();
Expand Down
14 changes: 14 additions & 0 deletions aui.views/src/AUI/Util/Declarative/Contracts.h
Original file line number Diff line number Diff line change
Expand Up @@ -104,6 +104,20 @@ struct In {
mImpl = Devastated {};
}

const T& value() const {
return std::visit(
aui::lambda_overloaded {
[&](const Devastated&) -> const T& { throw AException("an attempt to dereference a property twice"); },
[&](const Constant& c) -> const T& { return c.value; },
[&](const ReactiveExpression& c) -> const T& { return **c.value; },
}, mImpl
);
}

const T& operator*() const { return value(); }

const T* operator->() const { return &value(); }

private:
std::variant<Devastated, Constant, ReactiveExpression> mImpl;
};
Expand Down
144 changes: 144 additions & 0 deletions aui.views/src/AUI/View/AColorPicker.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,144 @@
// AUI Framework - Declarative UI toolkit for modern C++20
// Copyright (C) 2020-2025 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 <AUI/View/AGroupBox.h>
#include <AUI/View/ASlider.h>

namespace declarative::color_picker {

/**
* @brief View that displays a single color.
* @ingroup views_indication
* @details
* The `ColorView` simply renders a solid rectangle matching the provided color contract. It is intended to be used as a
* visual preview of a color value.
*
* <!-- aui:snippet examples/ui/color_picker1/src/main.cpp colorpicker_example -->
*/
struct ColorView {
/**
* @brief The color to display.
*/
contract::In<AColor> color;

_<AView> operator()() {
auto color = this->color;
return Centered {
_new<AView>() AUI_LET {
AObject::connect(
AUI_REACT(ass::PropertyListRecursive {
BackgroundSolid {
color.value(),
},
Expanding {},
}),
AUI_SLOT(it)::setCustomStyle);
},
};
}
Comment thread
Alex2772 marked this conversation as resolved.
};

/**
* @brief RGB sliders for editing a color.
* @ingroup views_input
* @details
* `SlidersRGB` exposes three sliders, one for each channel (red, green,
* blue). The sliders are bound to a shared `AColor` contract and notify a
* callback when the color changes.
*
* <!-- aui:snippet examples/ui/color_picker1/src/main.cpp colorpicker_example -->
*/
struct SlidersRGB {
/**
* @brief Pointer to a color channel.
*/
using Channel = float(AColor::*);

/**
* @brief The color contract to edit.
*/
contract::In<AColor> color;

/**
* @brief Callback invoked when the color changes.
*/
std::function<void(AColor)> onColorChanged;

/**
* @brief Factory used to create individual sliders.
*/
std::function<_<AView>(contract::In<AColor> color, std::function<void(AColor)> onColorChanged, Channel channel)>
sliderFactory = defaultSlider;

/**
* @brief Creates a slider for a single channel.
* @param color The color contract.
* @param onColorChanged Callback when the color changes.
* @param channel Pointer to the channel member.
* @return A view containing the slider.
*/
static _<AView>
defaultSlider(contract::In<AColor> color, std::function<void(AColor)> onColorChanged, Channel channel) {
return Slider {
.value = AUI_REACT(std::invoke(channel, color)),
.onValueChanged =
[color, onColorChanged = std::move(onColorChanged), channel](aui::float_within_0_1 v) {
auto copy = *color;
std::invoke(channel, copy) = v;
onColorChanged(copy);
},
.track =
_new<AView>() AUI_LET {
AObject::connect(
AUI_REACT(ass::PropertyListRecursive {
Expanding {},
BackgroundGradient {
adjustChannel(color.value(), channel, 0.0f),
adjustChannel(color.value(), channel, 1.0f),
90_deg,
},
MinSize { 20_dp },
}),
AUI_SLOT(it)::setCustomStyle);
},
.handle =
_new<AView>() AUI_OVERRIDE_STYLE {
FixedSize { 3_px, {} },
Expanding {},
BackgroundSolid { AColor::WHITE },
Border { 1_px, AColor::BLACK },
Margin { 4_px, 0 },
},
};
}

_<AView> operator()() {
return Vertical {
sliderFactory(color, onColorChanged, &AColor::r),
sliderFactory(color, onColorChanged, &AColor::g),
sliderFactory(color, onColorChanged, &AColor::b),
} AUI_OVERRIDE_STYLE { LayoutSpacing { 4_dp } };
}

private:
/**
* @brief Adjusts a single channel of a color.
* @param src The source color.
* @param channel Pointer to the channel member.
* @param newValue The new channel value.
* @return The color with the channel updated.
*/
static AColor adjustChannel(AColor src, float(AColor::* channel), float newValue) {
std::invoke(channel, src) = newValue;
return src;
}
};
} // namespace declarative::color_picker
6 changes: 6 additions & 0 deletions examples/ui/color_picker1/CMakeLists.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
cmake_minimum_required(VERSION 3.10)

get_filename_component(_t ${CMAKE_CURRENT_SOURCE_DIR} NAME)

aui_executable("aui.example.${_t}")
aui_link("aui.example.${_t}" PRIVATE aui::core aui::views)
49 changes: 49 additions & 0 deletions examples/ui/color_picker1/src/main.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,49 @@
/*
* AUI Framework - Declarative UI toolkit for modern C++20
* Copyright (C) 2020-2025 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/.
*/
/// [colorpicker_example]
#include <AUI/Platform/Entry.h>
#include <AUI/Platform/AWindow.h>
#include <AUI/View/AColorPicker.h>

using namespace ass;
using namespace declarative;


class MainWindow : public AWindow {
public:
MainWindow() : AWindow("Color picker", 600_dp, 300_dp) {
auto color = _new<AProperty<AColor>>(AColor::RED);
setContents(Vertical {
GroupBox {
Label { "View" },
color_picker::ColorView { AUI_REACT(**color) } AUI_OVERRIDE_STYLE {
FixedSize(40_dp, 20_dp),
Border { 1_px, AColor::BLACK },
Padding { 2_px },
},
},
GroupBox {
Label { "Sliders RGB" },
color_picker::SlidersRGB {
.color = AUI_REACT(**color),
.onColorChanged = [color](AColor c) { *color = c; },
},
},
});
}

};

AUI_ENTRY {
_new<MainWindow>()->show();
return 0;
}
/// [colorpicker_example]
Loading