Daniel@0
|
1 /* Part of DML (Digital Music Laboratory)
|
Daniel@0
|
2 Copyright 2014-2015 Samer Abdallah, University of London
|
Daniel@0
|
3
|
Daniel@0
|
4 This program is free software; you can redistribute it and/or
|
Daniel@0
|
5 modify it under the terms of the GNU General Public License
|
Daniel@0
|
6 as published by the Free Software Foundation; either version 2
|
Daniel@0
|
7 of the License, or (at your option) any later version.
|
Daniel@0
|
8
|
Daniel@0
|
9 This program is distributed in the hope that it will be useful,
|
Daniel@0
|
10 but WITHOUT ANY WARRANTY; without even the implied warranty of
|
Daniel@0
|
11 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
Daniel@0
|
12 GNU General Public License for more details.
|
Daniel@0
|
13
|
Daniel@0
|
14 You should have received a copy of the GNU General Public
|
Daniel@0
|
15 License along with this library; if not, write to the Free Software
|
Daniel@0
|
16 Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
|
Daniel@0
|
17 */
|
Daniel@0
|
18
|
Daniel@0
|
19 :- module(callgraph_ui, []).
|
Daniel@0
|
20
|
Daniel@0
|
21 :- use_module(library(http/html_write)).
|
Daniel@0
|
22 :- use_module(library(http/html_head)).
|
Daniel@0
|
23 :- use_module(library(http/http_dispatch)).
|
Daniel@0
|
24 :- use_module(library(http/http_parameters)).
|
Daniel@0
|
25 :- use_module(library(http/http_host)).
|
Daniel@0
|
26 :- use_module(library(http/js_write)).
|
Daniel@0
|
27 :- use_module(library(semweb/rdfs)).
|
Daniel@0
|
28 :- use_module(library(dcg_core)).
|
Daniel@0
|
29 :- use_module(library(fileutils)).
|
Daniel@0
|
30 :- use_module(library(callgraph)).
|
Daniel@0
|
31 :- use_module(library(decoration)).
|
Daniel@0
|
32 :- use_module(library(httpfiles)).
|
Daniel@0
|
33 :- use_module(components(icons)).
|
Daniel@0
|
34
|
Daniel@0
|
35
|
Daniel@0
|
36 :- http_handler(root(dml/callgraph/ui), callgraph_ui, []).
|
Daniel@0
|
37 :- http_handler(root(dml/callgraph/view), callgraph_viewer, []).
|
Daniel@0
|
38 :- http_handler(api(callgraph/render), callgraph_render, []).
|
Daniel@0
|
39
|
Daniel@0
|
40 :- html_resource(js('callgraph.js'), [requires(jquery)]).
|
Daniel@0
|
41
|
Daniel@0
|
42 cliopatria:menu_item(500=help/callgraph_ui,'Module callgraph').
|
Daniel@0
|
43
|
Daniel@0
|
44 % adds a cube icon to all module URIs to link to rendered callgraph
|
Daniel@0
|
45 decoration:resource_decoration(URI,Link) -->
|
Daniel@0
|
46 {rdfs_individual_of(URI,memo:'Module')}, !,
|
Daniel@0
|
47 {uripattern:pattern_uri(dml:module/prolog/enc(Mod),URI)},
|
Daniel@0
|
48 {http_link_to_id(callgraph_viewer,[module(Mod)],URL)},
|
Daniel@0
|
49 html_requires("//maxcdn.bootstrapcdn.com/font-awesome/4.1.0/css/font-awesome.min.css"),
|
Daniel@0
|
50 html(span([ a(href(URL),[' ',\icon(cube)]), \Link])).
|
Daniel@0
|
51
|
Daniel@0
|
52 %% callgraph_viewer(+Request) is det.
|
Daniel@0
|
53 % Web page displaying the callgraph for a given module.
|
Daniel@0
|
54 % Uses the callgraph_view//1 component for the view area.
|
Daniel@0
|
55 callgraph_viewer(Request) :-
|
Daniel@0
|
56 http_parameters(Request,
|
Daniel@0
|
57 [ module(Module, [ optional(false), description("Name of module to graph") ]) ]),
|
Daniel@0
|
58 reply_html_page(cliopatria(wide), [title(["Module callgraph: ",Module])],
|
Daniel@0
|
59 [ h1(["Module callgraph: ",Module]), \callgraph_view(Module) ],
|
Daniel@0
|
60 [ stable ]).
|
Daniel@0
|
61
|
Daniel@0
|
62
|
Daniel@0
|
63 %% callgraph_view(+Module:module)// is det.
|
Daniel@0
|
64 %
|
Daniel@0
|
65 % HTML component containing a pannable/zoomable SVG callgraph of the named module.
|
Daniel@0
|
66 % The graph itself is rendered by callgraph_render/1 via an HTTP request made just
|
Daniel@0
|
67 % by Javascript code inserted directly after the view element.
|
Daniel@0
|
68 callgraph_view(Module) -->
|
Daniel@0
|
69 html_requires(js('callgraph.js')),
|
Daniel@0
|
70 html_requires(js('svg-pan-zoom.min.js')),
|
Daniel@0
|
71 html_requires(jquery),
|
Daniel@0
|
72 html_post(head,style("svg text {font-family:Times}")),
|
Daniel@0
|
73 {http_link_to_id(callgraph_render,[module(Module),format(svg)],URL)},
|
Daniel@0
|
74 html( [ div([style="width:100%;height:25em;padding:0em",id=output,class="output-box"],[])
|
Daniel@0
|
75 , \js_script({|javascript(URL)|| load_svg('#output',URL);|})
|
Daniel@0
|
76 ]).
|
Daniel@0
|
77
|
Daniel@0
|
78 %% callgraph_render(+Request) is det.
|
Daniel@0
|
79 %
|
Daniel@0
|
80 % Replies with a the predicate dependency graph for a given module, created using library(callgraph).
|
Daniel@0
|
81 % Default reply format is SVG. In some formats, each predicate contains a link to the documentation
|
Daniel@0
|
82 % for that predicate.
|
Daniel@0
|
83 callgraph_render(Request) :-
|
Daniel@0
|
84 http_parameters(Request,
|
Daniel@0
|
85 [ module(Module, [ optional(false), description("Name of module to graph") ]),
|
Daniel@0
|
86 chain(Chain, [ optional(true), default(4), nonneg, description("unflatten -c parameter") ]),
|
Daniel@0
|
87 link(Link, [ optional(true), default(4), nonneg, description("unflatten -l parameter") ]),
|
Daniel@0
|
88 format(Fmt, [ optional(true), default(svg), atom, description("Graphviz output format") ])
|
Daniel@0
|
89 ]),
|
Daniel@0
|
90 debug(callgraph_ui,"Calling callgraph on ~w.",[Module]),
|
Daniel@0
|
91 http_link_to_id(pldoc_object,[object=''],DocBase),
|
Daniel@0
|
92 Method=unflatten([fl(Link),c(Chain)]),
|
Daniel@0
|
93 with_mutex(callgraph,
|
Daniel@0
|
94 with_temp_dir(Dir, (
|
Daniel@0
|
95 atomic_list_concat([Dir,'/',Module,'.',Fmt],File),
|
Daniel@0
|
96 with_output_to(string(_), module_render(Module,[ filename(File), linkbase(DocBase), format(Fmt), method(Method)])),
|
Daniel@0
|
97 reply_file(File,Fmt)))).
|
Daniel@0
|
98
|
Daniel@0
|
99
|
Daniel@0
|
100 %% callgraph_ui(+Request) is det.
|
Daniel@0
|
101 % Web page containing a form for a module name and an output area for
|
Daniel@0
|
102 % rendered graphs. The form and view area are created using the callgraph_view//1 component.
|
Daniel@0
|
103 callgraph_ui(_) :-
|
Daniel@0
|
104 reply_html_page(cliopatria(wide), [title("Module callgraph")],
|
Daniel@0
|
105 [ h1("Module callgraph") , \callgraph ],
|
Daniel@0
|
106 [ stable ]).
|
Daniel@0
|
107
|
Daniel@0
|
108 callgraph -->
|
Daniel@0
|
109 {http_location_by_id(callgraph_render,Loc)},
|
Daniel@0
|
110 html_requires(js('callgraph.js')),
|
Daniel@0
|
111 html_requires(js('svg-pan-zoom.min.js')),
|
Daniel@0
|
112 html_requires(jquery),
|
Daniel@0
|
113 html_post(head,style("svg text {font-family:Times}")),
|
Daniel@0
|
114 % html_post(head,script(type("text/javascript"),
|
Daniel@0
|
115 % "$(document).ready(function() { $('#output').on('load',activate_obj); });")),
|
Daniel@0
|
116 html( div(class="callgraph-ui",
|
Daniel@0
|
117 [ form([class=forms,target=dummy,method=post,action="about:blank",onsubmit="return false;"],
|
Daniel@0
|
118 [ label(["Module"
|
Daniel@0
|
119 , div(class="input-groups",
|
Daniel@0
|
120 [ input([type=text,autocomplete=on,name=module,id=module],[])
|
Daniel@0
|
121 , \seqmap( append_control,
|
Daniel@0
|
122 [ %number(chain,1-10,4)
|
Daniel@0
|
123 button(graph,"update_svg('~w');"-[Loc], "graph")
|
Daniel@0
|
124 , button(clear,"clear_output();", "clear")
|
Daniel@0
|
125 ])
|
Daniel@0
|
126 ])])
|
Daniel@0
|
127 , label(["Output"
|
Daniel@0
|
128 , div([style="width:100%;height:25em;padding:0em",id=output,class="output-box"],[])])
|
Daniel@0
|
129 ])
|
Daniel@0
|
130 , iframe([id=dummy,style="display:none",src="about:blank"],["Dummy"])
|
Daniel@0
|
131 ])).
|
Daniel@0
|
132
|
Daniel@0
|
133 append_control(B1) --> html(span(class="btn-append",\B1)).
|
Daniel@0
|
134
|
Daniel@0
|
135 number(Id,Min-Max,Val) -->
|
Daniel@0
|
136 html(input([type=number,id=Id,name=Id,min=Min,max=Max,value=Val,style="min-width:7ex"],[])).
|
Daniel@0
|
137
|
Daniel@0
|
138 button(Id,OnClick,Label) -->
|
Daniel@0
|
139 html(button([class="btn", onclick=OnClick,id=Id], Label)).
|