From 51c5f2f8c7afe7ebd1c0d18ab6ab64bc21c2a63a Mon Sep 17 00:00:00 2001
From: Finn Bear <finnbearlabs@gmail.com>
Date: Thu, 28 Apr 2022 21:25:05 -0700
Subject: [PATCH] Integrate text into arrow.

---
 src/component/arrow.rs   | 50 +++++++++++++++++++++++++++++++++++-----
 src/main.rs              |  1 +
 src/slide/s4_automata.rs | 24 ++++++-------------
 3 files changed, 52 insertions(+), 23 deletions(-)

diff --git a/src/component/arrow.rs b/src/component/arrow.rs
index 660903d..ab9df92 100644
--- a/src/component/arrow.rs
+++ b/src/component/arrow.rs
@@ -1,12 +1,29 @@
-use crate::egui::{Pos2, Stroke, Ui};
-use eframe::egui::Shape;
+use crate::egui::{Align2, Pos2, Stroke, Ui};
+use eframe::egui::{Color32, FontFamily, FontId, Shape};
 use eframe::emath::Rot2;
+use std::cmp::Ordering;
 
 /// Pointy line used to emphasize something.
 pub struct Arrow {
     pub origin: Pos2,
     pub tip: Pos2,
-    pub stroke: Stroke,
+    pub stroke: Color32,
+    pub stroke_width: f32,
+    pub label: String,
+    pub font_size: f32,
+}
+
+impl Default for Arrow {
+    fn default() -> Self {
+        Self {
+            origin: Pos2::ZERO,
+            tip: Pos2::new(1.0, 1.0),
+            stroke: Color32::BLACK,
+            stroke_width: 6.0,
+            label: String::new(),
+            font_size: 40.0,
+        }
+    }
 }
 
 impl Arrow {
@@ -14,18 +31,39 @@ impl Arrow {
         // Based on: https://docs.rs/egui/latest/src/egui/widgets/plot/items/mod.rs.html#977-985
         let vector = self.tip - self.origin;
         let rot = Rot2::from_angle(std::f32::consts::TAU / 10.0);
-        let tip_length = self.stroke.width * 4.0;
+        let tip_length = self.stroke_width * 4.0;
         let tip = self.origin + vector;
         let dir = vector.normalized();
+        let stroke = Stroke::new(self.stroke_width, self.stroke);
         ui.painter()
-            .add(Shape::line_segment([self.origin, self.tip], self.stroke));
+            .add(Shape::line_segment([self.origin, self.tip], stroke));
         ui.painter().add(Shape::line(
             vec![
                 tip - tip_length * (rot.inverse() * dir),
                 tip,
                 tip - tip_length * (rot * dir),
             ],
-            self.stroke,
+            stroke,
         ));
+        if !self.label.is_empty() {
+            let align = match (vector.x.total_cmp(&0.0), vector.y.total_cmp(&0.0)) {
+                (Ordering::Less, Ordering::Less) => Align2::LEFT_TOP,
+                (Ordering::Less, Ordering::Equal) => Align2::LEFT_CENTER,
+                (Ordering::Less, Ordering::Greater) => Align2::LEFT_BOTTOM,
+                (Ordering::Equal, Ordering::Less) => Align2::CENTER_TOP,
+                (Ordering::Equal, Ordering::Equal) => Align2::CENTER_CENTER,
+                (Ordering::Equal, Ordering::Greater) => Align2::CENTER_BOTTOM,
+                (Ordering::Greater, Ordering::Less) => Align2::RIGHT_TOP,
+                (Ordering::Greater, Ordering::Equal) => Align2::RIGHT_CENTER,
+                (Ordering::Greater, Ordering::Greater) => Align2::RIGHT_BOTTOM,
+            };
+            ui.painter().text(
+                self.origin,
+                align,
+                self.label.as_str(),
+                FontId::new(self.font_size, FontFamily::Proportional),
+                self.stroke,
+            );
+        }
     }
 }
diff --git a/src/main.rs b/src/main.rs
index b74843f..1df8175 100644
--- a/src/main.rs
+++ b/src/main.rs
@@ -1,5 +1,6 @@
 #![feature(derive_default_enum)]
 #![feature(mixed_integer_ops)]
+#![feature(total_cmp)]
 
 pub mod cartoon;
 pub mod color;
diff --git a/src/slide/s4_automata.rs b/src/slide/s4_automata.rs
index 74b2570..637acd7 100644
--- a/src/slide/s4_automata.rs
+++ b/src/slide/s4_automata.rs
@@ -1,7 +1,7 @@
 use crate::color::set_alpha;
 use crate::component::arrow::Arrow;
 use crate::component::grid::Grid;
-use crate::egui::{Align2, Context, FontFamily, FontId, Stroke};
+use crate::egui::Context;
 use crate::fade_in::fade_in_manual;
 use crate::governor::Governor;
 use crate::slide::Slide;
@@ -133,16 +133,11 @@ impl Slide for Automata {
                         Arrow {
                             origin: to_screen * self.life.center(4, 2),
                             tip: to_screen * self.life.center(7, 7),
-                            stroke: Stroke::new(6.0, color),
+                            stroke: color,
+                            label: "Alive".into(),
+                            ..Arrow::default()
                         }
                         .show(ui);
-                        ui.painter().text(
-                            to_screen * self.life.center(4, 2),
-                            Align2::RIGHT_BOTTOM,
-                            "Alive",
-                            FontId::new(40.0, FontFamily::Proportional),
-                            color,
-                        );
                     });
                 }
                 if let Some(dead) = dead {
@@ -151,16 +146,11 @@ impl Slide for Automata {
                         Arrow {
                             origin: to_screen * self.life.center(11, 13),
                             tip: to_screen * self.life.center(10, 10),
-                            stroke: Stroke::new(6.0, color),
+                            stroke: color,
+                            label: "Dead".into(),
+                            ..Arrow::default()
                         }
                         .show(ui);
-                        ui.painter().text(
-                            to_screen * self.life.center(11, 13),
-                            Align2::LEFT_TOP,
-                            "Dead",
-                            FontId::new(40.0, FontFamily::Proportional),
-                            color,
-                        );
                     });
                 }
             }
-- 
GitLab