diff options
author | Sébastien Dailly <sebastien@chimrod.com> | 2021-05-24 22:56:16 +0200 |
---|---|---|
committer | Sébastien Dailly <sebastien@dailly.me> | 2022-02-07 16:22:43 +0100 |
commit | 90f1f73f08b2d9231b2ee029b9e39dd570e36f36 (patch) | |
tree | 49c7828d2a549a3278ba5c54ca9b1f500c860951 | |
parent | 05008c81a9652472a454f47940a6d8aa9a228538 (diff) |
Update
-rwxr-xr-x | script.it/script.ml | 61 | ||||
-rwxr-xr-x | script.it/script_event/delete.ml | 31 | ||||
-rwxr-xr-x | script.it/script_event/mouse_down.ml | 84 | ||||
-rwxr-xr-x | script.it/script_event/out.ml | 25 | ||||
-rwxr-xr-x | script.it/state/state.ml | 147 |
5 files changed, 173 insertions, 175 deletions
diff --git a/script.it/script.ml b/script.it/script.ml index 200d118..a21afa9 100755 --- a/script.it/script.ml +++ b/script.it/script.ml @@ -332,10 +332,8 @@ let on_change canva mouse_position timer state = () let spawn_worker () = - try - Ok (Brr_webworkers.Worker.create (Jstr.v "worker.js")) - with - | Jv.Error e -> Error e + try Ok (Brr_webworkers.Worker.create (Jstr.v "worker.js")) + with Jv.Error e -> Error e let page_main id = @@ -351,17 +349,6 @@ let page_main id = set_sidebar el State.init end in - - let delete_event = E.map (fun () -> `Delete) parameters.delete - and export_event = E.map (fun () -> `Export) parameters.export - and angle_event = S.changes parameters.angle - |> E.map (fun value -> `Angle value) - and width_event = S.changes parameters.width - |> E.map (fun value -> `Width value) - in - - - (*begin match Document.find_el_by_id G.document id with*) begin match (Jv.is_none id) with | true -> Console.(error [str "No element with id '%s' found"; id]) | false -> @@ -369,7 +356,22 @@ let page_main id = match spawn_worker () with | Error e -> El.set_children (Jv.Id.of_jv id) [ El.p El.[txt (Jv.Error.message e)]] + | Ok worker -> + let delete_event = E.map + (fun () -> `Generic ( + let module Delete = Script_event.Delete in + State.E ( Delete.{ worker } + , (module Delete: State.Handler with type t = Delete.t) + ))) + parameters.delete + + and export_event = E.map (fun () -> `Export) parameters.export + and angle_event = S.changes parameters.angle + |> E.map (fun value -> `Angle value) + and width_event = S.changes parameters.width + |> E.map (fun value -> `Width value) + in let worker_event, worker_send = E.create () in let my_host = Uri.host @@ Window.location @@ G.window in @@ -389,24 +391,27 @@ let page_main id = - Get also the click event for starting to draw *) - let canva_events, mouse_position, canva = canva (Jv.Id.of_jv id) in - let canva_events = Note.E.map (function - | `MouseDown c -> `MouseDown c - | `Out c -> - + | `MouseDown c -> + let module MouseDown = Script_event.Mouse_down in `Generic ( State.E - ( Script_event.Out.{ point = c - ; worker - ; timer - } - , (module Script_event.Out: State.Handler with type t = Script_event.Out.t) - ) + ( MouseDown.{ position = c + ; timer + } + , (module MouseDown: State.Handler with type t = MouseDown.t))) - ) + | `Out c -> + let module Out = Script_event.Out in + `Generic ( + State.E + ( Out.{ point = c + ; worker + ; timer + } + , (module Out: State.Handler with type t = Out.t))) ) canva_events in @@ -419,7 +424,7 @@ let page_main id = successives events to the initial state *) let state = Application.run - (State.do_action worker timer) + (State.do_action worker) State.init (E.select [ worker_event diff --git a/script.it/script_event/delete.ml b/script.it/script_event/delete.ml new file mode 100755 index 0000000..edd5d23 --- /dev/null +++ b/script.it/script_event/delete.ml @@ -0,0 +1,31 @@ +(** Delete the selected element *) + +open StdLabels +module State = Script_state.State +module Selection = Script_state.Selection + +type t = { worker : Brr_webworkers.Worker.t } + +(* Click anywhere while in Out mode, we switch in edition *) +let apply { worker } state = + match state.State.mode with + | Selection (Path id) -> + let paths = List.filter + state.State.paths + ~f:(fun p -> + p.Outline.id != id + ) in + { state with paths ; mode = Out} + + | Selection (Point (id, point)) -> + List.iter + state.State.paths + ~f:(fun p -> + let id' = p.Outline.id in + match id' = id with + | false -> () + | true -> State.post worker (`DeletePoint (point, p)) + ); + { state with mode = Selection (Path id) } + + | _ -> state diff --git a/script.it/script_event/mouse_down.ml b/script.it/script_event/mouse_down.ml new file mode 100755 index 0000000..04ea2fd --- /dev/null +++ b/script.it/script_event/mouse_down.ml @@ -0,0 +1,84 @@ +module State = Script_state.State +module Selection = Script_state.Selection + +type t = { position : float * float + ; timer : Elements.Timer.t } + +let apply { position; timer } state = + match state.State.mode with + + | Out -> + let x, y = position in + Elements.Timer.start timer 0.3; + + let width = state.width + and angle = state.angle in + + let stamp = 0. in + let point = + match Selection.get_from_paths position state.paths with + | _, None -> + (* Start a new path with the point clicked *) + Path.Point.create ~x ~y ~angle ~width ~stamp + | _, Some (p, _, _, _) -> + (* If the point is close to an existing path, we use the closest + point in the path instead *) + let x, y = Gg.V2.to_tuple p in + Path.Point.create ~x ~y ~angle ~width ~stamp + in + + let current = Path.Path_Builder.add_point + point + state.current in + { state with + current + ; mode = Edit + ; mouse_down_position = Gg.V2.of_tuple (x, y)} + + | (Selection (Path id)) + | (Selection (Point (id, _))) -> + + let get_any () = + begin match Selection.get_from_paths position state.paths with + | _, None -> + { state with + mode = Out + ; mouse_down_position = Gg.V2.of_tuple position } + | dist, Some selection -> + let _, outline, _, _ = selection in + if outline.Outline.id != id then ( + let mouse_down_position = Gg.V2.of_tuple position in + State.select_segment position selection { state with mouse_down_position } dist + ) else + (* On the same segment, check for a point *) + let selection = Selection.select_point outline (Gg.V2.of_tuple position) in + match selection with + | Path _ -> + { state with + mode = Selection selection + ; mouse_down_position = Gg.V2.of_tuple position } + | Point (_, pt) -> + (* In order to handle the point move, start the timer *) + Elements.Timer.start timer 0.3; + { state with + mode = Selection selection + ; angle = Path.Point.get_angle pt + ; width = Path.Point.get_width pt + ; mouse_down_position = Gg.V2.of_tuple position } + end + in + (* First, check for a point in the selected path. If any of them in + found, check anything to select in all the elements *) + begin match Outline.find state.paths id with + | None -> get_any () + | Some outline -> + begin match Selection.select_point outline (Gg.V2.of_tuple position) with + | Path _ -> get_any () + | other -> + Elements.Timer.start timer 0.3; + {state with + mode = Selection other + ; mouse_down_position = Gg.V2.of_tuple position } + end + end + | Edit -> state diff --git a/script.it/script_event/out.ml b/script.it/script_event/out.ml index 45f05d3..b8b8599 100755 --- a/script.it/script_event/out.ml +++ b/script.it/script_event/out.ml @@ -8,6 +8,25 @@ type t = { point : float * float ; worker : Brr_webworkers.Worker.t } +(** Long click, move the selected element if any *) +let longClick mouse_coord state worker = function + | State.Selection t -> + let mouse_v2 = Gg.V2.of_tuple mouse_coord in + begin match Selection.find_selection t state.State.paths with + | None -> state + | Some (Point (path, point)) -> + let point' = Path.Point.copy point mouse_v2 in + State.post worker (`TranslatePoint (point', path)); + (* Just replace the position of the selected point *) + { state with mode = Selection (Point (path.id, point')) } + | Some (Path path) -> + let delta = Gg.V2.(mouse_v2 - state.State.mouse_down_position) in + State.post worker (`TranslatePath (path, delta)); + state + end + (* TODO Long click in out mode should translate the slate *) + | _ -> state + let apply {point; timer ; worker} state = match state.State.mode with @@ -61,9 +80,9 @@ let apply {point; timer ; worker} state = end end - | mode when Elements.Timer.delay timer < 0.3 -> - State.click state mode + | _ when Elements.Timer.delay timer < 0.3 -> + state | _ -> - State.longClick point state worker state.mode + longClick point state worker state.mode diff --git a/script.it/state/state.ml b/script.it/state/state.ml index d7cb13e..4cf6992 100755 --- a/script.it/state/state.ml +++ b/script.it/state/state.ml @@ -7,14 +7,6 @@ type mode = | Out (** Events *) -type canva_events = - [ `MouseDown of float * float - ] - -type button_events = - [ `Delete - | `Export - ] type render_event = [ `Rendering of Layer.Paths.printer @@ -47,8 +39,7 @@ end type t = E : 'a * (module Handler with type t = 'a) -> t type events = - [ canva_events - | button_events + [ `Export | render_event | worker_event | `Point of float * (float * float) @@ -98,30 +89,6 @@ let select_segment _ (_, selected, p0, p1) state dist = ; angle ; width } -(** Delete the selected element *) -let delete state worker = - match state.mode with - | Selection (Path id) -> - let paths = List.filter - state.paths - ~f:(fun p -> - p.Outline.id != id - ) in - { state with paths ; mode = Out} - - | Selection (Point (id, point)) -> - List.iter - state.paths - ~f:(fun p -> - let id' = p.Outline.id in - match id' = id with - | false -> () - | true -> post worker (`DeletePoint (point, p)) - ); - { state with mode = Selection (Path id) } - | _ -> - state - (** Tick event Tick only occurs when drawing a new path @@ -180,119 +147,15 @@ let angle worker angle state = | _ -> { state with angle } -(** Short click on any element, just do nothing (each element is on MouseDown - event) *) -let click state = function - | _ -> state - -(** Long click, move the selected element if any *) -let longClick mouse_coord state worker = function - | Selection t -> - let mouse_v2 = Gg.V2.of_tuple mouse_coord in - begin match Selection.find_selection t state.paths with - | None -> state - | Some (Point (path, point)) -> - let point' = Path.Point.copy point mouse_v2 in - post worker (`TranslatePoint (point', path)); - (* Just replace the position of the selected point *) - { state with mode = Selection (Point (path.id, point')) } - | Some (Path path) -> - let delta = Gg.V2.(mouse_v2 - state.mouse_down_position) in - post worker (`TranslatePath (path, delta)); - state - end - (* TODO Long click in out mode should translate the slate *) - | _ -> state - let do_action - : Brr_webworkers.Worker.t -> Elements.Timer.t -> (events, state) Application.t - = fun worker timer event state -> + : Brr_webworkers.Worker.t -> (events, state) Application.t + = fun worker event state -> match event, state.mode with | `Generic (E (t, (module Handler))), _ -> Handler.apply t state | `Point (delay, point), _ -> tick (delay, point) state - (* Click anywhere while in Out mode, we switch in edition *) - | `MouseDown ((x, y) as p), Out -> - Elements.Timer.start timer 0.3; - - let width = state.width - and angle = state.angle in - - let stamp = 0. in - let point = - match Selection.get_from_paths p state.paths with - | _, None -> - (* Start a new path with the point clicked *) - Path.Point.create ~x ~y ~angle ~width ~stamp - | _, Some (p, _, _, _) -> - (* If the point is close to an existing path, we use the closest - point in the path instead *) - let x, y = Gg.V2.to_tuple p in - Path.Point.create ~x ~y ~angle ~width ~stamp - in - - let current = Path.Path_Builder.add_point - point - state.current in - { state with - current - ; mode = Edit - ; mouse_down_position = Gg.V2.of_tuple (x, y)} - - (* Click anywhere while in selection mode, we either select another path, - or switch to Out mode*) - | `MouseDown position, (Selection (Path id)) - | `MouseDown position, (Selection (Point (id, _))) -> - - let get_any () = - begin match Selection.get_from_paths position state.paths with - | _, None -> - { state with - mode = Out - ; mouse_down_position = Gg.V2.of_tuple position } - | dist, Some selection -> - let _, outline, _, _ = selection in - if outline.Outline.id != id then ( - let mouse_down_position = Gg.V2.of_tuple position in - select_segment position selection { state with mouse_down_position } dist - ) else - (* On the same segment, check for a point *) - let selection = Selection.select_point outline (Gg.V2.of_tuple position) in - match selection with - | Path _ -> - { state with - mode = Selection selection - ; mouse_down_position = Gg.V2.of_tuple position } - | Point (_, pt) -> - (* In order to handle the point move, start the timer *) - Elements.Timer.start timer 0.3; - { state with - mode = Selection selection - ; angle = Path.Point.get_angle pt - ; width = Path.Point.get_width pt - ; mouse_down_position = Gg.V2.of_tuple position } - end - in - - (* First, check for a point in the selected path. If any of them in - found, check anything to select in all the elements *) - begin match Outline.find state.paths id with - | None -> get_any () - | Some outline -> - begin match Selection.select_point outline (Gg.V2.of_tuple position) with - | Path _ -> get_any () - | other -> - Elements.Timer.start timer 0.3; - {state with - mode = Selection other - ; mouse_down_position = Gg.V2.of_tuple position } - end - end - - | `Delete, _ -> - delete state worker | `Export, _ -> let my_host = Uri.host @@ Window.location @@ G.window in @@ -342,10 +205,6 @@ let do_action { state with paths } - (* Some non possible cases *) - | `MouseDown _, Edit - -> state - let init = { paths = [] ; current = Path.Path_Builder.empty |