diff --git a/src/plugins/gui/gtk_helper.ml b/src/plugins/gui/gtk_helper.ml index 63bbcd3c9f4535fb2d4bce5a5ed485aaec8db6a4..0c3551ccbb0663fc2a0859f8a2c8561377f999f7 100644 --- a/src/plugins/gui/gtk_helper.ml +++ b/src/plugins/gui/gtk_helper.ml @@ -121,6 +121,11 @@ module Configuration = struct widget#set init ; widget#connect (set_bool key) + let config_float ~key ~default widget = + let init = find_float ~default key in + widget#set init ; + widget#connect (set_float key) + let config_values ~key ~default ~values widget = begin let of_string s = fst (List.find (fun e -> snd e = s) values) in @@ -366,7 +371,7 @@ let on_bool ?tooltip ?use_markup (container:GPack.box) label get set = let container = GPack.hbox ~packing:container#pack () in do_tooltip ?tooltip container; let button = - GButton.check_button ~packing:container#pack ~active:!result () + GButton.check_button ~packing:container#pack ~active:!result () in ignore (mk_label ?use_markup container ~xalign:0. label); ignore (button#connect#toggled ~callback:(fun () -> set button#active)); @@ -428,7 +433,7 @@ let on_string ?tooltip ?use_markup ?(validator=(fun _ -> true)) ?width ignore (entry#event#connect#focus_out ~callback); ignore (entry#connect#activate ~callback:(fun () -> ignore (callback ()))); ignore (mk_label ?use_markup ~xalign:0. container label); - (fun () -> + (fun () -> if not (Gobject.Property.get entry#as_widget GtkBase.Widget.P.has_focus) then entry#set_text (get ())) @@ -440,7 +445,7 @@ let on_string_set ?tooltip ?use_markup ?width (container:GPack.box) label get se ignore (entry#event#connect#focus_out ~callback); ignore (entry#connect#activate ~callback:(fun () -> ignore (callback ()))); ignore (mk_label ?use_markup ~xalign:0. container (label ^ " (list)")); - (fun () -> + (fun () -> if not (Gobject.Property.get entry#as_widget GtkBase.Widget.P.has_focus) then entry#set_text (get())) @@ -497,20 +502,10 @@ let on_combo (* ------------------------------------------------------------------------ *) let save_paned_ratio key (paned:GPack.paned) = - let paned_min_pos = paned#min_position in - let paned_max_pos = paned#max_position in - let length = paned_max_pos - paned_min_pos in - let ratio = if length = 0 then 0.5 - else (float_of_int paned#position)/.(float_of_int length) - in + let ratio = Wutil.get_pane_ratio paned in Configuration.set key (Configuration.ConfFloat ratio) -let place_paned (paned:GPack.paned) factor = - let paned_min_pos = paned#min_position in - let offset = - int_of_float (float (paned#max_position - paned_min_pos)*.factor) - in - paned#set_position (paned_min_pos + offset) +let place_paned = Wutil.set_pane_ratio let old_gtk_compat f x = try f x with Not_found -> () @@ -723,7 +718,7 @@ class type host = object method private set_reset: (unit -> unit) -> unit end -class error_manager ?reset (o_parent:GWindow.window_skel) : host = +class error_manager ?reset (o_parent:GWindow.window_skel) : host = object (self: #host) val mutable f_reset = match reset with @@ -869,11 +864,11 @@ let open_in_external_viewer ?(line=1) (file : Datatype.Filepath.t) = ignore (Sys.command cmd) exception Too_many_events -let refresh_gui () = +let refresh_gui () = let counter = ref 0 in - try - while Glib.Main.iteration false do - if !counter >= 10 then raise Too_many_events + try + while Glib.Main.iteration false do + if !counter >= 10 then raise Too_many_events else incr counter done with Too_many_events -> () @@ -916,7 +911,7 @@ let source_files_chooser (main_ui: source_files_chooser_host) defaults f = ~packing:(hbox#pack ~expand:true ~fill:true) () in - Configuration.use_string "last_opened_dir" + Configuration.use_string "last_opened_dir" (fun s -> ignore (filechooser#set_current_folder s)); filechooser#set_select_multiple true; filechooser#add_filter (accepted_source_files ()); @@ -1043,8 +1038,8 @@ let graph_window_through_dot ~parent ~title dot_formatter = let fmt = Format.formatter_of_out_channel (open_out temp_file) in dot_formatter fmt; Format.pp_print_flush fmt (); - let view = - snd + let view = + snd (Dgraph.DGraphContainer.Dot.from_dot_with_commands ~packing temp_file) in view diff --git a/src/plugins/gui/gtk_helper.mli b/src/plugins/gui/gtk_helper.mli index 37c82a18e9aa136c706fb35baa76c52a84bf370e..776e4d3560d974bb684e74186bb8489875709025 100644 --- a/src/plugins/gui/gtk_helper.mli +++ b/src/plugins/gui/gtk_helper.mli @@ -95,7 +95,7 @@ module Configuration: sig val set_int: string -> int -> unit (** Sets a ConfigInt *) - + val find_bool : ?default:bool -> string -> bool (** Same as {find_int}. *) @@ -127,13 +127,13 @@ module Configuration: sig (** Helpers to connect widgets to configuration values. The configuration value is first pushed to the widget using method [#set], or the [~default] value is used instead. - + Then, a callback is registered into the widget via [#connect] such that subsequent - values from user's action are saved back into the + values from user's action are saved back into the configuration file. *) - (** Abstract interface to the connected widget. + (** Abstract interface to the connected widget. This API is consistent with the [Widget] ones. *) class type ['a] selector = object @@ -142,15 +142,16 @@ module Configuration: sig method connect : ('a -> unit) -> unit (** Register a callback invoked by the widget each time the value is edited. *) end - + val config_int : key:string -> default:int -> int #selector -> unit val config_bool : key:string -> default:bool -> bool #selector -> unit val config_string : key:string -> default:string -> string #selector -> unit + val config_float : key:string -> default:float -> float #selector -> unit val config_values : key:string -> default:'a -> values:('a * string) list -> 'a #selector -> unit - (** The [values] field is used as a dictionary of available values. + (** The [values] field is used as a dictionary of available values. They are compared with [Pervasives.(=)]. *) - + end (* ************************************************************************** *) diff --git a/src/plugins/gui/wbox.ml b/src/plugins/gui/wbox.ml index 593d2c11a6a2a80a7833e6895d25d18bf324a942..df6f6d122527fa15ff20294db9efd5f2a6034ec0 100644 --- a/src/plugins/gui/wbox.ml +++ b/src/plugins/gui/wbox.ml @@ -78,7 +78,7 @@ let vgroup (ws : widget list) = let box = GPack.vbox ~show:true ~homogeneous:true () in List.iter (fun w -> box#pack ~expand:false w#coerce) ws ; new Wutil.gobj_widget box - + let (<|>) xs ys = if ys = [] then xs else (xs @ (ToEnd::ys)) let toolbar xs ys = hbox (xs <|> ys) @@ -96,3 +96,38 @@ let panel ?top ?left ?right ?bottom center = | Some t , None -> vbox [ h t ; hv middle ] | None , Some t -> vbox [ hv middle ; w t ] | Some a , Some b -> vbox [ h a ; hv middle ; h b ] + +class type splitter = + object + inherit Wutil.widget + method get : float + method set : float -> unit + method connect : (float -> unit) -> unit + end + +let split ~dir w1 w2 = + let pane = GPack.paned dir () in + pane#add1 w1#coerce ; + pane#add2 w2#coerce ; + let splitter = + object + inherit (Wutil.gobj_widget pane) + method get = Wutil.get_pane_ratio pane + method set = Wutil.set_pane_ratio pane + method connect f = + let callback _ = f (Wutil.get_pane_ratio pane) ; false in + ignore (pane#event#connect#button_release ~callback) + end + in (splitter :> splitter) + +let scroll ?(hpolicy=`AUTOMATIC) ?(vpolicy=`AUTOMATIC) w = + (* Explicit conversion needed for lablgtk3, as policy_type has been extended + with another constructor but we still export the lablgtk2 type. *) + let vpolicy = (vpolicy :> Gtk.Tags.policy_type) in + let hpolicy = (hpolicy :> Gtk.Tags.policy_type) in + let scrolled = GBin.scrolled_window ~vpolicy ~hpolicy () in + scrolled#add_with_viewport w#coerce ; + new Wutil.gobj_widget scrolled + +let hscroll w = scroll ~vpolicy:`NEVER w +let vscroll w = scroll ~hpolicy:`NEVER w diff --git a/src/plugins/gui/wbox.mli b/src/plugins/gui/wbox.mli index 3cf819eb36ac278f6a07af3f760c791c668f0e29..822f9641f9972e998ffef70491c17debeb1a194c 100644 --- a/src/plugins/gui/wbox.mli +++ b/src/plugins/gui/wbox.mli @@ -52,12 +52,12 @@ val label : ?fill:bool -> ?style:style -> ?align:align -> ?padding:int -> string Default: [~fill:false ~style:`Label ~align:`Left ~padding:0] *) -(** [hbox] and [vbox] can be used to created nested boxes. - Typically, local scope opening can be used, typically: +(** [hbox] and [vbox] can be used to created nested boxes. + Typically, local scope opening can be used, typically: [Wbox.(hbox [ w A ; w B ; w C ])], - where [A], [B] and [C] are widgets, or boxes. + where [A], [B] and [C] are widgets, or boxes. - Notice that nested boxes can {i generally} be packed using default + Notice that nested boxes can {i generally} be packed using default [W] mode, even if they contains horizontal or vertical widgets. *) val hbox : box list -> widget (** Pack a list of boxes horizontally. *) @@ -69,16 +69,39 @@ val hgroup : widget list -> widget (** Pack a list of widgets vertically, with all widgets stuck to the same width *) val vgroup : widget list -> widget -(** The first list is packed to the left side of the toolbar. +(** The first list is packed to the left side of the toolbar. The second list is packed to the right side of the toolbar. *) val toolbar : box list -> box list -> widget -(** The first list is packed to the top of the sidebar. +(** The first list is packed to the top of the sidebar. The second list is packed to the bottom of the sidebar. *) val sidebar : box list -> box list -> widget (** Helper to create a full featured window: - [~top] is layout as a toolbar, [left] and [right] as sidebars, and [bottom] as a status bar. + [~top] is layout as a toolbar, [left] and [right] as sidebars, and [bottom] as a status bar. The main (non-optional) widget is centered with full expansion in both directions. *) val panel : ?top:widget -> ?left:widget -> ?right:widget -> ?bottom:widget -> #widget -> widget +class type splitter = + object + inherit Wutil.widget + method get : float + method set : float -> unit + method connect : (float -> unit) -> unit + end + +val split : + dir:[`HORIZONTAL|`VERTICAL] -> + widget -> widget -> splitter + +(** default policy is AUTOMATIC *) +val scroll: + ?hpolicy:[`AUTOMATIC|`ALWAYS|`NEVER] -> + ?vpolicy:[`AUTOMATIC|`ALWAYS|`NEVER] -> + widget -> widget + +(** Same as [scroll ~vpolicy:`NEVER] *) +val hscroll : widget -> widget + +(** Same as [scroll ~volicy:`NEVER] *) +val vscroll : widget -> widget diff --git a/src/plugins/gui/wutil.ml b/src/plugins/gui/wutil.ml index 42ee0a7912af178d9047560d5c128b7d0b9efde8..7836b767e86b0f7c75531b592d0589318e1915bd 100644 --- a/src/plugins/gui/wutil.ml +++ b/src/plugins/gui/wutil.ml @@ -81,6 +81,23 @@ let later f = let prio = Glib.int_of_priority `LOW in ignore (Glib.Idle.add ~prio for_idle) +(* -------------------------------------------------------------------------- *) +(* --- Ratio --- *) +(* -------------------------------------------------------------------------- *) + +let get_pane_ratio (paned:GPack.paned) = + let paned_min_pos = paned#min_position in + let paned_max_pos = paned#max_position in + let length = paned_max_pos - paned_min_pos in + if length = 0 then 0.5 + else (float_of_int paned#position)/.(float_of_int length) + +let set_pane_ratio (paned:GPack.paned) ratio = + let paned_min_pos = paned#min_position in + let offset = + int_of_float (float (paned#max_position - paned_min_pos) *. ratio) + in paned#set_position (paned_min_pos + offset) + (* -------------------------------------------------------------------------- *) (* --- Widget & Signals --- *) (* -------------------------------------------------------------------------- *) diff --git a/src/plugins/gui/wutil.mli b/src/plugins/gui/wutil.mli index aa07048eedd8128813b0655684314b569fed8b57..390967dbcb3295d6ab1e29fe74801eac34ee8b5c 100644 --- a/src/plugins/gui/wutil.mli +++ b/src/plugins/gui/wutil.mli @@ -43,6 +43,11 @@ val set_small_font : #GObj.widget -> unit val set_bold_font : #GObj.widget -> unit val to_utf8 : string -> string +(** {2 Ratios} *) + +val get_pane_ratio : GPack.paned -> float +val set_pane_ratio : GPack.paned -> float -> unit + (** {2 Timing} *) val later : (unit -> unit) -> unit diff --git a/src/plugins/wp/GuiGoal.ml b/src/plugins/wp/GuiGoal.ml index 9ba3bf0cc946a7afb8a246f85e5c5817624d3900..eb3a8695830e41ff49a3fc8090ca11a6556844fe 100644 --- a/src/plugins/wp/GuiGoal.ml +++ b/src/plugins/wp/GuiGoal.ml @@ -82,12 +82,7 @@ class pane (proverpane : GuiConfig.provers) = let composer = new GuiComposer.composer printer in let browser = new GuiComposer.browser printer in let layout = new Wutil.layout in - let scroll_palette = - GBin.scrolled_window ~vpolicy:`AUTOMATIC ~hpolicy:`NEVER () - in - let scroll_palette_widget = new Wutil.gobj_widget scroll_palette in let palette = new Wpalette.panel () in - let () = scroll_palette#add_with_viewport palette#coerce in let help = new Widget.button ~label:"Tactics" ~border:false ~tooltip:"List Available Tactics" () in let delete = new Widget.button @@ -122,7 +117,12 @@ class pane (proverpane : GuiConfig.provers) = w play_script ; w save_script ; w ~padding:6 icon ; h ~padding:6 status ] [ w help ; w delete ]) in - layout#populate (Wbox.panel ~top:toolbar ~right:scroll_palette_widget text) ; + let content = Wbox.split ~dir:`HORIZONTAL + text#widget (Wbox.scroll palette#widget) in + Wutil.later (fun () -> + Config.config_float ~key:"GuiGoal.palette" ~default:0.8 content + ); + layout#populate (Wbox.panel ~top:toolbar content#widget) ; provers <- VCS.([ new GuiProver.prover ~console:text ~prover:AltErgo ] @ List.map