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