Skip to content
160 changes: 142 additions & 18 deletions editor/src/messages/portfolio/document/overlays/utility_types.rs
Original file line number Diff line number Diff line change
Expand Up @@ -294,6 +294,147 @@ impl OverlayContext {
self.end_dpi_aware_transform();
}

#[allow(clippy::too_many_arguments)]
pub fn dashed_ellipse(
&mut self,
center: DVec2,
radius_x: f64,
radius_y: f64,
rotation: Option<f64>,
start_angle: Option<f64>,
end_angle: Option<f64>,
counterclockwise: Option<bool>,
color_fill: Option<&str>,
color_stroke: Option<&str>,
dash_width: Option<f64>,
dash_gap_width: Option<f64>,
dash_offset: Option<f64>,
) {
let color_stroke = color_stroke.unwrap_or(COLOR_OVERLAY_BLUE);
let center = center.round();

self.start_dpi_aware_transform();

if let Some(dash_width) = dash_width {
let dash_gap_width = dash_gap_width.unwrap_or(1.);
let array = js_sys::Array::new();
array.push(&JsValue::from(dash_width));
array.push(&JsValue::from(dash_gap_width));

if let Some(dash_offset) = dash_offset {
if dash_offset != 0. {
self.render_context.set_line_dash_offset(dash_offset);
}
}

self.render_context
.set_line_dash(&JsValue::from(array))
.map_err(|error| log::warn!("Error drawing dashed line: {:?}", error))
.ok();
}

self.render_context.begin_path();
self.render_context
.ellipse_with_anticlockwise(
center.x,
center.y,
radius_x,
radius_y,
rotation.unwrap_or_default(),
start_angle.unwrap_or_default(),
end_angle.unwrap_or(TAU),
counterclockwise.unwrap_or_default(),
)
.expect("Failed to draw ellipse");
self.render_context.set_stroke_style_str(color_stroke);

if let Some(fill_color) = color_fill {
self.render_context.set_fill_style_str(fill_color);
self.render_context.fill();
}
self.render_context.stroke();

// Reset the dash pattern back to solid
if dash_width.is_some() {
self.render_context
.set_line_dash(&JsValue::from(js_sys::Array::new()))
.map_err(|error| log::warn!("Error drawing dashed line: {:?}", error))
.ok();
}
if dash_offset.is_some() && dash_offset != Some(0.) {
self.render_context.set_line_dash_offset(0.);
}

self.end_dpi_aware_transform();
}

pub fn dashed_circle(
&mut self,
position: DVec2,
radius: f64,
color_fill: Option<&str>,
color_stroke: Option<&str>,
dash_width: Option<f64>,
dash_gap_width: Option<f64>,
dash_offset: Option<f64>,
transform: Option<DAffine2>,
) {
let color_stroke = color_stroke.unwrap_or(COLOR_OVERLAY_BLUE);
let position = position.round();

self.start_dpi_aware_transform();

if let Some(transform) = transform {
let [a, b, c, d, e, f] = transform.to_cols_array();
self.render_context.transform(a, b, c, d, e, f).expect("Failed to transform circle");
}

if let Some(dash_width) = dash_width {
let dash_gap_width = dash_gap_width.unwrap_or(1.);
let array = js_sys::Array::new();
array.push(&JsValue::from(dash_width));
array.push(&JsValue::from(dash_gap_width));

if let Some(dash_offset) = dash_offset {
if dash_offset != 0. {
self.render_context.set_line_dash_offset(dash_offset);
}
}

self.render_context
.set_line_dash(&JsValue::from(array))
.map_err(|error| log::warn!("Error drawing dashed line: {:?}", error))
.ok();
}

self.render_context.begin_path();
self.render_context.arc(position.x, position.y, radius, 0., TAU).expect("Failed to draw the circle");
self.render_context.set_stroke_style_str(color_stroke);

if let Some(fill_color) = color_fill {
self.render_context.set_fill_style_str(fill_color);
self.render_context.fill();
}
self.render_context.stroke();

// Reset the dash pattern back to solid
if dash_width.is_some() {
self.render_context
.set_line_dash(&JsValue::from(js_sys::Array::new()))
.map_err(|error| log::warn!("Error drawing dashed line: {:?}", error))
.ok();
}
if dash_offset.is_some() && dash_offset != Some(0.) {
self.render_context.set_line_dash_offset(0.);
}

self.end_dpi_aware_transform();
}

pub fn circle(&mut self, position: DVec2, radius: f64, color_fill: Option<&str>, color_stroke: Option<&str>) {
self.dashed_circle(position, radius, color_fill, color_stroke, None, None, None, None);
}

pub fn manipulator_handle(&mut self, position: DVec2, selected: bool, color: Option<&str>) {
self.start_dpi_aware_transform();

Expand Down Expand Up @@ -374,23 +515,6 @@ impl OverlayContext {
self.end_dpi_aware_transform();
}

pub fn circle(&mut self, position: DVec2, radius: f64, color_fill: Option<&str>, color_stroke: Option<&str>) {
let color_fill = color_fill.unwrap_or(COLOR_OVERLAY_WHITE);
let color_stroke = color_stroke.unwrap_or(COLOR_OVERLAY_BLUE);
let position = position.round();

self.start_dpi_aware_transform();

self.render_context.begin_path();
self.render_context.arc(position.x, position.y, radius, 0., TAU).expect("Failed to draw the circle");
self.render_context.set_fill_style_str(color_fill);
self.render_context.set_stroke_style_str(color_stroke);
self.render_context.fill();
self.render_context.stroke();

self.end_dpi_aware_transform();
}

pub fn draw_arc(&mut self, center: DVec2, radius: f64, start_from: f64, end_at: f64) {
let segments = ((end_at - start_from).abs() / (std::f64::consts::PI / 4.)).ceil() as usize;
let step = (end_at - start_from) / segments as f64;
Expand Down Expand Up @@ -591,7 +715,7 @@ impl OverlayContext {
}

pub fn arc_sweep_angle(&mut self, offset_angle: f64, angle: f64, end_point_position: DVec2, bold_radius: f64, pivot: DVec2, text: &str, transform: DAffine2) {
self.manipulator_handle(end_point_position, true, Some(COLOR_OVERLAY_RED));
self.manipulator_handle(end_point_position, true, None);
self.draw_arc_gizmo_angle(pivot, bold_radius, ARC_SWEEP_GIZMO_RADIUS, offset_angle, angle.to_radians());
self.text(&text, COLOR_OVERLAY_BLUE, None, transform, 16., [Pivot::Middle, Pivot::Middle]);
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -345,6 +345,23 @@ impl OverlayContext {
self.scene.stroke(&kurbo::Stroke::new(1.0), transform, Self::parse_color(color_stroke), None, &circle);
}

pub fn dashed_ellipse(
&mut self,
_center: DVec2,
_radius_x: f64,
_radius_y: f64,
_rotation: Option<f64>,
_start_angle: Option<f64>,
_end_angle: Option<f64>,
_counterclockwise: Option<bool>,
_color_fill: Option<&str>,
_color_stroke: Option<&str>,
_dash_width: Option<f64>,
_dash_gap_width: Option<f64>,
_dash_offset: Option<f64>,
) {
}

pub fn draw_arc(&mut self, center: DVec2, radius: f64, start_from: f64, end_at: f64) {
let segments = ((end_at - start_from).abs() / (std::f64::consts::PI / 4.)).ceil() as usize;
let step = (end_at - start_from) / segments as f64;
Expand Down Expand Up @@ -541,7 +558,7 @@ impl OverlayContext {

#[allow(clippy::too_many_arguments)]
pub fn arc_sweep_angle(&mut self, offset_angle: f64, angle: f64, end_point_position: DVec2, bold_radius: f64, pivot: DVec2, text: &str, transform: DAffine2) {
self.manipulator_handle(end_point_position, true, Some(COLOR_OVERLAY_RED));
self.manipulator_handle(end_point_position, true, None);
self.draw_arc_gizmo_angle(pivot, bold_radius, ARC_SWEEP_GIZMO_RADIUS, offset_angle, angle.to_radians());
self.text(text, COLOR_OVERLAY_BLUE, None, transform, 16., [Pivot::Middle, Pivot::Middle]);
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ use crate::messages::prelude::{DocumentMessageHandler, InputPreprocessorMessageH
use crate::messages::tool::common_functionality::graph_modification_utils;
use crate::messages::tool::common_functionality::shape_editor::ShapeState;
use crate::messages::tool::common_functionality::shapes::arc_shape::ArcGizmoHandler;
use crate::messages::tool::common_functionality::shapes::circle_shape::CircleGizmoHandler;
use crate::messages::tool::common_functionality::shapes::polygon_shape::PolygonGizmoHandler;
use crate::messages::tool::common_functionality::shapes::shape_utility::ShapeGizmoHandler;
use crate::messages::tool::common_functionality::shapes::star_shape::StarGizmoHandler;
Expand All @@ -26,6 +27,7 @@ pub enum ShapeGizmoHandlers {
Star(StarGizmoHandler),
Polygon(PolygonGizmoHandler),
Arc(ArcGizmoHandler),
Circle(CircleGizmoHandler),
}

impl ShapeGizmoHandlers {
Expand All @@ -36,6 +38,7 @@ impl ShapeGizmoHandlers {
Self::Star(_) => "star",
Self::Polygon(_) => "polygon",
Self::Arc(_) => "arc",
Self::Circle(_) => "circle",
Self::None => "none",
}
}
Expand All @@ -46,6 +49,7 @@ impl ShapeGizmoHandlers {
Self::Star(h) => h.handle_state(layer, mouse_position, document, responses),
Self::Polygon(h) => h.handle_state(layer, mouse_position, document, responses),
Self::Arc(h) => h.handle_state(layer, mouse_position, document, responses),
Self::Circle(h) => h.handle_state(layer, mouse_position, document, responses),
Self::None => {}
}
}
Expand All @@ -56,6 +60,7 @@ impl ShapeGizmoHandlers {
Self::Star(h) => h.is_any_gizmo_hovered(),
Self::Polygon(h) => h.is_any_gizmo_hovered(),
Self::Arc(h) => h.is_any_gizmo_hovered(),
Self::Circle(h) => h.is_any_gizmo_hovered(),
Self::None => false,
}
}
Expand All @@ -66,6 +71,7 @@ impl ShapeGizmoHandlers {
Self::Star(h) => h.handle_click(),
Self::Polygon(h) => h.handle_click(),
Self::Arc(h) => h.handle_click(),
Self::Circle(h) => h.handle_click(),
Self::None => {}
}
}
Expand All @@ -76,6 +82,7 @@ impl ShapeGizmoHandlers {
Self::Star(h) => h.handle_update(drag_start, document, input, responses),
Self::Polygon(h) => h.handle_update(drag_start, document, input, responses),
Self::Arc(h) => h.handle_update(drag_start, document, input, responses),
Self::Circle(h) => h.handle_update(drag_start, document, input, responses),
Self::None => {}
}
}
Expand All @@ -86,6 +93,7 @@ impl ShapeGizmoHandlers {
Self::Star(h) => h.cleanup(),
Self::Polygon(h) => h.cleanup(),
Self::Arc(h) => h.cleanup(),
Self::Circle(h) => h.cleanup(),
Self::None => {}
}
}
Expand All @@ -104,6 +112,7 @@ impl ShapeGizmoHandlers {
Self::Star(h) => h.overlays(document, layer, input, shape_editor, mouse_position, overlay_context),
Self::Polygon(h) => h.overlays(document, layer, input, shape_editor, mouse_position, overlay_context),
Self::Arc(h) => h.overlays(document, layer, input, shape_editor, mouse_position, overlay_context),
Self::Circle(h) => h.overlays(document, layer, input, shape_editor, mouse_position, overlay_context),
Self::None => {}
}
}
Expand All @@ -121,6 +130,7 @@ impl ShapeGizmoHandlers {
Self::Star(h) => h.dragging_overlays(document, input, shape_editor, mouse_position, overlay_context),
Self::Polygon(h) => h.dragging_overlays(document, input, shape_editor, mouse_position, overlay_context),
Self::Arc(h) => h.dragging_overlays(document, input, shape_editor, mouse_position, overlay_context),
Self::Circle(h) => h.dragging_overlays(document, input, shape_editor, mouse_position, overlay_context),
Self::None => {}
}
}
Expand All @@ -130,6 +140,7 @@ impl ShapeGizmoHandlers {
Self::Star(h) => h.mouse_cursor_icon(),
Self::Polygon(h) => h.mouse_cursor_icon(),
Self::Arc(h) => h.mouse_cursor_icon(),
Self::Circle(h) => h.mouse_cursor_icon(),
Self::None => None,
}
}
Expand Down Expand Up @@ -169,6 +180,10 @@ impl GizmoManager {
if graph_modification_utils::get_arc_id(layer, &document.network_interface).is_some() {
return Some(ShapeGizmoHandlers::Arc(ArcGizmoHandler::new()));
}
// Circle
if graph_modification_utils::get_circle_id(layer, &document.network_interface).is_some() {
return Some(ShapeGizmoHandlers::Circle(CircleGizmoHandler::default()));
}

None
}
Expand Down
Loading
Loading