1use bevy::{
2 ecs::{
3 entity::Entity,
4 hierarchy::Children,
5 observer::On,
6 system::{Commands, ResMut},
7 },
8 feathers::{
9 constants::icons,
10 containers::{flex_spacer, group, group_body, group_header, pane, pane_body, pane_header},
11 controls::{ButtonVariant, FeathersButton, FeathersToolButton},
12 display::{icon, label},
13 theme::ThemedText,
14 },
15 picking::events::{PointerEnter, PointerLeave},
16 scene::{CommandsSceneExt, Scene, bsn, on},
17 state::{state::NextState, state_scoped::DespawnOnExit},
18 ui::{
19 Display::{self},
20 FlexDirection, Node, PositionType, percent, px,
21 widget::Text,
22 },
23 ui_widgets::Activate,
24};
25
26use crate::{
27 editor::train::placing::CurrentPlacingTrain,
28 ui::{EditingWindow, IsHoveringUi, UiState, train::adding_train::adding_train_window},
29};
30
31pub mod adding_train;
32pub mod train_window;
33
34fn train_item(idx: usize, train_entity: Entity) -> impl Scene {
35 bsn! {
36 @group() Children [
37 @group_header() Children [ Text(format!("Train #{}", idx + 1)) ThemedText ]
38 --
39 @group_body() Children [
40 @label(format!("{}", train_entity))
41 ]
42 ]
43 }
44}
45
46pub fn trains_window(trains: impl Iterator<Item = Entity>) -> impl Scene {
47 let trains_list_items: Vec<_> = trains.enumerate().map(|(i, e)| train_item(i, e)).collect();
48
49 bsn! {
50 @pane() Children [
51 @pane_header() Children [
52 Text("Trains") ThemedText
53 --
54 @flex_spacer()
55 --
56 @FeathersToolButton {
57 @variant: ButtonVariant::Plain,
58 }
59 Children [
60 @icon(icons::X)
61 ]
62 on(|_: On<Activate>, mut next_state: ResMut<NextState<UiState>>| {
63 next_state.set(UiState::Default);
64 })
65 ]
66 --
67 @pane_body()
68 Children [
69 @FeathersButton {
70 @caption: bsn! { Text("Add train") ThemedText }
71 }
72 on(|_: On<Activate>, mut cmd: Commands, mut next_state: ResMut<NextState<UiState>>| {
73 let curr_train = CurrentPlacingTrain::default();
74 cmd.spawn_scene(adding_train_window(&curr_train));
75 cmd.insert_resource(curr_train);
76 next_state.set(UiState::AddingTrain);
77 })
78 --
79 {trains_list_items}
80 ]
81 ]
82 }
83}
84
85pub fn trains_overlay(trains: impl Iterator<Item = Entity>) -> impl Scene {
86 bsn! {
87 EditingWindow
88 Node {
89 position_type: PositionType::Absolute,
90 top: px(16),
91 left: px(16),
92 display: Display::Flex,
93 flex_direction: FlexDirection::Row,
94 width: percent(30),
95 min_width: px(200),
96 max_height: percent(80)
97 }
98 DespawnOnExit<UiState>(UiState::TrainsOverlay)
99 Children [
100 @trains_window(trains)
101 ]
102 on(|_: On<PointerEnter>, mut next_state: ResMut<NextState<IsHoveringUi>>| {
103 next_state.set(IsHoveringUi(true));
104 })
105 on(|_: On<PointerLeave>, mut next_state: ResMut<NextState<IsHoveringUi>>| {
106 next_state.set(IsHoveringUi(false));
107 })
108 }
109}