123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425 |
- /*
- * Copyright (c) 2018-2020, Andreas Kling <kling@serenityos.org>
- * All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions are met:
- *
- * 1. Redistributions of source code must retain the above copyright notice, this
- * list of conditions and the following disclaimer.
- *
- * 2. Redistributions in binary form must reproduce the above copyright notice,
- * this list of conditions and the following disclaimer in the documentation
- * and/or other materials provided with the distribution.
- *
- * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
- * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
- * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
- * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
- * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
- * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
- * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
- * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
- * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
- * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- */
- #include <AK/FlyString.h>
- #include <AK/JsonValue.h>
- #include <LibGUI/Variant.h>
- namespace GUI {
- const char* to_string(Variant::Type type)
- {
- switch (type) {
- case Variant::Type::Invalid:
- return "Invalid";
- case Variant::Type::Bool:
- return "Bool";
- case Variant::Type::Int32:
- return "Int32";
- case Variant::Type::Int64:
- return "Int64";
- case Variant::Type::UnsignedInt:
- return "UnsignedInt";
- case Variant::Type::Float:
- return "Float";
- case Variant::Type::String:
- return "String";
- case Variant::Type::Bitmap:
- return "Bitmap";
- case Variant::Type::Color:
- return "Color";
- case Variant::Type::Icon:
- return "Icon";
- case Variant::Type::Point:
- return "Point";
- case Variant::Type::Size:
- return "Size";
- case Variant::Type::Rect:
- return "Rect";
- case Variant::Type::Font:
- return "Font";
- }
- ASSERT_NOT_REACHED();
- }
- Variant::Variant()
- {
- m_value.as_string = nullptr;
- }
- Variant::~Variant()
- {
- clear();
- }
- void Variant::clear()
- {
- switch (m_type) {
- case Type::String:
- AK::unref_if_not_null(m_value.as_string);
- break;
- case Type::Bitmap:
- AK::unref_if_not_null(m_value.as_bitmap);
- break;
- case Type::Icon:
- AK::unref_if_not_null(m_value.as_icon);
- break;
- default:
- break;
- }
- m_type = Type::Invalid;
- m_value.as_string = nullptr;
- }
- Variant::Variant(i32 value)
- : m_type(Type::Int32)
- {
- m_value.as_i32 = value;
- }
- Variant::Variant(i64 value)
- : m_type(Type::Int64)
- {
- m_value.as_i64 = value;
- }
- Variant::Variant(unsigned value)
- : m_type(Type::UnsignedInt)
- {
- m_value.as_uint = value;
- }
- Variant::Variant(float value)
- : m_type(Type::Float)
- {
- m_value.as_float = value;
- }
- Variant::Variant(bool value)
- : m_type(Type::Bool)
- {
- m_value.as_bool = value;
- }
- Variant::Variant(const char* cstring)
- : Variant(String(cstring))
- {
- }
- Variant::Variant(const FlyString& value)
- : Variant(String(value.impl()))
- {
- }
- Variant::Variant(const String& value)
- : m_type(Type::String)
- {
- m_value.as_string = const_cast<StringImpl*>(value.impl());
- AK::ref_if_not_null(m_value.as_string);
- }
- Variant::Variant(const JsonValue& value)
- {
- if (value.is_null()) {
- m_value.as_string = nullptr;
- return;
- }
- if (value.is_i32()) {
- m_type = Type::Int32;
- m_value.as_i32 = value.as_i32();
- return;
- }
- if (value.is_u32()) {
- m_type = Type::UnsignedInt;
- m_value.as_uint = value.as_u32();
- return;
- }
- if (value.is_i64()) {
- m_type = Type::Int64;
- m_value.as_i64 = value.as_i64();
- return;
- }
- if (value.is_u64()) {
- // FIXME: Variant should have a 64-bit internal type.
- m_type = Type::UnsignedInt;
- m_value.as_uint = value.to_u32();
- return;
- }
- if (value.is_string()) {
- m_type = Type::String;
- m_value.as_string = value.as_string().impl();
- m_value.as_string->ref();
- return;
- }
- if (value.is_bool()) {
- m_type = Type::Bool;
- m_value.as_bool = value.as_bool();
- return;
- }
- ASSERT_NOT_REACHED();
- }
- Variant::Variant(const Gfx::Bitmap& value)
- : m_type(Type::Bitmap)
- {
- m_value.as_bitmap = const_cast<Gfx::Bitmap*>(&value);
- AK::ref_if_not_null(m_value.as_bitmap);
- }
- Variant::Variant(const GUI::Icon& value)
- : m_type(Type::Icon)
- {
- m_value.as_icon = &const_cast<GUI::IconImpl&>(value.impl());
- AK::ref_if_not_null(m_value.as_icon);
- }
- Variant::Variant(const Gfx::Font& value)
- : m_type(Type::Font)
- {
- m_value.as_font = &const_cast<Gfx::Font&>(value);
- AK::ref_if_not_null(m_value.as_font);
- }
- Variant::Variant(Color color)
- : m_type(Type::Color)
- {
- m_value.as_color = color.value();
- }
- Variant::Variant(const Gfx::Point& point)
- : m_type(Type::Point)
- {
- m_value.as_point = { point.x(), point.y() };
- }
- Variant::Variant(const Gfx::Size& size)
- : m_type(Type::Size)
- {
- m_value.as_size = { size.width(), size.height() };
- }
- Variant::Variant(const Gfx::Rect& rect)
- : m_type(Type::Rect)
- {
- m_value.as_rect = (const RawRect&)rect;
- }
- Variant& Variant::operator=(const Variant& other)
- {
- if (&other == this)
- return *this;
- clear();
- copy_from(other);
- return *this;
- }
- Variant& Variant::operator=(Variant&& other)
- {
- if (&other == this)
- return *this;
- // FIXME: Move, not copy!
- clear();
- copy_from(other);
- other.clear();
- return *this;
- }
- Variant::Variant(const Variant& other)
- {
- copy_from(other);
- }
- void Variant::copy_from(const Variant& other)
- {
- ASSERT(!is_valid());
- m_type = other.m_type;
- switch (m_type) {
- case Type::Bool:
- m_value.as_bool = other.m_value.as_bool;
- break;
- case Type::Int32:
- m_value.as_i32 = other.m_value.as_i32;
- break;
- case Type::Int64:
- m_value.as_i64 = other.m_value.as_i64;
- break;
- case Type::UnsignedInt:
- m_value.as_uint = other.m_value.as_uint;
- break;
- case Type::Float:
- m_value.as_float = other.m_value.as_float;
- break;
- case Type::String:
- m_value.as_string = other.m_value.as_string;
- AK::ref_if_not_null(m_value.as_bitmap);
- break;
- case Type::Bitmap:
- m_value.as_bitmap = other.m_value.as_bitmap;
- AK::ref_if_not_null(m_value.as_bitmap);
- break;
- case Type::Icon:
- m_value.as_icon = other.m_value.as_icon;
- AK::ref_if_not_null(m_value.as_icon);
- break;
- case Type::Font:
- m_value.as_font = other.m_value.as_font;
- AK::ref_if_not_null(m_value.as_font);
- break;
- case Type::Color:
- m_value.as_color = other.m_value.as_color;
- break;
- case Type::Point:
- m_value.as_point = other.m_value.as_point;
- break;
- case Type::Size:
- m_value.as_size = other.m_value.as_size;
- break;
- case Type::Rect:
- m_value.as_rect = other.m_value.as_rect;
- break;
- case Type::Invalid:
- break;
- }
- }
- bool Variant::operator==(const Variant& other) const
- {
- if (m_type != other.m_type)
- return to_string() == other.to_string();
- switch (m_type) {
- case Type::Bool:
- return as_bool() == other.as_bool();
- case Type::Int32:
- return as_i32() == other.as_i32();
- case Type::Int64:
- return as_i64() == other.as_i64();
- case Type::UnsignedInt:
- return as_uint() == other.as_uint();
- case Type::Float:
- return as_float() == other.as_float();
- case Type::String:
- return as_string() == other.as_string();
- case Type::Bitmap:
- return m_value.as_bitmap == other.m_value.as_bitmap;
- case Type::Icon:
- return m_value.as_icon == other.m_value.as_icon;
- case Type::Color:
- return m_value.as_color == other.m_value.as_color;
- case Type::Point:
- return as_point() == other.as_point();
- case Type::Size:
- return as_size() == other.as_size();
- case Type::Rect:
- return as_rect() == other.as_rect();
- case Type::Font:
- return &as_font() == &other.as_font();
- case Type::Invalid:
- return true;
- }
- ASSERT_NOT_REACHED();
- }
- bool Variant::operator<(const Variant& other) const
- {
- if (m_type != other.m_type)
- return to_string() < other.to_string();
- switch (m_type) {
- case Type::Bool:
- return as_bool() < other.as_bool();
- case Type::Int32:
- return as_i32() < other.as_i32();
- case Type::Int64:
- return as_i64() < other.as_i64();
- case Type::UnsignedInt:
- return as_uint() < other.as_uint();
- case Type::Float:
- return as_float() < other.as_float();
- case Type::String:
- return as_string() < other.as_string();
- case Type::Bitmap:
- // FIXME: Maybe compare bitmaps somehow differently?
- return m_value.as_bitmap < other.m_value.as_bitmap;
- case Type::Icon:
- // FIXME: Maybe compare icons somehow differently?
- return m_value.as_icon < other.m_value.as_icon;
- case Type::Color:
- return m_value.as_color < other.m_value.as_color;
- case Type::Point:
- case Type::Size:
- case Type::Rect:
- case Type::Font:
- // FIXME: Figure out how to compare these.
- ASSERT_NOT_REACHED();
- case Type::Invalid:
- break;
- }
- ASSERT_NOT_REACHED();
- }
- String Variant::to_string() const
- {
- switch (m_type) {
- case Type::Bool:
- return as_bool() ? "true" : "false";
- case Type::Int32:
- return String::number(as_i32());
- case Type::Int64:
- return String::number(as_i64());
- case Type::UnsignedInt:
- return String::number(as_uint());
- case Type::Float:
- return String::format("%.2f", (double)as_float());
- case Type::String:
- return as_string();
- case Type::Bitmap:
- return "[Gfx::Bitmap]";
- case Type::Icon:
- return "[GUI::Icon]";
- case Type::Color:
- return as_color().to_string();
- case Type::Point:
- return as_point().to_string();
- case Type::Size:
- return as_size().to_string();
- case Type::Rect:
- return as_rect().to_string();
- case Type::Font:
- return String::format("[Font: %s]", as_font().name().characters());
- case Type::Invalid:
- return "[null]";
- break;
- }
- ASSERT_NOT_REACHED();
- }
- }
|