Skip to content

Commit

Permalink
Merge pull request #98 from jacekpoz/circle
Browse files Browse the repository at this point in the history
add ellipse tool
  • Loading branch information
gabm authored Jul 14, 2024
2 parents 39e1934 + 667b91c commit 5a7e0c1
Show file tree
Hide file tree
Showing 5 changed files with 161 additions and 10 deletions.
1 change: 1 addition & 0 deletions icons.toml
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@ icons = [
"text-font-regular",
"minus-large",
"checkbox-unchecked-regular",
"circle-regular",
"crop-filled",
"arrow-up-right-filled",
"rectangle-landscape-regular",
Expand Down
2 changes: 2 additions & 0 deletions src/command_line.rs
Original file line number Diff line number Diff line change
Expand Up @@ -65,6 +65,7 @@ pub enum Tools {
Line,
Arrow,
Rectangle,
Ellipse,
Text,
Marker,
Blur,
Expand All @@ -88,6 +89,7 @@ impl std::fmt::Display for Tools {
Line => "line",
Arrow => "arrow",
Rectangle => "rectangle",
Ellipse => "ellipse",
Text => "text",
Marker => "marker",
Blur => "blur",
Expand Down
131 changes: 131 additions & 0 deletions src/tools/ellipse.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,131 @@
use anyhow::Result;
use femtovg::{FontId, Path};
use relm4::gtk::gdk::{Key, ModifierType};

use crate::{
math::Vec2D,
sketch_board::{MouseEventMsg, MouseEventType},
style::Style,
};

use super::{Drawable, DrawableClone, Tool, ToolUpdateResult};

#[derive(Clone, Copy, Debug)]
pub struct Ellipse {
middle: Vec2D,
radii: Option<Vec2D>,
style: Style,
}

impl Drawable for Ellipse {
fn draw(
&self,
canvas: &mut femtovg::Canvas<femtovg::renderer::OpenGl>,
_font: FontId,
) -> Result<()> {
let radii = match self.radii {
Some(s) => s,
None => return Ok(()), // early exit if none
};

canvas.save();
let mut path = Path::new();
path.ellipse(self.middle.x, self.middle.y, radii.x, radii.y);

canvas.stroke_path(&path, &self.style.into());
canvas.restore();

Ok(())
}
}

#[derive(Default)]
pub struct EllipseTool {
ellipse: Option<Ellipse>,
style: Style,
}

impl Tool for EllipseTool {
fn handle_mouse_event(&mut self, event: MouseEventMsg) -> ToolUpdateResult {
let shift_pressed = event.modifier.intersects(ModifierType::SHIFT_MASK);
match event.type_ {
MouseEventType::BeginDrag => {
// start new
self.ellipse = Some(Ellipse {
middle: event.pos,
radii: None,
style: self.style,
});

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

ToolUpdateResult::Redraw
} else {
if shift_pressed {
let max_size = event.pos.x.abs().max(event.pos.y.abs());
ellipse.radii = Some(Vec2D {
x: max_size * event.pos.x.signum(),
y: max_size * event.pos.y.signum(),
});
} else {
ellipse.radii = Some(event.pos);
}
let result = ellipse.clone_box();
self.ellipse = None;

ToolUpdateResult::Commit(result)
}
} else {
ToolUpdateResult::Unmodified
}
}
MouseEventType::UpdateDrag => {
if let Some(ellipse) = &mut self.ellipse {
if event.pos == Vec2D::zero() {
return ToolUpdateResult::Unmodified;
}
if shift_pressed {
let max_size = event.pos.x.abs().max(event.pos.y.abs());
ellipse.radii = Some(Vec2D {
x: max_size * event.pos.x.signum(),
y: max_size * event.pos.y.signum(),
});
} else {
ellipse.radii = Some(event.pos);
}

ToolUpdateResult::Redraw
} else {
ToolUpdateResult::Unmodified
}
}
_ => ToolUpdateResult::Unmodified,
}
}

fn handle_key_event(&mut self, event: crate::sketch_board::KeyEventMsg) -> ToolUpdateResult {
if event.key == Key::Escape && self.ellipse.is_some() {
self.ellipse = None;
ToolUpdateResult::Redraw
} else {
ToolUpdateResult::Unmodified
}
}

fn handle_style_event(&mut self, style: Style) -> ToolUpdateResult {
self.style = style;
ToolUpdateResult::Unmodified
}

fn get_drawable(&self) -> Option<&dyn Drawable> {
match &self.ellipse {
Some(d) => Some(d),
None => None,
}
}
}
29 changes: 19 additions & 10 deletions src/tools/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@ mod arrow;
mod blur;
mod brush;
mod crop;
mod ellipse;
mod highlight;
mod line;
mod marker;
Expand Down Expand Up @@ -132,6 +133,7 @@ pub enum ToolUpdateResult {
pub use arrow::ArrowTool;
pub use blur::BlurTool;
pub use crop::CropTool;
pub use ellipse::EllipseTool;
pub use highlight::{HighlightTool, Highlighters};
pub use line::LineTool;
pub use rectangle::RectangleTool;
Expand All @@ -147,11 +149,12 @@ pub enum Tools {
Line = 2,
Arrow = 3,
Rectangle = 4,
Text = 5,
Marker = 6,
Blur = 7,
Highlight = 8,
Brush = 9,
Ellipse = 5,
Text = 6,
Marker = 7,
Blur = 8,
Highlight = 9,
Brush = 10,
}

pub struct ToolsManager {
Expand All @@ -173,6 +176,10 @@ impl ToolsManager {
Tools::Rectangle,
Rc::new(RefCell::new(RectangleTool::default())),
);
tools.insert(
Tools::Ellipse,
Rc::new(RefCell::new(EllipseTool::default())),
);
tools.insert(Tools::Text, Rc::new(RefCell::new(TextTool::default())));
tools.insert(Tools::Blur, Rc::new(RefCell::new(BlurTool::default())));
tools.insert(
Expand Down Expand Up @@ -224,11 +231,12 @@ impl FromVariant for Tools {
2 => Some(Tools::Line),
3 => Some(Tools::Arrow),
4 => Some(Tools::Rectangle),
5 => Some(Tools::Text),
6 => Some(Tools::Marker),
7 => Some(Tools::Blur),
8 => Some(Tools::Highlight),
9 => Some(Tools::Brush),
5 => Some(Tools::Ellipse),
6 => Some(Tools::Text),
7 => Some(Tools::Marker),
8 => Some(Tools::Blur),
9 => Some(Tools::Highlight),
10 => Some(Tools::Brush),
_ => None,
})
}
Expand All @@ -242,6 +250,7 @@ impl From<command_line::Tools> for Tools {
command_line::Tools::Line => Self::Line,
command_line::Tools::Arrow => Self::Arrow,
command_line::Tools::Rectangle => Self::Rectangle,
command_line::Tools::Ellipse => Self::Ellipse,
command_line::Tools::Text => Self::Text,
command_line::Tools::Marker => Self::Marker,
command_line::Tools::Blur => Self::Blur,
Expand Down
8 changes: 8 additions & 0 deletions src/ui/toolbars.rs
Original file line number Diff line number Diff line change
Expand Up @@ -149,6 +149,14 @@ impl SimpleComponent for ToolsToolbar {
set_focusable: false,
set_hexpand: false,

set_icon_name: "circle-regular",
set_tooltip: "Ellipse tool",
ActionablePlus::set_action::<ToolsAction>: Tools::Ellipse,
},
gtk::ToggleButton {
set_focusable: false,
set_hexpand: false,

set_icon_name: "text-case-title-regular",
set_tooltip: "Text tool",
ActionablePlus::set_action::<ToolsAction>: Tools::Text,
Expand Down

0 comments on commit 5a7e0c1

Please sign in to comment.