(**************************************************************************)
(*                                                                        *)
(*  Ocamlviz --- real-time profiling tools for Objective Caml             *)
(*  Copyright (C) by INRIA - CNRS - Universite Paris Sud                  *)
(*  Authors: Julien Robert                                                *)
(*           Guillaume Von Tokarski                                       *)
(*           Sylvain Conchon                                              *)
(*           Jean-Christophe Filliatre                                    *)
(*           Fabrice Le Fessant                                           *)
(*  GNU Library General Public License version 2                          *)
(*  See file LICENSE for details                                          *)
(*                                                                        *)
(**************************************************************************)

let record_scale = ref None
let record_window = ref 0.

type default_preferences = {
  mutable steps : int;
  mutable gridx : int;
  mutable gridy : int;
  mutable xaxis : int;
  mutable yaxis : int;
  mutable period : int;
}

let pref_file = "preferences"
let default_pref =
  let st,gx,gy,xa,ya,p,r,l = Preflexer.read_file pref_file in
  record_window := r;
  Db.set_record_window r;
  Db.set_log_size l;
  {steps=st;gridx=gx;gridy=gy;xaxis=xa;yaxis=ya;period=p}



(***************************************************
                     PREFERENCES
****************************************************
****************************************************)

let save_preferences () = 
  let f = open_out pref_file in
  let fmt = Format.formatter_of_out_channel f in
  Format.fprintf fmt "steps %d \n" default_pref.steps;
  Format.fprintf fmt "gridx %d \n" default_pref.gridx;
  Format.fprintf fmt "gridy %d \n" default_pref.gridy;
  Format.fprintf fmt "xaxis %d \n" default_pref.xaxis;
  Format.fprintf fmt "yaxis %d \n" default_pref.yaxis;
  Format.fprintf fmt "period %d \n" default_pref.period;
  Format.fprintf fmt "record %f \n" !record_window;
  Format.fprintf fmt "log %d \n" (Db.get_log_size ());
  Format.fprintf fmt "@?";
  close_out f


let mk_label_and_spin (table : GPack.table) s top digits =
  let markup = Format.sprintf "<span weight=\"bold\">%s</span>" s in
  let _ = GMisc.label ~markup ~packing:(table#attach ~left:0 ~top)  () in
  let spin = GEdit.spin_button ~digits 
    ~update_policy:`IF_VALID ~packing:(table#attach ~left:1 ~top) () in
  spin

let mk_label_and_toggle (table : GPack.table) s top =
  let markup = Format.sprintf "<span weight=\"bold\">%s</span>" s in
  let _ = GMisc.label ~markup ~packing:(table#attach ~left:0 ~top)  () in
  let toggle = GButton.check_button ~packing:(table#attach ~left:1 ~top) () in
  toggle

let mk_time_window_preferences window = 
  let dial = GWindow.dialog ~title:" Time Window Preferences" ~position:`MOUSE ~parent:window () in
  let table = GPack.table ~rows:2 ~columns:2 
    ~col_spacings:5 ~row_spacings:10 ~packing:(dial#vbox#pack ~expand:false) () in

  let spin_time = mk_label_and_spin table "Record time" 0 2 in
  spin_time#adjustment#set_bounds ~lower:0. ~upper:3600. ~step_incr:1. ~page_incr:10. ();
  spin_time#set_value !record_window;

  let check_button = mk_label_and_toggle table "Save as default" 1 in

  let hb = GPack.hbox ~packing:(dial#vbox#pack ~expand:false) () in
  
  let bcancel = GButton.button ~packing:hb#add () in
  let im_cancel = GMisc.image ~stock:`CANCEL ~icon_size:`MENU () in
  bcancel#set_image im_cancel#coerce;
  ignore(bcancel#connect#clicked
	   ~callback:(fun () -> dial#destroy ()));

  let baccept = GButton.button ~packing:hb#add () in
  let im_accept = GMisc.image ~stock:`APPLY ~icon_size:`MENU () in
  baccept#set_image im_accept#coerce;

  ignore(baccept#connect#clicked
	   ~callback:(fun () -> 
			let nw = spin_time#adjustment#value in
			record_window := nw;
			Db.set_record_window nw;
			begin
			match !record_scale with
			  |None -> ()
			  |Some (scl: GRange.scale) ->   
			     scl#adjustment#set_bounds 
			       ~lower:(-. !record_window) ~upper:0.0 ~step_incr:0.01 ~page_incr:0.05 ()
			end;
			if check_button#active then save_preferences ();
			dial#destroy ()
		     ));
  dial#show ()


let mk_log_preferences window = 
  let dial = GWindow.dialog ~title:" Log Preferences" ~position:`MOUSE ~parent:window () in
  let table = GPack.table ~rows:2 ~columns:2 
    ~col_spacings:5 ~row_spacings:10 ~packing:(dial#vbox#pack ~expand:false) () in

  let spin_log = mk_label_and_spin table "Log size" 0 0 in
  spin_log#adjustment#set_bounds ~lower:1. ~upper:1000. ~step_incr:1. ~page_incr:10. ();
  spin_log#set_value (float (Db.get_log_size ()));

  let check_button = mk_label_and_toggle table "Save as default" 1 in

  let hb = GPack.hbox ~packing:(dial#vbox#pack ~expand:false) () in
  
  let bcancel = GButton.button ~packing:hb#add () in
  let im_cancel = GMisc.image ~stock:`CANCEL ~icon_size:`MENU () in
  bcancel#set_image im_cancel#coerce;
  ignore(bcancel#connect#clicked
	   ~callback:(fun () -> dial#destroy ()));

  let baccept = GButton.button ~packing:hb#add () in
  let im_accept = GMisc.image ~stock:`APPLY ~icon_size:`MENU () in
  baccept#set_image im_accept#coerce;

  ignore(baccept#connect#clicked
	   ~callback:(fun () -> 
			let size = spin_log#adjustment#value in
			Db.set_log_size (int_of_float size);
			if check_button#active then save_preferences ();
			dial#destroy ()
		     ));
  dial#show ()


let mk_pref window title = 
  let dial = GWindow.dialog ~title ~position:`MOUSE ~parent:window () in
  let table = GPack.table ~rows:6 ~columns:2 
    ~col_spacings:5 ~row_spacings:10 ~packing:(dial#vbox#pack ~expand:false) () in
   
  let spin_time = mk_label_and_spin table "Displayed time" 0 0 in
  spin_time#adjustment#set_bounds ~lower:5. ~upper:3600. ~step_incr:5. ~page_incr:50. ();

  let spin_divx = mk_label_and_spin table "X-axis divisions" 1 0 in
  spin_divx#adjustment#set_bounds ~lower:2. ~upper:30. ~step_incr:1. ~page_incr:1. ();

  let spin_divy = mk_label_and_spin table "Y-axis divisions" 2 0 in
  spin_divy#adjustment#set_bounds ~lower:2. ~upper:30. ~step_incr:1. ~page_incr:1. ();

  let spin_x = mk_label_and_spin table "X-axis legend frequency" 3 0 in
  spin_x#adjustment#set_bounds ~lower:1. ~upper:30. ~step_incr:1. ~page_incr:5. ();

  let spin_y = mk_label_and_spin table "Y-axis legend frequency" 4 0 in
  spin_y#adjustment#set_bounds ~lower:1. ~upper:30. ~step_incr:1. ~page_incr:5. ();

  let check_button = mk_label_and_toggle table "Save as default" 5 in

  let hb = GPack.hbox ~packing:(dial#vbox#pack ~expand:false) () in
  
  let bcancel = GButton.button ~packing:hb#add () in
  let im_cancel = GMisc.image ~stock:`CANCEL ~icon_size:`MENU () in
  bcancel#set_image im_cancel#coerce;
  ignore(bcancel#connect#clicked
	   ~callback:(fun () -> dial#destroy ()));

  let baccept = GButton.button ~packing:hb#add () in
  let im_accept = GMisc.image ~stock:`APPLY ~icon_size:`MENU () in
  baccept#set_image im_accept#coerce;

  dial#show ();
  (spin_time,spin_divx,spin_divy,spin_x,spin_y,baccept,check_button,dial)

 
let mk_graph_preferences_menu window =
  let st,sdx,sdy,sx,sy,ba,cb,dial = mk_pref window "Graph Preferences" in
  st#set_value ((float default_pref.steps) *. (float default_pref.period) /. 1000.);
  sdx#set_value (float default_pref.gridx);
  sdy#set_value (float default_pref.gridy);
  ignore(ba#connect#clicked
    ~callback:(fun () -> 
		 default_pref.steps <- (int_of_float (st#value) * 1000 / default_pref.period);
		 default_pref.gridx <- int_of_float (sdx#value);
		 default_pref.gridy <- int_of_float (sdy#value);
		 default_pref.xaxis <- int_of_float (sx#value);
		 default_pref.yaxis <- int_of_float (sy#value);
		 if cb#active then save_preferences ();
		 dial#destroy ()))
    

let mk_preferences_graph window gr name =
  let st,sdx,sdy,sx,sy,ba,cb,dial = mk_pref window (Format.sprintf "%s Preferences" name) in
  st#set_value (float (Graph.get_steps gr) *. float (Graph.get_period gr) /. 1000.);
  sdx#set_value (float (Graph.get_gridx gr));
  sdy#set_value (float (Graph.get_gridy gr));
  sx#set_value (float (Graph.get_xaxis gr));
  sy#set_value (float (Graph.get_yaxis gr));
  ignore(ba#connect#clicked
	   ~callback:(fun () ->
			Graph.set_preferences gr ~step:(int_of_float (st#value) * 1000 / (Graph.get_period gr))
			  ~divx:(int_of_float (sdx#value)) ~divy:(int_of_float (sdy#value)) ~xaxis:(int_of_float (sx#value)) 
			  ~yaxis:(int_of_float (sy#value)) ;
			if cb#active then 
			  begin 
			    default_pref.steps <- (int_of_float (st#value) * 1000 / default_pref.period);
			    default_pref.gridx <- int_of_float (sdx#value);
			    default_pref.gridy <- int_of_float (sdy#value);
			    default_pref.xaxis <- int_of_float (sx#value);
			    default_pref.yaxis <- int_of_float (sy#value);
			    save_preferences ();
			  end;
			dial#destroy ()))




 (*
Local Variables: 
compile-command: "unset LANG; make -C .."
End: 
*)
