paiagram/interface/tabs/
vehicle_overview.rs1use crate::interface::{AppTab, UiCommand};
2use crate::vehicles::*;
3use bevy::prelude::*;
4use bevy_egui::egui;
5use egui_deferred_table::{
6 Action, AxisParameters, CellIndex, DeferredTable, DeferredTableDataSource,
7 DeferredTableRenderer, TableDimensions,
8};
9
10struct VehicleOverviewRow {
11 vehicle: Entity,
12 name: String,
13 entry_count: usize,
14 service_count: usize,
15}
16
17struct VehicleOverviewDataSource {
18 rows: Vec<VehicleOverviewRow>,
19}
20
21impl VehicleOverviewDataSource {
22 fn new(rows: Vec<VehicleOverviewRow>) -> Self {
23 Self { rows }
24 }
25
26 fn row(&self, index: usize) -> Option<&VehicleOverviewRow> {
27 self.rows.get(index)
28 }
29}
30
31impl DeferredTableDataSource for VehicleOverviewDataSource {
32 fn get_dimensions(&self) -> TableDimensions {
33 TableDimensions {
34 row_count: self.rows.len(),
35 column_count: 2,
36 }
37 }
38}
39
40struct VehicleOverviewRenderer;
41
42impl DeferredTableRenderer<VehicleOverviewDataSource> for VehicleOverviewRenderer {
43 fn render_cell(
44 &self,
45 ui: &mut bevy_egui::egui::Ui,
46 cell_index: CellIndex,
47 source: &VehicleOverviewDataSource,
48 ) {
49 let Some(row) = source.row(cell_index.row) else {
50 return;
51 };
52
53 match cell_index.column {
54 0 => {
55 ui.label(format!("{}", row.entry_count));
56 }
57 1 => {
58 ui.label(format!("{}", row.service_count));
59 }
60 _ => {}
61 }
62 }
63}
64
65pub fn show_vehicle_overview(
66 InMut(ui): InMut<egui::Ui>,
67 vehicles: Query<(Entity, &Name, &crate::vehicles::Schedule, &Children), With<Vehicle>>,
68 services: Query<&Service>,
69 mut msg_ui: MessageWriter<UiCommand>,
70 displayed_lines: Query<(Entity, &Name), With<crate::lines::DisplayedLine>>,
71) {
72 for line in displayed_lines.iter() {
73 let (entity, name) = line;
74 if ui.button(format!("{}", name)).clicked() {
75 msg_ui.write(UiCommand::OpenOrFocusVehicleTab(AppTab::LineTimetable(
76 entity,
77 )));
78 }
79 }
80
81 let rows: Vec<VehicleOverviewRow> = vehicles
82 .iter()
83 .map(|(entity, name, schedule, children)| VehicleOverviewRow {
84 vehicle: entity,
85 name: name.as_str().to_owned(),
86 entry_count: schedule.1.len(),
87 service_count: {
88 let mut count = 0;
89 for child in children.iter() {
90 if let Ok(_service) = services.get(child) {
91 count += 1;
92 }
93 }
94 count
95 },
96 })
97 .collect();
98
99 if rows.is_empty() {
100 ui.label("No vehicles found.");
101 return;
102 }
103
104 let row_parameters: Vec<AxisParameters> = rows
105 .iter()
106 .map(|row| {
107 AxisParameters::default()
108 .name(row.name.clone())
109 .default_dimension(14.0)
110 .monospace(true)
111 })
112 .collect();
113
114 let mut data_source = VehicleOverviewDataSource::new(rows);
115
116 let column_parameters = vec![
117 AxisParameters::default()
118 .name("Entries")
119 .default_dimension(80.0)
120 .resizable(false)
121 .monospace(true),
122 AxisParameters::default()
123 .name("Services")
124 .default_dimension(80.0)
125 .resizable(false)
126 .monospace(true),
127 ];
128
129 let mut table = DeferredTable::new(ui.id().with("vehicle_overview"))
130 .default_cell_size(egui::vec2(160.0, 14.0))
131 .highlight_hovered_cell();
132
133 table = table.column_parameters(&column_parameters);
134
135 if !row_parameters.is_empty() {
136 table = table.row_parameters(&row_parameters);
137 }
138
139 let mut renderer = VehicleOverviewRenderer;
140 let (_response, actions) = table.show(ui, &mut data_source, &mut renderer);
141
142 for action in actions {
143 if let Action::CellClicked(cell_index) = action {
144 if let Some(row) = data_source.row(cell_index.row) {
145 msg_ui.write(UiCommand::OpenOrFocusVehicleTab(AppTab::Vehicle(
146 row.vehicle,
147 )));
148 }
149 }
150 }
151}