Skip to content

Commit

Permalink
feat: draft freehand highlighter
Browse files Browse the repository at this point in the history
  • Loading branch information
DerpDays committed Apr 25, 2024
1 parent 8755f86 commit a34772b
Show file tree
Hide file tree
Showing 2 changed files with 85 additions and 16 deletions.
9 changes: 5 additions & 4 deletions src/style.rs
Original file line number Diff line number Diff line change
Expand Up @@ -205,11 +205,12 @@ impl Size {
}
}

pub fn to_highlight_opacity(self) -> u8 {
pub fn to_highlight_width(self) -> f32 {
let size_factor = APP_CONFIG.read().annotation_size_factor();
match self {
Size::Small => 50,
Size::Medium => 100,
Size::Large => 150,
Size::Small => 15.0 * size_factor,
Size::Medium => 30.0 * size_factor,
Size::Large => 45.0 * size_factor,
}
}
}
92 changes: 80 additions & 12 deletions src/tools/highlight.rs
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
use anyhow::Result;
use femtovg::{Paint, Path};

use relm4::gtk::gdk::Key;
use relm4::gtk::gdk::{Key, ModifierType};

use crate::{
math::{self, Vec2D},
Expand All @@ -17,14 +17,41 @@ pub struct Highlight {
size: Option<Vec2D>,
style: Style,
editing: bool,
points: Option<Vec<Vec2D>>,
shift_pressed: bool,
}

impl Drawable for Highlight {
fn draw(
impl Highlight {
// This is triggered when a user does not press shift before highlighting.
fn draw_free_hand(
&self,
canvas: &mut femtovg::Canvas<femtovg::renderer::OpenGl>,
_font: femtovg::FontId,
) -> Result<()> {
canvas.save();
let mut path = Path::new();
if let Some(points) = &self.points {
let first = points.first().expect("atleast one point");
path.move_to(first.x, first.y);
for p in points.iter().skip(1) {
path.line_to(first.x + p.x, first.y + p.y);
}

let mut paint = Paint::color(femtovg::Color::rgba(
self.style.color.r,
self.style.color.g,
self.style.color.b,
(255.0 * 0.4) as u8,
));
paint.set_line_width(self.style.size.to_highlight_width());

canvas.stroke_path(&path, &paint);
}
canvas.restore();
Ok(())
}

/// This is triggered when the user presses shift *before* highlighting.
fn draw_aligned(&self, canvas: &mut femtovg::Canvas<femtovg::renderer::OpenGl>) -> Result<()> {
let size = match self.size {
Some(s) => s,
None => return Ok(()), // early exit if size is none
Expand All @@ -48,14 +75,29 @@ impl Drawable for Highlight {
self.style.color.r,
self.style.color.g,
self.style.color.b,
self.style.size.to_highlight_opacity(),
(255.0 * 0.4) as u8,
));

canvas.fill_path(&shadow_path, &shadow_paint);
Ok(())
}
}

impl Drawable for Highlight {
fn draw(
&self,
canvas: &mut femtovg::Canvas<femtovg::renderer::OpenGl>,
_font: femtovg::FontId,
) -> Result<()> {
if self.points.is_some() {
self.draw_free_hand(canvas)?;
} else {
self.draw_aligned(canvas)?;
}
Ok(())
}
}

#[derive(Default)]
pub struct HighlightTool {
highlight: Option<Highlight>,
Expand All @@ -64,28 +106,45 @@ pub struct HighlightTool {

impl Tool for HighlightTool {
fn handle_mouse_event(&mut self, event: MouseEventMsg) -> ToolUpdateResult {
let shift_pressed = event.modifier.intersects(ModifierType::SHIFT_MASK);
let ctrl_pressed = event.modifier.intersects(ModifierType::CONTROL_MASK);
match event.type_ {
MouseEventType::BeginDrag => {
self.highlight = Some(Highlight {
top_left: event.pos,
size: None,
style: self.style,
editing: true,
points: if !ctrl_pressed {
Some(vec![event.pos])
} else {
None
},
shift_pressed,
});

ToolUpdateResult::Redraw
}
MouseEventType::EndDrag => {
if let Some(a) = &mut self.highlight {
if let Some(highlight) = &mut self.highlight {
if event.pos == Vec2D::zero() {
self.highlight = None;

ToolUpdateResult::Redraw
} else {
a.size = Some(event.pos);
a.editing = false;

let result = a.clone_box();
if let Some(points) = &mut highlight.points {
if shift_pressed {
let last = points.last().expect("should have atleast one point");
points.push(Vec2D::new(event.pos.x, last.y));
} else {
points.push(event.pos);
}
}

highlight.shift_pressed = shift_pressed;
highlight.editing = false;

let result = highlight.clone_box();
self.highlight = None;

ToolUpdateResult::Commit(result)
Expand All @@ -95,11 +154,20 @@ impl Tool for HighlightTool {
}
}
MouseEventType::UpdateDrag => {
if let Some(a) = &mut self.highlight {
if let Some(highlight) = &mut self.highlight {
if event.pos == Vec2D::zero() {
return ToolUpdateResult::Unmodified;
}
a.size = Some(event.pos);
if let Some(points) = &mut highlight.points {
if shift_pressed {
let last = points.last().expect("should have atleast one point");
points.push(Vec2D::new(event.pos.x, last.y));
} else {
points.push(event.pos);
}
}
highlight.size = Some(event.pos);
highlight.shift_pressed = shift_pressed;

ToolUpdateResult::Redraw
} else {
Expand Down

0 comments on commit a34772b

Please sign in to comment.