Skip to main content

rust_constructor/
basic_front.rs

1//! This file contains basic front resources. Basic front resources can be used independently or to create advanced front-end resources.
2//!
3//! 此文件包含基本前端资源。基本前端资源可以单独使用,也可被用于创建高级前端资源。
4use crate::{
5    BasicFrontResource, BasicFrontResourceConfig, BorderKind, DisplayInfo, PositionSizeConfig,
6    RustConstructorResource,
7};
8#[cfg(feature = "bevy")]
9use egui_bevy::{ColorImage, TextureHandle};
10#[cfg(feature = "standard")]
11use egui_standard::{ColorImage, TextureHandle};
12use std::{
13    any::Any,
14    collections::HashMap,
15    fmt::{Debug, Formatter},
16    sync::{Arc, Mutex},
17};
18
19/// Config options for custom rectangles.
20///
21/// 矩形的可配置选项。
22///
23/// This struct contains all configurable properties for creating and modifying
24/// rectangular UI elements with various visual properties.
25///
26/// 该结构体包含用于创建和修改具有各种视觉属性的矩形UI元素的所有可配置属性。
27#[derive(Debug, Default, Clone, PartialEq, PartialOrd)]
28pub struct CustomRectConfig {
29    /// Config for position, size, and layout of the rectangle.
30    ///
31    /// 矩形的位置、尺寸和布局配置。
32    pub position_size_config: Option<PositionSizeConfig>,
33
34    /// Optional clipping rectangle that defines the visible area.
35    ///
36    /// 定义可见区域的可选裁剪矩形。
37    pub clip_rect: Option<Option<PositionSizeConfig>>,
38
39    /// Controls whether the rectangle is visible or hidden.
40    ///
41    /// 控制矩形是否可见或隐藏。
42    pub hidden: Option<bool>,
43
44    /// If true, the rectangle ignores render layer.
45    ///
46    /// 如果为true,矩形忽略渲染层。
47    pub ignore_render_layer: Option<bool>,
48
49    /// Radius for rounded corners. Zero for sharp corners.
50    ///
51    /// 圆角半径。零表示直角。
52    pub rounding: Option<f32>,
53
54    /// Fill color of the rectangle as [R, G, B].
55    ///
56    /// 矩形的填充颜色,格式为[R, G, B]。
57    pub color: Option<[u8; 3]>,
58
59    /// Opacity of the rectangle (0-255).
60    ///
61    /// 矩形的不透明度(0-255)。
62    pub alpha: Option<u8>,
63
64    /// Fill color overlay of the rectangle as [R, G, B].
65    ///
66    /// 矩形的填充颜色覆盖层,格式为[R, G, B]。
67    pub overlay_color: Option<[u8; 3]>,
68
69    /// Opacity of the fill color overlay (0-255).
70    ///
71    /// 矩形的填充颜色覆盖层不透明度(0-255)。
72    pub overlay_alpha: Option<Option<u8>>,
73
74    /// Width of the border.
75    ///
76    /// 边框宽度。
77    pub border_width: Option<f32>,
78
79    /// Color of the border as [R, G, B].
80    ///
81    /// 边框颜色,格式为[R, G, B]。
82    pub border_color: Option<[u8; 3]>,
83
84    /// Opacity of the border (0-255).
85    ///
86    /// 边框的不透明度(0-255)。
87    pub border_alpha: Option<u8>,
88
89    /// Color overlay of the border as [R, G, B].
90    ///
91    /// 边框的颜色覆盖层,格式为[R, G, B]。
92    pub overlay_border_color: Option<[u8; 3]>,
93
94    /// Opacity of the border color overlay (0-255).
95    ///
96    /// 边框的颜色覆盖层不透明度(0-255)。
97    pub overlay_border_alpha: Option<Option<u8>>,
98
99    /// Placement of the border relative to the rectangle's bounds.
100    ///
101    /// 边框相对于矩形边界的放置方式。
102    pub border_kind: Option<BorderKind>,
103
104    /// Key-value pairs for categorization and metadata.
105    ///
106    /// 用于分类和元数据的键值对标签。
107    pub tags: Option<Vec<[String; 2]>>,
108}
109
110impl CustomRectConfig {
111    pub fn from_custom_rect(custom_rect: &CustomRect) -> Self {
112        Self {
113            position_size_config: Some(
114                custom_rect.basic_front_resource_config.position_size_config,
115            ),
116            clip_rect: Some(custom_rect.basic_front_resource_config.clip_rect),
117            hidden: Some(custom_rect.display_info.hidden),
118            ignore_render_layer: Some(custom_rect.display_info.ignore_render_layer),
119            rounding: Some(custom_rect.rounding),
120            color: Some(custom_rect.color),
121            alpha: Some(custom_rect.alpha),
122            overlay_color: Some(custom_rect.overlay_color),
123            overlay_alpha: Some(custom_rect.overlay_alpha),
124            border_width: Some(custom_rect.border_width),
125            border_color: Some(custom_rect.border_color),
126            border_alpha: Some(custom_rect.border_alpha),
127            overlay_border_color: Some(custom_rect.overlay_border_color),
128            overlay_border_alpha: Some(custom_rect.overlay_border_alpha),
129            border_kind: Some(custom_rect.border_kind),
130            tags: Some(custom_rect.tags.clone()),
131        }
132    }
133
134    #[inline]
135    pub fn position_size_config(
136        mut self,
137        position_size_config: Option<PositionSizeConfig>,
138    ) -> Self {
139        self.position_size_config = position_size_config;
140        self
141    }
142
143    #[inline]
144    pub fn clip_rect(mut self, clip_rect: Option<Option<PositionSizeConfig>>) -> Self {
145        self.clip_rect = clip_rect;
146        self
147    }
148
149    #[inline]
150    pub fn hidden(mut self, hidden: Option<bool>) -> Self {
151        self.hidden = hidden;
152        self
153    }
154
155    #[inline]
156    pub fn ignore_render_layer(mut self, ignore_render_layer: Option<bool>) -> Self {
157        self.ignore_render_layer = ignore_render_layer;
158        self
159    }
160
161    #[inline]
162    pub fn rounding(mut self, rounding: Option<f32>) -> Self {
163        self.rounding = rounding;
164        self
165    }
166
167    #[inline]
168    pub fn color(mut self, color: Option<[u8; 3]>) -> Self {
169        self.color = color;
170        self
171    }
172
173    #[inline]
174    pub fn alpha(mut self, alpha: Option<u8>) -> Self {
175        self.alpha = alpha;
176        self
177    }
178
179    #[inline]
180    pub fn overlay_color(mut self, overlay_color: Option<[u8; 3]>) -> Self {
181        self.overlay_color = overlay_color;
182        self
183    }
184
185    #[inline]
186    pub fn overlay_alpha(mut self, overlay_alpha: Option<Option<u8>>) -> Self {
187        self.overlay_alpha = overlay_alpha;
188        self
189    }
190
191    #[inline]
192    pub fn border_width(mut self, border_width: Option<f32>) -> Self {
193        self.border_width = border_width;
194        self
195    }
196
197    #[inline]
198    pub fn border_color(mut self, border_color: Option<[u8; 3]>) -> Self {
199        self.border_color = border_color;
200        self
201    }
202
203    #[inline]
204    pub fn border_alpha(mut self, border_alpha: Option<u8>) -> Self {
205        self.border_alpha = border_alpha;
206        self
207    }
208
209    #[inline]
210    pub fn overlay_border_color(mut self, overlay_border_color: Option<[u8; 3]>) -> Self {
211        self.overlay_border_color = overlay_border_color;
212        self
213    }
214
215    #[inline]
216    pub fn overlay_border_alpha(mut self, overlay_border_alpha: Option<Option<u8>>) -> Self {
217        self.overlay_border_alpha = overlay_border_alpha;
218        self
219    }
220
221    #[inline]
222    pub fn border_kind(mut self, border_kind: Option<BorderKind>) -> Self {
223        self.border_kind = border_kind;
224        self
225    }
226
227    #[inline]
228    pub fn tags(mut self, tags: Option<Vec<[String; 2]>>) -> Self {
229        self.tags = tags;
230        self
231    }
232}
233
234/// Custom rectangle resource for drawing rectangles with various visual properties.
235///
236/// 自定义矩形资源,用于绘制具有各种视觉属性的矩形。
237#[derive(Debug, Clone, PartialEq, PartialOrd)]
238pub struct CustomRect {
239    /// Config for basic front resource properties.
240    ///
241    /// 基本前端资源属性配置。
242    pub basic_front_resource_config: BasicFrontResourceConfig,
243
244    /// Current display position of the rectangle as [x, y].
245    ///
246    /// 矩形的当前显示位置,为[x, y]。
247    pub position: [f32; 2],
248
249    /// Current display size of the rectangle as [width, height].
250    ///
251    /// 矩形的当前显示尺寸,为[width, height]。
252    pub size: [f32; 2],
253
254    /// Display info controlling visibility and rendering.
255    ///
256    /// 显示信息,控制可见性和渲染。
257    pub display_info: DisplayInfo,
258
259    /// Radius for rounded corners.
260    ///
261    /// 圆角。
262    pub rounding: f32,
263
264    /// Fill color of the rectangle as [R, G, B].
265    ///
266    /// 填充矩形颜色,为[R, G, B]。
267    pub color: [u8; 3],
268
269    /// Opacity of the rectangle (0-255).
270    ///
271    /// 矩形的不透明度(0-255)。
272    pub alpha: u8,
273
274    /// Fill color overlay of the rectangle as [R, G, B].
275    ///
276    /// 矩形的填充颜色覆盖层,格式为[R, G, B]。
277    pub overlay_color: [u8; 3],
278
279    /// Opacity of the fill color overlay (0-255).
280    ///
281    /// 矩形的填充颜色覆盖层不透明度(0-255)。
282    pub overlay_alpha: Option<u8>,
283
284    /// Width of the border.
285    ///
286    /// 边框宽度。
287    pub border_width: f32,
288
289    /// Color of the border as [R, G, B].
290    ///
291    /// 边框颜色,为[R, G, B]。
292    pub border_color: [u8; 3],
293
294    /// Opacity of the border (0-255).
295    ///
296    /// 边框的不透明度(0-255)。
297    pub border_alpha: u8,
298
299    /// Color overlay of the border as [R, G, B].
300    ///
301    /// 边框的颜色覆盖层,格式为[R, G, B]。
302    pub overlay_border_color: [u8; 3],
303
304    /// Opacity of the border color overlay (0-255).
305    ///
306    /// 边框的颜色覆盖层不透明度(0-255)。
307    pub overlay_border_alpha: Option<u8>,
308
309    /// Placement of the border relative to the rectangle's bounds.
310    ///
311    /// 边框相对于矩形边界的位置。
312    pub border_kind: BorderKind,
313
314    /// Key-value pairs for categorization and metadata.
315    ///
316    /// 用于分类和元数据的键值对标签。
317    pub tags: Vec<[String; 2]>,
318}
319
320impl RustConstructorResource for CustomRect {
321    fn as_any(&self) -> &dyn Any {
322        self
323    }
324
325    fn as_any_mut(&mut self) -> &mut dyn Any {
326        self
327    }
328
329    fn display_display_info(&self) -> Option<DisplayInfo> {
330        Some(self.display_info)
331    }
332
333    fn modify_display_info(&mut self, display_info: DisplayInfo) {
334        self.display_info = display_info;
335    }
336
337    fn display_tags(&self) -> Vec<[String; 2]> {
338        self.tags.clone()
339    }
340
341    fn modify_tags(&mut self, tags: &[[String; 2]], replace: bool) {
342        if replace {
343            self.tags = tags.to_owned();
344        } else {
345            for tag in tags {
346                if let Some(index) = self.tags.iter().position(|x| x[0] == tag[0]) {
347                    self.tags.remove(index);
348                };
349            }
350            self.tags.extend(tags.iter().cloned());
351        };
352    }
353}
354
355impl BasicFrontResource for CustomRect {
356    fn display_basic_front_resource_config(&self) -> BasicFrontResourceConfig {
357        self.basic_front_resource_config.clone()
358    }
359
360    fn display_position_size_config(&self) -> PositionSizeConfig {
361        self.basic_front_resource_config.position_size_config
362    }
363
364    fn display_clip_rect(&self) -> Option<PositionSizeConfig> {
365        self.basic_front_resource_config.clip_rect
366    }
367
368    fn display_position(&self) -> [f32; 2] {
369        self.position
370    }
371
372    fn display_size(&self) -> [f32; 2] {
373        self.size
374    }
375
376    fn modify_basic_front_resource_config(
377        &mut self,
378        basic_front_resource_config: BasicFrontResourceConfig,
379    ) {
380        self.basic_front_resource_config = basic_front_resource_config;
381    }
382
383    fn modify_position_size_config(&mut self, position_size_config: PositionSizeConfig) {
384        self.basic_front_resource_config.position_size_config = position_size_config;
385    }
386
387    fn modify_clip_rect(&mut self, clip_rect: Option<PositionSizeConfig>) {
388        self.basic_front_resource_config.clip_rect = clip_rect;
389    }
390}
391
392impl Default for CustomRect {
393    fn default() -> Self {
394        Self {
395            basic_front_resource_config: BasicFrontResourceConfig::default(),
396            position: [0_f32, 0_f32],
397            size: [0_f32, 0_f32],
398            display_info: DisplayInfo::default(),
399            rounding: 2_f32,
400            color: [255, 255, 255],
401            alpha: 255,
402            overlay_border_color: [255, 255, 255],
403            overlay_alpha: None,
404            border_width: 2_f32,
405            border_color: [0, 0, 0],
406            border_alpha: 255,
407            overlay_color: [255, 255, 255],
408            overlay_border_alpha: None,
409            border_kind: BorderKind::default(),
410            tags: Vec::new(),
411        }
412    }
413}
414
415impl CustomRect {
416    pub fn from_config(mut self, config: &CustomRectConfig) -> Self {
417        if let Some(position_size_config) = config.position_size_config {
418            self.basic_front_resource_config.position_size_config = position_size_config;
419        };
420        if let Some(clip_rect) = config.clip_rect {
421            self.basic_front_resource_config.clip_rect = clip_rect;
422        };
423        if let Some(hidden) = config.hidden {
424            self.display_info.hidden = hidden;
425        };
426        if let Some(ignore_render_layer) = config.ignore_render_layer {
427            self.display_info.ignore_render_layer = ignore_render_layer;
428        };
429        if let Some(rounding) = config.rounding {
430            self.rounding = rounding;
431        };
432        if let Some(color) = config.color {
433            self.color = color;
434        };
435        if let Some(alpha) = config.alpha {
436            self.alpha = alpha;
437        };
438        if let Some(overlay_color) = config.overlay_color {
439            self.overlay_color = overlay_color;
440        };
441        if let Some(overlay_alpha) = config.overlay_alpha {
442            self.overlay_alpha = overlay_alpha;
443        };
444        if let Some(border_width) = config.border_width {
445            self.border_width = border_width;
446        };
447        if let Some(border_color) = config.border_color {
448            self.border_color = border_color;
449        };
450        if let Some(border_alpha) = config.border_alpha {
451            self.border_alpha = border_alpha;
452        };
453        if let Some(overlay_border_color) = config.overlay_border_color {
454            self.overlay_border_color = overlay_border_color;
455        };
456        if let Some(overlay_border_alpha) = config.overlay_border_alpha {
457            self.overlay_border_alpha = overlay_border_alpha;
458        };
459        if let Some(border_kind) = config.border_kind {
460            self.border_kind = border_kind;
461        };
462        if let Some(tags) = config.tags.clone() {
463            self.tags = tags;
464        };
465        self
466    }
467
468    #[inline]
469    pub fn basic_front_resource_config(
470        mut self,
471        basic_front_resource_config: &BasicFrontResourceConfig,
472    ) -> Self {
473        self.basic_front_resource_config = basic_front_resource_config.clone();
474        self
475    }
476
477    #[inline]
478    pub fn hidden(mut self, hidden: bool) -> Self {
479        self.display_info.hidden = hidden;
480        self
481    }
482
483    #[inline]
484    pub fn ignore_render_layer(mut self, ignore_render_layer: bool) -> Self {
485        self.display_info.ignore_render_layer = ignore_render_layer;
486        self
487    }
488
489    #[inline]
490    pub fn rounding(mut self, rounding: f32) -> Self {
491        self.rounding = rounding;
492        self
493    }
494
495    #[inline]
496    pub fn color(mut self, r: u8, g: u8, b: u8) -> Self {
497        self.color = [r, g, b];
498        self
499    }
500
501    #[inline]
502    pub fn alpha(mut self, alpha: u8) -> Self {
503        self.alpha = alpha;
504        self
505    }
506
507    #[inline]
508    pub fn overlay_color(mut self, r: u8, g: u8, b: u8) -> Self {
509        self.overlay_color = [r, g, b];
510        self
511    }
512
513    #[inline]
514    pub fn overlay_alpha(mut self, overlay_alpha: Option<u8>) -> Self {
515        self.overlay_alpha = overlay_alpha;
516        self
517    }
518
519    #[inline]
520    pub fn border_width(mut self, border_width: f32) -> Self {
521        self.border_width = border_width;
522        self
523    }
524
525    #[inline]
526    pub fn border_color(mut self, r: u8, g: u8, b: u8) -> Self {
527        self.border_color = [r, g, b];
528        self
529    }
530
531    #[inline]
532    pub fn border_alpha(mut self, border_alpha: u8) -> Self {
533        self.border_alpha = border_alpha;
534        self
535    }
536
537    #[inline]
538    pub fn overlay_border_color(mut self, r: u8, g: u8, b: u8) -> Self {
539        self.overlay_border_color = [r, g, b];
540        self
541    }
542
543    #[inline]
544    pub fn overlay_border_alpha(mut self, overlay_border_alpha: Option<u8>) -> Self {
545        self.overlay_border_alpha = overlay_border_alpha;
546        self
547    }
548
549    #[inline]
550    pub fn border_kind(mut self, border_kind: BorderKind) -> Self {
551        self.border_kind = border_kind;
552        self
553    }
554
555    #[inline]
556    pub fn tags(mut self, tags: &[[String; 2]], replace: bool) -> Self {
557        if replace {
558            self.tags = tags.to_owned();
559        } else {
560            for tag in tags {
561                if let Some(index) = self.tags.iter().position(|x| x[0] == tag[0]) {
562                    self.tags.remove(index);
563                };
564            }
565            self.tags.extend(tags.iter().cloned());
566        };
567        self
568    }
569}
570
571/// Wrapper for TextureHandle that supports Debug trait derivation.
572///
573/// 支持Debug特征派生的TextureHandle包装器。
574#[derive(Clone, PartialEq, Eq, Hash)]
575pub struct DebugTextureHandle(pub TextureHandle);
576
577impl Debug for DebugTextureHandle {
578    fn fmt(&self, f: &mut Formatter) -> std::fmt::Result {
579        // 只输出类型信息,不输出具体纹理数据
580        f.debug_struct("DebugTextureHandle").finish()
581    }
582}
583
584impl DebugTextureHandle {
585    pub fn new(texture_handle: &TextureHandle) -> Self {
586        Self(texture_handle.clone())
587    }
588}
589
590/// Request sent to the background worker thread to load an image from disk.
591///
592/// 发送到后台工作线程的图片加载请求。
593/// Result returned from the background worker thread after loading an image.
594///
595/// 后台工作线程完成图片加载后返回的结果。
596#[derive(Debug, Default, Clone, PartialEq, Eq)]
597pub struct LoadedImageData {
598    /// Decoded image data ready for texture upload on the main thread.
599    ///
600    /// 已解码的图像数据,可在主线程直接上传为纹理。
601    pub color_image: ColorImage,
602}
603
604/// Manages the background image loading infrastructure.
605///
606/// 管理后台图片加载基础设施。
607#[derive(Debug, Default, Clone)]
608pub struct ImageLoader {
609    /// Completed loads from worker threads, keyed by resource name.
610    /// Each frame, completed loads are drained to create egui textures.
611    ///
612    /// 工作线程完成的加载结果,按资源名称索引。每帧消耗以创建 egui 纹理。
613    pub completed: Arc<Mutex<HashMap<String, LoadedImageData>>>,
614}
615
616/// Methods for loading images into the resource.
617///
618/// 将图像加载到资源中的方法。
619#[derive(Debug, Clone, PartialEq, Eq, Hash)]
620pub enum ImageLoadMethod {
621    /// Load image from a file path.
622    ///
623    /// 从文件路径加载图像。
624    ByPath((String, [bool; 2])),
625
626    /// Use an existing TextureHandle for the image.
627    ///
628    /// 使用现有的TextureHandle作为图像。
629    ByTexture(DebugTextureHandle),
630}
631
632/// Config options for image resources.
633///
634/// 图像资源的配置选项。
635#[derive(Debug, Default, Clone, PartialEq)]
636pub struct ImageConfig {
637    /// Config for position, size, and layout.
638    ///
639    /// 位置、尺寸和布局配置。
640    pub position_size_config: Option<PositionSizeConfig>,
641
642    /// Optional clipping rectangle that defines the visible area.
643    ///
644    /// 定义可见区域的可选裁剪矩形。
645    pub clip_rect: Option<Option<PositionSizeConfig>>,
646
647    /// Controls whether the image is visible or hidden.
648    ///
649    /// 控制图像是否可见或隐藏。
650    pub hidden: Option<bool>,
651
652    /// If true, the image ignores render layer.
653    ///
654    /// 如果为true,图像忽略渲染层。
655    pub ignore_render_layer: Option<bool>,
656
657    /// Opacity of the image (0-255).
658    ///
659    /// 图像的不透明度(0-255)。
660    pub alpha: Option<u8>,
661
662    /// Color overlay applied to the image as [R, G, B].
663    ///
664    /// 应用于图像的色彩覆盖,格式为[R, G, B]。
665    pub overlay_color: Option<[u8; 3]>,
666
667    /// Opacity of the overlay (0-255).
668    ///
669    /// 覆盖层的不透明度(0-255)。
670    pub overlay_alpha: Option<u8>,
671
672    /// Background color behind the image as [R, G, B].
673    ///
674    /// 图像背后的背景颜色,格式为[R, G, B]。
675    pub background_color: Option<[u8; 3]>,
676
677    /// Opacity of the background (0-255).
678    ///
679    /// 背景的不透明度(0-255)。
680    pub background_alpha: Option<u8>,
681
682    /// Rotation angle of the image in degrees.
683    ///
684    /// 图像的旋转角度(度)。
685    pub rotate_angle: Option<f32>,
686
687    /// Center point for rotation, compare it with the actual size to obtain as [width, height].
688    ///
689    /// 旋转中心点,通过与实际大小的比得出,为[width, height]。
690    pub rotate_center: Option<[f32; 2]>,
691
692    /// Method used to load the image.
693    ///
694    /// 用于加载图像的方法。
695    pub image_load_method: Option<ImageLoadMethod>,
696
697    /// Key-value pairs for categorization and metadata.
698    ///
699    /// 用于分类和元数据的键值对标签。
700    pub tags: Option<Vec<[String; 2]>>,
701}
702
703impl ImageConfig {
704    pub fn from_image(image: &Image) -> Self {
705        Self {
706            position_size_config: Some(image.basic_front_resource_config.position_size_config),
707            clip_rect: Some(image.basic_front_resource_config.clip_rect),
708            hidden: Some(image.display_info.hidden),
709            ignore_render_layer: Some(image.display_info.ignore_render_layer),
710            alpha: Some(image.alpha),
711            overlay_color: Some(image.overlay_color),
712            overlay_alpha: Some(image.overlay_alpha),
713            background_color: Some(image.background_color),
714            background_alpha: Some(image.background_alpha),
715            rotate_angle: Some(image.rotate_angle),
716            rotate_center: Some(image.rotate_center),
717            image_load_method: Some(image.image_load_method.clone()),
718            tags: Some(image.tags.clone()),
719        }
720    }
721
722    #[inline]
723    pub fn position_size_config(
724        mut self,
725        position_size_config: Option<PositionSizeConfig>,
726    ) -> Self {
727        self.position_size_config = position_size_config;
728        self
729    }
730
731    #[inline]
732    pub fn clip_rect(mut self, clip_rect: Option<Option<PositionSizeConfig>>) -> Self {
733        self.clip_rect = clip_rect;
734        self
735    }
736
737    #[inline]
738    pub fn hidden(mut self, hidden: Option<bool>) -> Self {
739        self.hidden = hidden;
740        self
741    }
742
743    #[inline]
744    pub fn ignore_render_layer(mut self, ignore_render_layer: Option<bool>) -> Self {
745        self.ignore_render_layer = ignore_render_layer;
746        self
747    }
748
749    #[inline]
750    pub fn alpha(mut self, alpha: Option<u8>) -> Self {
751        self.alpha = alpha;
752        self
753    }
754
755    #[inline]
756    pub fn overlay_color(mut self, overlay_color: Option<[u8; 3]>) -> Self {
757        self.overlay_color = overlay_color;
758        self
759    }
760
761    #[inline]
762    pub fn overlay_alpha(mut self, overlay_alpha: Option<u8>) -> Self {
763        self.overlay_alpha = overlay_alpha;
764        self
765    }
766
767    #[inline]
768    pub fn background_color(mut self, background_color: Option<[u8; 3]>) -> Self {
769        self.background_color = background_color;
770        self
771    }
772
773    #[inline]
774    pub fn background_alpha(mut self, background_alpha: Option<u8>) -> Self {
775        self.background_alpha = background_alpha;
776        self
777    }
778
779    #[inline]
780    pub fn rotate_angle(mut self, rotate_angle: Option<f32>) -> Self {
781        self.rotate_angle = rotate_angle;
782        self
783    }
784
785    #[inline]
786    pub fn rotate_center(mut self, rotate_center: Option<[f32; 2]>) -> Self {
787        self.rotate_center = rotate_center;
788        self
789    }
790
791    #[inline]
792    pub fn image_load_method(mut self, image_load_method: Option<ImageLoadMethod>) -> Self {
793        self.image_load_method = image_load_method;
794        self
795    }
796
797    #[inline]
798    pub fn tags(mut self, tags: Option<Vec<[String; 2]>>) -> Self {
799        self.tags = tags;
800        self
801    }
802}
803
804/// Image resource for displaying graphical content in the GUI.
805///
806/// 用于在GUI中显示图形内容的图像资源。
807#[derive(Debug, Clone, PartialEq)]
808pub struct Image {
809    /// Config for basic front resource properties.
810    ///
811    /// 基本前端资源属性配置。
812    pub basic_front_resource_config: BasicFrontResourceConfig,
813
814    /// Current display position of the image as [x, y].
815    ///
816    /// 图像的当前显示位置,坐标为[x, y]。
817    pub position: [f32; 2],
818
819    /// Current display size of the image as [width, height].
820    ///
821    /// 图像的当前显示尺寸,为[width, height]。
822    pub size: [f32; 2],
823
824    /// Display info controlling visibility and rendering.
825    ///
826    /// 显示信息,控制可见性和渲染。
827    pub display_info: DisplayInfo,
828
829    /// Handle to the loaded texture, if available.
830    ///
831    /// 已加载纹理的句柄(如果可用)。
832    pub texture: Option<DebugTextureHandle>,
833
834    /// Opacity of the image (0-255).
835    ///
836    /// 图像的不透明度(0-255)。
837    pub alpha: u8,
838
839    /// Color overlay applied to the image as [R, G, B].
840    ///
841    /// 应用于图像的色彩覆盖,格式为[R, G, B]。
842    pub overlay_color: [u8; 3],
843
844    /// Opacity of the overlay (0-255).
845    ///
846    /// 覆盖层的不透明度(0-255)。
847    pub overlay_alpha: u8,
848
849    /// Background color behind the image as [R, G, B].
850    ///
851    /// 图像背后的背景颜色,格式为[R, G, B]。
852    pub background_color: [u8; 3],
853
854    /// Opacity of the background (0-255).
855    ///
856    /// 背景的不透明度(0-255)。
857    pub background_alpha: u8,
858
859    /// Rotation angle of the image in degrees.
860    ///
861    /// 图像的旋转角度(度)。
862    pub rotate_angle: f32,
863
864    /// Center point for rotation, compare it with the actual size to obtain as [width, height].
865    ///
866    /// 旋转中心点,通过与实际大小的比得出,为[width, height]。
867    pub rotate_center: [f32; 2],
868
869    /// Method used to load the image.
870    ///
871    /// 用于加载图像的方法。
872    pub image_load_method: ImageLoadMethod,
873
874    /// The path for loading the image in the previous frame.
875    ///
876    /// 上一帧加载图片的路径。
877    pub last_frame_path: String,
878
879    /// Key-value pairs for categorization and metadata.
880    ///
881    /// 用于分类和元数据的键值对标签。
882    pub tags: Vec<[String; 2]>,
883}
884
885impl RustConstructorResource for Image {
886    fn as_any(&self) -> &dyn Any {
887        self
888    }
889
890    fn as_any_mut(&mut self) -> &mut dyn Any {
891        self
892    }
893
894    fn display_display_info(&self) -> Option<DisplayInfo> {
895        Some(self.display_info)
896    }
897
898    fn modify_display_info(&mut self, display_info: DisplayInfo) {
899        self.display_info = display_info;
900    }
901
902    fn display_tags(&self) -> Vec<[String; 2]> {
903        self.tags.clone()
904    }
905
906    fn modify_tags(&mut self, tags: &[[String; 2]], replace: bool) {
907        if replace {
908            self.tags = tags.to_owned();
909        } else {
910            for tag in tags {
911                if let Some(index) = self.tags.iter().position(|x| x[0] == tag[0]) {
912                    self.tags.remove(index);
913                };
914            }
915            self.tags.extend(tags.iter().cloned());
916        };
917    }
918}
919
920impl BasicFrontResource for Image {
921    fn display_basic_front_resource_config(&self) -> BasicFrontResourceConfig {
922        self.basic_front_resource_config.clone()
923    }
924
925    fn display_position_size_config(&self) -> PositionSizeConfig {
926        self.basic_front_resource_config.position_size_config
927    }
928
929    fn display_clip_rect(&self) -> Option<PositionSizeConfig> {
930        self.basic_front_resource_config.clip_rect
931    }
932
933    fn display_position(&self) -> [f32; 2] {
934        self.position
935    }
936
937    fn display_size(&self) -> [f32; 2] {
938        self.size
939    }
940
941    fn modify_basic_front_resource_config(
942        &mut self,
943        basic_front_resource_config: BasicFrontResourceConfig,
944    ) {
945        self.basic_front_resource_config = basic_front_resource_config;
946    }
947
948    fn modify_position_size_config(&mut self, position_size_config: PositionSizeConfig) {
949        self.basic_front_resource_config.position_size_config = position_size_config;
950    }
951
952    fn modify_clip_rect(&mut self, clip_rect: Option<PositionSizeConfig>) {
953        self.basic_front_resource_config.clip_rect = clip_rect;
954    }
955}
956
957impl Default for Image {
958    fn default() -> Self {
959        Self {
960            basic_front_resource_config: BasicFrontResourceConfig::default(),
961            position: [0_f32, 0_f32],
962            size: [0_f32, 0_f32],
963            display_info: DisplayInfo::default(),
964            texture: None,
965            alpha: 255,
966            overlay_color: [255, 255, 255],
967            overlay_alpha: 255,
968            background_color: [0, 0, 0],
969            background_alpha: 0,
970            rotate_angle: 0_f32,
971            rotate_center: [0_f32, 0_f32],
972            image_load_method: ImageLoadMethod::ByPath((String::new(), [false, false])),
973            last_frame_path: String::new(),
974            tags: Vec::new(),
975        }
976    }
977}
978
979impl Image {
980    pub fn from_config(mut self, config: &ImageConfig) -> Self {
981        if let Some(position_size_config) = config.position_size_config {
982            self.basic_front_resource_config.position_size_config = position_size_config;
983        };
984        if let Some(clip_rect) = config.clip_rect {
985            self.basic_front_resource_config.clip_rect = clip_rect;
986        };
987        if let Some(hidden) = config.hidden {
988            self.display_info.hidden = hidden;
989        };
990        if let Some(ignore_render_layer) = config.ignore_render_layer {
991            self.display_info.ignore_render_layer = ignore_render_layer;
992        };
993        if let Some(alpha) = config.alpha {
994            self.alpha = alpha;
995        };
996        if let Some(overlay_color) = config.overlay_color {
997            self.overlay_color = overlay_color;
998        };
999        if let Some(overlay_alpha) = config.overlay_alpha {
1000            self.overlay_alpha = overlay_alpha;
1001        };
1002        if let Some(background_color) = config.background_color {
1003            self.background_color = background_color;
1004        };
1005        if let Some(background_alpha) = config.background_alpha {
1006            self.background_alpha = background_alpha;
1007        };
1008        if let Some(rotate_angle) = config.rotate_angle {
1009            self.rotate_angle = rotate_angle;
1010        };
1011        if let Some(rotate_center) = config.rotate_center {
1012            self.rotate_center = rotate_center;
1013        };
1014        if let Some(image_load_method) = config.image_load_method.clone() {
1015            self.image_load_method = image_load_method;
1016        };
1017        if let Some(tags) = config.tags.clone() {
1018            self.tags = tags;
1019        };
1020        self
1021    }
1022
1023    #[inline]
1024    pub fn basic_front_resource_config(
1025        mut self,
1026        basic_front_resource_config: &BasicFrontResourceConfig,
1027    ) -> Self {
1028        self.basic_front_resource_config = basic_front_resource_config.clone();
1029        self
1030    }
1031
1032    #[inline]
1033    pub fn hidden(mut self, hidden: bool) -> Self {
1034        self.display_info.hidden = hidden;
1035        self
1036    }
1037
1038    #[inline]
1039    pub fn ignore_render_layer(mut self, ignore_render_layer: bool) -> Self {
1040        self.display_info.ignore_render_layer = ignore_render_layer;
1041        self
1042    }
1043
1044    #[inline]
1045    pub fn alpha(mut self, alpha: u8) -> Self {
1046        self.alpha = alpha;
1047        self
1048    }
1049
1050    #[inline]
1051    pub fn overlay_color(mut self, r: u8, g: u8, b: u8) -> Self {
1052        self.overlay_color = [r, g, b];
1053        self
1054    }
1055
1056    #[inline]
1057    pub fn overlay_alpha(mut self, overlay_alpha: u8) -> Self {
1058        self.overlay_alpha = overlay_alpha;
1059        self
1060    }
1061
1062    #[inline]
1063    pub fn background_color(mut self, r: u8, g: u8, b: u8) -> Self {
1064        self.background_color = [r, g, b];
1065        self
1066    }
1067
1068    #[inline]
1069    pub fn background_alpha(mut self, background_alpha: u8) -> Self {
1070        self.background_alpha = background_alpha;
1071        self
1072    }
1073
1074    #[inline]
1075    pub fn rotate_angle(mut self, rotate_angle: f32) -> Self {
1076        self.rotate_angle = rotate_angle;
1077        self
1078    }
1079
1080    #[inline]
1081    pub fn rotate_center(mut self, x: f32, y: f32) -> Self {
1082        self.rotate_center = [x, y];
1083        self
1084    }
1085
1086    #[inline]
1087    pub fn image_load_method(mut self, image_load_method: &ImageLoadMethod) -> Self {
1088        self.image_load_method = image_load_method.clone();
1089        self
1090    }
1091
1092    #[inline]
1093    pub fn tags(mut self, tags: &[[String; 2]], replace: bool) -> Self {
1094        if replace {
1095            self.tags = tags.to_owned();
1096        } else {
1097            for tag in tags {
1098                if let Some(index) = self.tags.iter().position(|x| x[0] == tag[0]) {
1099                    self.tags.remove(index);
1100                };
1101            }
1102            self.tags.extend(tags.iter().cloned());
1103        };
1104        self
1105    }
1106}
1107
1108/// Control the selection method of hyperlinks.
1109///
1110/// 控制超链接的选取方法。
1111#[derive(Debug, Clone, PartialEq, Eq, Hash, PartialOrd, Ord)]
1112pub enum HyperlinkSelectMethod {
1113    /// Selects all occurrences of the hyperlink text.
1114    ///
1115    /// 选取所有匹配的超链接文本。
1116    All(String),
1117    /// Selects specific segments of the hyperlink text with indices.
1118    ///
1119    /// 选取指定的超链接文本段。
1120    Segment(Vec<(usize, String)>),
1121}
1122
1123/// Config options for text resources.
1124///
1125/// 文本资源的配置选项。
1126#[derive(Debug, Default, Clone, PartialEq, PartialOrd)]
1127pub struct TextConfig {
1128    /// Config for position, size, and layout.
1129    ///
1130    /// 位置、尺寸和布局配置。
1131    pub position_size_config: Option<PositionSizeConfig>,
1132
1133    /// Optional clipping rectangle that defines the visible area.
1134    ///
1135    /// 定义可见区域的可选裁剪矩形。
1136    pub clip_rect: Option<Option<PositionSizeConfig>>,
1137
1138    /// Controls whether the text is visible or hidden.
1139    ///
1140    /// 控制文本是否可见或隐藏。
1141    pub hidden: Option<bool>,
1142
1143    /// If true, the text ignores render layer.
1144    ///
1145    /// 如果为true,文本忽略渲染层。
1146    pub ignore_render_layer: Option<bool>,
1147
1148    /// Text content to be displayed.
1149    ///
1150    /// 要显示的文本内容。
1151    pub content: Option<String>,
1152
1153    /// Font size in points.
1154    ///
1155    /// 字体大小(点)。
1156    pub font_size: Option<f32>,
1157
1158    /// Text color as [R, G, B].
1159    ///
1160    /// 文本颜色,格式为[R, G, B]。
1161    pub color: Option<[u8; 3]>,
1162
1163    /// Opacity of the text (0-255).
1164    ///
1165    /// 文本的不透明度(0-255)。
1166    pub alpha: Option<u8>,
1167
1168    /// Background color behind the text as [R, G, B].
1169    ///
1170    /// 文本背后的背景颜色,格式为[R, G, B]。
1171    pub background_color: Option<[u8; 3]>,
1172
1173    /// Opacity of the background (0-255).
1174    ///
1175    /// 背景的不透明度(0-255)。
1176    pub background_alpha: Option<u8>,
1177
1178    /// Radius for rounded corners of the background.
1179    ///
1180    /// 背景圆角半径。
1181    pub background_rounding: Option<f32>,
1182
1183    /// The font used for the specified text.
1184    ///
1185    /// 指定文本使用的字体。
1186    pub font: Option<String>,
1187
1188    /// Whether the text can be selected by the user.
1189    ///
1190    /// 文本是否可以被用户选择。
1191    pub selectable: Option<bool>,
1192
1193    /// Hyperlink texts for clickable regions.
1194    ///
1195    /// 可点击区域的超链接文本。
1196    pub hyperlink_text: Option<Vec<(String, HyperlinkSelectMethod)>>,
1197
1198    /// Automatically adjust size to fit content.
1199    ///
1200    /// 自动调整尺寸以适应内容。
1201    pub auto_fit: Option<[bool; 2]>,
1202
1203    /// Key-value pairs for categorization and metadata.
1204    ///
1205    /// 用于分类和元数据的键值对标签。
1206    pub tags: Option<Vec<[String; 2]>>,
1207}
1208
1209impl TextConfig {
1210    pub fn from_text(text: &Text) -> Self {
1211        Self {
1212            position_size_config: Some(text.basic_front_resource_config.position_size_config),
1213            clip_rect: Some(text.basic_front_resource_config.clip_rect),
1214            hidden: Some(text.display_info.hidden),
1215            ignore_render_layer: Some(text.display_info.ignore_render_layer),
1216            content: Some(text.content.clone()),
1217            font_size: Some(text.font_size),
1218            color: Some(text.color),
1219            alpha: Some(text.alpha),
1220            background_color: Some(text.background_color),
1221            background_alpha: Some(text.background_alpha),
1222            background_rounding: Some(text.background_rounding),
1223            font: Some(text.font.clone()),
1224            selectable: Some(text.selectable),
1225            hyperlink_text: Some(text.hyperlink_text.clone()),
1226            auto_fit: Some(text.auto_fit),
1227            tags: Some(text.tags.clone()),
1228        }
1229    }
1230
1231    #[inline]
1232    pub fn position_size_config(
1233        mut self,
1234        position_size_config: Option<PositionSizeConfig>,
1235    ) -> Self {
1236        self.position_size_config = position_size_config;
1237        self
1238    }
1239
1240    #[inline]
1241    pub fn clip_rect(mut self, clip_rect: Option<Option<PositionSizeConfig>>) -> Self {
1242        self.clip_rect = clip_rect;
1243        self
1244    }
1245
1246    #[inline]
1247    pub fn hidden(mut self, hidden: Option<bool>) -> Self {
1248        self.hidden = hidden;
1249        self
1250    }
1251
1252    #[inline]
1253    pub fn ignore_render_layer(mut self, ignore_render_layer: Option<bool>) -> Self {
1254        self.ignore_render_layer = ignore_render_layer;
1255        self
1256    }
1257
1258    #[inline]
1259    pub fn content(mut self, content: Option<String>) -> Self {
1260        self.content = content;
1261        self
1262    }
1263
1264    #[inline]
1265    pub fn font_size(mut self, font_size: Option<f32>) -> Self {
1266        self.font_size = font_size;
1267        self
1268    }
1269
1270    #[inline]
1271    pub fn color(mut self, color: Option<[u8; 3]>) -> Self {
1272        self.color = color;
1273        self
1274    }
1275
1276    #[inline]
1277    pub fn alpha(mut self, alpha: Option<u8>) -> Self {
1278        self.alpha = alpha;
1279        self
1280    }
1281
1282    #[inline]
1283    pub fn background_color(mut self, background_color: Option<[u8; 3]>) -> Self {
1284        self.background_color = background_color;
1285        self
1286    }
1287
1288    #[inline]
1289    pub fn background_alpha(mut self, background_alpha: Option<u8>) -> Self {
1290        self.background_alpha = background_alpha;
1291        self
1292    }
1293
1294    #[inline]
1295    pub fn background_rounding(mut self, background_rounding: Option<f32>) -> Self {
1296        self.background_rounding = background_rounding;
1297        self
1298    }
1299
1300    #[inline]
1301    pub fn font(mut self, font: Option<String>) -> Self {
1302        self.font = font;
1303        self
1304    }
1305
1306    #[inline]
1307    pub fn selectable(mut self, selectable: Option<bool>) -> Self {
1308        self.selectable = selectable;
1309        self
1310    }
1311
1312    #[inline]
1313    pub fn hyperlink_text(
1314        mut self,
1315        hyperlink_text: Option<Vec<(String, HyperlinkSelectMethod)>>,
1316    ) -> Self {
1317        self.hyperlink_text = hyperlink_text;
1318        self
1319    }
1320
1321    #[inline]
1322    pub fn auto_fit(mut self, auto_fit: Option<[bool; 2]>) -> Self {
1323        self.auto_fit = auto_fit;
1324        self
1325    }
1326
1327    #[inline]
1328    pub fn tags(mut self, tags: Option<Vec<[String; 2]>>) -> Self {
1329        self.tags = tags;
1330        self
1331    }
1332}
1333
1334/// Text resource for displaying and interacting with textual content.
1335///
1336/// 用于显示和交互文本内容的文本资源。
1337#[derive(Debug, Clone, PartialEq, PartialOrd)]
1338pub struct Text {
1339    /// Config for basic front resource properties.
1340    ///
1341    /// 基本前端资源属性配置。
1342    pub basic_front_resource_config: BasicFrontResourceConfig,
1343
1344    /// Current display position of the text as [x, y].
1345    ///
1346    /// 文本的当前显示位置,坐标为[x, y]。
1347    pub position: [f32; 2],
1348
1349    /// Current display size of the text as [width, height].
1350    ///
1351    /// 文本的当前显示尺寸,为[width, height]。
1352    pub size: [f32; 2],
1353
1354    /// Display info controlling visibility and rendering.
1355    ///
1356    /// 显示信息,控制可见性和渲染。
1357    pub display_info: DisplayInfo,
1358
1359    /// Text content to be displayed.
1360    ///
1361    /// 要显示的文本内容。
1362    pub content: String,
1363
1364    /// Font size in points.
1365    ///
1366    /// 字体大小(点)。
1367    pub font_size: f32,
1368
1369    /// Text color as [R, G, B].
1370    ///
1371    /// 文本颜色,格式为[R, G, B]。
1372    pub color: [u8; 3],
1373
1374    /// Opacity of the text (0-255).
1375    ///
1376    /// 文本的不透明度(0-255)。
1377    pub alpha: u8,
1378
1379    /// Background color behind the text as [R, G, B].
1380    ///
1381    /// 文本背后的背景颜色,格式为[R, G, B]。
1382    pub background_color: [u8; 3],
1383
1384    /// Opacity of the background (0-255).
1385    ///
1386    /// 背景的不透明度(0-255)。
1387    pub background_alpha: u8,
1388
1389    /// Radius for rounded corners of the background.
1390    ///
1391    /// 背景圆角半径。
1392    pub background_rounding: f32,
1393
1394    /// The font used for the specified text.
1395    ///
1396    /// 指定文本使用的字体。
1397    pub font: String,
1398
1399    /// Whether the text can be selected by the user.
1400    ///
1401    /// 文本是否可以被用户选择。
1402    pub selectable: bool,
1403
1404    /// Hyperlink texts with their selection methods for clickable regions.
1405    ///
1406    /// 可点击区域的超链接文本及其选择方法。
1407    pub hyperlink_text: Vec<(String, HyperlinkSelectMethod)>,
1408
1409    /// Hyperlink indices and URLs: (start_index, end_index, url).
1410    ///
1411    /// 超链接索引值和链接:(起始索引, 结束索引, 链接)。
1412    pub hyperlink_index: Vec<(usize, usize, String)>,
1413
1414    /// Auto-fit behavior: [horizontal_fit, vertical_fit].
1415    ///
1416    /// 是否让渲染层大小自动匹配实际大小:[水平适应, 垂直适应]。
1417    pub auto_fit: [bool; 2],
1418
1419    /// Text content from the previous frame for change detection.
1420    ///
1421    /// 上一帧的文本内容,用于变化检测。
1422    pub last_frame_content: String,
1423
1424    /// Currently selected text range (start_index, end_index).
1425    ///
1426    /// 框选选中的文本范围(起始索引, 结束索引)。
1427    pub selection: Option<(usize, usize)>,
1428
1429    /// Size at which text is truncated for display.
1430    ///
1431    /// 文本被截断以供显示的尺寸。
1432    pub truncate_size: [f32; 2],
1433
1434    /// Actual size of the text content.
1435    ///
1436    /// 文本内容的实际尺寸。
1437    pub actual_size: [f32; 2],
1438
1439    /// Key-value pairs for categorization and metadata.
1440    ///
1441    /// 用于分类和元数据的键值对标签。
1442    pub tags: Vec<[String; 2]>,
1443}
1444
1445impl RustConstructorResource for Text {
1446    fn as_any(&self) -> &dyn Any {
1447        self
1448    }
1449
1450    fn as_any_mut(&mut self) -> &mut dyn Any {
1451        self
1452    }
1453
1454    fn display_display_info(&self) -> Option<DisplayInfo> {
1455        Some(self.display_info)
1456    }
1457
1458    fn modify_display_info(&mut self, display_info: DisplayInfo) {
1459        self.display_info = display_info;
1460    }
1461
1462    fn display_tags(&self) -> Vec<[String; 2]> {
1463        self.tags.clone()
1464    }
1465
1466    fn modify_tags(&mut self, tags: &[[String; 2]], replace: bool) {
1467        if replace {
1468            self.tags = tags.to_owned();
1469        } else {
1470            for tag in tags {
1471                if let Some(index) = self.tags.iter().position(|x| x[0] == tag[0]) {
1472                    self.tags.remove(index);
1473                };
1474            }
1475            self.tags.extend(tags.iter().cloned());
1476        };
1477    }
1478}
1479
1480impl BasicFrontResource for Text {
1481    fn display_basic_front_resource_config(&self) -> BasicFrontResourceConfig {
1482        self.basic_front_resource_config.clone()
1483    }
1484
1485    fn display_position_size_config(&self) -> PositionSizeConfig {
1486        self.basic_front_resource_config.position_size_config
1487    }
1488
1489    fn display_clip_rect(&self) -> Option<PositionSizeConfig> {
1490        self.basic_front_resource_config.clip_rect
1491    }
1492
1493    fn display_position(&self) -> [f32; 2] {
1494        self.position
1495    }
1496
1497    fn display_size(&self) -> [f32; 2] {
1498        self.size
1499    }
1500
1501    fn modify_basic_front_resource_config(
1502        &mut self,
1503        basic_front_resource_config: BasicFrontResourceConfig,
1504    ) {
1505        self.basic_front_resource_config = basic_front_resource_config;
1506    }
1507
1508    fn modify_position_size_config(&mut self, position_size_config: PositionSizeConfig) {
1509        self.basic_front_resource_config.position_size_config = position_size_config;
1510    }
1511
1512    fn modify_clip_rect(&mut self, clip_rect: Option<PositionSizeConfig>) {
1513        self.basic_front_resource_config.clip_rect = clip_rect;
1514    }
1515}
1516
1517impl Default for Text {
1518    fn default() -> Self {
1519        Self {
1520            basic_front_resource_config: BasicFrontResourceConfig::default(),
1521            position: [0_f32, 0_f32],
1522            size: [0_f32, 0_f32],
1523            display_info: DisplayInfo::default(),
1524            content: String::from("Hello world"),
1525            font_size: 16_f32,
1526            color: [255, 255, 255],
1527            alpha: 255,
1528            background_color: [0, 0, 0],
1529            background_alpha: 0,
1530            background_rounding: 2_f32,
1531            font: String::new(),
1532            selectable: true,
1533            auto_fit: [true, true],
1534            hyperlink_text: Vec::new(),
1535            hyperlink_index: Vec::new(),
1536            last_frame_content: String::from(""),
1537            selection: None,
1538            truncate_size: [0_f32, 0_f32],
1539            actual_size: [0_f32, 0_f32],
1540            tags: Vec::new(),
1541        }
1542    }
1543}
1544
1545impl Text {
1546    pub fn from_config(mut self, config: &TextConfig) -> Self {
1547        if let Some(position_size_config) = config.position_size_config {
1548            self.basic_front_resource_config.position_size_config = position_size_config;
1549        };
1550        if let Some(clip_rect) = config.clip_rect {
1551            self.basic_front_resource_config.clip_rect = clip_rect;
1552        };
1553        if let Some(hidden) = config.hidden {
1554            self.display_info.hidden = hidden;
1555        };
1556        if let Some(ignore_render_layer) = config.ignore_render_layer {
1557            self.display_info.ignore_render_layer = ignore_render_layer;
1558        };
1559        if let Some(content) = config.content.clone() {
1560            self.content = content;
1561        };
1562        if let Some(font_size) = config.font_size {
1563            self.font_size = font_size;
1564        };
1565        if let Some(color) = config.color {
1566            self.color = color;
1567        };
1568        if let Some(alpha) = config.alpha {
1569            self.alpha = alpha;
1570        };
1571        if let Some(background_color) = config.background_color {
1572            self.background_color = background_color;
1573        };
1574        if let Some(background_alpha) = config.background_alpha {
1575            self.background_alpha = background_alpha;
1576        };
1577        if let Some(background_rounding) = config.background_rounding {
1578            self.background_rounding = background_rounding;
1579        };
1580        if let Some(font) = config.font.clone() {
1581            self.font = font;
1582        };
1583        if let Some(selectable) = config.selectable {
1584            self.selectable = selectable;
1585        };
1586        if let Some(hyperlink_text) = config.hyperlink_text.clone() {
1587            self.hyperlink_text = hyperlink_text;
1588        };
1589        if let Some(auto_fit) = config.auto_fit {
1590            self.auto_fit = auto_fit;
1591        };
1592        if let Some(tags) = config.tags.clone() {
1593            self.tags = tags;
1594        };
1595        self
1596    }
1597
1598    #[inline]
1599    pub fn basic_front_resource_config(
1600        mut self,
1601        basic_front_resource_config: &BasicFrontResourceConfig,
1602    ) -> Self {
1603        self.basic_front_resource_config = basic_front_resource_config.clone();
1604        self
1605    }
1606
1607    #[inline]
1608    pub fn hidden(mut self, hidden: bool) -> Self {
1609        self.display_info.hidden = hidden;
1610        self
1611    }
1612
1613    #[inline]
1614    pub fn ignore_render_layer(mut self, ignore_render_layer: bool) -> Self {
1615        self.display_info.ignore_render_layer = ignore_render_layer;
1616        self
1617    }
1618
1619    #[inline]
1620    pub fn content(mut self, content: &str) -> Self {
1621        self.content = content.to_string();
1622        self
1623    }
1624
1625    #[inline]
1626    pub fn font_size(mut self, font_size: f32) -> Self {
1627        self.font_size = font_size;
1628        self
1629    }
1630
1631    #[inline]
1632    pub fn color(mut self, r: u8, g: u8, b: u8) -> Self {
1633        self.color = [r, g, b];
1634        self
1635    }
1636
1637    #[inline]
1638    pub fn alpha(mut self, alpha: u8) -> Self {
1639        self.alpha = alpha;
1640        self
1641    }
1642
1643    #[inline]
1644    pub fn background_color(mut self, r: u8, g: u8, b: u8) -> Self {
1645        self.background_color = [r, g, b];
1646        self
1647    }
1648
1649    #[inline]
1650    pub fn background_alpha(mut self, alpha: u8) -> Self {
1651        self.background_alpha = alpha;
1652        self
1653    }
1654
1655    #[inline]
1656    pub fn background_rounding(mut self, background_rounding: f32) -> Self {
1657        self.background_rounding = background_rounding;
1658        self
1659    }
1660
1661    #[inline]
1662    pub fn font(mut self, font: &str) -> Self {
1663        self.font = font.to_string();
1664        self
1665    }
1666
1667    #[inline]
1668    pub fn selectable(mut self, selectable: bool) -> Self {
1669        self.selectable = selectable;
1670        self
1671    }
1672
1673    #[inline]
1674    pub fn push_hyperlink_text(
1675        mut self,
1676        target_text: &str,
1677        select_method: HyperlinkSelectMethod,
1678    ) -> Self {
1679        self.hyperlink_text
1680            .push((target_text.to_string(), select_method));
1681        self
1682    }
1683
1684    #[inline]
1685    pub fn hyperlink_text(mut self, hyperlink_text: Vec<(String, HyperlinkSelectMethod)>) -> Self {
1686        self.hyperlink_text = hyperlink_text;
1687        self
1688    }
1689
1690    #[inline]
1691    pub fn auto_fit(mut self, x: bool, y: bool) -> Self {
1692        self.auto_fit = [x, y];
1693        self
1694    }
1695
1696    #[inline]
1697    pub fn tags(mut self, tags: &[[String; 2]], replace: bool) -> Self {
1698        if replace {
1699            self.tags = tags.to_owned();
1700        } else {
1701            for tag in tags {
1702                if let Some(index) = self.tags.iter().position(|x| x[0] == tag[0]) {
1703                    self.tags.remove(index);
1704                };
1705            }
1706            self.tags.extend(tags.iter().cloned());
1707        };
1708        self
1709    }
1710}