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 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 293 294 295 296 297 298 299 300 301 302 303 304 305 306 307 308 309 310 311 312 313 314 315 316 317 318 319 320 321 322 323 324 325
|
(**************************************************************************)
(* *)
(* Ocamlgraph: a generic graph library for OCaml *)
(* Copyright (C) 2004-2007 *)
(* Sylvain Conchon, Jean-Christophe Filliatre and Julien Signoles *)
(* *)
(* This software is free software; you can redistribute it and/or *)
(* modify it under the terms of the GNU Library General Public *)
(* License version 2, with the special exception on linking *)
(* described in file LICENSE. *)
(* *)
(* This software is distributed in the hope that it will be useful, *)
(* but WITHOUT ANY WARRANTY; without even the implied warranty of *)
(* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. *)
(* *)
(**************************************************************************)
(* This file is a contribution of Benjamin Vadon *)
open Graph
open Ed_hyper
type visibility = Visible | BorderNode | Hidden
type mode = Normal | Selected | Focused | Selected_Focused
type node_info =
{
label : string;
mutable visible : visibility;
mutable depth : int;
mutable vertex_mode : mode;
mutable turtle : turtle;
}
let make_node_info s =
{
label = s;
visible = Hidden;
depth = 0;
vertex_mode = Normal;
turtle = dummy_turtle
}
type edge_info =
{
mutable visited : bool;
mutable edge_mode : mode;
mutable edge_turtle : turtle;
mutable edge_distance : float;
mutable edge_steps : int;
}
let make_edge_info () =
{
visited = false;
edge_mode = Normal;
edge_turtle = dummy_turtle;
edge_distance = 0.;
edge_steps = 0;
}
module EDGE = struct
type t = edge_info
let compare = Pervasives.compare
let default = make_edge_info ()
end
module G =
Imperative.Graph.AbstractLabeled(struct type t = node_info end)(EDGE)
module B = Builder.I(G)
(* current graph *)
let graph = ref (G.create ())
type name = string option
let graph_name = ref (None: name)
(* useful functions for vertex and edge *)
let string_of_label x = (G.V.label x).label
let edge v w = G.mem_edge !graph v w || G.mem_edge !graph w v
(* two Parser modules *)
module GmlParser =
Gml.Parse
(B)
(struct
let node l =
make_node_info
(try
match List.assoc "id" l
with Gml.Int n -> string_of_int n | _ -> "<no id>"
with Not_found -> "<no id>")
let edge _ = make_edge_info ()
end)
module DotParser =
Dot.Parse
(B)
(struct
let node (id,_) _ = match id with
| Dot_ast.Ident s
| Dot_ast.Number s
| Dot_ast.String s
| Dot_ast.Html s -> make_node_info s
let edge _ = make_edge_info ()
end)
(* a parsing file function *)
let parse_file f =
if Filename.check_suffix f ".gml" then
GmlParser.parse f
else
DotParser.parse f
(* two Printer Modules *)
module GmlPrinter =
Gml.Print
(G)
(struct
let node (v: G.V.label) = ["label", Gml.Int (int_of_string v.label)]
let edge (e: G.E.label) = []
end)
module DotPrinter =
Graphviz.Dot
( struct
include G
let vertex_name vertex = string_of_label vertex
let graph_attributes _ = []
let default_vertex_attributes _ = []
let vertex_attributes _ = []
let default_edge_attributes _ = []
let edge_attributes _ = []
let get_subgraph _ = None
end )
(* two outputs functions, and a save graph function *)
let gml_output g f =
let c = open_out f in
let fmt = Format.formatter_of_out_channel c in
Format.fprintf fmt "%a@." GmlPrinter.print g;
close_out c
let dot_output g f =
let oc = open_out f in
DotPrinter.output_graph oc g;
close_out oc
let save_graph name =
if Filename.check_suffix name "gml"
then ( gml_output !graph name; graph_name := Some name)
else if Filename.check_suffix name "dot"
then ( dot_output !graph name; graph_name := Some name)
else ( let name = name^".dot" in
dot_output !graph name;
graph_name := Some name )
module Components = Components.Make(G)
module Dfs = Traverse.Dfs(G)
exception Choose of G.V.t
let choose_root () =
try
G.iter_vertex (fun v -> raise (Choose v)) !graph;
None
with Choose v ->
Some v
(* Parsing of the command line *)
let load_graph f =
graph := parse_file f;
graph_name := Some f
let dfs = ref false
let refresh_rate = ref 10
let aa = ref true
let () =
Arg.parse
["-dfs", Arg.Set dfs, "DFS drawing strategy";
"-bfs", Arg.Clear dfs, "BFS drawing strategy";
"-rr", Arg.Set_int refresh_rate, "set the refresh rate, must be greater than 0";
"-aa", Arg.Clear aa, "turn off anti-aliased mode";
]
load_graph
"editor [options] <graph file>"
(* successor edges *)
module H2 =
Hashtbl.Make
(struct
type t = G.V.t * G.V.t
let hash (v,w) = Hashtbl.hash (G.V.hash v, G.V.hash w)
let equal (v1,w1) (v2,w2) = G.V.equal v1 v2 && G.V.equal w1 w2
end)
module H = Hashtbl.Make(G.V)
(* vertex select and unselect *)
(* a counter for selected vertices *)
let nb_selected = ref 0
(* a belonging test to selection *)
let is_selected (x:G.V.t) =
let mode =(G.V.label x).vertex_mode in
mode = Selected ||
mode = Selected_Focused
type mode_select_list =
REMOVE_FROM of G.V.t
| ADD_FROM of G.V.t
| NONE
let selected_list mode =
let vertex_selection =ref [] in
G.iter_vertex (fun v ->
if (is_selected v)
&& (match mode with
| ADD_FROM vertex -> not (edge v vertex)
| REMOVE_FROM vertex -> (edge v vertex)
| NONE -> true)
then vertex_selection := v::(!vertex_selection)) !graph;
let compare s1 s2 = String.compare (string_of_label s1) (string_of_label s2) in
List.sort compare !vertex_selection
type ed_event = Select | Unselect | Focus | Unfocus
let update_vertex vertex event =
let vertex_info = G.V.label vertex in
begin
match vertex_info.vertex_mode, event with
| Normal, Select -> vertex_info.vertex_mode <- Selected; incr nb_selected
| Normal, Focus -> vertex_info.vertex_mode <- Focused
| Normal, _ -> ()
| Selected, Focus -> vertex_info.vertex_mode <- Selected_Focused
| Selected, Unselect -> vertex_info.vertex_mode <- Normal; decr nb_selected
| Selected, _ -> ()
| Focused, Select -> vertex_info.vertex_mode <- Selected_Focused; incr nb_selected
| Focused, Unfocus -> vertex_info.vertex_mode <- Normal
| Focused, _ -> ()
| Selected_Focused, Unselect -> vertex_info.vertex_mode <- Focused; decr nb_selected
| Selected_Focused, Unfocus -> vertex_info.vertex_mode <- Selected
| Selected_Focused, _ -> ()
end;
G.iter_succ_e
( fun edge ->
let edge_info = G.E.label edge in
let dest_vertex = G.E.dst edge in
begin match edge_info.edge_mode, event with
| Normal, Select -> edge_info.edge_mode <- Selected
| Normal, Focus -> edge_info.edge_mode <- Focused
| Normal, _ -> ()
| Selected, Focus -> edge_info.edge_mode <- Selected_Focused
| Selected, Unselect -> if not(is_selected dest_vertex) then edge_info.edge_mode <- Normal
| Selected, _ -> ()
| Focused, Select -> edge_info.edge_mode <- Selected_Focused
| Focused, Unfocus -> edge_info.edge_mode <- Normal
| Focused, _ -> ()
| Selected_Focused, Unselect -> if not(is_selected dest_vertex) then edge_info.edge_mode <- Focused; decr nb_selected
| Selected_Focused, Unfocus -> edge_info.edge_mode <- Selected
| Selected_Focused, _ -> ()
end;
) !graph vertex
(* to select and unselect all vertices *)
let select_all () =
G.iter_vertex (fun v ->
if not(is_selected v)
then begin
let v = G.V.label v in
v.vertex_mode <- Selected;
incr nb_selected
end
) !graph;
G.iter_edges_e (fun e -> let e = G.E.label e in e.edge_mode <- Selected) !graph
let unselect_all () =
G.iter_vertex (fun v ->
if (is_selected v)
then begin
let l = G.V.label v in
l.vertex_mode <- Normal;
decr nb_selected
end
) !graph;
G.iter_edges_e (fun e -> let e = G.E.label e in e.edge_mode <- Normal) !graph
|