diff --git a/CMakeLists.txt b/CMakeLists.txt index d68eb4a..91e2e54 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -131,6 +131,8 @@ PRIVATE ui/style/style_core_font.h ui/style/style_core_icon.cpp ui/style/style_core_icon.h + ui/style/style_core_palette.cpp + ui/style/style_core_palette.h ui/style/style_core_scale.cpp ui/style/style_core_scale.h ui/style/style_core_types.cpp diff --git a/ui/style/style_core_color.cpp b/ui/style/style_core_color.cpp index 8e3a29b..f9b3227 100644 --- a/ui/style/style_core_color.cpp +++ b/ui/style/style_core_color.cpp @@ -6,7 +6,7 @@ // #include "ui/style/style_core_color.h" -#include "styles/palette.h" +#include "ui/style/style_core_palette.h" namespace style { namespace internal { diff --git a/ui/style/style_core_color.h b/ui/style/style_core_color.h index 8dfca90..c11815c 100644 --- a/ui/style/style_core_color.h +++ b/ui/style/style_core_color.h @@ -14,6 +14,7 @@ namespace style { +class palette_data; class palette; namespace internal { @@ -41,6 +42,7 @@ private: friend class Color; friend class OwnedColor; friend class style::palette; + friend class style::palette_data; }; @@ -80,6 +82,7 @@ public: private: friend class OwnedColor; friend class style::palette; + friend class style::palette_data; Color(ColorData *data) : _data(data) { } diff --git a/ui/style/style_core_icon.cpp b/ui/style/style_core_icon.cpp index 09b7c21..e26d406 100644 --- a/ui/style/style_core_icon.cpp +++ b/ui/style/style_core_icon.cpp @@ -6,9 +6,9 @@ // #include "ui/style/style_core_icon.h" +#include "ui/style/style_core_palette.h" #include "ui/style/style_core.h" #include "base/basic_types.h" -#include "styles/palette.h" #include diff --git a/ui/style/style_core_palette.cpp b/ui/style/style_core_palette.cpp new file mode 100644 index 0000000..7677d7c --- /dev/null +++ b/ui/style/style_core_palette.cpp @@ -0,0 +1,187 @@ +// This file is part of Desktop App Toolkit, +// a set of libraries for developing nice desktop applications. +// +// For license and copyright information please follow this link: +// https://github.com/desktop-app/legal/blob/master/LEGAL +// +#include "ui/style/style_core_palette.h" + +namespace style { + +int palette::indexOfColor(style::color c) const { + auto start = data(0); + if (c._data >= start && c._data < start + kCount) { + return static_cast(c._data - start); + } + return -1; +} + +color palette::colorAtIndex(int index) const { + Assert(_ready); + Assert(index >= 0 && index < kCount); + return _colors[index]; +} + +void palette::finalize() { + if (_ready) return; + _ready = true; + + palette_data::finalize(*this); +} + +palette &palette::operator=(const palette &other) { + auto wasReady = _ready; + for (int i = 0; i != kCount; ++i) { + if (other._status[i] == Status::Loaded) { + if (_status[i] == Status::Initial) { + new (data(i)) internal::ColorData(*other.data(i)); + } else { + *data(i) = *other.data(i); + } + _status[i] = Status::Loaded; + } else if (_status[i] != Status::Initial) { + data(i)->~ColorData(); + _status[i] = Status::Initial; + _ready = false; + } + } + if (wasReady && !_ready) { + finalize(); + } + return *this; +} + +QByteArray palette::save() const { + if (!_ready) { + const_cast(this)->finalize(); + } + + auto result = QByteArray(kCount * 4, Qt::Uninitialized); + for (auto i = 0, index = 0; i != kCount; ++i) { + result[index++] = static_cast(data(i)->c.red()); + result[index++] = static_cast(data(i)->c.green()); + result[index++] = static_cast(data(i)->c.blue()); + result[index++] = static_cast(data(i)->c.alpha()); + } + return result; +} + +bool palette::load(const QByteArray &cache) { + if (cache.size() != kCount * 4) { + return false; + } + + auto p = reinterpret_cast(cache.constData()); + for (auto i = 0; i != kCount; ++i) { + setData(i, { p[i * 4 + 0], p[i * 4 + 1], p[i * 4 + 2], p[i * 4 + 3] }); + } + return true; +} + +palette::SetResult palette::setColor(QLatin1String name, uchar r, uchar g, uchar b, uchar a) { + auto nameIndex = internal::GetPaletteIndex(name); + if (nameIndex < 0) return SetResult::KeyNotFound; + auto duplicate = (_status[nameIndex] != Status::Initial); + + setData(nameIndex, { r, g, b, a }); + return duplicate ? SetResult::Duplicate : SetResult::Ok; +} + +palette::SetResult palette::setColor(QLatin1String name, QLatin1String from) { + const auto nameIndex = internal::GetPaletteIndex(name); + if (nameIndex < 0) { + return SetResult::KeyNotFound; + } + const auto duplicate = (_status[nameIndex] != Status::Initial); + + const auto fromIndex = internal::GetPaletteIndex(from); + if (fromIndex < 0 || _status[fromIndex] != Status::Loaded) { + return SetResult::ValueNotFound; + } + + setData(nameIndex, *data(fromIndex)); + return duplicate ? SetResult::Duplicate : SetResult::Ok; +} + +void palette::reset() { + clear(); + finalize(); +} + +void palette::clear() { + for (auto i = 0; i != kCount; ++i) { + if (_status[i] != Status::Initial) { + data(i)->~ColorData(); + _status[i] = Status::Initial; + _ready = false; + } + } +} + +void palette::compute(int index, int fallbackIndex, TempColorData value) { + if (_status[index] == Status::Initial) { + if (fallbackIndex >= 0 && _status[fallbackIndex] == Status::Loaded) { + _status[index] = Status::Loaded; + new (data(index)) internal::ColorData(*data(fallbackIndex)); + } else { + _status[index] = Status::Created; + new (data(index)) internal::ColorData(value.r, value.g, value.b, value.a); + } + } +} + +void palette::setData(int index, const internal::ColorData &value) { + if (_status[index] == Status::Initial) { + new (data(index)) internal::ColorData(value); + } else { + *data(index) = value; + } + _status[index] = Status::Loaded; +} + + +namespace main_palette { +namespace { + +palette &GetMutable() { + return const_cast(*get()); +} + +} // namespace + +QByteArray save() { + return GetMutable().save(); +} + +bool load(const QByteArray &cache) { + if (GetMutable().load(cache)) { + style::internal::resetIcons(); + return true; + } + return false; +} + +palette::SetResult setColor(QLatin1String name, uchar r, uchar g, uchar b, uchar a) { + return GetMutable().setColor(name, r, g, b, a); +} + +palette::SetResult setColor(QLatin1String name, QLatin1String from) { + return GetMutable().setColor(name, from); +} + +void apply(const palette &other) { + GetMutable() = other; + style::internal::resetIcons(); +} + +void reset() { + GetMutable().reset(); + style::internal::resetIcons(); +} + +int indexOfColor(color c) { + return GetMutable().indexOfColor(c); +} + +} // namespace main_palette +} // namespace style diff --git a/ui/style/style_core_palette.h b/ui/style/style_core_palette.h new file mode 100644 index 0000000..e6d3f31 --- /dev/null +++ b/ui/style/style_core_palette.h @@ -0,0 +1,66 @@ +// This file is part of Desktop App Toolkit, +// a set of libraries for developing nice desktop applications. +// +// For license and copyright information please follow this link: +// https://github.com/desktop-app/legal/blob/master/LEGAL +// +#pragma once + +#include "ui/style/style_core.h" +#include "styles/palette.h" + +namespace style { + +class palette : public palette_data { +public: + palette() = default; + palette(const palette &other) = delete; + palette &operator=(const palette &other); + ~palette() { + clear(); + } + + QByteArray save() const; + bool load(const QByteArray &cache); + + enum class SetResult { + Ok, + KeyNotFound, + ValueNotFound, + Duplicate, + }; + SetResult setColor(QLatin1String name, uchar r, uchar g, uchar b, uchar a); + SetResult setColor(QLatin1String name, QLatin1String from); + void reset(); + + // Created not inited, should be finalized before usage. + void finalize(); + + int indexOfColor(color c) const; + color colorAtIndex(int index) const; + +private: + struct TempColorData { uchar r, g, b, a; }; + friend class palette_data; + + void clear(); + void compute(int index, int fallbackIndex, TempColorData value); + void setData(int index, const internal::ColorData &value); + + bool _ready = false; + +}; + +namespace main_palette { + +not_null get(); +QByteArray save(); +bool load(const QByteArray &cache); +palette::SetResult setColor(QLatin1String name, uchar r, uchar g, uchar b, uchar a); +palette::SetResult setColor(QLatin1String name, QLatin1String from); +void apply(const palette &other); +void reset(); +int indexOfColor(color c); + +} // namespace main_palette +} // namespace style