(* Copyright (C) 2006, HELM Team. * * This file is part of HELM, an Hypertextual, Electronic * Library of Mathematics, developed at the Computer Science * Department, University of Bologna, Italy. * * HELM is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2 * of the License, or (at your option) any later version. * * HELM 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. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with HELM; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, * MA 02111-1307, USA. * * For details, see the HELM World-Wide-Web page, * http://helm.cs.unibo.it/ *) (* $Id$ *) open Printf type attribute = string * string (* pair *) let png_flags = "-Tpng" let map_flags = "-Tcmapx" let tempfile () = Filename.temp_file "matita_" "" class type graphviz_widget = object method load_graph_from_file: string -> unit method connect_href: (GdkEvent.Button.t -> (string * string) list -> unit) -> unit method as_image: GMisc.image method as_viewport: GBin.viewport end class graphviz_impl ?packing gviz_cmd = let viewport = GBin.viewport ?packing () in let image = GMisc.image ~packing:viewport#add ~xalign:0. ~yalign:0. ~xpad:0 ~ypad:0 () in object (self) val mutable href_cb = fun _ _ -> () val mutable map = [] initializer ignore (viewport#event#connect#button_press (fun button -> (*eprintf "x: %f; y: %f;\n%!" (GdkEvent.Button.x button +. viewport#hadjustment#value) (GdkEvent.Button.y button +. viewport#vadjustment#value);*) (* compute coordinates relative to image origin *) let x = GdkEvent.Button.x button +. viewport#hadjustment#value in let y = GdkEvent.Button.y button +. viewport#vadjustment#value in (try href_cb button (self#find_href x y) with Not_found -> ()); false)) method load_graph_from_file fname = let tmp_png = tempfile () in ignore (Sys.command (sprintf "%s %s %s > %s" gviz_cmd png_flags fname tmp_png)); image#set_file tmp_png; HExtlib.safe_remove tmp_png; let tmp_map = tempfile () in ignore (Sys.command (sprintf "%s %s %s > %s" gviz_cmd map_flags fname tmp_map)); self#load_map tmp_map; HExtlib.safe_remove tmp_map method private load_map fname = let areas = ref [] in let p = XmlPushParser.create_parser { XmlPushParser.default_callbacks with XmlPushParser.start_element = Some (fun elt attrs -> match elt with | "area" -> areas := attrs :: !areas | _ -> ()) } in XmlPushParser.parse p (`File fname); map <- !areas method private find_href x y = let parse_coords s = match List.map float_of_string (HExtlib.split ~sep:',' s) with | [x1; y1; x2; y2 ] -> x1, y1, x2, y2 | _ -> assert false in List.find (fun attrs -> let x1, y1, x2, y2 = parse_coords (List.assoc "coords" attrs) in x1 <= x && x <= x2 && y1 <= y && y <= y2) map method connect_href (cb: GdkEvent.Button.t -> (string * string) list -> unit) = href_cb <- cb method as_image = image method as_viewport = viewport end let factory cmd ?packing () = (new graphviz_impl ?packing cmd :> graphviz_widget) let gDot = factory "dot" let gNeato = factory "neato" let gTwopi = factory "twopi" let gCirco = factory "circo" let gFdp = factory "fdp" module Pp = struct module type GraphvizFormatter = sig val header: ?name:string -> Format.formatter -> unit val node: string -> ?attrs:(attribute list) -> Format.formatter -> unit val edge: string -> string -> ?attrs:(attribute list) -> Format.formatter -> unit val raw: string -> Format.formatter -> unit val trailer: Format.formatter -> unit end open Format module Dot = struct let attribute fmt (k, v) = fprintf fmt "@[%s=@,\"%s\",@]" k v let attributes attrs fmt = List.iter (attribute fmt) attrs let header ?(name = "g") fmt = fprintf fmt "@[digraph %s {@," name let node name ?(attrs = []) fmt = fprintf fmt "@[%s@ [" name; attributes attrs fmt; fprintf fmt "];@]@," let edge name1 name2 ?(attrs = []) fmt = fprintf fmt "@[%s ->@ %s@ [" name1 name2; attributes attrs fmt; fprintf fmt "];@]@," let raw s fmt = pp_print_string fmt s let trailer fmt = fprintf fmt "@,}@]%!" end end