diff options
author | Akshay <[email protected]> | 2021-04-11 11:01:32 +0100 |
---|---|---|
committer | Akshay <[email protected]> | 2021-04-12 11:02:49 +0100 |
commit | abcf2b32777ffb934788e3219cacc2bbc048b6a3 (patch) | |
tree | d310c7d2c69531a4583dac7ab34705f6ae5c12c7 /src | |
parent | b0685c1638044b85dc7e8b07555a7b639b54d69a (diff) |
add `selection-start` and `selection-end` primitives
Diffstat (limited to 'src')
-rw-r--r-- | src/app.rs | 89 | ||||
-rw-r--r-- | src/lisp/eval.rs | 13 | ||||
-rw-r--r-- | src/lisp/expr.rs | 6 | ||||
-rw-r--r-- | src/lisp/number.rs | 7 | ||||
-rw-r--r-- | src/lisp/prelude.rs | 38 | ||||
-rw-r--r-- | src/utils.rs | 5 |
6 files changed, 111 insertions, 47 deletions
@@ -1,5 +1,5 @@ | |||
1 | use crate::{ | 1 | use crate::{ |
2 | bitmap::{positive_angle_with_x, abs_difference, Axis, MapPoint, Pixmap}, | 2 | bitmap::{abs_difference, positive_angle_with_x, Axis, MapPoint, Pixmap}, |
3 | brush::{Brush, CircleBrush, LineBrush, RectSelectBrush}, | 3 | brush::{Brush, CircleBrush, LineBrush, RectSelectBrush}, |
4 | cache::Cache, | 4 | cache::Cache, |
5 | command::CommandBox, | 5 | command::CommandBox, |
@@ -458,27 +458,34 @@ impl<'ctx> AppState<'ctx> { | |||
458 | "{:.width$}°", | 458 | "{:.width$}°", |
459 | angle, | 459 | angle, |
460 | width = if (angle - ANGLE).abs() < 1e-3 { 3 } else { 0 } | 460 | width = if (angle - ANGLE).abs() < 1e-3 { 3 } else { 0 } |
461 | ), | 461 | ), |
462 | PINK, | 462 | PINK, |
463 | (self.mouse.0 + size as i32, self.mouse.1 + size as i32), | 463 | (self.mouse.0 + size as i32, self.mouse.1 + size as i32), |
464 | ); | 464 | ); |
465 | for MapPoint { x, y } in line.into_iter() { | 465 | for MapPoint { x, y } in line.into_iter() { |
466 | self.canvas.set_draw_color(PINK); | 466 | self.canvas.set_draw_color(PINK); |
467 | self.canvas | 467 | self.canvas |
468 | .fill_rect(Rect::new( | 468 | .fill_rect(Rect::new( |
469 | x as i32 * cs as i32 + self.start.x(), | 469 | x as i32 * cs as i32 + self.start.x(), |
470 | y as i32 * cs as i32 + self.start.y(), | 470 | y as i32 * cs as i32 + self.start.y(), |
471 | cs, | 471 | cs, |
472 | cs, | 472 | cs, |
473 | )) | 473 | )) |
474 | .unwrap(); | 474 | .unwrap(); |
475 | } | 475 | } |
476 | } | 476 | } |
477 | } | 477 | } |
478 | Brush::RectSelect(RectSelectBrush { start: Some(s), end: Some(e), active_end }) => { | 478 | Brush::RectSelect(RectSelectBrush { |
479 | start: Some(s), | ||
480 | end: Some(e), | ||
481 | .. | ||
482 | }) => { | ||
479 | self.canvas.set_draw_color(PINK); | 483 | self.canvas.set_draw_color(PINK); |
480 | let (width, height) = (abs_difference(s.x, e.x), abs_difference(s.y, e.y)); | 484 | let (width, height) = (abs_difference(s.x, e.x), abs_difference(s.y, e.y)); |
481 | let MapPoint{x: start_x, y: start_y} = utils::rect_coords(s, e).0; | 485 | let MapPoint { |
486 | x: start_x, | ||
487 | y: start_y, | ||
488 | } = utils::rect_coords(s, e).0; | ||
482 | let start_loc_x = self.start.x() + (start_x * cs) as i32; | 489 | let start_loc_x = self.start.x() + (start_x * cs) as i32; |
483 | let start_loc_y = self.start.y() + (start_y * cs) as i32; | 490 | let start_loc_y = self.start.y() + (start_y * cs) as i32; |
484 | draw_text( | 491 | draw_text( |
@@ -488,11 +495,11 @@ impl<'ctx> AppState<'ctx> { | |||
488 | PINK, | 495 | PINK, |
489 | (start_loc_x, start_loc_y - 20), | 496 | (start_loc_x, start_loc_y - 20), |
490 | ); | 497 | ); |
491 | self.canvas.draw_rect( | 498 | self.canvas |
492 | rect!(start_loc_x, start_loc_y, width * cs, height * cs) | 499 | .draw_rect(rect!(start_loc_x, start_loc_y, width * cs, height * cs)) |
493 | ).unwrap(); | 500 | .unwrap(); |
494 | } | 501 | } |
495 | _ => () | 502 | _ => (), |
496 | } | 503 | } |
497 | } | 504 | } |
498 | 505 | ||
@@ -748,7 +755,7 @@ impl<'ctx> AppState<'ctx> { | |||
748 | Keycode::Escape => { | 755 | Keycode::Escape => { |
749 | match self.brush { | 756 | match self.brush { |
750 | Brush::RectSelect(_) => self.brush = Brush::rect(), | 757 | Brush::RectSelect(_) => self.brush = Brush::rect(), |
751 | _ => () | 758 | _ => (), |
752 | } | 759 | } |
753 | continue; | 760 | continue; |
754 | } | 761 | } |
@@ -879,42 +886,50 @@ impl<'ctx> AppState<'ctx> { | |||
879 | } => { | 886 | } => { |
880 | if mousestate.is_mouse_button_pressed(MouseButton::Left) { | 887 | if mousestate.is_mouse_button_pressed(MouseButton::Left) { |
881 | match self.brush { | 888 | match self.brush { |
882 | Brush::RectSelect(RectSelectBrush{start, end, active_end}) => { | 889 | Brush::RectSelect(RectSelectBrush { |
890 | start, | ||
891 | end, | ||
892 | active_end, | ||
893 | }) => { | ||
883 | if active_end { | 894 | if active_end { |
884 | self.brush = Brush::RectSelect(RectSelectBrush{ | 895 | self.brush = Brush::RectSelect(RectSelectBrush { |
885 | start, | 896 | start, |
886 | end: self.idx_at_coord((x, y)).map(MapPoint::from), | 897 | end: self |
887 | active_end | 898 | .idx_at_coord((x, y)) |
899 | .map(MapPoint::from), | ||
900 | active_end, | ||
888 | }); | 901 | }); |
889 | } else { | 902 | } else { |
890 | self.brush = Brush::RectSelect(RectSelectBrush{ | 903 | self.brush = Brush::RectSelect(RectSelectBrush { |
891 | start: self.idx_at_coord((x, y)).map(MapPoint::from), | 904 | start: self |
905 | .idx_at_coord((x, y)) | ||
906 | .map(MapPoint::from), | ||
892 | end, | 907 | end, |
893 | active_end | 908 | active_end, |
894 | }); | 909 | }); |
895 | } | 910 | } |
896 | }, | 911 | } |
897 | Brush::Circle(CircleBrush { size }) | 912 | Brush::Circle(CircleBrush { size }) |
898 | | Brush::Line(LineBrush { size, .. }) => { | 913 | | Brush::Line(LineBrush { size, .. }) => { |
899 | let pt = (x, y); | 914 | let pt = (x, y); |
900 | let val = self.active_color; | 915 | let val = self.active_color; |
901 | if let Ok(o) = self.paint_point(pt, val, size) { | 916 | if let Ok(o) = self.paint_point(pt, val, size) { |
902 | self.current_operation.extend(o); | 917 | self.current_operation.extend(o); |
903 | } | 918 | } |
904 | }, | 919 | } |
905 | _ => () | 920 | _ => (), |
906 | } | 921 | } |
907 | } else if mousestate.is_mouse_button_pressed(MouseButton::Right) { | 922 | } else if mousestate.is_mouse_button_pressed(MouseButton::Right) { |
908 | match self.brush { | 923 | match self.brush { |
909 | Brush::Circle(CircleBrush { size }) | 924 | Brush::Circle(CircleBrush { size }) |
910 | | Brush::Line(LineBrush { size, .. }) => { | 925 | | Brush::Line(LineBrush { size, .. }) => { |
911 | let pt = (x, y); | 926 | let pt = (x, y); |
912 | let val = !self.active_color; | 927 | let val = !self.active_color; |
913 | if let Ok(o) = self.paint_point(pt, val, size) { | 928 | if let Ok(o) = self.paint_point(pt, val, size) { |
914 | self.current_operation.extend(o); | 929 | self.current_operation.extend(o); |
915 | } | 930 | } |
916 | }, | 931 | } |
917 | _ => () | 932 | _ => (), |
918 | } | 933 | } |
919 | } | 934 | } |
920 | } | 935 | } |
diff --git a/src/lisp/eval.rs b/src/lisp/eval.rs index 0cf267c..b404662 100644 --- a/src/lisp/eval.rs +++ b/src/lisp/eval.rs | |||
@@ -217,12 +217,13 @@ where | |||
217 | 217 | ||
218 | pub fn eval_for(&mut self, args: &[LispExpr]) -> Result<LispExpr, LispError> { | 218 | pub fn eval_for(&mut self, args: &[LispExpr]) -> Result<LispExpr, LispError> { |
219 | let arity = Arity::Exact(2); | 219 | let arity = Arity::Exact(2); |
220 | let valid_binding_stmt = |expr: &LispExpr| | 220 | let valid_binding_stmt = |expr: &LispExpr| { |
221 | matches!( | 221 | matches!( |
222 | expr, | 222 | expr, |
223 | LispExpr::List(v) | 223 | LispExpr::List(v) |
224 | if v.len() == 2 | 224 | if v.len() == 2 |
225 | && matches!(v[0], LispExpr::Ident(_))); | 225 | && matches!(v[0], LispExpr::Ident(_))) |
226 | }; | ||
226 | 227 | ||
227 | if !arity.check(args) { | 228 | if !arity.check(args) { |
228 | Err(arity.to_error()) | 229 | Err(arity.to_error()) |
@@ -258,8 +259,8 @@ where | |||
258 | } | 259 | } |
259 | _ => { | 260 | _ => { |
260 | error!("invalid for loop args"); | 261 | error!("invalid for loop args"); |
261 | Err(EvalError::BadForm.into()) | 262 | Err(EvalError::BadForm.into()) |
262 | }, | 263 | } |
263 | } | 264 | } |
264 | } | 265 | } |
265 | } | 266 | } |
diff --git a/src/lisp/expr.rs b/src/lisp/expr.rs index 692f951..d086ecf 100644 --- a/src/lisp/expr.rs +++ b/src/lisp/expr.rs | |||
@@ -310,6 +310,12 @@ impl TryFrom<LispExpr> for LispNumber { | |||
310 | } | 310 | } |
311 | } | 311 | } |
312 | 312 | ||
313 | impl From<i64> for LispExpr { | ||
314 | fn from(num: i64) -> Self { | ||
315 | LispExpr::Number(num.into()) | ||
316 | } | ||
317 | } | ||
318 | |||
313 | impl<'a> TryFrom<&'a LispExpr> for &'a LispNumber { | 319 | impl<'a> TryFrom<&'a LispExpr> for &'a LispNumber { |
314 | type Error = LispError; | 320 | type Error = LispError; |
315 | fn try_from(value: &'a LispExpr) -> Result<Self, Self::Error> { | 321 | fn try_from(value: &'a LispExpr) -> Result<Self, Self::Error> { |
diff --git a/src/lisp/number.rs b/src/lisp/number.rs index 4824e21..06c6baa 100644 --- a/src/lisp/number.rs +++ b/src/lisp/number.rs | |||
@@ -1,5 +1,6 @@ | |||
1 | use std::{ | 1 | use std::{ |
2 | cmp::{Eq, Ord, Ordering, PartialEq, PartialOrd}, | 2 | cmp::{Eq, Ord, Ordering, PartialEq, PartialOrd}, |
3 | convert::From, | ||
3 | fmt, | 4 | fmt, |
4 | ops::{Add, Mul, Sub}, | 5 | ops::{Add, Mul, Sub}, |
5 | }; | 6 | }; |
@@ -113,3 +114,9 @@ impl fmt::Display for LispNumber { | |||
113 | } | 114 | } |
114 | } | 115 | } |
115 | } | 116 | } |
117 | |||
118 | impl From<i64> for LispNumber { | ||
119 | fn from(target: i64) -> Self { | ||
120 | LispNumber::Integer(target) | ||
121 | } | ||
122 | } | ||
diff --git a/src/lisp/prelude.rs b/src/lisp/prelude.rs index e24ade5..1d37a32 100644 --- a/src/lisp/prelude.rs +++ b/src/lisp/prelude.rs | |||
@@ -1,6 +1,6 @@ | |||
1 | use crate::{ | 1 | use crate::{ |
2 | bitmap::MapPoint, | 2 | bitmap::MapPoint, |
3 | brush::Brush, | 3 | brush::{Brush, RectSelectBrush}, |
4 | grid::GridKind, | 4 | grid::GridKind, |
5 | guide::Guide, | 5 | guide::Guide, |
6 | lisp::{ | 6 | lisp::{ |
@@ -11,7 +11,7 @@ use crate::{ | |||
11 | }, | 11 | }, |
12 | primitive, | 12 | primitive, |
13 | undo::PaintRecord, | 13 | undo::PaintRecord, |
14 | utils::load_script, | 14 | utils::{load_script, rect_coords}, |
15 | }; | 15 | }; |
16 | 16 | ||
17 | use std::convert::TryInto; | 17 | use std::convert::TryInto; |
@@ -437,6 +437,40 @@ pub fn new_env() -> Result<Environment, LispError> { | |||
437 | } | 437 | } |
438 | }); | 438 | }); |
439 | 439 | ||
440 | primitive!(env, Arity::Exact(0), "selection-start", |_, app| { | ||
441 | if let Brush::RectSelect(RectSelectBrush { | ||
442 | start: Some(s), | ||
443 | end: Some(e), | ||
444 | .. | ||
445 | }) = app.brush | ||
446 | { | ||
447 | let pt = rect_coords(s, e).0; | ||
448 | Ok(LispExpr::DottedList(vec![ | ||
449 | (pt.x as i64).into(), | ||
450 | (pt.y as i64).into(), | ||
451 | ])) | ||
452 | } else { | ||
453 | Err(EvalError::CustomInternal("No active selection!").into()) | ||
454 | } | ||
455 | }); | ||
456 | |||
457 | primitive!(env, Arity::Exact(0), "selection-end", |_, app| { | ||
458 | if let Brush::RectSelect(RectSelectBrush { | ||
459 | start: Some(s), | ||
460 | end: Some(e), | ||
461 | .. | ||
462 | }) = app.brush | ||
463 | { | ||
464 | let pt = rect_coords(s, e).1; | ||
465 | Ok(LispExpr::DottedList(vec![ | ||
466 | (pt.x as i64).into(), | ||
467 | (pt.y as i64).into(), | ||
468 | ])) | ||
469 | } else { | ||
470 | Err(EvalError::CustomInternal("No active selection!").into()) | ||
471 | } | ||
472 | }); | ||
473 | |||
440 | primitive!(env, Arity::Exact(2), "range", |args, _| { | 474 | primitive!(env, Arity::Exact(2), "range", |args, _| { |
441 | if type_match!( | 475 | if type_match!( |
442 | args, | 476 | args, |
diff --git a/src/utils.rs b/src/utils.rs index 0825c8c..d5d4039 100644 --- a/src/utils.rs +++ b/src/utils.rs | |||
@@ -1,7 +1,7 @@ | |||
1 | use crate::{ | 1 | use crate::{ |
2 | app::AppState, | 2 | app::AppState, |
3 | consts::FONT_PATH, | ||
4 | bitmap::{abs_difference, MapPoint}, | 3 | bitmap::{abs_difference, MapPoint}, |
4 | consts::FONT_PATH, | ||
5 | lisp::{ | 5 | lisp::{ |
6 | error::{EvalError, LispError, ParseError}, | 6 | error::{EvalError, LispError, ParseError}, |
7 | eval::Evaluator, | 7 | eval::Evaluator, |
@@ -143,7 +143,8 @@ pub fn rect_coords(s: MapPoint, e: MapPoint) -> (MapPoint, MapPoint) { | |||
143 | (e.x, s.y) | 143 | (e.x, s.y) |
144 | } else { | 144 | } else { |
145 | (e.x, e.y) | 145 | (e.x, e.y) |
146 | }.into(); | 146 | } |
147 | .into(); | ||
147 | let end_loc = start_loc + (width, height).into(); | 148 | let end_loc = start_loc + (width, height).into(); |
148 | (start_loc, end_loc) | 149 | (start_loc, end_loc) |
149 | } | 150 | } |