component.ml 2.3 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980
  1. open Base
  2. type t =
  3. | Arm of Draw_tree.dir * t list
  4. | Figure of fig_b
  5. | With_handler of Event.handler * t
  6. | With_fold of Source.value
  7. * (Event.t -> Source.value -> Source.value)
  8. * (Source.t -> t)
  9. and fig_b =
  10. Draw_tree.fig Behavior.t
  11. let arm dir ts =
  12. Arm(dir, ts)
  13. let rect b =
  14. let f (dim, c) = Draw_tree.Rect(dim, c) in
  15. Figure(Behavior.map b ~f)
  16. let callback ~f t =
  17. let handler e = f e ; Source.empty_map in
  18. With_handler(handler, t)
  19. let fold ~init ~f make_child =
  20. With_fold (init, f, fun src -> make_child (Behavior.of_source src))
  21. type sink = Draw_tree.Path.t * fig_b
  22. type callbacks =
  23. { sinks : sink list Source.map
  24. ; handlers : Event.handler Event.map
  25. }
  26. let empty_callbacks =
  27. { sinks = Source.empty_map
  28. ; handlers = Event.empty_map }
  29. let mount state t0 : Source.State.t * callbacks * Draw_tree.t =
  30. let state = ref state in
  31. let rec mount rev_path callbacks = function
  32. | Arm(dir, ts) ->
  33. let mount' i cbs t = mount (i::rev_path) cbs t in
  34. let callbacks, dts = List.fold_mapi ts ~init:callbacks ~f:mount' in
  35. callbacks, Draw_tree.arm dir dts
  36. | Figure(fb) ->
  37. let deps = Behavior.dependencies fb in
  38. let callbacks =
  39. if Sequence.is_empty deps then
  40. callbacks
  41. else
  42. let path = Draw_tree.Path.of_list_rev rev_path in
  43. let register cbs src =
  44. { cbs with
  45. sinks = Map.add_multi cbs.sinks
  46. ~key:src ~data:(path, fb) }
  47. in
  48. Sequence.fold deps ~init:callbacks ~f:register
  49. in
  50. callbacks, Draw_tree.figure (Behavior.sample fb !state)
  51. | With_handler(handler, child) ->
  52. mount_handler rev_path callbacks handler child
  53. | With_fold(init, f, make_child) ->
  54. let src = Source.create () in
  55. let () = state := Source.State.set src init !state in
  56. mount_handler rev_path callbacks
  57. (fun ev -> Map.singleton (module Source) src (f ev))
  58. (make_child src)
  59. and mount_handler rev_path callbacks handler child =
  60. let ev_id = Event.Id.gen () in
  61. let callbacks, dt = mount (0::rev_path) callbacks child in
  62. { callbacks with
  63. handlers = Map.add_exn callbacks.handlers
  64. ~key:ev_id ~data:handler },
  65. Draw_tree.capture ev_id dt
  66. in
  67. let cbs, dt = mount [] empty_callbacks t0 in
  68. !state, cbs, dt