gled-ui 2.32.1

gled's egui interface, shared by the desktop app and the browser
Documentation
use super::{App, controller_feedback};
use crate::ui::{asset_tree::TreeSelection, gled_slider::GledSlider};
use egui::{Color32, Id, Rect, Sense, Ui, Vec2, pos2};
use gled_protocol::state::TouchedControl;

impl App {
    pub(crate) fn palette_asset_tree_id(&mut self, ui: &mut Ui) -> Id {
        *self
            .palette_asset_tree_id
            .get_or_insert_with(|| ui.make_persistent_id("preview palette tree"))
    }

    #[cfg_attr(feature = "profiling", profiling::function)]
    pub(crate) fn preview(&mut self, ui: &mut egui::Ui) {
        let palette_asset_tree_id = self.palette_asset_tree_id(ui);

        let height = ui.available_height();
        ui.horizontal(|ui| {
            let size = Vec2::splat(height.min(ui.available_width()));

            // the rig's background (an old project's installation drawing)
            // behind the LEDs, which leave it showing wherever they are not
            let background = self
                .project
                .as_ref()
                .and_then(|project| project.patch.topology.default_layout.background.as_deref())
                .and_then(|path| self.preview_background.texture(ui.ctx(), path));
            let (rect, _) = ui.allocate_exact_size(size, Sense::hover());
            let painter = ui.painter();
            let whole = Rect::from_min_max(pos2(0.0, 0.0), pos2(1.0, 1.0));
            painter.rect_filled(rect, 0.0, Color32::BLACK);
            if let Some(background) = background {
                painter.image(background.id(), rect, whole, Color32::WHITE);
            }
            painter.image(self.ui_preview.texture_id.0, rect, whole, Color32::WHITE);
            // outline the viewport, so the extent of the rig preview is
            // visible even when most of it is unlit
            painter.rect_stroke(
                rect,
                0.0,
                egui::Stroke::new(1.0, Color32::from_gray(70)),
                egui::StrokeKind::Inside,
            );

            if let Some(project) = &mut self.project {
                ui.add_space(ui.available_width() - (300.0 + 16.0 + 40.0 + 16.0));
                ui.scope(|ui| {
                    ui.set_max_width(300.0);
                    if self.palette_asset_tree.show(
                        ui,
                        palette_asset_tree_id,
                        &mut self.model.replica.assets,
                    ) && let TreeSelection::Asset(palette) = self.palette_asset_tree.selected()
                    {
                        project.palette = Some(palette.data.clone());
                    }

                    //TODO: Show and make project palette editable
                });

                let mut rect = ui.available_rect_before_wrap();
                *rect.top_mut() += 16.0;
                *rect.left_mut() = rect.right() - 56.0;
                *rect.bottom_mut() -= 16.0;

                let preview_value = if self.blackout {
                    0.0
                } else {
                    project.main_dimmer
                };
                let response = ui.put(
                    rect,
                    GledSlider::new(&mut project.main_dimmer, 100.0)
                        .size(40.0)
                        .show_label()
                        .preview_value(preview_value),
                );
                if controller_feedback::is_touched(ui.ctx(), &TouchedControl::MainDimmer) {
                    controller_feedback::outline_touched(ui, response.rect);
                }
            }
        });
    }
}