cloud_terrastodon_ui_egui 0.35.1

User interface for the Cloud Terrastodon project leveraging egui
use crate::app::MyApp;
use crate::windows::dir_window::ui_dir_windows;
use eframe::egui::MenuBar;
use eframe::egui::TopBottomPanel;
use eframe::egui::Window;
#[expect(unused)] // TODO(EGUI-TRACING)
use egui_toast::Toast;
#[expect(unused)] // TODO(EGUI-TRACING)
use egui_toast::ToastKind;
#[expect(unused)] // TODO(EGUI-TRACING)
use egui_toast::ToastOptions;
#[expect(unused)] // TODO(EGUI-TRACING)
use tracing::Level;
impl MyApp {
    pub fn draw_app(&mut self, ctx: &eframe::egui::Context) {
        let app = self;

        // Top menu bar with About and Logs
        TopBottomPanel::top("top_panel").show(ctx, |ui| {
            MenuBar::new().ui(ui, |ui| {
                // Logs toggle button
                if ui
                    .button(if app.logs_visible {
                        "Logs (on)"
                    } else {
                        "Logs"
                    })
                    .clicked()
                {
                    app.logs_visible = !app.logs_visible;
                }

                // About button
                if ui.button("About").clicked() {
                    app.about_open = !app.about_open;
                }

                // Right-align Quit (if desired) placeholder
                ui.with_layout(
                    eframe::egui::Layout::right_to_left(eframe::egui::Align::Center),
                    |ui| {
                        if ui.button("Quit").clicked() {
                            ctx.send_viewport_cmd(eframe::egui::ViewportCommand::Close);
                        }
                    },
                );
            });
        });

        // Draw existing windows as tiles in the central panel
        eframe::egui::CentralPanel::default().show(ctx, |ui| {
            // Compute app pointer first, then borrow the behavior.
            let app_ptr = app as *mut _;
            let behavior = &mut app.tiles_behavior;
            behavior.set_app(app_ptr);
            app.tiles.ui(behavior, ui);
            behavior.clear_app();

            // Handle pending behavior requests that must be done outside of the tree UI pass
            use egui_tiles::Tile;
            use egui_tiles::Container;

            // Add requested Home tabs
            let add_count = behavior.take_pending_new_home_tabs();
            if add_count > 0 {
                for _ in 0..add_count {
                    let new_pane = app.tiles.tiles.insert_pane(crate::tiles::Pane::Home);
                    if let Some(root) = app.tiles.root && let Some(Tile::Container(Container::Tabs(tabs))) = app.tiles.tiles.get_mut(root) {
                        tabs.add_child(new_pane);
                        tabs.set_active(new_pane);
                    }
                }
            }

            // Open a resources tab if requested
            if behavior.take_pending_open_resources_tab() {
                let new_pane = app.tiles.tiles.insert_pane(crate::tiles::Pane::Resources);
                if let Some(root) = app.tiles.root && let Some(Tile::Container(Container::Tabs(tabs))) = app.tiles.tiles.get_mut(root) {
                    tabs.add_child(new_pane);
                    tabs.set_active(new_pane);
                }
            }

            // Ensure there is at least one Home tab if requested
            if behavior.take_ensure_home_tab() {
                if app.tiles.root.is_none() {
                    let home = app.tiles.tiles.insert_pane(crate::tiles::Pane::Home);
                    let root = app.tiles.tiles.insert_tab_tile(vec![home]);
                    app.tiles.root = Some(root);
                } else if let Some(root) = app.tiles.root {
                    // Check empty using an immutable borrow first to avoid double mutable borrows.
                    let need_home = matches!(app.tiles.tiles.get(root), Some(Tile::Container(Container::Tabs(tabs))) if tabs.children.is_empty());
                    if need_home {
                        let new_child = app.tiles.tiles.insert_pane(crate::tiles::Pane::Home);
                        if let Some(Tile::Container(Container::Tabs(tabs_mut))) = app.tiles.tiles.get_mut(root) {
                            tabs_mut.add_child(new_child);
                            tabs_mut.set_active(new_child);
                        }
                    }
                }
            }
        });

        // Keep directory pop-out windows for now
        ui_dir_windows(app, ctx);

        // About window
        if app.about_open {
            Window::new("About")
                .resizable(false)
                .collapsible(false)
                .anchor(eframe::egui::Align2::CENTER_CENTER, [0.0, 0.0])
                .open(&mut app.about_open)
                .show(ctx, |ui| {
                    ui.vertical_centered(|ui| {
                        ui.heading("cloud_terrastodon_ui_egui");
                        ui.add_space(10.0);
                        ui.label(app.app_info.to_string());
                        ui.add_space(10.0);
                        ui.label("UI for the Cloud Terrastodon project.");
                        ui.add_space(10.0);
                        ui.hyperlink_to("GitHub", "https://github.com/TeamDman/cloud-terrastodon");
                    });
                });
        }

        // TODO(EGUI-TRACING)
        // Logs window (egui_tracing widget)
        // if app.logs_visible {
        //     Window::new("Logs")
        //         .default_size([800.0, 400.0])
        //         .open(&mut app.logs_visible)
        //         .show(ctx, |ui| {
        //             let collector = cloud_terrastodon_tracing::event_collector();
        //             ui.add(egui_tracing::Logs::new(collector));
        //         });
        // }

        // TODO(EGUI-TRACING)
        // Process new tracing events and create toasts for INFO and ERROR levels
        // let collector = cloud_terrastodon_tracing::event_collector();
        // let events = collector.events();
        // let new_events = &events[app.last_seen_event_count..];
        // for event in new_events {
        //     let kind = match event.level {
        //         Level::INFO => Some(ToastKind::Info),
        //         Level::ERROR => Some(ToastKind::Error),
        //         _ => None,
        //     };
        //     if let Some(kind) = kind {
        //         let message = event
        //             .fields
        //             .get("message")
        //             .map_or("", std::string::String::as_str)
        //             .to_string();
        //         app.toasts.add(
        //             Toast::default().kind(kind).text(message).options(
        //                 ToastOptions::default()
        //                     .duration_in_seconds(5.0)
        //                     .show_progress(true)
        //                     .show_icon(true),
        //             ),
        //         );
        //     }
        // }
        // app.last_seen_event_count = events.len();

        // Show toasts
        app.toasts.show(ctx);
    }
}