Serenity Operating System
at portability 284 lines 7.3 kB view raw
1/* 2 * Copyright (c) 2018-2020, Andreas Kling <kling@serenityos.org> 3 * All rights reserved. 4 * 5 * Redistribution and use in source and binary forms, with or without 6 * modification, are permitted provided that the following conditions are met: 7 * 8 * 1. Redistributions of source code must retain the above copyright notice, this 9 * list of conditions and the following disclaimer. 10 * 11 * 2. Redistributions in binary form must reproduce the above copyright notice, 12 * this list of conditions and the following disclaimer in the documentation 13 * and/or other materials provided with the distribution. 14 * 15 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 16 * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 17 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE 18 * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE 19 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 20 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR 21 * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER 22 * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, 23 * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 24 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 25 */ 26 27#pragma once 28 29#include <AK/String.h> 30#include <LibGfx/Font.h> 31#include <LibGfx/Bitmap.h> 32#include <LibGUI/Icon.h> 33 34namespace GUI { 35 36class Variant { 37public: 38 Variant(); 39 Variant(bool); 40 Variant(float); 41 Variant(i32); 42 Variant(i64); 43 Variant(unsigned); 44 Variant(const char*); 45 Variant(const String&); 46 Variant(const Gfx::Bitmap&); 47 Variant(const GIcon&); 48 Variant(const Gfx::Point&); 49 Variant(const Gfx::Size&); 50 Variant(const Gfx::Rect&); 51 Variant(const Gfx::Font&); 52 Variant(const AK::JsonValue&); 53 Variant(Color); 54 55 Variant(const Variant&); 56 Variant& operator=(const Variant&); 57 58 Variant(Variant&&) = delete; 59 Variant& operator=(Variant&&); 60 61 void clear(); 62 ~Variant(); 63 64 enum class Type { 65 Invalid, 66 Bool, 67 Int32, 68 Int64, 69 UnsignedInt, 70 Float, 71 String, 72 Bitmap, 73 Color, 74 Icon, 75 Point, 76 Size, 77 Rect, 78 Font, 79 }; 80 81 bool is_valid() const { return m_type != Type::Invalid; } 82 bool is_bool() const { return m_type == Type::Bool; } 83 bool is_i32() const { return m_type == Type::Int32; } 84 bool is_i64() const { return m_type == Type::Int64; } 85 bool is_uint() const { return m_type == Type::UnsignedInt; } 86 bool is_float() const { return m_type == Type::Float; } 87 bool is_string() const { return m_type == Type::String; } 88 bool is_bitmap() const { return m_type == Type::Bitmap; } 89 bool is_color() const { return m_type == Type::Color; } 90 bool is_icon() const { return m_type == Type::Icon; } 91 bool is_point() const { return m_type == Type::Point; } 92 bool is_size() const { return m_type == Type::Size; } 93 bool is_rect() const { return m_type == Type::Rect; } 94 bool is_font() const { return m_type == Type::Font; } 95 Type type() const { return m_type; } 96 97 bool as_bool() const 98 { 99 ASSERT(type() == Type::Bool); 100 return m_value.as_bool; 101 } 102 103 bool to_bool() const 104 { 105 if (type() == Type::Bool) 106 return as_bool(); 107 if (type() == Type::String) 108 return !!m_value.as_string; 109 if (type() == Type::Int32) 110 return m_value.as_i32 != 0; 111 if (type() == Type::Int64) 112 return m_value.as_i64 != 0; 113 if (type() == Type::UnsignedInt) 114 return m_value.as_uint != 0; 115 if (type() == Type::Rect) 116 return !as_rect().is_null(); 117 if (type() == Type::Size) 118 return !as_size().is_null(); 119 if (type() == Type::Point) 120 return !as_point().is_null(); 121 return is_valid(); 122 } 123 124 int as_i32() const 125 { 126 ASSERT(type() == Type::Int32); 127 return m_value.as_i32; 128 } 129 130 int as_i64() const 131 { 132 ASSERT(type() == Type::Int64); 133 return m_value.as_i64; 134 } 135 136 unsigned as_uint() const 137 { 138 ASSERT(type() == Type::UnsignedInt); 139 return m_value.as_uint; 140 } 141 142 template<typename T> 143 T to_integer() const 144 { 145 if (is_i32()) 146 return as_i32(); 147 if (is_i64()) 148 return as_i64(); 149 if (is_bool()) 150 return as_bool() ? 1 : 0; 151 if (is_float()) 152 return (int)as_float(); 153 if (is_uint()) { 154 ASSERT(as_uint() <= INT32_MAX); 155 return (int)as_uint(); 156 } 157 if (is_string()) { 158 bool ok; 159 int value = as_string().to_int(ok); 160 if (!ok) 161 return 0; 162 return value; 163 } 164 return 0; 165 } 166 167 i32 to_i32() const 168 { 169 return to_integer<i32>(); 170 } 171 172 i64 to_i64() const 173 { 174 return to_integer<i64>(); 175 } 176 177 float as_float() const 178 { 179 ASSERT(type() == Type::Float); 180 return m_value.as_float; 181 } 182 183 Gfx::Point as_point() const 184 { 185 return { m_value.as_point.x, m_value.as_point.y }; 186 } 187 188 Gfx::Size as_size() const 189 { 190 return { m_value.as_size.width, m_value.as_size.height }; 191 } 192 193 Gfx::Rect as_rect() const 194 { 195 return { as_point(), as_size() }; 196 } 197 198 String as_string() const 199 { 200 ASSERT(type() == Type::String); 201 return m_value.as_string; 202 } 203 204 const Gfx::Bitmap& as_bitmap() const 205 { 206 ASSERT(type() == Type::Bitmap); 207 return *m_value.as_bitmap; 208 } 209 210 GIcon as_icon() const 211 { 212 ASSERT(type() == Type::Icon); 213 return GIcon(*m_value.as_icon); 214 } 215 216 Color as_color() const 217 { 218 ASSERT(type() == Type::Color); 219 return Color::from_rgba(m_value.as_color); 220 } 221 222 const Gfx::Font& as_font() const 223 { 224 ASSERT(type() == Type::Font); 225 return *m_value.as_font; 226 } 227 228 Color to_color(Color default_value = {}) const 229 { 230 if (type() == Type::Color) 231 return as_color(); 232 if (type() == Type::String) { 233 auto color = Color::from_string(as_string()); 234 if (color.has_value()) 235 return color.value(); 236 } 237 return default_value; 238 } 239 240 String to_string() const; 241 242 bool operator==(const Variant&) const; 243 bool operator<(const Variant&) const; 244 245private: 246 void copy_from(const Variant&); 247 248 struct RawPoint { 249 int x; 250 int y; 251 }; 252 253 struct RawSize { 254 int width; 255 int height; 256 }; 257 258 struct RawRect { 259 RawPoint location; 260 RawSize size; 261 }; 262 263 union { 264 StringImpl* as_string; 265 Gfx::Bitmap* as_bitmap; 266 GIconImpl* as_icon; 267 Gfx::Font* as_font; 268 bool as_bool; 269 i32 as_i32; 270 i64 as_i64; 271 unsigned as_uint; 272 float as_float; 273 Gfx::RGBA32 as_color; 274 RawPoint as_point; 275 RawSize as_size; 276 RawRect as_rect; 277 } m_value; 278 279 Type m_type { Type::Invalid }; 280}; 281 282const char* to_string(Variant::Type); 283 284}