无语了
This commit is contained in:
@@ -0,0 +1,423 @@
|
||||
#pragma once
|
||||
#include "Gallery_Properties.h"
|
||||
#include "adminive/adminive.hpp"
|
||||
#include "adminive/adapters/nlohmann_json.hpp"
|
||||
#include <array>
|
||||
#include <optional>
|
||||
#include <string_view>
|
||||
#include <tuple>
|
||||
#include <type_traits>
|
||||
#include <utility>
|
||||
#include <vector>
|
||||
namespace renderive::web::gallery_adminive {
|
||||
template <class Enum>
|
||||
struct Enum_Metadata;
|
||||
template <>
|
||||
struct Enum_Metadata<Gallery_Cache_Mode> {
|
||||
static constexpr std::array values{
|
||||
std::pair{Gallery_Cache_Mode::Direct, std::string_view{"Direct"}},
|
||||
std::pair{Gallery_Cache_Mode::Local_Pixel, std::string_view{"Local_Pixel"}}
|
||||
};
|
||||
};
|
||||
template <>
|
||||
struct Enum_Metadata<Gallery_Axis_Orientation> {
|
||||
static constexpr std::array values{
|
||||
std::pair{Gallery_Axis_Orientation::Horizontal, std::string_view{"Horizontal"}},
|
||||
std::pair{Gallery_Axis_Orientation::Vertical, std::string_view{"Vertical"}}
|
||||
};
|
||||
};
|
||||
template <>
|
||||
struct Enum_Metadata<Gallery_Decimal_Separator> {
|
||||
static constexpr std::array values{
|
||||
std::pair{Gallery_Decimal_Separator::Dot, std::string_view{"."}},
|
||||
std::pair{Gallery_Decimal_Separator::Comma, std::string_view{","}}
|
||||
};
|
||||
};
|
||||
template <>
|
||||
struct Enum_Metadata<Gallery_Line_Interpolation> {
|
||||
static constexpr std::array values{
|
||||
std::pair{Gallery_Line_Interpolation::Nearest_Sample, std::string_view{"Nearest_Sample"}},
|
||||
std::pair{Gallery_Line_Interpolation::Linear_Value, std::string_view{"Linear_Value"}},
|
||||
std::pair{Gallery_Line_Interpolation::Linear_Power_Domain, std::string_view{"Linear_Power_Domain"}},
|
||||
std::pair{Gallery_Line_Interpolation::Step_Left, std::string_view{"Step_Left"}},
|
||||
std::pair{Gallery_Line_Interpolation::Step_Right, std::string_view{"Step_Right"}},
|
||||
std::pair{Gallery_Line_Interpolation::Cubic_Value, std::string_view{"Cubic_Value"}}
|
||||
};
|
||||
};
|
||||
template <>
|
||||
struct Enum_Metadata<Gallery_Image_Interpolation> {
|
||||
static constexpr std::array values{
|
||||
std::pair{Gallery_Image_Interpolation::Nearest, std::string_view{"Nearest"}},
|
||||
std::pair{Gallery_Image_Interpolation::Bilinear, std::string_view{"Bilinear"}},
|
||||
std::pair{Gallery_Image_Interpolation::Bicubic, std::string_view{"Bicubic"}}
|
||||
};
|
||||
};
|
||||
template <>
|
||||
struct Enum_Metadata<Gallery_Color_Map> {
|
||||
static constexpr std::array values{
|
||||
std::pair{Gallery_Color_Map::Spectrum, std::string_view{"Spectrum"}},
|
||||
std::pair{Gallery_Color_Map::Ember, std::string_view{"Ember"}},
|
||||
std::pair{Gallery_Color_Map::Grayscale, std::string_view{"Grayscale"}}
|
||||
};
|
||||
};
|
||||
template <>
|
||||
struct Enum_Metadata<Gallery_Constellation_Type> {
|
||||
static constexpr std::array values{
|
||||
std::pair{Gallery_Constellation_Type::PSK4, std::string_view{"PSK4"}},
|
||||
std::pair{Gallery_Constellation_Type::PSK8, std::string_view{"PSK8"}},
|
||||
std::pair{Gallery_Constellation_Type::PSK16, std::string_view{"PSK16"}}
|
||||
};
|
||||
};
|
||||
template <class Enum>
|
||||
struct Enum_Adapter {
|
||||
static std::vector<Enum> values() {
|
||||
std::vector<Enum> result;
|
||||
result.reserve(Enum_Metadata<Enum>::values.size());
|
||||
for(const auto& [value, name] : Enum_Metadata<Enum>::values)
|
||||
result.push_back(value);
|
||||
return result;
|
||||
}
|
||||
static std::string_view name(Enum value) {
|
||||
for(const auto& [candidate, name] : Enum_Metadata<Enum>::values) {
|
||||
if(candidate == value)
|
||||
return name;
|
||||
}
|
||||
return {};
|
||||
}
|
||||
static std::optional<Enum> cast(std::string_view name) {
|
||||
for(const auto& [value, candidate] : Enum_Metadata<Enum>::values) {
|
||||
if(candidate == name)
|
||||
return value;
|
||||
}
|
||||
return std::nullopt;
|
||||
}
|
||||
};
|
||||
template <auto Member>
|
||||
auto boolean_property(std::string name, std::string label, std::string api) {
|
||||
return adminive::field<Member>(std::move(name), std::move(label)).editable().boolean_input().description(std::move(api));
|
||||
}
|
||||
template <auto Member>
|
||||
auto number_property(std::string name, std::string label, std::string api) {
|
||||
return adminive::field<Member>(std::move(name), std::move(label)).editable().number_input().description(std::move(api));
|
||||
}
|
||||
template <auto Member>
|
||||
auto text_property(std::string name, std::string label, std::string api) {
|
||||
return adminive::field<Member>(std::move(name), std::move(label)).editable().text_input().description(std::move(api));
|
||||
}
|
||||
template <auto Member>
|
||||
auto color_property(std::string name, std::string label, std::string api) {
|
||||
return adminive::field<Member>(std::move(name), std::move(label)).editable().color_input().description(std::move(api));
|
||||
}
|
||||
template <auto Member>
|
||||
auto select_property(std::string name, std::string label, std::string api) {
|
||||
return adminive::field<Member>(std::move(name), std::move(label)).editable().select_input().description(std::move(api));
|
||||
}
|
||||
inline auto common_fields() {
|
||||
using T = Gallery_Common_Properties;
|
||||
return std::tuple{
|
||||
color_property<&T::background_color>("background_color", "背景颜色", "Plot_Core::set_background_color"),
|
||||
boolean_property<&T::performance_overlay>("performance_overlay", "性能叠层", "set_performance_overlay_enabled"),
|
||||
boolean_property<&T::renderable_visible>("renderable_visible", "控件可见", "Renderable::set_visible"),
|
||||
select_property<&T::cache_mode>("cache_mode", "缓存模式", "Renderable::set_cache_mode"),
|
||||
text_property<&T::object_name>("object_name", "对象名称", "Renderable::set_object_name")
|
||||
};
|
||||
}
|
||||
inline auto low_latency_fields() {
|
||||
using T = Gallery_Low_Latency_Properties;
|
||||
return std::tuple{
|
||||
boolean_property<&T::frequency_limit_enabled>("frequency_limit_enabled", "启用频率上限", "Plot_Core::set_max_render_fps / clear_max_render_fps"),
|
||||
number_property<&T::max_render_fps>("max_render_fps", "最大渲染 FPS", "Plot_Core::set_max_render_fps"),
|
||||
boolean_property<&T::consumer_feedback_enabled>("consumer_feedback_enabled", "启用消费者反馈", "Plot_Core::set_consumer_feedback / clear_consumer_feedback"),
|
||||
boolean_property<&T::consumer_pixel_feedback_enabled>("consumer_pixel_feedback_enabled", "启用像素响应反馈", "Gallery_Plot_Session::set_client_metrics"),
|
||||
boolean_property<&T::consumer_presentation_feedback_enabled>("consumer_presentation_feedback_enabled", "启用浏览器呈现反馈", "Gallery_Plot_Session::set_client_metrics"),
|
||||
boolean_property<&T::consumer_manual_feedback_enabled>("consumer_manual_feedback_enabled", "启用手动消费者反馈", "Gallery_Plot_Session::apply_consumer_feedback"),
|
||||
number_property<&T::consumer_manual_fps>("consumer_manual_fps", "手动消费者 FPS", "Gallery_Plot_Session::apply_consumer_feedback")
|
||||
};
|
||||
}
|
||||
inline auto axis_fields() {
|
||||
using T = Gallery_Axis_Properties;
|
||||
return std::tuple{
|
||||
select_property<&T::axis_orientation>("axis_orientation", "主轴方向", "Abs_Axis::set_orientation"),
|
||||
number_property<&T::axis_x_offset>("axis_x_offset", "X 偏移", "Abs_Axis::set_x"),
|
||||
number_property<&T::axis_y_offset>("axis_y_offset", "Y 偏移", "Abs_Axis::set_y"),
|
||||
number_property<&T::axis_length_percent>("axis_length_percent", "轴长百分比", "Abs_Axis::set_pixel_length"),
|
||||
number_property<&T::tick_length>("tick_length", "主刻度长度", "Abs_Axis::set_tick_length"),
|
||||
number_property<&T::sub_tick_length>("sub_tick_length", "次刻度长度", "Abs_Axis::set_sub_tick_length"),
|
||||
color_property<&T::axis_color>("axis_color", "轴颜色", "Abs_Axis::set_color"),
|
||||
select_property<&T::decimal_separator>("decimal_separator", "小数点", "Abs_Axis::set_locale"),
|
||||
text_property<&T::unit_text>("unit_text", "单位文本", "Abs_Axis::set_unit_text"),
|
||||
number_property<&T::unit_font_size>("unit_font_size", "单位字号", "Abs_Axis::set_unit_text_font"),
|
||||
number_property<&T::unit_font_weight>("unit_font_weight", "单位字重", "Abs_Axis::set_unit_text_font"),
|
||||
boolean_property<&T::unit_font_italic>("unit_font_italic", "单位斜体", "Abs_Axis::set_unit_text_font"),
|
||||
color_property<&T::unit_pen_color>("unit_pen_color", "单位文字颜色", "Abs_Axis::set_unit_text_pen"),
|
||||
color_property<&T::unit_background_color>("unit_background_color", "单位背景颜色", "Abs_Axis::set_unit_text_background_brush"),
|
||||
number_property<&T::label_rotation>("label_rotation", "标签旋转角度", "Abs_Axis::set_label_rotation_degrees"),
|
||||
number_property<&T::coord_origin>("coord_origin", "坐标起点", "Axis::set_coord_range"),
|
||||
number_property<&T::coord_target>("coord_target", "坐标终点", "Axis::set_coord_range"),
|
||||
number_property<&T::label_precision>("label_precision", "标签精度", "Axis::set_label_precision"),
|
||||
boolean_property<&T::use_wheel>("use_wheel", "启用滚轮缩放", "Axis::set_use_wheel"),
|
||||
boolean_property<&T::use_drag>("use_drag", "启用拖拽平移", "Axis::set_use_drag")
|
||||
};
|
||||
}
|
||||
inline auto time_axis_fields() {
|
||||
using T = Gallery_Time_Axis_Properties;
|
||||
return std::tuple{
|
||||
number_property<&T::time_visible_count>("time_visible_count", "可见时间点", "Time_Axis::set_visible_time_point_count"),
|
||||
number_property<&T::time_label_spacing>("time_label_spacing", "时间标签间距", "Time_Axis::set_tick_label_spacing_px"),
|
||||
text_property<&T::time_format>("time_format", "时间格式", "Time_Axis::set_time_format"),
|
||||
number_property<&T::time_font_size>("time_font_size", "时间字体", "Time_Axis::set_font"),
|
||||
boolean_property<&T::time_newest_at_start>("time_newest_at_start", "最新数据位于轴起点", "Time_Axis::set_newest_at_axis_start")
|
||||
};
|
||||
}
|
||||
inline auto hover_fields() {
|
||||
using T = Gallery_Hover_Properties;
|
||||
return std::tuple{
|
||||
boolean_property<&T::hover_enabled>("hover_enabled", "悬浮信息", "Hover_Tooltip_Mixin::set_use_hover_info"),
|
||||
number_property<&T::hover_font_size>("hover_font_size", "悬浮字体", "Hover_Tooltip_Mixin::set_hover_tooltip_font"),
|
||||
color_property<&T::hover_text_color>("hover_text_color", "悬浮文字", "Hover_Tooltip_Mixin::set_tooltip_text_pen"),
|
||||
color_property<&T::hover_background>("hover_background", "悬浮背景", "Hover_Tooltip_Mixin::set_hover_tooltip_background_brush")
|
||||
};
|
||||
}
|
||||
inline auto spectrum_fields() {
|
||||
using T = Gallery_Spectrum_Properties;
|
||||
return std::tuple{
|
||||
number_property<&T::frequency_point_size>("frequency_point_size", "频率点数", "Spectrum::set_frequency_point_size"),
|
||||
number_property<&T::frequency_origin>("frequency_origin", "数据频率起点", "Spectrum::set_frequency_range"),
|
||||
number_property<&T::frequency_target>("frequency_target", "数据频率终点", "Spectrum::set_frequency_range"),
|
||||
number_property<&T::center_frequency>("center_frequency", "中心频率", "Spectrum::set_center_frequency"),
|
||||
number_property<&T::sweep_origin>("sweep_origin", "扫频区起点", "Spectrum::set_sweep_frequency_range"),
|
||||
number_property<&T::sweep_target>("sweep_target", "扫频区终点", "Spectrum::set_sweep_frequency_range"),
|
||||
boolean_property<&T::max_hold_visible>("max_hold_visible", "最大保持线", "Spectrum::set_max_hold_visible"),
|
||||
boolean_property<&T::min_hold_visible>("min_hold_visible", "最小保持线", "Spectrum::set_min_hold_visible"),
|
||||
boolean_property<&T::max_marker_visible>("max_marker_visible", "峰值 Marker", "Spectrum::set_max_marker_visible"),
|
||||
boolean_property<&T::use_min_marker>("use_min_marker", "最小值 Marker", "Spectrum::set_use_min_marker"),
|
||||
boolean_property<&T::sweep_region_visible>("sweep_region_visible", "扫频区域", "Spectrum::set_sweep_region_visible"),
|
||||
boolean_property<&T::visible_range_only>("visible_range_only", "仅绘制可见范围", "Spectrum::set_visible_range_only"),
|
||||
select_property<&T::line_interpolation>("line_interpolation", "线插值模式", "Spectrum::set_interpolation_mode"),
|
||||
color_property<&T::max_brush>("max_brush", "最大保持填充", "Spectrum::set_max_brush"),
|
||||
color_property<&T::current_brush>("current_brush", "当前曲线填充", "Spectrum::set_current_brush"),
|
||||
color_property<&T::min_brush>("min_brush", "最小保持填充", "Spectrum::set_min_brush"),
|
||||
color_property<&T::max_pen>("max_pen", "最大保持线颜色", "Spectrum::set_max_pen"),
|
||||
color_property<&T::current_pen>("current_pen", "当前曲线颜色", "Spectrum::set_current_pen"),
|
||||
color_property<&T::min_pen>("min_pen", "最小保持线颜色", "Spectrum::set_min_pen"),
|
||||
color_property<&T::selected_marker_pen>("selected_marker_pen", "选中 Marker", "Spectrum::set_selected_marker_pen"),
|
||||
color_property<&T::marker_pen>("marker_pen", "Marker 颜色", "Spectrum::set_marker_pen"),
|
||||
color_property<&T::middle_frequency_pen>("middle_frequency_pen", "中心频率线", "Spectrum::set_middle_frequency_pen"),
|
||||
color_property<&T::sweep_region_brush>("sweep_region_brush", "扫频区填充", "Spectrum::set_sweep_region_brush")
|
||||
};
|
||||
}
|
||||
template <class T>
|
||||
struct Property_Fields;
|
||||
template <>
|
||||
struct Property_Fields<Gallery_Axis_Lab_Properties> {
|
||||
static auto get() {
|
||||
return std::tuple_cat(common_fields(), axis_fields(), time_axis_fields());
|
||||
}
|
||||
};
|
||||
template <>
|
||||
struct Property_Fields<Gallery_Spectrum_Properties> {
|
||||
static auto get() {
|
||||
return std::tuple_cat(common_fields(), axis_fields(), spectrum_fields(), hover_fields());
|
||||
}
|
||||
};
|
||||
template <>
|
||||
struct Property_Fields<Gallery_Selection_Overlay_Properties> {
|
||||
static auto get() {
|
||||
using T = Gallery_Selection_Overlay_Properties;
|
||||
return std::tuple_cat(Property_Fields<Gallery_Spectrum_Properties>::get(), std::tuple{
|
||||
number_property<&T::selection_font_size>("selection_font_size", "框选标签字体", "Selection_Rectangle_Overlay::set_label_font"),
|
||||
color_property<&T::selection_label_pen>("selection_label_pen", "框选标签颜色", "Selection_Rectangle_Overlay::set_label_pen"),
|
||||
color_property<&T::selection_brush>("selection_brush", "框选填充", "Selection_Rectangle_Overlay::set_selection_brush"),
|
||||
color_property<&T::selection_border>("selection_border", "框选边框", "Selection_Rectangle_Overlay::set_selection_border_pen")
|
||||
});
|
||||
}
|
||||
};
|
||||
template <>
|
||||
struct Property_Fields<Gallery_Waterfall_Properties> {
|
||||
static auto get() {
|
||||
using T = Gallery_Waterfall_Properties;
|
||||
return std::tuple_cat(common_fields(), axis_fields(), time_axis_fields(), std::tuple{
|
||||
number_property<&T::frequency_origin>("frequency_origin", "频率起点", "Waterfall::set_frequency_range"),
|
||||
number_property<&T::frequency_target>("frequency_target", "频率终点", "Waterfall::set_frequency_range"),
|
||||
number_property<&T::power_origin>("power_origin", "功率起点", "Waterfall::set_power_range"),
|
||||
number_property<&T::power_target>("power_target", "功率终点", "Waterfall::set_power_range"),
|
||||
number_property<&T::frequency_bin_count>("frequency_bin_count", "频率 Bin", "Waterfall::set_frequency_bin_count"),
|
||||
boolean_property<&T::visible_range_only>("visible_range_only", "仅绘制可见范围", "Waterfall::set_visible_range_only"),
|
||||
select_property<&T::image_interpolation>("image_interpolation", "图像插值(三模式)", "Waterfall::set_interpolation_mode"),
|
||||
select_property<&T::color_map>("color_map", "颜色映射(重建 Builder)", "Waterfall::Builder::set_color_map / Color_Map::set_colors")
|
||||
}, hover_fields());
|
||||
}
|
||||
};
|
||||
template <>
|
||||
struct Property_Fields<Gallery_Afterglow_Properties> {
|
||||
static auto get() {
|
||||
using T = Gallery_Afterglow_Properties;
|
||||
return std::tuple_cat(common_fields(), axis_fields(), std::tuple{
|
||||
number_property<&T::frequency_origin>("frequency_origin", "频率起点", "Afterglow::set_frequency_range"),
|
||||
number_property<&T::frequency_target>("frequency_target", "频率终点", "Afterglow::set_frequency_range"),
|
||||
number_property<&T::power_origin>("power_origin", "功率起点", "Afterglow::set_power_range"),
|
||||
number_property<&T::power_target>("power_target", "功率终点", "Afterglow::set_power_range"),
|
||||
number_property<&T::frequency_point_size>("frequency_point_size", "频率格点", "Afterglow::set_frequency_point_size"),
|
||||
number_property<&T::power_point_size>("power_point_size", "功率格点", "Afterglow::set_power_point_size"),
|
||||
boolean_property<&T::interpolate_power>("interpolate_power", "功率 Bin 插值", "Afterglow::set_interpolate"),
|
||||
number_property<&T::attenuation_rate>("attenuation_rate", "衰减率", "Afterglow::set_attenuation_rate"),
|
||||
select_property<&T::color_map>("color_map", "颜色映射(重建 Builder)", "Afterglow::Builder::set_color_map / Color_Map::set_colors")
|
||||
});
|
||||
}
|
||||
};
|
||||
template <>
|
||||
struct Property_Fields<Gallery_Sweep_Spectrum_Properties> {
|
||||
static auto get() {
|
||||
using T = Gallery_Sweep_Spectrum_Properties;
|
||||
return std::tuple_cat(common_fields(), axis_fields(), std::tuple{
|
||||
number_property<&T::frequency_origin>("frequency_origin", "扫频起点", "Sweep_Spectrum::set_frequency_range"),
|
||||
number_property<&T::frequency_target>("frequency_target", "扫频终点", "Sweep_Spectrum::set_frequency_range"),
|
||||
number_property<&T::bins_per_block>("bins_per_block", "每块 Bin", "Sweep_Spectrum::set_bins_per_block"),
|
||||
number_property<&T::block_count>("block_count", "块数量", "Sweep_Spectrum::set_block_count"),
|
||||
color_property<&T::sweep_pen>("sweep_pen", "扫频曲线", "Sweep_Spectrum::set_pen"),
|
||||
color_property<&T::current_frequency_pen>("current_frequency_pen", "当前频率游标", "Sweep_Spectrum::set_cur_frequency_pen"),
|
||||
boolean_property<&T::visible_range_only>("visible_range_only", "仅绘制可见范围", "Sweep_Spectrum::set_visible_range_only"),
|
||||
select_property<&T::line_interpolation>("line_interpolation", "线插值模式", "Sweep_Spectrum::set_interpolation_mode")
|
||||
});
|
||||
}
|
||||
};
|
||||
template <>
|
||||
struct Property_Fields<Gallery_Frequency_Trace_Properties> {
|
||||
static auto get() {
|
||||
using T = Gallery_Frequency_Trace_Properties;
|
||||
return std::tuple_cat(common_fields(), axis_fields(), time_axis_fields(), std::tuple{
|
||||
color_property<&T::trace_pen>("trace_pen", "轨迹颜色(重建 Builder)", "Frequency_Trace::Builder::set_pen"),
|
||||
number_property<&T::trace_pen_width>("trace_pen_width", "轨迹宽度(重建 Builder)", "Frequency_Trace::Builder::set_pen"),
|
||||
number_property<&T::trace_value_min>("trace_value_min", "数值下限", "Axis::set_coord_range"),
|
||||
number_property<&T::trace_value_max>("trace_value_max", "数值上限", "Axis::set_coord_range")
|
||||
});
|
||||
}
|
||||
};
|
||||
template <>
|
||||
struct Property_Fields<Gallery_Constellation_Properties> {
|
||||
static auto get() {
|
||||
using T = Gallery_Constellation_Properties;
|
||||
return std::tuple_cat(common_fields(), axis_fields(), std::tuple{
|
||||
number_property<&T::i_origin>("i_origin", "I 起点", "Constellation_Diagram::set_i_range"),
|
||||
number_property<&T::i_target>("i_target", "I 终点", "Constellation_Diagram::set_i_range"),
|
||||
number_property<&T::q_origin>("q_origin", "Q 起点", "Constellation_Diagram::set_q_range"),
|
||||
number_property<&T::q_target>("q_target", "Q 终点", "Constellation_Diagram::set_q_range"),
|
||||
color_property<&T::point_color>("point_color", "采样点颜色", "Constellation_Diagram::set_point_color"),
|
||||
color_property<&T::anchor_color>("anchor_color", "锚点颜色", "Constellation_Diagram::set_anchor_color"),
|
||||
number_property<&T::point_lifetime_ms>("point_lifetime_ms", "采样点寿命", "Constellation_Diagram::set_point_lifetime_ms"),
|
||||
select_property<&T::constellation_type>("constellation_type", "星座模式(重建 Builder)", "Constellation_Diagram::Builder::set_type"),
|
||||
number_property<&T::phase_offset>("phase_offset", "相位偏移(重建 Builder)", "Constellation_Diagram::Builder::set_phase_offset_radians")
|
||||
});
|
||||
}
|
||||
};
|
||||
template <class Properties>
|
||||
struct Property_Fields<Gallery_Low_Latency_Case_Properties<Properties>> {
|
||||
static auto get() {
|
||||
return std::tuple_cat(Property_Fields<Properties>::get(), low_latency_fields());
|
||||
}
|
||||
};
|
||||
struct Property_Validator {
|
||||
template <class T>
|
||||
void operator()(const T& value, adminive::Validation_Context& context) const {
|
||||
if constexpr(requires { value.coord_origin; value.coord_target; })
|
||||
validate_pair(context, "coord_origin", "coord_target", value.coord_origin, value.coord_target);
|
||||
if constexpr(requires { value.frequency_origin; value.frequency_target; })
|
||||
validate_pair(context, "frequency_origin", "frequency_target", value.frequency_origin, value.frequency_target);
|
||||
if constexpr(requires { value.power_origin; value.power_target; })
|
||||
validate_pair(context, "power_origin", "power_target", value.power_origin, value.power_target);
|
||||
if constexpr(requires { value.sweep_origin; value.sweep_target; })
|
||||
validate_pair(context, "sweep_origin", "sweep_target", value.sweep_origin, value.sweep_target);
|
||||
if constexpr(requires { value.trace_value_min; value.trace_value_max; })
|
||||
validate_pair(context, "trace_value_min", "trace_value_max", value.trace_value_min, value.trace_value_max);
|
||||
if constexpr(requires { value.i_origin; value.i_target; })
|
||||
validate_pair(context, "i_origin", "i_target", value.i_origin, value.i_target);
|
||||
if constexpr(requires { value.q_origin; value.q_target; })
|
||||
validate_pair(context, "q_origin", "q_target", value.q_origin, value.q_target);
|
||||
}
|
||||
private:
|
||||
template <class Origin, class Target>
|
||||
static void validate_pair(adminive::Validation_Context& context, std::string_view origin, std::string_view target, const Origin& origin_value, const Target& target_value) {
|
||||
if(static_cast<double>(origin_value) == static_cast<double>(target_value)) {
|
||||
context.error(std::string(origin), std::string(origin) + " 与 " + std::string(target) + " 不能相等");
|
||||
context.error(std::string(target), std::string(origin) + " 与 " + std::string(target) + " 不能相等");
|
||||
}
|
||||
}
|
||||
};
|
||||
template <class T>
|
||||
auto property_descriptor() {
|
||||
auto fields = Property_Fields<T>::get();
|
||||
return std::apply([](auto... field) {
|
||||
return adminive::object<T>("renderive_gallery_properties", "Renderive 控件属性", std::move(field)...).validator(Property_Validator{});
|
||||
}, std::move(fields));
|
||||
}
|
||||
}
|
||||
namespace adminive {
|
||||
template <class T, T Minimum, T Maximum, T Step, class Json>
|
||||
struct Value_Adapter<renderive::web::Gallery_Number<T, Minimum, Maximum, Step>, Json> {
|
||||
using Storage = renderive::web::Gallery_Number<T, Minimum, Maximum, Step>;
|
||||
using value_type = T;
|
||||
static constexpr T minimum = Minimum;
|
||||
static constexpr T maximum = Maximum;
|
||||
static constexpr T multiple_of = Step;
|
||||
static T read(const Storage& value) noexcept {
|
||||
return value.value();
|
||||
}
|
||||
static void write(Storage& target, T value) {
|
||||
target = value;
|
||||
}
|
||||
};
|
||||
template <class Json>
|
||||
struct Value_Adapter<renderive::web::Gallery_Text, Json> {
|
||||
using value_type = std::string;
|
||||
static const std::string& read(const renderive::web::Gallery_Text& value) noexcept {
|
||||
return value.value();
|
||||
}
|
||||
static void write(renderive::web::Gallery_Text& target, std::string value) {
|
||||
target = std::move(value);
|
||||
}
|
||||
};
|
||||
template <class Json>
|
||||
struct Value_Adapter<renderive::web::Gallery_Color, Json> {
|
||||
using value_type = std::string;
|
||||
static const std::string& read(const renderive::web::Gallery_Color& value) noexcept {
|
||||
return value.value();
|
||||
}
|
||||
static void write(renderive::web::Gallery_Color& target, std::string value) {
|
||||
target = std::move(value);
|
||||
}
|
||||
};
|
||||
#define RENDERIVE_GALLERY_ENUM_ADAPTER(Type) \
|
||||
template <> \
|
||||
struct Enum_Adapter<renderive::web::Type> : renderive::web::gallery_adminive::Enum_Adapter<renderive::web::Type> {}
|
||||
RENDERIVE_GALLERY_ENUM_ADAPTER(Gallery_Cache_Mode);
|
||||
RENDERIVE_GALLERY_ENUM_ADAPTER(Gallery_Axis_Orientation);
|
||||
RENDERIVE_GALLERY_ENUM_ADAPTER(Gallery_Decimal_Separator);
|
||||
RENDERIVE_GALLERY_ENUM_ADAPTER(Gallery_Line_Interpolation);
|
||||
RENDERIVE_GALLERY_ENUM_ADAPTER(Gallery_Image_Interpolation);
|
||||
RENDERIVE_GALLERY_ENUM_ADAPTER(Gallery_Color_Map);
|
||||
RENDERIVE_GALLERY_ENUM_ADAPTER(Gallery_Constellation_Type);
|
||||
#undef RENDERIVE_GALLERY_ENUM_ADAPTER
|
||||
#define RENDERIVE_GALLERY_PROPERTY_DESCRIPTOR(Type) \
|
||||
template <> \
|
||||
struct Type_Descriptor<renderive::web::Type> { \
|
||||
static auto get() { \
|
||||
return renderive::web::gallery_adminive::property_descriptor<renderive::web::Type>(); \
|
||||
} \
|
||||
}
|
||||
RENDERIVE_GALLERY_PROPERTY_DESCRIPTOR(Gallery_Axis_Lab_Properties);
|
||||
RENDERIVE_GALLERY_PROPERTY_DESCRIPTOR(Gallery_Spectrum_Properties);
|
||||
RENDERIVE_GALLERY_PROPERTY_DESCRIPTOR(Gallery_Selection_Overlay_Properties);
|
||||
RENDERIVE_GALLERY_PROPERTY_DESCRIPTOR(Gallery_Waterfall_Properties);
|
||||
RENDERIVE_GALLERY_PROPERTY_DESCRIPTOR(Gallery_Afterglow_Properties);
|
||||
RENDERIVE_GALLERY_PROPERTY_DESCRIPTOR(Gallery_Sweep_Spectrum_Properties);
|
||||
RENDERIVE_GALLERY_PROPERTY_DESCRIPTOR(Gallery_Frequency_Trace_Properties);
|
||||
RENDERIVE_GALLERY_PROPERTY_DESCRIPTOR(Gallery_Constellation_Properties);
|
||||
#undef RENDERIVE_GALLERY_PROPERTY_DESCRIPTOR
|
||||
template <class Properties>
|
||||
struct Type_Descriptor<renderive::web::Gallery_Low_Latency_Case_Properties<Properties>> {
|
||||
static auto get() {
|
||||
using T = renderive::web::Gallery_Low_Latency_Case_Properties<Properties>;
|
||||
return renderive::web::gallery_adminive::property_descriptor<T>();
|
||||
}
|
||||
};
|
||||
}
|
||||
Reference in New Issue
Block a user