Skip to main content

rust_constructor/
advance_front.rs

1//! This file contains advanced front-end resources, which can be used to handle complex tasks.
2//!
3//! 此文件包含高级前端资源,高级前端资源可以用于处理复杂的任务。
4use crate::{
5    DisplayInfo, RustConstructorId, RustConstructorResource,
6    basic_front::{CustomRectConfig, ImageConfig, TextConfig},
7};
8use eframe::egui::PointerButton;
9use std::any::Any;
10
11/// Control the basic front resource type for Background selection.
12///
13/// 控制Background选择的基础前端资源类型。
14#[derive(Clone, Debug, PartialEq)]
15pub enum BackgroundType {
16    /// Use an image as the background.
17    ///
18    /// 选择图像作为背景。
19    Image(ImageConfig),
20
21    /// Use a custom rectangle as the background.
22    ///
23    /// 选择自定义矩形作为背景。
24    CustomRect(CustomRectConfig),
25}
26
27impl Default for BackgroundType {
28    fn default() -> Self {
29        BackgroundType::CustomRect(CustomRectConfig::default())
30    }
31}
32
33/// Background resource for UI elements.
34///
35/// UI元素的背景资源。
36#[derive(Clone, Debug, Default, PartialEq)]
37pub struct Background {
38    /// Type of background to display.
39    ///
40    /// 要显示的背景类型。
41    pub background_type: BackgroundType,
42
43    /// If true, the background config updates automatically.
44    ///
45    /// 如果为true,则背景会自动更新。
46    pub auto_update: bool,
47
48    /// If true, resources created by the background use its tags.
49    ///
50    /// 如果为true,则背景创建的资源使用其标签。
51    pub use_background_tags: bool,
52
53    /// Key-value pairs for categorization and metadata.
54    ///
55    /// 用于分类和元数据的键值对标签。
56    pub tags: Vec<[String; 2]>,
57}
58
59impl RustConstructorResource for Background {
60    fn as_any(&self) -> &dyn Any {
61        self
62    }
63
64    fn as_any_mut(&mut self) -> &mut dyn Any {
65        self
66    }
67
68    fn display_display_info(&self) -> Option<DisplayInfo> {
69        None
70    }
71
72    fn modify_display_info(&mut self, _display_info: DisplayInfo) {}
73
74    fn display_tags(&self) -> Vec<[String; 2]> {
75        self.tags.clone()
76    }
77
78    fn modify_tags(&mut self, tags: &[[String; 2]], replace: bool) {
79        if replace {
80            self.tags = tags.to_owned();
81        } else {
82            for tag in tags {
83                if let Some(index) = self.tags.iter().position(|x| x[0] == tag[0]) {
84                    self.tags.remove(index);
85                };
86            }
87            self.tags.extend(tags.iter().cloned());
88        };
89    }
90}
91
92impl Background {
93    #[inline]
94    pub fn background_type(mut self, background_type: &BackgroundType) -> Self {
95        self.background_type = background_type.clone();
96        self
97    }
98
99    #[inline]
100    pub fn auto_update(mut self, auto_update: bool) -> Self {
101        self.auto_update = auto_update;
102        self
103    }
104
105    #[inline]
106    pub fn use_background_tags(mut self, use_background_tags: bool) -> Self {
107        self.use_background_tags = use_background_tags;
108        self
109    }
110
111    #[inline]
112    pub fn tags(mut self, tags: &[[String; 2]], replace: bool) -> Self {
113        if replace {
114            self.tags = tags.to_owned();
115        } else {
116            for tag in tags {
117                if let Some(index) = self.tags.iter().position(|x| x[0] == tag[0]) {
118                    self.tags.remove(index);
119                };
120            }
121            self.tags.extend(tags.iter().cloned());
122        };
123        self
124    }
125}
126
127/// Methods for determining scroll bar length in panels.
128///
129/// 面板中滚动条长度的确定方法。
130#[derive(Debug, Clone, Copy, PartialEq, PartialOrd)]
131pub enum ScrollLengthMethod {
132    /// Fixed length in pixels regardless of content size.
133    ///
134    /// 固定的像素长度,与内容大小无关。
135    Fixed(f32),
136    /// Automatically adjusts based on visible content proportion.
137    ///
138    /// 根据可见内容比例自动调整。
139    AutoFit(f32),
140}
141
142/// Mouse click interaction types for panels.
143///
144/// 面板的鼠标点击交互类型。
145///
146/// Defines the intended action when clicking on different parts of a panel's border or interior.
147///
148/// 定义点击面板边框或内部不同区域时的预期操作。
149#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash, PartialOrd, Ord)]
150pub enum ClickAim {
151    /// Move the entire panel.
152    ///
153    /// 移动资源板。
154    Move,
155    /// Resize from the top edge.
156    ///
157    /// 在上方缩放。
158    TopResize,
159    /// Resize from the bottom edge.
160    ///
161    /// 在下方缩放。
162    BottomResize,
163    /// Resize from the left edge.
164    ///
165    /// 在左侧缩放。
166    LeftResize,
167    /// Resize from the right edge.
168    ///
169    /// 在右侧缩放。
170    RightResize,
171    /// Resize from the top-left corner.
172    ///
173    /// 在左上方缩放。
174    LeftTopResize,
175    /// Resize from the top-right corner.
176    ///
177    /// 在右上方缩放。
178    RightTopResize,
179    /// Resize from the bottom-left corner.
180    ///
181    /// 在左下方缩放。
182    LeftBottomResize,
183    /// Resize from the bottom-right corner.
184    ///
185    /// 在右下方缩放。
186    RightBottomResize,
187}
188
189/// Scroll bar display behavior for panels.
190///
191/// 面板的滚动条显示行为。
192///
193/// Defines when and how the scroll bar should be displayed to the user.
194///
195/// 定义滚动条何时以及如何向用户显示。
196#[derive(Debug, Clone, PartialEq)]
197pub enum ScrollBarDisplayMethod {
198    /// Always show the scroll bar with specified background, offset, and width.
199    ///
200    /// 持续显示滚动条,使用指定的背景、偏移量和宽度。
201    Always(BackgroundType, [f32; 2], f32),
202    /// Show the scroll bar only during scrolling with specified properties.
203    ///
204    /// 仅在滚动时显示滚动条,使用指定的属性。
205    OnlyScroll(BackgroundType, [f32; 2], f32),
206    /// Never show the scroll bar (scrollable but no visual indicator).
207    ///
208    /// 隐藏滚动条(可滚动但无视觉指示器)。
209    Hidden,
210}
211
212/// Margin config for resources within panels.
213///
214/// 面板内资源的外边距配置。
215///
216/// Defines spacing and layout behavior for resources placed inside panel containers.
217///
218/// 定义放置在面板容器内的资源的间距和布局行为。
219#[derive(Debug, Clone, Copy, PartialEq, PartialOrd)]
220pub enum PanelMargin {
221    /// Vertical layout with margins [top, bottom, left, right] and reverse flag.
222    ///
223    /// 垂直布局,外边距为[top, bottom, left, right],包含反转标志。
224    Vertical([f32; 4], bool),
225    /// Horizontal layout with margins [top, bottom, left, right] and reverse flag.
226    ///
227    /// 水平布局,外边距为[top, bottom, left, right],包含反转标志。
228    Horizontal([f32; 4], bool),
229    /// No layout with margins [top, bottom, left, right] and influence layout flag.
230    ///
231    /// 无布局,外边距为[top, bottom, left, right],包含影响布局标志。
232    None([f32; 4], bool),
233}
234
235/// Panel layout config determining how resources are arranged within panels.
236///
237/// 面板布局配置,确定资源如何在面板内排列。
238#[derive(Debug, Clone, Copy, PartialEq, PartialOrd)]
239pub struct PanelLayout {
240    /// Margin config for resources within the panel.
241    ///
242    /// 面板内资源的边距配置。
243    pub panel_margin: PanelMargin,
244    /// Location config for resources within the panel.
245    ///
246    /// 面板内资源的位置配置。
247    pub panel_location: PanelLocation,
248}
249
250/// Positioning method for resources within panels.
251///
252/// 面板内资源的定位方式。
253///
254/// Defines how resources are positioned relative to their containing panel.
255///
256/// 定义资源相对于其包含面板的定位方法。
257#[derive(Debug, Clone, Copy, PartialEq, PartialOrd)]
258pub enum PanelLocation {
259    /// Absolute positioning using pixel coordinates relative to panel's top-left corner.
260    ///
261    /// 依照此资源到资源板左上角的距离定位(绝对定位)。
262    Absolute([f32; 2]),
263    /// Relative positioning using grid-based coordinates.
264    ///
265    /// 依照网格式定位方法进行定位(相对定位)。
266    Relative([[f32; 2]; 2]),
267}
268
269/// Used for customizing the layout of resources.
270///
271/// 用于自定义资源排版方式。
272#[derive(Debug, Clone, PartialEq, PartialOrd)]
273pub enum CustomPanelLayout {
274    /// Locate resources by type.
275    ///
276    /// 通过类型定位资源。
277    Type(String, PanelLayout),
278    /// Locate resources through ID.
279    ///
280    /// 通过ID定位资源。
281    Id(RustConstructorId, PanelLayout),
282}
283
284/// Storage structure for panel resource metadata.
285///
286/// 面板资源元数据的存储结构。
287///
288/// This struct holds essential information about resources stored within panels,
289/// including visibility, rendering behavior, and sizing information.
290///
291/// 该结构体保存面板内存储资源的基本信息,包括可见性、渲染行为和尺寸信息。
292#[derive(Debug, Default, Clone, PartialEq, PartialOrd)]
293pub struct PanelStorage {
294    /// Unique identifier for the stored resource.
295    ///
296    /// 存储资源的唯一标识符。
297    pub id: RustConstructorId,
298
299    /// If true, the resource ignores render layer.
300    ///
301    /// 如果为true,则资源忽略渲染层。
302    pub ignore_render_layer: bool,
303
304    /// Controls whether the resource is visible.
305    ///
306    /// 控制资源是否可见。
307    pub hidden: bool,
308}
309
310/// Resource panel for organizing and managing UI elements with scrolling capabilities.
311///
312/// 资源板,用于组织和管理具有滚动能力的UI元素。
313#[derive(Debug, Clone, PartialEq)]
314pub struct ResourcePanel {
315    /// Which edges can be resized: [top, bottom, left, right].
316    ///
317    /// 哪些边可以调整尺寸:[top, bottom, left, right]。
318    pub resizable: [bool; 4],
319
320    /// Background display for the panel.
321    ///
322    /// 面板的背景显示。
323    pub background: BackgroundType,
324
325    /// Minimum size constraints for the panel.
326    ///
327    /// 面板的最小尺寸限制。
328    pub min_size: [f32; 2],
329
330    /// Optional maximum size constraints for the panel.
331    ///
332    /// 面板的可选最大尺寸限制。
333    pub max_size: Option<[f32; 2]>,
334
335    /// Whether the panel can be moved: [horizontal, vertical].
336    ///
337    /// 面板是否可以移动:[horizontal, vertical]。
338    pub movable: [bool; 2],
339
340    /// Methods for calculating scroll length: [horizontal, vertical].
341    ///
342    /// 计算滚动长度的方法:[horizontal, vertical]。
343    pub scroll_length_method: [Option<ScrollLengthMethod>; 2],
344
345    /// Sensitivity of scrolling interactions.
346    ///
347    /// 滚动交互的敏感性。
348    pub scroll_sensitivity: f32,
349
350    /// Whether to use smooth scrolling with delta values.
351    ///
352    /// 是否使用平滑滚动。
353    pub use_smooth_scroll_delta: bool,
354
355    /// Display behavior of the scroll bar.
356    ///
357    /// 显示滚动条的方法。
358    pub scroll_bar_display_method: ScrollBarDisplayMethod,
359
360    /// Layout config for resources within the panel.
361    ///
362    /// 面板内资源的布局配置。
363    pub overall_layout: PanelLayout,
364
365    /// Custom layout config of specific resources within the panel.
366    ///
367    /// 面板内特定资源的自定义布局配置。
368    pub custom_layout: Vec<CustomPanelLayout>,
369
370    /// Whether the panel is visible.
371    ///
372    /// 面板是否可见。
373    pub hidden: bool,
374
375    /// Reverse scroll direction: [horizontal, vertical].
376    ///
377    /// 反转滚动方向:[horizontal, vertical]。
378    pub reverse_scroll_direction: [bool; 2],
379
380    /// Inner margin of the panel.
381    ///
382    /// 面板内边距。
383    ///
384    /// Use this field to ensure that functions such as resizing can be used normally.
385    ///
386    /// 使用此字段以保证缩放等功能可以正常使用。
387    pub inner_margin: [f32; 4],
388
389    /// Whether to place the panel in the front when clicking
390    ///
391    /// 是否在点击时将面板前置。
392    pub raise_on_focus: bool,
393
394    /// Current scroll length: [horizontal, vertical].
395    ///
396    /// 当前滚动长度:[horizontal, vertical]。
397    pub scroll_length: [f32; 2],
398
399    /// Current scroll progress: [horizontal, vertical].
400    ///
401    /// 当前滚动进度:[horizontal, vertical]。
402    pub scroll_progress: [f32; 2],
403
404    /// Mouse state from previous frame: (position, click_aim, scroll_delta).
405    ///
406    /// 上一帧的鼠标状态:(位置,点击目标,滚动增量)。
407    pub last_frame_mouse_status: Option<([f32; 2], ClickAim, [f32; 2])>,
408
409    /// Whether scrolling occurred in this frame: [horizontal, vertical].
410    ///
411    /// 在这一帧中是否发生了滚动:[horizontal, vertical]。
412    pub scrolled: [bool; 2],
413
414    /// Scroll bar transparency: [horizontal, vertical].
415    ///
416    /// 滚动条透明度:[horizontal, vertical]。
417    pub scroll_bar_alpha: [u8; 2],
418
419    /// Storage for resource metadata within the panel.
420    ///
421    /// 面板内资源元数据的存储。
422    pub resource_storage: Vec<PanelStorage>,
423
424    /// Key-value pairs for categorization and metadata.
425    ///
426    /// 用于分类和元数据的键值对标签。
427    pub tags: Vec<[String; 2]>,
428}
429
430impl RustConstructorResource for ResourcePanel {
431    fn as_any(&self) -> &dyn Any {
432        self
433    }
434
435    fn as_any_mut(&mut self) -> &mut dyn Any {
436        self
437    }
438
439    fn display_display_info(&self) -> Option<DisplayInfo> {
440        None
441    }
442
443    fn modify_display_info(&mut self, _display_info: DisplayInfo) {}
444
445    fn display_tags(&self) -> Vec<[String; 2]> {
446        self.tags.clone()
447    }
448
449    fn modify_tags(&mut self, tags: &[[String; 2]], replace: bool) {
450        if replace {
451            self.tags = tags.to_owned();
452        } else {
453            for tag in tags {
454                if let Some(index) = self.tags.iter().position(|x| x[0] == tag[0]) {
455                    self.tags.remove(index);
456                };
457            }
458            self.tags.extend(tags.iter().cloned());
459        };
460    }
461}
462
463impl Default for ResourcePanel {
464    fn default() -> Self {
465        Self {
466            resizable: [true, true, true, true],
467            background: BackgroundType::default(),
468            min_size: [10_f32, 10_f32],
469            max_size: None,
470            movable: [true, true],
471            scroll_length_method: [None, None],
472            scroll_sensitivity: 0_f32,
473            use_smooth_scroll_delta: true,
474            scroll_bar_display_method: ScrollBarDisplayMethod::OnlyScroll(
475                BackgroundType::default(),
476                [4_f32, 2_f32],
477                4_f32,
478            ),
479            overall_layout: (PanelLayout {
480                panel_margin: PanelMargin::Vertical([0_f32, 0_f32, 0_f32, 0_f32], false),
481                panel_location: PanelLocation::Absolute([0_f32, 0_f32]),
482            }),
483            custom_layout: Vec::new(),
484            hidden: false,
485            reverse_scroll_direction: [false, false],
486            inner_margin: [6_f32, 6_f32, 6_f32, 6_f32],
487            raise_on_focus: true,
488            scroll_length: [0_f32, 0_f32],
489            scroll_progress: [0_f32, 0_f32],
490            last_frame_mouse_status: None,
491            scrolled: [false, false],
492            scroll_bar_alpha: [0, 0],
493            resource_storage: Vec::new(),
494            tags: Vec::new(),
495        }
496    }
497}
498
499impl ResourcePanel {
500    #[inline]
501    pub fn resizable(mut self, top: bool, bottom: bool, left: bool, right: bool) -> Self {
502        self.resizable = [top, bottom, left, right];
503        self
504    }
505
506    #[inline]
507    pub fn background(mut self, background: &BackgroundType) -> Self {
508        self.background = background.clone();
509        self
510    }
511
512    #[inline]
513    pub fn min_size(mut self, width: f32, height: f32) -> Self {
514        self.min_size = [width, height];
515        self
516    }
517
518    #[inline]
519    pub fn max_size(mut self, max_size: Option<[f32; 2]>) -> Self {
520        self.max_size = max_size;
521        self
522    }
523
524    #[inline]
525    pub fn movable(mut self, horizontal: bool, vertical: bool) -> Self {
526        self.movable = [horizontal, vertical];
527        self
528    }
529
530    #[inline]
531    pub fn scroll_length_method(
532        mut self,
533        horizontal: Option<ScrollLengthMethod>,
534        vertical: Option<ScrollLengthMethod>,
535    ) -> Self {
536        self.scroll_length_method = [horizontal, vertical];
537        self
538    }
539
540    #[inline]
541    pub fn scroll_sensitivity(mut self, scroll_sensitivity: f32) -> Self {
542        self.scroll_sensitivity = scroll_sensitivity;
543        self
544    }
545
546    #[inline]
547    pub fn use_smooth_scroll_delta(mut self, use_smooth_scroll_delta: bool) -> Self {
548        self.use_smooth_scroll_delta = use_smooth_scroll_delta;
549        self
550    }
551
552    #[inline]
553    pub fn scroll_bar_display_method(
554        mut self,
555        scroll_bar_display_method: ScrollBarDisplayMethod,
556    ) -> Self {
557        self.scroll_bar_display_method = scroll_bar_display_method;
558        self
559    }
560
561    #[inline]
562    pub fn overall_layout(mut self, overall_layout: PanelLayout) -> Self {
563        self.overall_layout = overall_layout;
564        self
565    }
566
567    #[inline]
568    pub fn push_custom_layout(mut self, custom_layout: CustomPanelLayout) -> Self {
569        self.custom_layout.push(custom_layout);
570        self
571    }
572
573    #[inline]
574    pub fn custom_layout(mut self, custom_layout: &[CustomPanelLayout]) -> Self {
575        self.custom_layout = custom_layout.to_owned();
576        self
577    }
578
579    #[inline]
580    pub fn hidden(mut self, hidden: bool) -> Self {
581        self.hidden = hidden;
582        self
583    }
584
585    #[inline]
586    pub fn reverse_scroll_direction(mut self, horizontal: bool, vertical: bool) -> Self {
587        self.reverse_scroll_direction = [horizontal, vertical];
588        self
589    }
590
591    #[inline]
592    pub fn inner_margin(mut self, top: f32, bottom: f32, left: f32, right: f32) -> Self {
593        self.inner_margin = [top, bottom, left, right];
594        self
595    }
596
597    #[inline]
598    pub fn raise_on_focus(mut self, raise_on_focus: bool) -> Self {
599        self.raise_on_focus = raise_on_focus;
600        self
601    }
602
603    #[inline]
604    pub fn tags(mut self, tags: &[[String; 2]], replace: bool) -> Self {
605        if replace {
606            self.tags = tags.to_owned();
607        } else {
608            for tag in tags {
609                if let Some(index) = self.tags.iter().position(|x| x[0] == tag[0]) {
610                    self.tags.remove(index);
611                };
612            }
613            self.tags.extend(tags.iter().cloned());
614        };
615        self
616    }
617}
618
619/// Appearance config for switch resources.
620///
621/// 开关资源的外观配置。
622#[derive(Clone, Debug, Default, PartialEq)]
623pub struct SwitchAppearanceConfig {
624    /// Config for the background element.
625    ///
626    /// 背景元素的配置项。
627    pub background_config: BackgroundType,
628
629    /// Config for the main text.
630    ///
631    /// 主要文本的配置项。
632    pub text_config: TextConfig,
633
634    /// Config for the hint text.
635    ///
636    /// 提示文本的配置项。
637    pub hint_text_config: TextConfig,
638}
639
640/// Click config for switch resources.
641///
642/// 开关资源的点击配置。
643#[derive(Debug, Clone, Copy, PartialEq, Eq)]
644pub struct SwitchClickConfig {
645    /// Mouse button used to trigger the switch.
646    ///
647    /// 用于触发开关的鼠标按钮。
648    pub click_method: PointerButton,
649
650    /// Whether clicking changes the switch state.
651    ///
652    /// 单击是否改变开关状态。
653    pub action: bool,
654}
655
656/// Data structure for tracking switch state and interactions.
657///
658/// 用于跟踪开关状态和交互的数据结构。
659#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash, PartialOrd, Ord)]
660pub struct SwitchData {
661    /// Whether the switch was toggled by a click.
662    ///
663    /// 是否通过点击打开开关。
664    pub switched: bool,
665
666    /// Click method from the previous frame, if any.
667    ///
668    /// 前一帧中的单击方法(如果有的话)。
669    pub last_frame_clicked: Option<usize>,
670
671    /// Current state of the switch.
672    ///
673    /// 开关当前的状态。
674    pub state: usize,
675}
676
677/// Switch resource for toggleable UI elements.
678///
679/// 用于可切换UI元素的开关资源。
680#[derive(Debug, Clone, PartialEq)]
681pub struct Switch {
682    /// Appearance configs for each state combination.
683    ///
684    /// 每个状态组合的外观配置。
685    pub appearance: Vec<SwitchAppearanceConfig>,
686
687    /// Type of background to display.
688    ///
689    /// 要显示的背景类型。
690    pub background_type: BackgroundType,
691
692    /// Config for the main text display.
693    ///
694    /// 主文本显示的配置。
695    pub text_config: TextConfig,
696
697    /// Config for the hint text display.
698    ///
699    /// 提示文本显示的配置。
700    pub hint_text_config: TextConfig,
701
702    /// Enable animations for hover and click: [hover, click].
703    ///
704    /// 启用悬停动画和单击动画:[hover, click]。
705    pub enable_animation: [bool; 2],
706
707    /// Total number of possible switch states.
708    ///
709    /// 开关可能的状态总数。
710    pub state_amount: u32,
711
712    /// Configs for click interactions.
713    ///
714    /// 单击交互的配置。
715    pub click_method: Vec<SwitchClickConfig>,
716
717    /// Set the single-choice grouping of the switch.
718    ///
719    /// 设置开关的单选分组。
720    ///
721    /// Only one switch can be activated within the same single-choice group.
722    ///
723    /// 同一单选分组内只能有一个开关被激活。
724    pub radio_group: String,
725
726    /// Whether the switch is enabled (disabled shows but not interactive).
727    ///
728    /// 开关是否启用(disabled会显示,但无法交互)。
729    pub enable: bool,
730
731    /// Current state of the switch.
732    ///
733    /// 开关当前状态。
734    pub state: usize,
735
736    /// Whether the mouse was hovering in the previous frame.
737    ///
738    /// 鼠标是否在前一帧中悬停。
739    pub last_frame_hovered: bool,
740
741    /// Click method from the previous frame, if any.
742    ///
743    /// 前一帧中的单击方法(如果有的话)。
744    pub last_frame_clicked: Option<usize>,
745
746    /// Whether the switch was toggled.
747    ///
748    /// 开关是否被切换。
749    pub switched: bool,
750
751    /// If true, resources created by the switch use its tags.
752    ///
753    /// 如果为true,则开关创建的资源使用其标签。
754    pub use_switch_tags: bool,
755
756    /// Key-value pairs for categorization and metadata.
757    ///
758    /// 用于分类和元数据的键值对标签。
759    pub tags: Vec<[String; 2]>,
760}
761
762impl RustConstructorResource for Switch {
763    fn as_any(&self) -> &dyn Any {
764        self
765    }
766
767    fn as_any_mut(&mut self) -> &mut dyn Any {
768        self
769    }
770
771    fn display_display_info(&self) -> Option<DisplayInfo> {
772        None
773    }
774
775    fn modify_display_info(&mut self, _display_info: DisplayInfo) {}
776
777    fn display_tags(&self) -> Vec<[String; 2]> {
778        self.tags.clone()
779    }
780
781    fn modify_tags(&mut self, tags: &[[String; 2]], replace: bool) {
782        if replace {
783            self.tags = tags.to_owned();
784        } else {
785            for tag in tags {
786                if let Some(index) = self.tags.iter().position(|x| x[0] == tag[0]) {
787                    self.tags.remove(index);
788                };
789            }
790            self.tags.extend(tags.iter().cloned());
791        };
792    }
793}
794
795impl Default for Switch {
796    fn default() -> Self {
797        Self {
798            appearance: vec![],
799            background_type: BackgroundType::default(),
800            text_config: TextConfig::default(),
801            hint_text_config: TextConfig::default(),
802            enable_animation: [false, false],
803            state_amount: 0,
804            click_method: vec![],
805            radio_group: String::new(),
806            enable: true,
807            state: 0,
808            last_frame_hovered: false,
809            last_frame_clicked: None,
810            switched: false,
811            use_switch_tags: false,
812            tags: Vec::new(),
813        }
814    }
815}
816
817impl Switch {
818    #[inline]
819    pub fn appearance(mut self, appearance: &[SwitchAppearanceConfig]) -> Self {
820        self.appearance = appearance.to_owned();
821        self
822    }
823
824    #[inline]
825    pub fn background_type(mut self, background_type: &BackgroundType) -> Self {
826        self.background_type = background_type.clone();
827        self
828    }
829
830    #[inline]
831    pub fn text_config(mut self, text_config: &TextConfig) -> Self {
832        self.text_config = text_config.clone();
833        self
834    }
835
836    #[inline]
837    pub fn hint_text_config(mut self, hint_text_config: &TextConfig) -> Self {
838        self.hint_text_config = hint_text_config.clone();
839        self
840    }
841
842    #[inline]
843    pub fn enable_animation(mut self, enable_hover: bool, enable_click: bool) -> Self {
844        self.enable_animation = [enable_hover, enable_click];
845        self
846    }
847
848    #[inline]
849    pub fn state_amount(mut self, state_amount: u32) -> Self {
850        self.state_amount = state_amount;
851        self
852    }
853
854    #[inline]
855    pub fn click_method(mut self, click_method: Vec<SwitchClickConfig>) -> Self {
856        self.click_method = click_method;
857        self
858    }
859
860    #[inline]
861    pub fn radio_group(mut self, radio_group: &str) -> Self {
862        self.radio_group = radio_group.to_string();
863        self
864    }
865
866    #[inline]
867    pub fn enable(mut self, enable: bool) -> Self {
868        self.enable = enable;
869        self
870    }
871
872    #[inline]
873    pub fn state(mut self, state: usize) -> Self {
874        self.state = state;
875        self
876    }
877
878    #[inline]
879    pub fn use_switch_tags(mut self, use_switch_tags: bool) -> Self {
880        self.use_switch_tags = use_switch_tags;
881        self
882    }
883
884    #[inline]
885    pub fn tags(mut self, tags: &[[String; 2]], replace: bool) -> Self {
886        if replace {
887            self.tags = tags.to_owned();
888        } else {
889            for tag in tags {
890                if let Some(index) = self.tags.iter().position(|x| x[0] == tag[0]) {
891                    self.tags.remove(index);
892                };
893            }
894            self.tags.extend(tags.iter().cloned());
895        };
896        self
897    }
898}