Skip to content
Snippets Groups Projects
s3_complexity.rs 4.26 KiB
Newer Older
Finn Bear's avatar
Finn Bear committed
use crate::egui::{Context, Ui, Window};
Finn Bear's avatar
Finn Bear committed
use crate::Slide;
use eframe::egui::text_edit::{CCursorRange, TextEditState};
use eframe::egui::{Align2, Frame, TextEdit, Vec2, Widget};
Finn Bear's avatar
Finn Bear committed
use eframe::epaint::text::cursor::CCursor;
Finn Bear's avatar
Finn Bear committed

Finn Bear's avatar
Finn Bear committed
/// Introduction for emergent complexity.
Finn Bear's avatar
Finn Bear committed
#[derive(Default)]
Finn Bear's avatar
Finn Bear committed
pub struct Complexity {
    state: ComplexityState,
    last_time: f64,
}

Finn Bear's avatar
Finn Bear committed
/// What state we are in, with respect to the action of selecting "Complex" and replacing it
/// with "Simple."
Finn Bear's avatar
Finn Bear committed
#[derive(Default, Eq, PartialEq, Debug)]
enum ComplexityState {
Finn Bear's avatar
Finn Bear committed
    /// Haven't started the transition yet.
Finn Bear's avatar
Finn Bear committed
    #[default]
    Before,
Finn Bear's avatar
Finn Bear committed
    /// Selected this many characters of "Complex."
Finn Bear's avatar
Finn Bear committed
    Selecting(usize),
Finn Bear's avatar
Finn Bear committed
    /// Typed this many characters of "Simple."
Finn Bear's avatar
Finn Bear committed
    Typing(usize),
Finn Bear's avatar
Finn Bear committed
    /// Animation over.
Finn Bear's avatar
Finn Bear committed
    After,
}
Finn Bear's avatar
Finn Bear committed

impl Slide for Complexity {
Finn Bear's avatar
Finn Bear committed
    fn transition(&mut self, _ctx: &Context) -> bool {
Finn Bear's avatar
Finn Bear committed
        if self.state == ComplexityState::Before {
Finn Bear's avatar
Finn Bear committed
            // If we haven't started the animation, start it.
Finn Bear's avatar
Finn Bear committed
            self.state = ComplexityState::Selecting(0);
            false
        } else {
Finn Bear's avatar
Finn Bear committed
            // Otherwise, continue to next slide.
Finn Bear's avatar
Finn Bear committed
            true
        }
    }

    fn show(&mut self, ui: &mut Ui) {
Finn Bear's avatar
Finn Bear committed
        Window::new("complexity")
            .title_bar(false)
            .resizable(false)
Finn Bear's avatar
Finn Bear committed
            // Don't show window background.
Finn Bear's avatar
Finn Bear committed
            .frame(Frame::none())
            .anchor(Align2::CENTER_CENTER, Vec2::ZERO)
Finn Bear's avatar
Finn Bear committed
            // Width was determined anecdotally. Height is arbitrary.
Finn Bear's avatar
Finn Bear committed
            .fixed_size(Vec2::new(440.0, 100.0))
            .show(ui.ctx(), |ui| {
Finn Bear's avatar
Finn Bear committed
                ui.ctx().request_repaint();
Finn Bear's avatar
Finn Bear committed

                // TODO(finnb) replace with [`Governor`].
Finn Bear's avatar
Finn Bear committed
                let time = ui.input().time;
                let time_delta = (time - self.last_time).min(1.0);
                let made_progress = time_delta > 0.1;
                if made_progress {
                    self.last_time = time;
                }

Finn Bear's avatar
Finn Bear committed
                ui.vertical_centered_justified(|ui| {
                    let mut state = TextEditState::default();
Finn Bear's avatar
Finn Bear committed
                    let text;
                    match &mut self.state {
                        ComplexityState::Before => {
                            text = String::from("Complex Rules ➡ Complex Results?");
                        }
                        ComplexityState::Selecting(progress) => {
                            text = String::from("Complex Rules ➡ Complex Results?");
                            state.set_ccursor_range(Some(CCursorRange::two(
                                CCursor::new(0),
                                CCursor::new(*progress),
                            )));
                            if made_progress {
                                if *progress == "Complex".len() {
                                    self.state = ComplexityState::Typing(0);
                                } else {
                                    *progress += 1;
                                }
                            }
                        }
                        ComplexityState::Typing(progress) => {
                            text = format!(" {} Rules ➡ Complex Results?", &"Simple"[0..*progress]);
                            if made_progress {
                                if *progress == "Simple".len() {
                                    self.state = ComplexityState::After;
                                } else {
                                    *progress += 1;
                                }
                            }
                        }
                        ComplexityState::After => {
                            text = String::from(" Simple Rules ➡ Complex Results!");
                        }
                    }

                    let text_edit = TextEdit::singleline(&mut text.as_str())
                        .desired_width(f32::INFINITY)
                        .ui(ui);
Finn Bear's avatar
Finn Bear committed
                    if state.ccursor_range().is_some() {
Finn Bear's avatar
Finn Bear committed
                        // Necessary to render selecting.
Finn Bear's avatar
Finn Bear committed
                        text_edit.request_focus();
                    } else {
Finn Bear's avatar
Finn Bear committed
                        // We're done selecting.
Finn Bear's avatar
Finn Bear committed
                        text_edit.surrender_focus();
                    }
                    TextEdit::store_state(ui.ctx(), text_edit.id, state);
Finn Bear's avatar
Finn Bear committed
                });
            });
    }
}