/src/dialog.ml

http://github.com/hhughes/ocaml-frui · OCaml · 116 lines · 105 code · 11 blank · 0 comment · 7 complexity · 0734ced8789340c8a750e27d65fd5234 MD5 · raw file

  1. module D = Dom
  2. module F = Froc
  3. module Fd = Froc_dom
  4. type dlgstate =
  5. Normal
  6. | Moving of int * int
  7. | Resizing of int * int
  8. let set_text (e : D.element) text =
  9. let text_node = (D.document#createTextNode "" : D.text) in
  10. text_node#_set_data text;
  11. ignore (e#appendChild text_node)
  12. let mouse_down_if_e p (elt : D.element) =
  13. let e, s = F.make_event () in
  14. let f_down me = if p me then F.send s (true, me#_get_clientX - elt#_get_offsetLeft, me#_get_clientY - elt#_get_offsetTop) in
  15. let f_up me = if p me then F.send s (false, me#_get_clientX - elt#_get_offsetLeft, me#_get_clientY - elt#_get_offsetTop) in
  16. elt#addEventListener_mouseEvent_ "mousedown" f_down false;
  17. elt#addEventListener_mouseEvent_ "mouseup" f_up false;
  18. F.cleanup (fun () -> elt#removeEventListener_mouseEvent_ "mousedown" f_down false; elt#removeEventListener_mouseEvent_ "mouseup" f_up false);
  19. e
  20. let mouse_down_e (elt : D.element) = mouse_down_if_e (fun x -> true) elt
  21. class dialog ~elt:(elt: D.element) ?x0:(x=50) ?y0:(y=50) () =
  22. object (self)
  23. val dialog = (D.document#createElement "div")
  24. val mutable state = Normal
  25. method add_title =
  26. let title = (D.document#createElement "div") in
  27. let close = (D.document#createElement "div") in
  28. set_text title "title";
  29. set_text close "x";
  30. ignore (title#_get_style#_set_border "1px solid black");
  31. ignore (title#_get_style#_set_display "absolute");
  32. ignore (title#_get_style#_set_left "0");
  33. ignore (title#_get_style#_set_top "0");
  34. ignore (title#_get_style#_set_right "0");
  35. ignore (title#_get_style#_set_height "20px");
  36. ignore (close#_get_style#_set_display "inline-block");
  37. ignore (close#_get_style#_set_position "absolute");
  38. ignore (close#_get_style#_set_right "5px");
  39. ignore (close#_get_style#_set_cursor "hand");
  40. close#_set_onclick
  41. (fun _ -> self#hide; true);
  42. ignore (title#appendChild close);
  43. ignore (dialog#appendChild title)
  44. method add_body =
  45. let body = (D.document#createElement "div") in
  46. set_text body "body";
  47. ignore (body#_get_style#_set_position "absolute");
  48. ignore (body#_get_style#_set_border "1px solid black");
  49. ignore (body#_get_style#_set_borderTop "1px none black");
  50. ignore (body#_get_style#_set_left "0");
  51. ignore (body#_get_style#_set_top "20px");
  52. ignore (body#_get_style#_set_right "0");
  53. ignore (body#_get_style#_set_bottom "0");
  54. ignore (dialog#appendChild body)
  55. method add_mouse_events =
  56. let mouse_move = Fd.mouse_b () in
  57. Fd.appendChild elt
  58. (F.blift mouse_move (fun (x,y) ->
  59. match state with
  60. | Moving (o_x, o_y) ->
  61. begin
  62. dialog#_get_style#_set_left (string_of_int (x - o_x));
  63. dialog#_get_style#_set_top (string_of_int (y - o_y));
  64. dialog
  65. end
  66. | Resizing (o_x, o_y) ->
  67. begin
  68. let l = dialog#_get_offsetLeft in
  69. let t = dialog#_get_offsetTop in
  70. dialog#_get_style#_set_width (string_of_int (x - l + 5));
  71. dialog#_get_style#_set_height (string_of_int (y - t + 5));
  72. dialog
  73. end
  74. | _ -> dialog
  75. ));
  76. let is_resize me =
  77. let x = me#_get_clientX in
  78. let y = me#_get_clientY in
  79. let l = dialog#_get_offsetLeft in
  80. let t = dialog#_get_offsetTop in
  81. let w = dialog#_get_offsetWidth in
  82. let h = dialog#_get_offsetHeight in
  83. x > (l+w)-20 && y > (t+h)-20
  84. in
  85. let mouse_down_move = F.hold (false,0,0) (mouse_down_if_e (fun me -> not (is_resize me)) dialog) in
  86. F.notify_result_b (F.blift mouse_down_move (fun a -> a)) (fun r -> match r with
  87. | F.Value (b,x,y) -> (state <- if b then Moving (x,y) else Normal)
  88. | _ -> ());
  89. let mouse_down_resize = F.hold (false,0,0) (mouse_down_if_e (fun me -> is_resize me) dialog) in
  90. F.notify_result_b (F.blift mouse_down_resize (fun a -> a)) (fun r -> match r with
  91. | F.Value (b,x,y) -> (state <- if b then Resizing (x,y) else Normal)
  92. | _ -> ())
  93. method hide = ignore (elt#removeChild dialog);
  94. method decorate =
  95. self#add_title;
  96. self#add_body;
  97. self#add_mouse_events;
  98. ignore (dialog#_get_style#_set_display "inline-block");
  99. ignore (dialog#_get_style#_set_position "absolute");
  100. ignore (dialog#_get_style#_set_width "200px");
  101. ignore (dialog#_get_style#_set_height "150px");
  102. ignore (dialog#_get_style#_set_left (string_of_int x));
  103. ignore (dialog#_get_style#_set_top (string_of_int y))
  104. initializer self#decorate
  105. end