Skip to main content

traaains/ui/track/segment/signals_list/item/data/
max_speed_select.rs

1use core::panic;
2
3use bevy::{
4    ecs::{
5        entity::Entity,
6        event::EntityEvent,
7        hierarchy::ChildOf,
8        observer::On,
9        query::With,
10        system::{Commands, Query},
11    },
12    feathers::controls::{FeathersCheckbox, FeathersSelect, OptionIndex, list_rows_from_strings},
13    log::tracing,
14    scene::{Scene, bsn, on},
15    ui_widgets::ValueChange,
16};
17use strum::IntoEnumIterator;
18
19use crate::{
20    sim::signal::{
21        Signals,
22        main::{MainSignalState, MaxSpeed},
23    },
24    ui::{
25        Target,
26        segment::signals_list::item::{
27            SignalListItem,
28            data::{MaxSpeedField, is_checkbox_checked, update_checkbox_visual},
29            find_root_with_target,
30        },
31    },
32};
33
34fn on_value_change(
35    e: On<ValueChange<Entity>>,
36    options: Query<&OptionIndex>,
37    target: Query<(Entity, &Target), With<SignalListItem>>,
38    children: Query<&ChildOf>,
39    max_speed_field: Query<&MaxSpeedField>,
40    mut signals: Query<&mut Signals>,
41) {
42    let Some((_, target_signal)) = find_root_with_target(e.event_target(), &target, &children)
43    else {
44        tracing::error!(
45            "Could not find parent UI entity with a target component pointing to a signal!"
46        );
47        return;
48    };
49
50    let Ok(option) = options.get(e.value) else {
51        return;
52    };
53
54    let new_speed = MaxSpeed::iter().nth(option.0).unwrap();
55
56    let Ok(max_speed_field) = max_speed_field.get(e.event_target()) else {
57        tracing::warn!("Max speed select doesn't have field set, add a MaxSpeedField component!");
58        return;
59    };
60
61    let Ok(mut signal) = signals.get_mut(target_signal) else {
62        return;
63    };
64
65    match &mut *signal {
66        Signals::Main(main_signal) => match &mut main_signal.state {
67            MainSignalState::Warning {
68                max_speed,
69                next_speed,
70            } => match max_speed_field {
71                MaxSpeedField::MaxSpeed => *max_speed = Some(new_speed),
72                MaxSpeedField::NextSpeed => *next_speed = Some(new_speed),
73            },
74            MainSignalState::Free { max_speed } => match max_speed_field {
75                MaxSpeedField::MaxSpeed => *max_speed = Some(new_speed),
76                _ => panic!("Invalid max speed field"),
77            },
78            _ => panic!("Invalid signal state"),
79        },
80        _ => panic!("Invalid signal"),
81    }
82}
83
84pub fn max_speed_select(curr: &MaxSpeed, field: MaxSpeedField) -> impl Scene {
85    let selected_signal = MaxSpeed::iter().enumerate().find_map(|(i, v)| {
86        if v == *curr {
87            return Some(i);
88        }
89
90        None
91    });
92
93    bsn! {
94        @FeathersSelect {
95            @options: list_rows_from_strings(MaxSpeed::iter().map(|s| u32::from(s).to_string()), selected_signal),
96        }
97        field
98        on(on_value_change)
99    }
100}
101
102fn on_value_change_toggle(
103    e: On<ValueChange<bool>>,
104    mut cmd: Commands,
105    target: Query<(Entity, &Target), With<SignalListItem>>,
106    children: Query<&ChildOf>,
107    max_speed_field: Query<&MaxSpeedField>,
108    mut signals: Query<&mut Signals>,
109) {
110    update_checkbox_visual(e.value, e.event_target(), &mut cmd);
111
112    let Some((_, target_signal)) = find_root_with_target(e.event_target(), &target, &children)
113    else {
114        tracing::error!(
115            "Could not find parent UI entity with a target component pointing to a signal!"
116        );
117        return;
118    };
119
120    let Ok(max_speed_field) = max_speed_field.get(e.event_target()) else {
121        tracing::warn!("Max speed toggle doesn't have field set, add a MaxSpeedField component!");
122        return;
123    };
124
125    let Ok(mut signal) = signals.get_mut(target_signal) else {
126        return;
127    };
128
129    match &mut *signal {
130        Signals::Main(main_signal) => match &mut main_signal.state {
131            MainSignalState::Warning {
132                max_speed,
133                next_speed,
134            } => match max_speed_field {
135                MaxSpeedField::MaxSpeed => {
136                    *max_speed = if e.value {
137                        Some(Default::default())
138                    } else {
139                        None
140                    }
141                }
142                MaxSpeedField::NextSpeed => {
143                    *next_speed = if e.value {
144                        Some(Default::default())
145                    } else {
146                        None
147                    }
148                }
149            },
150            MainSignalState::Free { max_speed } => match max_speed_field {
151                MaxSpeedField::MaxSpeed => {
152                    *max_speed = if e.value {
153                        Some(Default::default())
154                    } else {
155                        None
156                    }
157                }
158                _ => panic!("Invalid max speed field"),
159            },
160            _ => panic!("Invalid signal state"),
161        },
162        _ => panic!("Invalid signal"),
163    }
164}
165
166pub fn max_speed_toggle(is_present: bool, field: MaxSpeedField) -> impl Scene {
167    bsn! {
168        @FeathersCheckbox
169        @is_checkbox_checked(is_present)
170        field
171        on(on_value_change_toggle)
172    }
173}