gantz_egui 0.2.0

UI traits and widgets that make up the GUI for gantz, an environment for creative systems.
Documentation
//! A widget for configuring per-head graph layout settings and renaming.

use super::gantz::OpenHeadState;
use super::head_name_edit::{head_name, head_name_edit};

/// Per-head graph configuration widget.
///
/// Provides a name-editing text field and layout settings
/// (`auto_layout`, `layout_flow`, `center_view`).
pub struct GraphConfig<'a> {
    head: &'a gantz_ca::Head,
    head_state: &'a mut OpenHeadState,
    names: &'a gantz_ca::registry::Names,
    is_base: bool,
    immutable: bool,
}

/// Response from the [`GraphConfig`] widget.
pub struct GraphConfigResponse {
    /// A new branch name was committed via the name editor.
    pub new_branch: Option<(gantz_ca::Head, String)>,
    /// The "Export" button was clicked.
    pub export: bool,
}

impl<'a> GraphConfig<'a> {
    pub fn new(
        head: &'a gantz_ca::Head,
        head_state: &'a mut OpenHeadState,
        names: &'a gantz_ca::registry::Names,
    ) -> Self {
        Self {
            head,
            head_state,
            names,
            is_base: false,
            immutable: false,
        }
    }

    /// Whether this graph is a base node - a pre-composed graph that ships
    /// with the binary and is reset to its original form on every launch.
    /// Users who want to customize a base node should duplicate it under a
    /// new name.
    pub fn is_base(mut self, is_base: bool) -> Self {
        self.is_base = is_base;
        self
    }

    /// Whether this graph is immutable - layout controls will be disabled.
    pub fn immutable(mut self, immutable: bool) -> Self {
        self.immutable = immutable;
        self
    }

    pub fn show(self, ui: &mut egui::Ui) -> GraphConfigResponse {
        // Name editing TextEdit with per-head temp state.
        let edit_id = egui::Id::new("graph_config_name_edit").with(self.head);
        let mut name = ui
            .memory_mut(|m| m.data.get_temp::<String>(edit_id))
            .unwrap_or_else(|| head_name(self.head));
        let name_res = head_name_edit(self.head, &mut name, self.names, ui);
        ui.memory_mut(|m| m.data.insert_temp(edit_id, name));
        let new_branch = name_res.new_branch;

        if self.is_base {
            ui.label(
                egui::RichText::new("\"base\" node, included with gantz")
                    .italics()
                    .weak(),
            );
        }

        // Layout config.
        ui.checkbox(&mut self.head_state.center_view, "Center View");
        ui.add_enabled_ui(!self.immutable, |ui| {
            ui.horizontal(|ui| {
                ui.checkbox(&mut self.head_state.auto_layout, "Automatic Layout");
            });
            ui.horizontal(|ui| {
                ui.label("Flow:");
                ui.radio_value(
                    &mut self.head_state.layout_flow,
                    egui::Direction::LeftToRight,
                    "Right",
                );
                ui.radio_value(
                    &mut self.head_state.layout_flow,
                    egui::Direction::TopDown,
                    "Down",
                );
            });
        });

        let export = ui.button("Export").clicked();
        GraphConfigResponse { new_branch, export }
    }
}