123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343 |
- open Base
- open OUnit2
- open Helper
- module Logging_graphics : Ax.React_loop.GRAPHICS_LAYER = struct
- let clear () = log "clear"
- let rect aabb color =
- logf "rect{%s;%s}"
- (Ax.Math.AABB.to_string aabb)
- (Ax.Color.to_string color)
- end
- ;;
- run_test_tt_main @@
- test_list
- [
- ts (module Int)
- ["math1", 3 + 4, 7;
- "math2", 8 * 2, 16];
- ts (module IntOption)
- ["opt1", Some(3), Some(1 + 2);
- "opt2", None, None];
- t_log "hello_world" ["hello";"world"]
- (fun () -> log "hello"; logf "w%sld" "or");
- tfails
- [ "fail_world", Failure("ello"),
- (fun () -> failwith "hello world")
- ; "math3", Division_by_zero,
- (fun () -> 3 / (2 - 4 / 2)) ];
- ts (module ListUnordered_(Int))
- ["uo1", [1;2;3], [3;2;1];
- "uo2", [1;3;4;3], [3;3;1;4];
- "uo3", [], []];
- "Draw_tree">:::begin
- let open Ax.Color in
- let open Ax.Math in
- let open Ax.Draw_tree in
- let t_render name (expected : Draw.t list) (tree : tree) =
- t name (module List_(Draw))
- expected
- (Sequence.to_list (render tree))
- in
- let rects = [ figure (Rect({w=30;h=40}, red))
- ; figure (Rect({w=70;h=20}, blue))
- ; figure (Rect({w=10;h=50}, black)) ] in
- [ t_render "H_rects"
- [ Rect({bx=0;by=5;bw=30;bh=40},red)
- ; Rect({bx=30;by=15;bw=70;bh=20},blue)
- ; Rect({bx=100;by=0;bw=10;bh=50},black) ]
- (arm `H rects)
- ; t_render "V_rects"
- [ Rect({bx=20;by=0;bw=30;bh=40},red)
- ; Rect({bx=0;by=40;bw=70;bh=20},blue)
- ; Rect({bx=30;by=60;bw=10;bh=50},black) ]
- (arm `V rects)
- ; t_render "H+V"
- [ Rect({bx=0;by=35;bw=20;bh=20},red)
- ; Rect({bx=25;by=0;bw=30;bh=40},blue)
- ; Rect({bx=20;by=40;bw=40;bh=50},green)
- ; Rect({bx=60;by=30;bw=10;bh=10},yellow)
- ; Rect({bx=60;by=40;bw=10;bh=20},cyan) ]
- (arm `H [ figure (Rect({w=20;h=20}, red))
- ; arm `V [ figure (Rect({w=30;h=40}, blue))
- ; figure (Rect({w=40;h=50}, green)) ]
- ; arm `V [ figure (Rect({w=10;h=10}, yellow))
- ; figure (Rect({w=10;h=20}, cyan)) ] ])
- ; t_render "ignore_captures"
- (Sequence.to_list (render (arm `H rects)))
- (capture (Ax.Event.Id.gen ()) (arm `H rects))
- ; t_render "ignore_captures'"
- (Sequence.to_list (render (arm `H rects)))
- (arm `H @@ List.map rects ~f:(fun r -> capture (Ax.Event.Id.gen ()) r))
- ]
- end;
- "Draw_tree.capture_point">:begin
- let open Ax.Color in
- let open Ax.Math in
- let open Ax.Draw_tree in
- let r10x10 = figure (Rect({w=10;h=10},red)) in
- let id1, id2 = Ax.Event.Id.gen (), Ax.Event.Id.gen () in
- let cap x y t = capture_point ~pos:{x;y} t in
- ts (module List_(Ax.Event.Id))
- [ "empty",
- [], cap 5 5 @@ arm `H []
- ; "didnt_hit",
- [], cap 5 5 @@ arm `H [ r10x10 ; capture id1 r10x10 ]
- ; "did_hit",
- [id1], cap 15 5 @@ arm `H [ r10x10 ; capture id1 r10x10 ]
- ; "hit_nested",
- [id1;id2], cap 15 5 @@ capture id1 (arm `H [ r10x10 ; capture id2 r10x10 ])
- ; "hit_partial",
- [id1], cap 5 5 @@ capture id1 (arm `H [ r10x10 ; capture id2 r10x10 ])
- ]
- end;
- "Generic_tree.Zipper">:begin
- let open Ax.Private.Generic_tree in
- let module Z = Ax.Private.Generic_tree.Zipper in
- let module Tree = struct
- type nonrec t = (char, string) t
- include Make_show_eq(Char)(String)
- end in
- let lf_x = Leaf("xx") in let lf_y = Leaf("yy") in let lf_z = Leaf("zz") in
- let build mid = Arm('P', [ lf_x ; Arm('Q', [ lf_y ; lf_z ; mid ]) ; lf_z ; lf_y ]) in
- let zip = Z.(build lf_x |> of_tree |> down_exn 1 |> down_exn 2) in
- ts (module Tree)
- [ "get_focus",
- lf_x,
- Z.get zip
- ; "set_focus",
- build lf_y,
- Z.(zip |> set lf_y |> to_tree)
- ; "set_up",
- Arm('P', [lf_x;lf_y;lf_z;lf_y]),
- Z.(zip |> up_exn |> set lf_y |> to_tree)
- ; "side_zero",
- build lf_x,
- Z.(zip |> side_exn 0 |> to_tree)
- ; "side_positive",
- Arm('P', [ lf_x ; Arm('Q', [lf_y;lf_z;lf_z]) ; lf_z ; lf_y ]),
- Z.(of_tree (build lf_x) |> down_exn 1 |> down_exn 0 |> side_exn 2 |> set lf_z |> to_tree)
- ; "side_negative",
- Arm('P', [ lf_x ; Arm('Q', [lf_x;lf_z;lf_x]) ; lf_z ; lf_y ]),
- Z.(of_tree (build lf_x) |> down_exn 1 |> down_exn 2 |> side_exn ~-2 |> set lf_x |> to_tree)
- ]
- end;
- "Draw_tree.Path">:begin
- let open Ax.Draw_tree in
- ts (module Bool) @@
- List.map ~f:(fun (n,x,y,cmp) -> (n, true, (cmp (Path.compare x y) 0)))
- [ "cmp1", [], [], (=)
- ; "cmp2", [1], [], (<)
- ; "cmp3", [], [1], (>)
- ; "cmp4", [2;3], [2;3], (=)
- ; "cmp5", [2;3], [2;4], (<)
- ; "cmp6", [2;7], [2;4], (>) ]
- end;
- "Draw_tree.update">:begin
- let open Ax.Color in
- let open Ax.Draw_tree in
- let f1 = Rect({w=1;h=1}, red) in
- let f2 = Rect({w=2;h=2}, blue) in
- let f3 = Rect({w=3;h=3}, white) in
- let f4 = Rect({w=4;h=4}, black) in
- let f5 = Rect({w=5;h=5}, red) in
- let r1 = figure f1 in let r2 = figure f2 in
- let r3 = figure f3 in let r4 = figure f4 in let r5 = figure f5 in
- let t0 = arm `H [ r1 ; arm `V [ r2 ; r3 ; arm `H [r4;r5] ] ] in
- let t1 = arm `H [ r4 ; arm `V [ r2 ; r3 ; arm `H [r4;r5] ] ] in
- let t2 = arm `H [ r1 ; arm `V [ r2 ; r3 ; arm `H [r1;r5] ] ] in
- let t3 = arm `H [ r1 ; arm `V [ r2 ; r5 ; arm `H [r1;r5] ] ] in
- let t4 = arm `H [ r1 ; arm `V [ r2 ; r3 ; arm `H [r1;r2] ] ] in
- ts (module Ax.Draw_tree) @@
- List.map ~f:(fun (n,t',ps) -> (n, t', apply_updates_exn (Sequence.of_list ps) t0))
- [ "root", r1, [ [], f1 ]
- ; "shallow", t1, [ [0], f4 ]
- ; "deep", t2, [ [1;2;0], f1 ]
- ; "two", t3, [ [1;1], f5 ; [1;2;0], f1 ]
- ; "two'", t3, [ [1;2;0], f1 ; [1;1], f5 ]
- ; "adjacent", t4, [ [1;2;0], f1 ; [1;2;1], f2 ] ]
- end;
- "Source">:::begin
- let open Ax.Source in
- let src1 = create () in
- let src2 = create () in
- [ tfail "empty_state" (Failure("source unset"))
- (fun () -> State.(get_exn src1 empty))
- ; t "not_equal" (module Bool)
- false
- (equal src1 src2)
- ; t "set_get" (module Int)
- 5
- State.(get_exn src1 (set src1 5 empty))
- ; t "set_set_get" (module Int)
- 8
- State.(get_exn src1 (set src1 8 (set src1 5 empty)))
- ; t "set_other_get" (module Int)
- 5
- State.(get_exn src1 (set src2 8 (set src1 5 empty)))
- ]
- end;
- "Component.mount">:::begin
- let module T = Ax.Draw_tree in
- let module C = Ax.Component in
- let module B = Ax.Behavior in
- let module S = Ax.Source in
- let module E = Ax.Event in
- let module Sinks_ = Map_(S)(ListUnordered_(T.Path)) in
- let open Ax.Color in
- let open Ax.Math in
- let r1 = C.rect @@ B.const ({w=1;h=1}, red) in
- let r2 = C.rect @@ B.const ({w=2;h=2}, blue) in
- let r3 = C.rect @@ B.const ({w=3;h=3}, white) in
- let r_dyn b = C.rect @@ B.(b >>| fun t -> {w=t;h=t}, black) in
- let state = S.State.of_time 25 in
- [ t "static" (module Ax.Draw_tree)
- C.(let _, _, t = mount state @@
- arm `H [ r1
- ; arm `V [ r2
- ; r3 ] ]
- in t)
- T.(arm `H [ figure (Rect({w=1;h=1}, red))
- ; arm `V [ figure (Rect({w=2;h=2}, blue))
- ; figure (Rect({w=3;h=3}, white)) ] ])
- ; "time">:::begin
- let _, callbacks, tree =
- C.(mount state @@
- arm `H
- [ arm `V
- [ r1
- ; r_dyn B.time ]
- ; r2
- ])
- in
- [ t "init_tree" (module Ax.Draw_tree)
- T.(arm `H [ arm `V [ figure (Rect({w=1;h=1}, red))
- ; figure (Rect({w=25;h=25}, black)) ]
- ; figure (Rect({w=2;h=2}, blue)) ])
- tree
- ; t "sinks" (module Sinks_)
- (Map.of_alist_exn (module S)
- [ S.time, [ [0;1] ] ])
- (Map.map callbacks.sinks ~f:(List.map ~f:fst))
- ; t "handlers" (module ListUnordered_(E.Id))
- []
- (Map.keys callbacks.handlers) ]
- end
- ; "events">:::begin
- let src = S.Private.next_id ~diff:0 in
- let eid1 = E.Id.Private.next_id ~diff:0 in
- let eid2 = E.Id.Private.next_id ~diff:1 in
- let init_state, callbacks, tree =
- C.(mount state @@
- arm `H
- [ arm `V
- [ r1
- ; fold ~init:57 ~f:(fun _ -> Int.succ)
- r_dyn ]
- ; callback ~f:ignore r3
- ])
- in
- [ t "init_tree" (module Ax.Draw_tree)
- T.(arm `H [ arm `V [ figure (Rect({w=1;h=1}, red))
- ; capture eid1
- (figure (Rect({w=57;h=57}, black))) ]
- ; capture eid2
- (figure (Rect({w=3;h=3}, white))) ])
- tree
- ; t "init_state" (module Int)
- 57 (S.State.get_exn src init_state)
- ; t "sinks" (module Sinks_)
- (Map.of_alist_exn (module S)
- [ src, [ [0;1;0] ] ])
- (Map.map callbacks.sinks ~f:(List.map ~f:fst))
- ; t "handlers" (module ListUnordered_(E.Id))
- [eid1;eid2]
- (Map.keys callbacks.handlers)
- ]
- end;
- ]
- end;
- "React_loop">:::begin
- let open Ax.Color in
- let open Ax.Math in
- let open Ax.Component in
- let module B = Ax.Behavior in
- let current_cb = ref ignore in
- let current_time = ref 0 in
- let tick () = Int.incr current_time ; !current_cb Ax.React_loop.Tick in
- let click x y = !current_cb (Ax.React_loop.Click {x;y}) in
- let exit () = !current_cb Ax.React_loop.Exit in
- let module RL =
- Ax.React_loop.Make
- (struct
- type callback_id = unit
- let bind_callback f = current_cb := f
- let unregister () = current_cb := ignore ; logf "unreg"
- let poll_time_ms () = 1000 * !current_time
- end)
- (Logging_graphics)
- in
- [ t_log "no_callbacks"
- [ "clear" ; "rect{<0,0 4x4>;#0ff}" ; "unreg" ]
- (fun () -> RL.run (rect @@ B.const ({w=4;h=4}, cyan))
- ; tick ()
- ; tick ()
- ; exit ())
- ; t_log "simple"
- [ "clear" ; "rect{<0,0 25x26>;#0ff}"
- ; "clear" ; "rect{<0,0 26x27>;#0ff}"
- ; "clear" ; "rect{<0,0 27x28>;#0ff}"
- ; "unreg" ]
- (fun () -> current_time := 25
- ; RL.run (rect B.(time >>| fun t -> {w=t;h=t+1}, cyan))
- ; tick ()
- ; tick ()
- ; exit ())
- ; t_log "click"
- [ "clear" ; "rect{<0,0 25x30>;#0ff}"
- ; "CLICK <5,5>" ; "CLICK <15,5>"
- ; "unreg" ]
- (fun () ->
- let f = function Ax.Event.Click(pos) ->
- logf "CLICK %s" (Pos.to_string pos)
- in
- RL.run (callback ~f (rect (B.const ({w=25;h=30}, cyan))))
- ; click 5 5 ; click 28 5 ; click 15 5 ; click 5 37
- ; exit ())
- ; t_log "click+state"
- [ "clear" ; "rect{<0,0 25x30>;#0ff}"
- ; "clear" ; "rect{<0,0 26x31>;#0ff}"
- ; "clear" ; "rect{<0,0 27x32>;#0ff}"
- ; "unreg" ]
- (fun () ->
- let inc _ n = n + 1 in
- let comp n = rect B.(n >>| fun n -> ({w=n;h=n+5}, cyan)) in
- RL.run (fold ~init:25 ~f:inc comp)
- ; click 5 5 ; click 28 5 ; click 15 5 ; click 5 37
- ; exit ())
- ]
- end;
- ]
|