blob: 75c4fcdbff662f68cf8e7f740c498d4402b8f869 (
plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
|
open Js_of_ocaml
open Js_of_ocaml_lwt
(** Event generated once the library has created the svg image *)
let (generated_svg_event:(Dom_svg.svgElement Js.t * Js.js_string Js.t) Dom.Event.typ)
= Dom_html.Event.make "generated_svg"
(* Save the generated image *)
let on_result_png image = begin
let a = Dom_html.createA Dom_html.document in
a##.href := image##.src;
Js.Unsafe.set a (Js.string "download") (Js.string "output.png");
Dom.appendChild Dom_html.document##.body a;
a##click;
Dom.removeChild Dom_html.document##.body a
end
let on_result_svg
: Dom_html.element Js.t -> (Dom.node Js.t) -> unit
= fun svg_display image -> begin
let childNodes = svg_display##.childNodes in
for i = 0 to childNodes##.length do
Js.Opt.iter (childNodes##item i) (fun elem -> ignore @@ svg_display##removeChild elem)
done;
Dom.appendChild svg_display image;
()
end
let download data (filename : Js.js_string Js.t) (mime: Js.js_string Js.t)
= Js.Unsafe.(
fun_call (js_expr "download")
[| inject data
; inject filename
; inject mime |])
(** Message send by the worker *)
type message = Process.t
type worker = (Js.js_string Js.t, message) Worker.worker Js.t
let change_event (worker:worker) input _ev _ = begin
let text: Js.js_string Js.t = input##.value in
(* Send the content to the worker *)
let () = worker##postMessage text in
Lwt.return_unit
end
class type _Dom_parser = object
method parseFromString: Js.js_string Js.t -> Js.js_string Js.t -> Dom_html.document Js.t Js.meth
end
let dom_parser = (Js.Unsafe.global##._DOMParser)
let dom_parser = new%js dom_parser
let load () =
(* The URL is be relative with the page location. If the worker is called
from diffenent location, it becomes mandatory to declare the URL as
absolute. *)
let (worker:worker) = Worker.create "/resources/viz.js/worker.js" in
worker##.onmessage := Dom.handler (fun (event: message Worker.messageEvent Js.t) ->
let gv, image = event##.data in
let image = dom_parser##parseFromString image "image/svg+xml" in
let image = image##.documentElement in
let _ = Dispatch.call generated_svg_event (image, gv) in
Js._true);
let svg_display = Dom_html.getElementById_exn "svg"
and output_button = Dom_html.getElementById_exn "png_output"
and dot_button = Dom_html.getElementById_exn "dot_output"
and editor = Dom_html.getElementById_exn "editor" in
ignore @@ Dispatch.register generated_svg_event (fun (image, input) ->
on_result_svg svg_display (image :> Dom.node Js.t);
(* Download the dot file *)
dot_button##.onclick := Dom_html.handler (fun _ev ->
let _ = download input (Js.string "output.dot") (Js.string "text/plain") in
Js._false
);
(* Convert the svg in png *)
output_button##.onclick := Dom_html.handler (fun _->
(*download image*)
CanvasTool.generate_png image (fun image ->
let _ = download image (Js.string "output.png") (Js.string "text/plain") in
()
);
Js._false
);
);
Js.Opt.iter (Dom_html.CoerceTo.textarea editor) (fun input ->
Lwt_js_events.async (fun () -> (Lwt_js_events.limited_loop Lwt_js_events.change ~elapsed_time:0.1 editor (change_event worker input) ));
Lwt_js_events.async (fun () -> (Lwt_js_events.limited_loop Lwt_js_events.input ~elapsed_time:0.1 editor (change_event worker input) ));
(* Run the first generation *)
Lwt.ignore_result (change_event worker input () ());
);
(** Handle the separation window *)
Option.iter
(fun button ->
let _ = Dom_events.listen button Dom_html.Event.click (fun _ _ ->
let opt_window2 = Dom_html.window##open_
(Js.string "")
(Js.string "_image")
Js.Opt.empty in
Js.Opt.iter opt_window2 (fun window2 ->
let callback
: Dom_svg.svgElement Js.t * Js.js_string Js.t -> unit
= fun (image, _gv) -> begin
let node2 = image##cloneNode Js._true in
let () = on_result_svg window2##.document##.body
(node2 :> Dom.node Js.t) in
()
end in
let handler = Dispatch.register generated_svg_event callback in
(* Remove the update event when the window is closed *)
window2##.onunload := Dom_html.handler (fun _ev ->
Dispatch.remove generated_svg_event handler;
Js._false
);
(* Copy the current display to the new window *)
let childNodes = svg_display##.childNodes in
for i = 0 to childNodes##.length do
Js.Opt.iter
(childNodes##item i)
(fun elem ->
Dom.appendChild window2##.document##.body (elem##cloneNode Js._true)
)
done;
);
false
) in
()
)
(Dom_html.getElementById_opt "btn_window");
Lwt.return Js._false
let _ = Lwt.bind (Lwt_js_events.onload ()) (fun _ -> load())
let _ =
Js.export "generator"
(object%js
method load = load ()
end)
|