Skip to main content

traaains/ui/train/
mod.rs

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}