/* * Copyright (c) 2018-2020, Andreas Kling * Copyright (c) 2022, Filiph Sandström * Copyright (c) 2022, Ali Mohammad Pur * * SPDX-License-Identifier: BSD-2-Clause */ #pragma once #include #include #include #include #include #include namespace GUI { namespace Detail { struct Boolean { bool value; }; using VariantUnderlyingType = AK::Variant, NonnullRefPtr, GUI::Icon>; } class Variant : public Detail::VariantUnderlyingType { public: using Detail::VariantUnderlyingType::Variant; using Detail::VariantUnderlyingType::operator=; Variant(JsonValue const&); Variant& operator=(JsonValue const&); Variant(bool v) : Variant(Detail::Boolean { v }) { } Variant& operator=(bool v) { set(Detail::Boolean { v }); return *this; } template Variant(T&& value) requires(IsConstructible) : Variant(String(forward(value))) { } template Variant& operator=(T&& v) requires(IsConstructible) { set(String(v)); return *this; } template T> Variant(T const& value) : Variant(NonnullRefPtr>(value)) { } template T> Variant& operator=(T&& value) { set(NonnullRefPtr>(forward(value))); return *this; } ~Variant() = default; bool is_valid() const { return !has(); } bool is_bool() const { return has(); } bool is_i32() const { return has(); } bool is_i64() const { return has(); } bool is_u32() const { return has(); } bool is_u64() const { return has(); } bool is_float() const { return has(); } bool is_string() const { return has(); } bool is_bitmap() const { return has>(); } bool is_color() const { return has(); } bool is_icon() const { return has(); } bool is_point() const { return has(); } bool is_size() const { return has(); } bool is_rect() const { return has(); } bool is_font() const { return has>(); } bool is_text_alignment() const { return has(); } bool is_color_role() const { return has(); } bool is_alignment_role() const { return has(); } bool is_flag_role() const { return has(); } bool is_metric_role() const { return has(); } bool is_path_role() const { return has(); } bool as_bool() const { return get().value; } bool to_bool() const { return visit( [](Empty) { return false; }, [](Detail::Boolean v) { return v.value; }, [](String const& v) { return !v.is_null(); }, [](Integral auto v) { return v != 0; }, [](OneOf auto const& v) { return !v.is_null(); }, [](Enum auto const&) { return true; }, [](OneOf, NonnullRefPtr, GUI::Icon> auto const&) { return true; }); } i32 as_i32() const { return get(); } i64 as_i64() const { return get(); } u32 as_u32() const { return get(); } u64 as_u64() const { return get(); } template T to_integer() const { return visit( [](Empty) -> T { return 0; }, [](Integral auto v) { return static_cast(v); }, [](FloatingPoint auto v) { return (T)v; }, [](Detail::Boolean v) -> T { return v.value ? 1 : 0; }, [](String const& v) { if constexpr (IsUnsigned) return v.to_uint().value_or(0u); else return v.to_int().value_or(0); }, [](Enum auto const&) -> T { return 0; }, [](OneOf, NonnullRefPtr, GUI::Icon> auto const&) -> T { return 0; }); } i32 to_i32() const { return to_integer(); } i64 to_i64() const { return to_integer(); } float as_float() const { return get(); } float as_float_or(float fallback) const { if (auto const* p = get_pointer()) return *p; return fallback; } Gfx::IntPoint as_point() const { return get(); } Gfx::IntSize as_size() const { return get(); } Gfx::IntRect as_rect() const { return get(); } String as_string() const { return get(); } Gfx::Bitmap const& as_bitmap() const { return *get>(); } GUI::Icon as_icon() const { return get(); } Color as_color() const { return get(); } Gfx::Font const& as_font() const { return *get>(); } Gfx::TextAlignment to_text_alignment(Gfx::TextAlignment default_value) const { if (auto const* p = get_pointer()) return *p; return default_value; } Gfx::ColorRole to_color_role() const { if (auto const* p = get_pointer()) return *p; return Gfx::ColorRole::NoRole; } Gfx::AlignmentRole to_alignment_role() const { if (auto const* p = get_pointer()) return *p; return Gfx::AlignmentRole::NoRole; } Gfx::FlagRole to_flag_role() const { if (auto const* p = get_pointer()) return *p; return Gfx::FlagRole::NoRole; } Gfx::MetricRole to_metric_role() const { if (auto const* p = get_pointer()) return *p; return Gfx::MetricRole::NoRole; } Gfx::PathRole to_path_role() const { if (auto const* p = get_pointer()) return *p; return Gfx::PathRole::NoRole; } Color to_color(Color default_value = {}) const { if (auto const* p = get_pointer()) return *p; if (auto const* p = get_pointer()) return Color::from_string(*p).value_or(default_value); return default_value; } String to_string() const { return visit( [](Empty) -> String { return "[null]"; }, [](Gfx::TextAlignment v) { return String::formatted("Gfx::TextAlignment::{}", Gfx::to_string(v)); }, [](Gfx::ColorRole v) { return String::formatted("Gfx::ColorRole::{}", Gfx::to_string(v)); }, [](Gfx::AlignmentRole v) { return String::formatted("Gfx::AlignmentRole::{}", Gfx::to_string(v)); }, [](Gfx::FlagRole v) { return String::formatted("Gfx::FlagRole::{}", Gfx::to_string(v)); }, [](Gfx::MetricRole v) { return String::formatted("Gfx::MetricRole::{}", Gfx::to_string(v)); }, [](Gfx::PathRole v) { return String::formatted("Gfx::PathRole::{}", Gfx::to_string(v)); }, [](NonnullRefPtr const& font) { return String::formatted("[Font: {}]", font->name()); }, [](NonnullRefPtr const&) -> String { return "[Gfx::Bitmap]"; }, [](GUI::Icon const&) -> String { return "[GUI::Icon]"; }, [](Detail::Boolean v) { return String::formatted("{}", v.value); }, [](auto const& v) { return String::formatted("{}", v); }); } bool operator==(Variant const&) const; bool operator<(Variant const&) const; }; }