TODO 风格系统

This commit is contained in:
Nanako 2025-04-07 09:44:56 +08:00
parent 3d58348c12
commit 1c3aee5ca1
10 changed files with 203 additions and 3 deletions

View File

@ -0,0 +1,36 @@
#pragma once
#include <unordered_map>
#include <string>
/**
* name_t
* @brief 使
* @note name_t , name_map hash
*/
template<typename StringType>
struct name_t {
public:
explicit name_t(const StringType& in_str) {
hash_value_ = hash(in_str);
name_map[hash_value_] = in_str;
}
[[nodiscard]] auto to_string() const {
return name_map[hash_value_];
}
private:
static uint64_t hash(const StringType& str) {
uint64_t hash = 5381;
for (const auto c : str) {
hash = (hash << 5) + hash + c; // hash * 33 + c
}
return hash;
}
private:
uint64_t hash_value_;
inline static std::unordered_map<uint64_t, StringType> name_map;
};
using u8name_t = name_t<std::string>;
using u16name_t = name_t<std::u16string>;
using u32name_t = name_t<std::u32string>;

View File

@ -1,2 +1,110 @@
#include "color.h"
#include <charconv>
#include <vector>
linear_color linear_color::from_string(const std::string& in_str) {
// **定义一个表示无效输入的默认返回值 (C++20 designated initializers)**
// Made static constexpr for potential compile-time use if needed elsewhere
static linear_color invalid_color = { 0.0f, 0.0f, 0.0f, 0.0f };
std::string str = in_str;
// **1. 去除前后空格 (No major C++23 change here, std::find_if is efficient)**
auto trim_func = [](unsigned char ch){ return !std::isspace(ch); };
str.erase(str.begin(), std::ranges::find_if(str, trim_func));
str.erase(std::find_if(str.rbegin(), str.rend(), trim_func).base(), str.end());
// **2. 检查格式前缀和后缀 (C++20 starts_with/ends_with)**
bool is_rgba = false;
std::string_view value_part_sv;
if (str.starts_with("rgb(") && str.ends_with(')')) {
is_rgba = false;
value_part_sv = std::string_view(str).substr(4, str.length() - 5); // Skip "rgb(" and ")"
} else if (str.starts_with("rgba(") && str.ends_with(')')) {
is_rgba = true;
value_part_sv = std::string_view(str).substr(5, str.length() - 6); // Skip "rgba(" and ")"
} else {
return invalid_color; // **无效格式前缀/后缀**
}
if (value_part_sv.empty() && (is_rgba ? 4 : 3) > 0) {
// Handle cases like "rgb()" or "rgba()" which are invalid if components are expected
return invalid_color; // **括号内为空**
}
// **3. 分割数值字符串 (Using stringstream, C++23 views could be an alternative but more complex here)**
std::vector<float> values;
std::stringstream ss;
ss << value_part_sv;
std::string segment;
while (std::getline(ss, segment, ',')) {
// **4. 处理每个分量**
// 去除分量前后的空格
segment.erase(segment.begin(), std::ranges::find_if(segment, trim_func));
segment.erase(std::find_if(segment.rbegin(), segment.rend(), trim_func).base(), segment.end());
if (segment.empty()) {
return invalid_color; // **空分量值**
}
const char* const first = segment.data();
const char* const last = first + segment.size();
float component_value = 0.0f;
// **C++23 std::string::contains to check for decimal point**
if (segment.contains('.')) {
// **处理浮点数 [0, 1]**
float val = 0.0f;
auto [ptr, ec] = std::from_chars(first, last, val);
// Check for errors: conversion failed OR not the entire segment was parsed
if (ec != std::errc() || ptr != last) {
return invalid_color; // **无效浮点数格式**
}
// Check range [0, 1] for floats
if (val < 0.0f || val > 1.0f) {
return invalid_color; // **浮点数值超出 [0, 1] 范围**
}
component_value = val;
} else {
// **处理整数 [0, 255]**
int int_val = 0;
auto [ptr, ec] = std::from_chars(first, last, int_val);
// Check for errors: conversion failed OR not the entire segment was parsed
if (ec != std::errc() || ptr != last) {
return invalid_color; // **无效整数格式**
}
// Check range [0, 255] for integers
if (int_val < 0 || int_val > 255) {
return invalid_color; // **整数值超出 [0, 255] 范围**
}
// **归一化: 将 uint8 范围的值映射到 [0, 1] float**
component_value = static_cast<float>(int_val) / 255.0f;
}
values.push_back(component_value);
}
// **5. 检查分量数量是否匹配**
if (is_rgba) {
if (values.size() != 4) {
return invalid_color; // **rgba 分量数量错误**
}
return { values[0], values[1], values[2], values[3] };
}
// rgb
if (values.size() != 3) {
return invalid_color; // **rgb 分量数量错误**
}
// **对于 rgbalpha 默认为 1.0f**
return { values[0], values[1], values[2], 1.f };
}

View File

@ -135,6 +135,21 @@ public:
return r == in_color.r && g == in_color.g && b == in_color.b && a == in_color.a;
}
/**
* @brief (C++23 Style adaptation)
* : "rgb(r, g, b)" "rgba(r, g, b, a)"
* - ****: '.', [0, 1]
* - ****: :
* - [0, 1] 使 0.0f 1.0f ()
* - ** (1, 255] uint8_t [0, 1] (value / 255.0f)**
* - < 0 > 255
* @param in_str
* @return linear_color
* @note **/ linear_color{0.0f, 0.0f, 0.0f, 0.0f}**
* 使 [[nodiscard]]
*/
[[nodiscard]] static linear_color from_string(const std::string& in_str);
//-------------- 成员变量 --------------
/** 红色分量,范围 [0,1] */

View File

@ -3,6 +3,8 @@ project(mirage_widget)
set(SRC_FILES)
retrieve_files(${CMAKE_CURRENT_SOURCE_DIR}/src SRC_FILES)
add_subdirectory(third_party/tomlplusplus)
add_library(${PROJECT_NAME} STATIC ${SRC_FILES})
target_include_directories(${PROJECT_NAME} PUBLIC ${CMAKE_CURRENT_SOURCE_DIR}/src)
target_link_libraries(${PROJECT_NAME} PUBLIC mirage_core mirage_render)
target_link_libraries(${PROJECT_NAME} PUBLIC mirage_core mirage_render tomlplusplus::tomlplusplus)

View File

@ -0,0 +1,10 @@
[info]
name = "default_style"
version = "0.0.1"
description = "mirage的默认样式"
author = "奶酪"
[button]
hover_color = "rgb(31, 31, 31)"
pressed_color = "rgb(31, 31, 31)"
normal_color = "rgb(31, 31, 31)"

View File

@ -0,0 +1,10 @@
#include "mirage_style.h"
bool mirage_style::load_config(const std::filesystem::path& in_filename) {
try {
tbl = toml::parse_file(in_filename.string());
}
catch (const toml::parse_error& err) {
fprintf(stderr, "%s\n", err.what());
}
}

View File

@ -0,0 +1,19 @@
#pragma once
#include "misc/name.h"
#include <toml++/toml.hpp>
#include <filesystem>
class mirage_style {
public:
static auto& get() {
static mirage_style instance;
return instance;
}
bool load_config(const std::filesystem::path& in_filename);
private:
mirage_style() = default;
toml::table tbl{};
};

View File

@ -1 +0,0 @@
#include "mborder.h"

View File

@ -71,6 +71,6 @@ public:
// 或使用现有的 margin.get_total_spacing() 方法
return child_size + margin.get_total_spacing();
}
return Eigen::Vector2f(10, 10);
return { 10, 10 };
}
};

View File

@ -122,4 +122,5 @@ protected:
std::weak_ptr<mwidget> parent_;
std::vector<std::shared_ptr<mwidget>> children_;
geometry_t geometry_{};
std::string tag{}; // 风格标签
};