Skip to main content

rust_constructor/
lib.rs

1//! # Rust Constructor V2
2//!
3//! A cross-platform `GUI` framework built on `egui`, the simplest way to develop `GUI` projects with `Rust`
4//!
5//! 基于`egui`构建的跨平台`GUI`框架, 用`Rust`开发`GUI`项目最简单的方式
6//!
7//! ## Overview 概述
8//!
9//! `Rust Constructor` is a fully functional GUI framework that leverages the power of `egui` to provide
10//! a simple and intuitive instrument for building cross-platform applications.
11//!
12//! `Rust Constructor`是一个功能全面的GUI框架,它利用了`egui`的强大功能,为构建跨平台应用程序提供了一个简单直观的工具。
13//!
14//! ## Quick Start 快速入门
15//!
16//! Due to dependency issues, we cannot provide the test cases directly within the code. However, you can
17//! find the directly usable code in the `README`.
18//!
19//! 由于依赖问题,我们无法直接在代码中提供测试用例,你可以在`README`中找到能直接使用的代码。
20//!
21//! ## Documentation 文档
22//!
23//! - [Rust Constructor Guide](https://github.com/ChepleBob30/Rust-Constructor-Guide)
24//! - [GitHub Repository](https://github.com/ChepleBob30/Rust-Constructor)
25//! - [Binder 必达](https://github.com/Binder-organize) - Other projects from our organization 我们组织的其他项目
26pub mod advance_front;
27pub mod app;
28pub mod background;
29pub mod basic_front;
30#[cfg(all(feature = "standard", feature = "bevy"))]
31compile_error!(
32    "You cannot use both 'bevy' and 'standard' features simultaneously!
33    If you are developing using Rust Constructor independently, please select 'standard'; if you are developing using bevy, please select 'bevy'."
34);
35#[cfg(not(any(feature = "standard", feature = "bevy")))]
36compile_error!(
37    "You must enable at least one of the 'bevy' or 'standard' features!
38    If you are developing using Rust Constructor independently, please select 'standard'; if you are developing using bevy, please select 'bevy'."
39);
40#[cfg(feature = "bevy")]
41use egui_bevy::{Context, Ui};
42#[cfg(feature = "standard")]
43use egui_standard::Ui;
44use std::{
45    any::{Any, type_name, type_name_of_val},
46    error::Error,
47    fmt::{Debug, Display, Formatter},
48    time::Instant,
49    vec::Vec,
50};
51
52/// Core trait for managing Rust Constructor resources uniformly.
53///
54/// 统一管理Rust Constructor资源的核心特性。
55///
56/// This trait provides a common interface for all GUI resources in the framework,
57/// allowing for the acquisition and modification of specific resources and their details.
58///
59/// 此特征为框架中的所有GUI资源提供了一个公共接口,允许获取具体资源及其细节并对其进行修改。
60///
61/// # Thread Safety
62///
63/// This trait is automatically impl'd for types that implement `Send` and `Sync`,
64/// allowing `App` to be used in multi-threaded contexts (e.g., Bevy).
65///
66/// # 线程安全
67///
68/// 此特征自动为实现了 `Send` 和 `Sync` 的类型 impl,使 `App` 可以在多线程上下文中使用(例如 Bevy)。
69pub trait RustConstructorResource: Debug + Send + Sync {
70    /// Returns a reference to the resource as `Any` for extract the specific type.
71    ///
72    /// 以`Any`返回对资源的引用,用于取出具体类型。
73    ///
74    /// This allows downcasting to the concrete type when the actual type is known.
75    ///
76    /// 当实际类型已知时,允许向下转换到具体类型。
77    fn as_any(&self) -> &dyn Any;
78
79    /// Returns a mutable reference to the resource as `Any` for extract the specific type.
80    ///
81    /// 以`Any`返回对资源的可变引用,用于取出具体类型。
82    ///
83    /// This allows mutable downcasting when the actual type is known.
84    ///
85    /// 当实际类型已知时,允许向下可变转换到具体类型。
86    fn as_any_mut(&mut self) -> &mut dyn Any;
87
88    /// Retrieves the display info field for this resource.
89    ///
90    /// 取出此资源的显示信息字段。
91    ///
92    /// Returns `Some(DisplayInfo)` if the resource has display info field,
93    /// or `None` if it doesn't have display info field.
94    ///
95    /// 如果资源具有显示信息字段则返回`Some(DisplayInfo)`,如果资源没有显示信息字段则返回`None`。
96    fn display_display_info(&self) -> Option<DisplayInfo>;
97
98    /// Updates the display info field for this resource.
99    ///
100    /// 更新此资源的显示信息字段。
101    fn modify_display_info(&mut self, display_info: DisplayInfo);
102
103    /// Returns all tags associated with this resource.
104    ///
105    /// 返回与此资源关联的所有标签。
106    ///
107    /// Tags are stored as key-value pairs (`[String; 2]`) and can be used
108    /// for categorization, filtering, or metadata storage.
109    ///
110    /// 标签以键值对(`[String; 2]`)的形式存储,可用于分类、过滤或元数据存储。
111    fn display_tags(&self) -> Vec<[String; 2]>;
112
113    /// Updates the tags for this resource.
114    ///
115    /// 更新此资源的标签。
116    ///
117    /// # Arguments
118    ///
119    /// * `replace` - If `true`, replaces all existing tags;
120    ///   if `false`, merges with existing tags.
121    ///
122    /// # 参数
123    ///
124    /// * `replace` - 若为`true`,则替换所有现有的标签;
125    ///   若为`false`,则与现有标签合并。
126    fn modify_tags(&mut self, tags: &[[String; 2]], replace: bool);
127}
128
129/// Trait for managing basic front resources that are displayed to the user.
130///
131/// 用于管理显示给用户的基本前端资源的特征。
132///
133/// This trait extends `RustConstructorResource` with additional methods specific
134/// to visual elements.
135///
136/// 此特征扩展了`RustConstructorResource`,添加了特定视觉元素的方法。
137pub trait BasicFrontResource: RustConstructorResource {
138    /// Returns the complete basic resource config.
139    ///
140    /// 返回完整的基本前端资源配置。
141    ///
142    /// This includes both position/size config and clipping information.
143    ///
144    /// 包括位置/大小配置和裁剪信息。
145    fn display_basic_front_resource_config(&self) -> BasicFrontResourceConfig;
146
147    /// Returns the position and size config for this resource.
148    ///
149    /// 返回此资源的位置和大小配置。
150    ///
151    /// Includes grid-based positioning, alignment settings, and offset values.
152    ///
153    /// 包括基于网格的定位、对齐设置和偏移值。
154    fn display_position_size_config(&self) -> PositionSizeConfig;
155
156    /// Returns the clipping rectangle config if this resource has one.
157    ///
158    /// 返回裁剪矩形配置(如果此资源有的话)。
159    ///
160    /// Clipping rectangles define the visible area of the resource.
161    ///
162    /// 裁剪矩形定义资源的可见区域。
163    ///
164    /// Returns `None` if no clipping is applied.
165    ///
166    /// 如果没有应用裁剪矩形,则返回`None`。
167    fn display_clip_rect(&self) -> Option<PositionSizeConfig>;
168
169    /// Returns the current display position of the resource.
170    ///
171    /// 返回资源的当前显示位置。
172    ///
173    /// The position is returned as `[x, y]` coordinates.
174    ///
175    /// 位置以`[x, y]`坐标返回。
176    fn display_position(&self) -> [f32; 2];
177
178    /// Returns the current display size of the resource.
179    ///
180    /// 返回资源的当前显示大小。
181    ///
182    /// The size is returned as `[width, height]`.
183    ///
184    /// 大小以`[width, height]`返回。
185    fn display_size(&self) -> [f32; 2];
186
187    /// Updates the complete basic resource config.
188    ///
189    /// 更新完整的前端资源配置。
190    fn modify_basic_front_resource_config(
191        &mut self,
192        basic_front_resource_config: BasicFrontResourceConfig,
193    );
194
195    /// Updates the position and size config.
196    ///
197    /// 更新位置和大小配置。
198    fn modify_position_size_config(&mut self, position_size_config: PositionSizeConfig);
199
200    /// Updates the clipping rectangle config.
201    ///
202    /// 更新裁剪矩形配置。
203    fn modify_clip_rect(&mut self, clip_rect: Option<PositionSizeConfig>);
204}
205
206/// Unique identifier for Rust Constructor resources.
207///
208/// Rust Constructor资源的唯一标识符。
209///
210/// This struct combines a resource name and type to create a unique identifier
211/// that can be used to reference resources throughout the application.
212///
213/// 这个结构体结合了资源名称和类型来创建一个唯一的标识符,可以在整个应用程序中用来引用资源。
214#[derive(Debug, Default, Clone, PartialEq, Eq, Hash, PartialOrd, Ord)]
215pub struct RustConstructorId {
216    /// Unique name identifying the resource instance, Resources of different
217    /// types can have the same name.
218    ///
219    /// 标识资源实例的唯一名称,不同类型的资源可以重名。
220    pub name: String,
221
222    /// Type of the resource (e.g., `Image`).
223    ///
224    /// 资源的类型(例如`Image`)。
225    pub discern_type: String,
226}
227
228/// Container for Rust Constructor resources with type-erased storage.
229///
230/// 具有类型擦除存储的Rust Constructor资源的容器。
231///
232/// This struct pairs a resource identifier with the actual resource content,
233/// allowing for heterogeneous storage of different resource types while
234/// maintaining the ability to identify and manage them individually.
235///
236/// 这个结构体将资源标识符与实际资源内容配对,允许不同资源类型的异构存储,同时保持单独识别和管理它们的能力。
237///
238/// # Type Erasure 类型擦除
239///
240/// The `content` field uses a `Box<dyn RustConstructorResource>` to store
241/// any type that implements the `RustConstructorResource` trait, enabling
242/// polymorphic behavior and storage.
243///
244/// `content`字段使用`Box<dyn RustConstructorResource>`来存储任何实现`RustConstructorResource`
245/// 特征的类型,从而启用多态行为和存储。
246#[derive(Debug)]
247pub struct RustConstructorResourceBox {
248    /// Unique identifier for the contained resource.
249    ///
250    /// 所包含资源的唯一标识符。
251    pub id: RustConstructorId,
252
253    /// Type-erased resource content.
254    ///
255    /// 类型擦除的资源内容。
256    pub content: Box<dyn RustConstructorResource>,
257}
258
259unsafe impl Send for RustConstructorResourceBox {}
260
261unsafe impl Sync for RustConstructorResourceBox {}
262
263impl RustConstructorResourceBox {
264    pub fn new(name: &str, discern_type: &str, content: Box<dyn RustConstructorResource>) -> Self {
265        Self {
266            id: RustConstructorId {
267                name: name.to_string(),
268                discern_type: discern_type.to_string(),
269            },
270            content,
271        }
272    }
273}
274
275/// Config for basic front resources.
276///
277/// 基本前端资源的配置。
278///
279/// This struct contains all the essential config needed for positioning,
280/// sizing, and clipping visual elements in the GUI.
281///
282/// 这个结构体包含了在GUI中定位、调整大小和裁剪可视元素所需的所有配置。
283#[derive(Debug, Default, Clone, PartialEq, PartialOrd)]
284pub struct BasicFrontResourceConfig {
285    /// Config for position, size, and layout properties.
286    ///
287    /// 位置、大小和布局属性的配置。
288    pub position_size_config: PositionSizeConfig,
289
290    /// Optional clipping rectangle that defines the visible area.
291    /// If `None`, the resource is rendered without clipping.
292    ///
293    /// 可选的裁剪矩形,用于定义可见区域。如果为`None`,则渲染资源时不进行裁剪。
294    pub clip_rect: Option<PositionSizeConfig>,
295}
296
297impl BasicFrontResourceConfig {
298    #[inline]
299    pub fn position_size_config(mut self, position_size_config: PositionSizeConfig) -> Self {
300        self.position_size_config = position_size_config;
301        self
302    }
303
304    #[inline]
305    pub fn clip_rect(mut self, clip_rect: Option<PositionSizeConfig>) -> Self {
306        self.clip_rect = clip_rect;
307        self
308    }
309}
310
311/// Config for positioning and sizing resources in a flexible grid system.
312///
313/// 用于在灵活的网格系统中定位和调整资源大小的配置。
314///
315/// This struct provides comprehensive control over how resources are positioned
316/// and sized within the GUI, supporting grid-based layouts with multiple alignment options.
317///
318/// 这个结构体提供了对GUI中资源如何定位和大小的全面控制,支持具有多种对齐选项的基于网格的布局。
319///
320/// # Grid System 网格系统
321///
322/// The grid system allows for relative positioning and sizing using fractions of
323/// the available space, making layouts responsive and adaptable to different screen sizes.
324///
325/// 网格系统允许使用可用空间的一部分进行相对定位和大小调整,使布局响应并适应不同的屏幕尺寸。
326#[derive(Debug, Copy, Clone, PartialEq, PartialOrd)]
327pub struct PositionSizeConfig {
328    /// Absolute position coordinates in pixels (`[x, y]`).
329    ///
330    /// 以像素为单位的绝对位置坐标(`[x, y]`)。
331    pub origin_position: [f32; 2],
332
333    /// Absolute size dimensions in pixels (`[width, height]`).
334    ///
335    /// 以像素为单位的绝对尺寸(`[width, height]`)。
336    pub origin_size: [f32; 2],
337
338    /// Grid-based X-axis positioning (`[numerator, denominator]`).
339    ///
340    /// 基于网格的x轴定位(`[numerator, denominator]`)。
341    ///
342    /// Position = (total_width * numerator / denominator)
343    ///
344    /// 位置 = (总宽度 * 分子 / 分母)
345    pub x_location_grid: [f32; 2],
346
347    /// Grid-based Y-axis positioning (`[numerator, denominator]`).
348    ///
349    /// 基于网格的y轴定位(`[numerator, denominator]`)。
350    ///
351    /// Position = (total_height * numerator / denominator)
352    ///
353    /// 位置 = (总高度 * 分子 / 分母)
354    pub y_location_grid: [f32; 2],
355
356    /// Grid-based X-axis sizing (`[numerator, denominator]`).
357    ///
358    /// 基于网格的x轴缩放(`[numerator, denominator]`)。
359    ///
360    /// Width = (total_width * numerator / denominator)
361    ///
362    /// 宽度 = (总宽度 * 分子 / 分母)
363    pub x_size_grid: [f32; 2],
364
365    /// Grid-based Y-axis sizing (`[numerator, denominator]`).
366    ///
367    /// 基于网格的y轴缩放(`[numerator, denominator]`)。
368    ///
369    /// Height = (total_height * numerator / denominator)
370    ///
371    /// 高度 = (总高度 * 分子 / 分母)
372    pub y_size_grid: [f32; 2],
373
374    /// Horizontal and vertical alignment methods.
375    ///
376    /// 水平和垂直对齐方法。
377    pub display_method: (HorizontalAlign, VerticalAlign),
378
379    /// Additional offset in pixels (`[x_offset, y_offset]`).
380    ///
381    /// 额外的像素偏移量(`[x_offset, y_offset]`)。
382    pub offset: [f32; 2],
383}
384
385impl Default for PositionSizeConfig {
386    fn default() -> Self {
387        PositionSizeConfig {
388            origin_position: [0_f32, 0_f32],
389            origin_size: [0_f32, 0_f32],
390            x_location_grid: [0_f32, 0_f32],
391            y_location_grid: [0_f32, 0_f32],
392            x_size_grid: [0_f32, 0_f32],
393            y_size_grid: [0_f32, 0_f32],
394            display_method: (HorizontalAlign::default(), VerticalAlign::default()),
395            offset: [0_f32, 0_f32],
396        }
397    }
398}
399
400impl PositionSizeConfig {
401    #[inline]
402    pub fn origin_position(mut self, x: f32, y: f32) -> Self {
403        self.origin_position = [x, y];
404        self
405    }
406
407    #[inline]
408    pub fn origin_size(mut self, width: f32, height: f32) -> Self {
409        self.origin_size = [width, height];
410        self
411    }
412
413    #[inline]
414    pub fn x_size_grid(mut self, fetch: f32, total: f32) -> Self {
415        self.x_size_grid = [fetch, total];
416        self
417    }
418
419    #[inline]
420    pub fn y_size_grid(mut self, fetch: f32, total: f32) -> Self {
421        self.y_size_grid = [fetch, total];
422        self
423    }
424
425    #[inline]
426    pub fn x_location_grid(mut self, fetch: f32, total: f32) -> Self {
427        self.x_location_grid = [fetch, total];
428        self
429    }
430
431    #[inline]
432    pub fn y_location_grid(mut self, fetch: f32, total: f32) -> Self {
433        self.y_location_grid = [fetch, total];
434        self
435    }
436
437    #[inline]
438    pub fn display_method(
439        mut self,
440        horizontal_align: HorizontalAlign,
441        vertical_align: VerticalAlign,
442    ) -> Self {
443        self.display_method = (horizontal_align, vertical_align);
444        self
445    }
446
447    #[inline]
448    pub fn offset(mut self, x: f32, y: f32) -> Self {
449        self.offset = [x, y];
450        self
451    }
452}
453
454/// Timer for tracking application and page runtimes.
455///
456/// 用于跟踪应用程序和页面运行时间的计时器。
457#[derive(Debug, Clone, Copy, PartialEq, PartialOrd)]
458pub struct Timer {
459    /// Time when the current page was entered, in milliseconds.
460    ///
461    /// 进入当前页面的时间(毫秒)。
462    pub start_time: u128,
463
464    /// Total runtime of the application since start, in milliseconds.
465    ///
466    /// 应用程序自启动以来的总运行时间(毫秒)。
467    pub total_time: u128,
468
469    /// Core timer instance for precise timing.
470    ///
471    /// 用于精确计时的核心计时器实例。
472    pub timer: Instant,
473
474    /// Runtime of the current page, in milliseconds.
475    ///
476    /// 当前页面的运行时间(毫秒)。
477    pub now_time: u128,
478}
479
480impl Default for Timer {
481    fn default() -> Self {
482        Timer {
483            start_time: 0,
484            total_time: 0,
485            timer: Instant::now(),
486            now_time: 0,
487        }
488    }
489}
490
491/// Error type for Rust Constructor framework.
492///
493/// Rust Constructor框架的错误类型。
494#[derive(Debug, Clone, PartialEq, Eq, Hash, PartialOrd, Ord)]
495pub struct RustConstructorError {
496    /// Identifier for the error type.
497    ///
498    /// 错误类型的标识符。
499    pub error_id: String,
500
501    /// Description of the error.
502    ///
503    /// 对此错误的描述。
504    pub description: String,
505}
506
507impl Display for RustConstructorError {
508    fn fmt(&self, f: &mut Formatter) -> std::fmt::Result {
509        Debug::fmt(self, f)
510    }
511}
512
513impl Error for RustConstructorError {}
514
515/// Horizontal alignment options for UI elements.
516///
517/// UI元素的水平对齐选项。
518#[derive(Debug, Default, Clone, Copy, PartialEq, Eq, Hash, PartialOrd, Ord)]
519pub enum HorizontalAlign {
520    /// Align to the left.
521    ///
522    /// 左对齐。
523    #[default]
524    Left,
525    /// Center align horizontally.
526    ///
527    /// 居中对齐。
528    Center,
529    /// Align to the right.
530    ///
531    /// 右对齐。
532    Right,
533}
534
535/// Vertical alignment options for UI elements.
536///
537/// UI元素的垂直对齐选项。
538#[derive(Debug, Default, Clone, Copy, PartialEq, Eq, Hash, PartialOrd, Ord)]
539pub enum VerticalAlign {
540    /// Align to the top.
541    ///
542    /// 顶部对齐。
543    #[default]
544    Top,
545    /// Center align vertically.
546    ///
547    /// 居中对齐。
548    Center,
549    /// Align to the bottom.
550    ///
551    /// 底部对齐。
552    Bottom,
553}
554
555/// Defines the placement of borders relative to the element's bounds.
556///
557/// 定义边框相对于元素边界的放置方式。
558#[derive(Debug, Default, Clone, Copy, PartialEq, Eq, Hash, PartialOrd, Ord)]
559pub enum BorderKind {
560    /// Border is drawn inside the element's bounds, reducing the content area.
561    ///
562    /// 边框在元素边界内部绘制,减少内容区域。
563    #[default]
564    Inside,
565    /// Border is centered on the element's bounds, half inside and half outside.
566    ///
567    /// 边框以元素边界为中心,一半在内部一半在外部。
568    Middle,
569    /// Border is drawn outside the element's bounds, preserving the content area.
570    ///
571    /// 边框在元素边界外部绘制,保持内容区域不变。
572    Outside,
573}
574
575/// Config for rendering.
576///
577/// 渲染的配置。
578#[derive(Debug, Clone, Copy, PartialEq, PartialOrd)]
579pub enum RenderConfig {
580    /// Line with width and color.
581    ///
582    /// 线段,包含宽度和颜色。
583    Line(f32, [u8; 4]),
584    /// Rectangle with corner radius, fill color, border color, border width, and border kind.
585    ///
586    /// 矩形,包含圆角半径,填充颜色,边框颜色,边框宽度,边框类型。
587    Rect([u8; 4], [u8; 4], [u8; 4], f32, BorderKind),
588}
589
590/// Display config for resources, controlling visibility and rendering behavior.
591///
592/// 资源的显示配置,控制可见性和渲染行为。
593#[derive(Debug, Default, Clone, Copy, PartialEq, Eq, Hash, PartialOrd, Ord)]
594pub struct DisplayInfo {
595    /// Enables or disables the resource. If false, the resource is not processed.
596    ///
597    /// 启用或禁用资源。如果为false,资源不会被处理。
598    pub enable: bool,
599
600    /// Hides the resource visually but keeps it active for event handling.
601    ///
602    /// 隐藏资源视觉显示但保持其事件处理活性。
603    pub hidden: bool,
604
605    /// If true, the resource ignores the rendering layer and does not occupy the mouse focus.
606    ///
607    /// 如果为true,资源忽略渲染层,不占用鼠标焦点。
608    pub ignore_render_layer: bool,
609}
610
611/// The lookup method for requesting resources to skip the rendering queue.
612///
613/// 请求资源跳过渲染队列的查找方法。
614#[derive(Debug, Clone, PartialEq, Eq, Hash, PartialOrd, Ord)]
615pub enum RequestMethod {
616    /// Request by resource identifier.
617    ///
618    /// 按资源标识符请求。
619    Id(RustConstructorId),
620    /// Request by resource citer.
621    ///
622    /// 通过资源引用者请求。
623    Citer(RustConstructorId),
624}
625
626/// Types of rendering layer requests.
627///
628/// 渲染层请求类型。
629#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash, PartialOrd, Ord)]
630pub enum RequestType {
631    /// Move resource to the top layer.
632    ///
633    /// 移动资源到顶层。
634    Top,
635    /// Move resource up by specified number of layers.
636    ///
637    /// 按指定层数向上移动资源。
638    Up(usize),
639}
640
641/// Methods for describing list information.
642///
643/// 用于描述列表信息的方法。
644#[derive(Debug, Default, Clone, Copy, PartialEq, Eq, Hash, PartialOrd, Ord)]
645pub enum ListInfoDescribeMethod {
646    /// Detailed display including resource and ID (with optional formatting).
647    ///
648    /// 详细显示,包括资源和ID(可选格式)。
649    Detailed(bool),
650    /// Simple display showing only resource IDs.
651    ///
652    /// 简单显示,只显示资源ID。
653    #[default]
654    Simple,
655}
656
657/// Methods for compatibility with different versions of egui.
658///
659/// 用于兼容不同版本egui的方法。
660///
661/// Use when you need to call egui::Context.
662///
663/// 需要调用egui::Context时使用。
664///
665/// # Arguments
666///
667/// * `ui` - The UI context for drawing
668///
669/// # Returns
670///
671/// Return Ui directly.
672///
673/// # 参数
674///
675/// * `ui` - 用于绘制的UI上下文
676///
677/// # 返回值
678///
679/// 直接返回Ui。
680#[cfg(feature = "standard")]
681pub fn ctx_adapter(ui: &mut Ui) -> &mut Ui {
682    ui
683}
684/// Methods for compatibility with different versions of egui.
685///
686/// 用于兼容不同版本egui的方法。
687///
688/// Use when you need to call egui::Context.
689///
690/// 需要调用egui::Context时使用。
691///
692/// # Arguments
693///
694/// * `ui` - The UI context for drawing
695///
696/// # Returns
697///
698/// Return Context.
699///
700/// # 参数
701///
702/// * `ui` - 用于绘制的UI上下文
703///
704/// # 返回值
705///
706/// 返回Context。
707#[cfg(feature = "bevy")]
708pub fn ctx_adapter(ui: &mut Ui) -> &Context {
709    ui.ctx()
710}
711
712/// Obtain the type name of the target resource.
713///
714/// 获取目标资源的类型名称。
715///
716/// # Arguments
717///
718/// * `target` - Target resource
719///
720/// # Returns
721///
722/// Returns the type name of the target resource.
723///
724/// # 参数
725///
726/// * `target` - 目标资源
727///
728/// # 返回值
729///
730/// 目标资源的类型名称。
731pub fn type_processor(target: &impl RustConstructorResource) -> String {
732    let result: Vec<_> = if let Some(list) = type_name_of_val(target).split_once("<") {
733        list.0
734    } else {
735        type_name_of_val(&target)
736    }
737    .split("::")
738    .collect();
739    result[result.len() - 1].to_string()
740}
741
742/// Gets a tag value from the specified tag list by name.
743///
744/// 从指定标签列表中根据名称获取标签值。
745///
746/// # Arguments
747///
748/// * `tag_name` - The name of the tag to retrieve
749/// * `target` - The list of tags to search through
750///
751/// # Returns
752///
753/// Returns `Some((index, value))` if the tag is found, or `None` if not found.
754///
755/// # 参数
756///
757/// * `tag_name` - 要检索的标签名称
758/// * `target` - 要搜索的标签列表
759///
760/// # 返回值
761///
762/// 如果找到标签则返回`Some((索引, 值))`,否则返回`None`。
763pub fn get_tag(tag_name: &str, target: &[[String; 2]]) -> Option<(usize, String)> {
764    target
765        .iter()
766        .position(|x| x[0] == tag_name)
767        .map(|index| (index, target[index][1].clone()))
768}
769
770/// Safely convert resource references to references of specific types of resources.
771///
772/// 安全地将资源引用转换为具体类型资源的引用。
773///
774/// When using the traversal method to retrieve resources, it should be combined with this method to obtain
775/// the reference of the specific type of resource.
776///
777/// 当采用遍历的方式取出资源时,应和此方法配合来获取具体类型的资源引用。
778///
779/// # Arguments
780///
781/// * `resource` - Reference to resources
782///
783/// # Returns
784///
785/// Return a reference to the specific type of resource on success; otherwise, return `Err(RustConstructorError)`.
786///
787/// # 参数
788///
789/// * `resource` - 资源的引用
790///
791/// # 返回值
792///
793/// 成功时返回具体类型资源的引用,否则返回`Err(RustConstructorError)`。
794pub fn downcast_resource<T: RustConstructorResource + 'static>(
795    resource: &dyn RustConstructorResource,
796) -> Result<&T, RustConstructorError> {
797    if let Some(resource) = resource.as_any().downcast_ref::<T>() {
798        Ok(resource)
799    } else {
800        Err(RustConstructorError {
801            error_id: "ResourceDowncastTypeMismatch".to_string(),
802            description: format!(
803                "Failed to downcast resource to type '{}'.",
804                type_name::<T>()
805            ),
806        })
807    }
808}
809
810/// Safely convert mutable references to resources to mutable references to resources of specific types.
811///
812/// 安全地将资源可变引用转换为具体类型资源的可变引用。
813///
814/// When using the traversal method to retrieve resources, it should be combined with this method to obtain
815/// the mutable reference of the specific type of resource.
816///
817/// 当采用遍历的方式取出资源时,应和此方法配合来获取具体类型的资源可变引用。
818///
819/// # Arguments
820///
821/// * `resource` - Mutable reference to resources
822///
823/// # Returns
824///
825/// Return a mutable reference to the specific type of resource on success; otherwise, return `Err(RustConstructorError)`.
826///
827/// # 参数
828///
829/// * `resource` - 资源的可变引用
830///
831/// # 返回值
832///
833/// 成功时返回具体类型资源的可变引用,否则返回`Err(RustConstructorError)`。
834pub fn downcast_resource_mut<T: RustConstructorResource + 'static>(
835    resource: &mut dyn RustConstructorResource,
836) -> Result<&mut T, RustConstructorError> {
837    if let Some(resource) = resource.as_any_mut().downcast_mut::<T>() {
838        Ok(resource)
839    } else {
840        Err(RustConstructorError {
841            error_id: "ResourceDowncastTypeMismatch".to_string(),
842            description: format!(
843                "Failed to downcast resource to type '{}'.",
844                type_name::<T>()
845            ),
846        })
847    }
848}
849
850/// Processes position and size calculations for resources.
851///
852/// 处理资源的最基本位置和尺寸计算。
853///
854/// This method handles the complex positioning logic including grid-based layout,
855/// alignment, and offset calculations for UI resources.
856///
857/// 此方法处理复杂的定位逻辑,包括基于网格的布局、对齐方式和UI资源的偏移计算。
858///
859/// # Arguments
860///
861/// * `position_size_config` - The configuration for position and size
862/// * `ui` - The UI context for drawing
863///
864/// # Returns
865///
866/// Returns `[position, size]` as computed from the configuration
867///
868/// # 参数
869///
870/// * `position_size_config` - 位置和尺寸的配置
871/// * `ui` - 用于绘制的UI上下文
872///
873/// # 返回值
874///
875/// 返回根据配置计算出的 `[位置, 尺寸]`
876pub fn position_size_processor(position_size_config: PositionSizeConfig, ui: &Ui) -> [[f32; 2]; 2] {
877    let mut position = [0_f32, 0_f32];
878    let mut size = [0_f32, 0_f32];
879    size[0] = match position_size_config.x_size_grid[0] {
880        0_f32 => position_size_config.origin_size[0],
881        _ => {
882            (ui.available_width() / position_size_config.x_size_grid[1]
883                * position_size_config.x_size_grid[0])
884                + position_size_config.origin_size[0]
885        }
886    };
887    size[1] = match position_size_config.y_size_grid[0] {
888        0_f32 => position_size_config.origin_size[1],
889        _ => {
890            (ui.available_height() / position_size_config.y_size_grid[1]
891                * position_size_config.y_size_grid[0])
892                + position_size_config.origin_size[1]
893        }
894    };
895    position[0] = match position_size_config.x_location_grid[1] {
896        0_f32 => position_size_config.origin_position[0],
897        _ => {
898            (ui.available_width() / position_size_config.x_location_grid[1]
899                * position_size_config.x_location_grid[0])
900                + position_size_config.origin_position[0]
901        }
902    };
903    position[1] = match position_size_config.y_location_grid[1] {
904        0_f32 => position_size_config.origin_position[1],
905        _ => {
906            (ui.available_height() / position_size_config.y_location_grid[1]
907                * position_size_config.y_location_grid[0])
908                + position_size_config.origin_position[1]
909        }
910    };
911    match position_size_config.display_method.0 {
912        HorizontalAlign::Left => {}
913        HorizontalAlign::Center => position[0] -= size[0] / 2.0,
914        HorizontalAlign::Right => position[0] -= size[0],
915    };
916    match position_size_config.display_method.1 {
917        VerticalAlign::Top => {}
918        VerticalAlign::Center => position[1] -= size[1] / 2.0,
919        VerticalAlign::Bottom => position[1] -= size[1],
920    };
921    position[0] += position_size_config.offset[0];
922    position[1] += position_size_config.offset[1];
923    [position, size]
924}