gardesk/garshot / 88c3588

Browse files

annotate: add highlight marker tool

Authored by mfwolffe <wolffemf@dukes.jmu.edu>
SHA
88c3588b39ac4148300a01647864bfe04ebe58b4
Parents
7a50daa
Tree
4573ad4

1 changed file

StatusFile+-
A garshot/src/annotate/tools/highlight.rs 107 0
garshot/src/annotate/tools/highlight.rsadded
@@ -0,0 +1,107 @@
1
+//! Highlight tool - semi-transparent marker.
2
+
3
+use super::Tool;
4
+use crate::annotate::state::ToolProperties;
5
+use gartk_core::{Color, InputEvent, MouseButton, Point};
6
+use gartk_render::cairo::Context;
7
+use gartk_render::set_color;
8
+use gartk_x11::CursorShape;
9
+
10
+/// Highlight marker tool - like a highlighter pen.
11
+pub struct HighlightTool {
12
+    /// Points in the current stroke.
13
+    points: Vec<Point>,
14
+    /// Whether we're currently drawing.
15
+    drawing: bool,
16
+}
17
+
18
+impl HighlightTool {
19
+    /// Create a new highlight tool.
20
+    pub fn new() -> Self {
21
+        Self {
22
+            points: Vec::new(),
23
+            drawing: false,
24
+        }
25
+    }
26
+
27
+    /// Draw the highlight stroke.
28
+    fn draw_stroke(&self, ctx: &Context, props: &ToolProperties) {
29
+        if self.points.len() < 2 {
30
+            return;
31
+        }
32
+
33
+        // Make color semi-transparent for highlight effect
34
+        let highlight_color = Color::new(props.color.r, props.color.g, props.color.b, 0.4);
35
+
36
+        // Use thicker line for highlight
37
+        let highlight_width = props.line_width * 4.0;
38
+
39
+        set_color(ctx, highlight_color);
40
+        ctx.set_line_width(highlight_width);
41
+        ctx.set_line_cap(cairo::LineCap::Round);
42
+        ctx.set_line_join(cairo::LineJoin::Round);
43
+
44
+        ctx.new_path();
45
+        ctx.move_to(self.points[0].x as f64, self.points[0].y as f64);
46
+
47
+        for point in &self.points[1..] {
48
+            ctx.line_to(point.x as f64, point.y as f64);
49
+        }
50
+
51
+        let _ = ctx.stroke();
52
+    }
53
+}
54
+
55
+impl Default for HighlightTool {
56
+    fn default() -> Self {
57
+        Self::new()
58
+    }
59
+}
60
+
61
+impl Tool for HighlightTool {
62
+    fn handle_event(&mut self, event: &InputEvent, _props: &ToolProperties) -> bool {
63
+        match event {
64
+            InputEvent::MousePress(e) if e.button == Some(MouseButton::Left) => {
65
+                self.points.clear();
66
+                self.points.push(e.position);
67
+                self.drawing = true;
68
+                true
69
+            }
70
+            InputEvent::MouseMove(e) if self.drawing => {
71
+                self.points.push(e.position);
72
+                true
73
+            }
74
+            InputEvent::MouseRelease(e) if e.button == Some(MouseButton::Left) && self.drawing => {
75
+                self.points.push(e.position);
76
+                self.drawing = false;
77
+                true
78
+            }
79
+            _ => false,
80
+        }
81
+    }
82
+
83
+    fn draw_preview(&self, ctx: &Context, props: &ToolProperties) {
84
+        self.draw_stroke(ctx, props);
85
+    }
86
+
87
+    fn commit(&self, ctx: &Context, props: &ToolProperties) {
88
+        self.draw_stroke(ctx, props);
89
+    }
90
+
91
+    fn reset(&mut self) {
92
+        self.points.clear();
93
+        self.drawing = false;
94
+    }
95
+
96
+    fn cursor(&self) -> CursorShape {
97
+        CursorShape::Crosshair
98
+    }
99
+
100
+    fn is_drawing(&self) -> bool {
101
+        self.drawing
102
+    }
103
+
104
+    fn can_commit(&self) -> bool {
105
+        self.points.len() >= 2
106
+    }
107
+}