Skip to content

Commit f264b40

Browse files
authored
Merge pull request #29 from talex5/minibuffer
Allow setting viewport values explicitly
2 parents 36995a9 + 5b7bec8 commit f264b40

File tree

7 files changed

+148
-19
lines changed

7 files changed

+148
-19
lines changed

README.md

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -113,6 +113,14 @@ In the above trace, the upper domain performed GC while suspended
113113
(the dark "minor" region in the top right, inside the "suspend-domain" region).
114114
This is possible because each domain has a "backup" thread that handles GC while the domain is suspended.
115115

116+
## Controls
117+
118+
- F5 : reload the trace file
119+
- s : start-time (elapsed time at left edge of window since trace start)
120+
- d : duration (duration to show in the currently visible area of the window)
121+
122+
`d` is useful for getting two windows to use the same scale, so that they can be compared easily.
123+
116124
## Limitations
117125

118126
- OCaml 5.1 can [deadlock when tracing multiple domains](https://github.com/ocaml/ocaml/issues/12897). This should be fixed in OCaml 5.2.

gtk/gtk_ui.ml

Lines changed: 63 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -7,12 +7,13 @@ let create ~title tracefile =
77
let window = GWindow.window () in
88
window#set_title title;
99
window#event#connect#delete ==> (fun _ -> GMain.quit (); true);
10-
let table = GPack.table ~rows:2 ~columns:2 ~homogeneous:false ~packing:window#add () in
10+
let table = GPack.table ~rows:3 ~columns:2 ~homogeneous:false ~packing:window#add () in
1111
let hadjustment = GData.adjustment () in
1212
let vadjustment = GData.adjustment () in
1313
let area = GMisc.drawing_area ~packing:(table#attach ~left:0 ~top:0 ~expand:`BOTH ~fill:`BOTH) () in
1414
let _hscroll = GRange.scrollbar `HORIZONTAL ~adjustment:hadjustment ~packing:(table#attach ~left:0 ~top:1 ~expand:`X ~fill:`BOTH) () in
1515
let _vscroll = GRange.scrollbar `VERTICAL ~adjustment:vadjustment ~packing:(table#attach ~left:1 ~top:0 ~expand:`Y ~fill:`BOTH) () in
16+
let minibuffer = Minibuffer.create ~packing:(table#attach ~left:0 ~top:2 ~right:2 ~fill:`BOTH) () in
1617
let v =
1718
let layout = Layout.load tracefile in
1819
View.of_layout layout ~width:1000. ~height:1000.
@@ -49,6 +50,52 @@ let create ~title tracefile =
4950
);
5051
area#misc#set_app_paintable true;
5152

53+
let show_start () =
54+
let current = View.time_of_x v 0. /. 1e9 in
55+
Minibuffer.show minibuffer
56+
~label:"Viewport start: "
57+
~value:(Time.to_string current)
58+
(fun s ->
59+
match Time.of_string s with
60+
| Ok time ->
61+
set_start_time (time *. 1e9);
62+
redraw ();
63+
Minibuffer.hide minibuffer
64+
| Error message ->
65+
let box =
66+
GWindow.message_dialog ()
67+
~message
68+
~parent:window
69+
~buttons:GWindow.Buttons.close
70+
in
71+
box#connect#response ==> (fun _ -> box#destroy ());
72+
box#show ()
73+
)
74+
in
75+
76+
let show_duration () =
77+
let current = View.get_duration v /. 1e9 in
78+
Minibuffer.show minibuffer
79+
~label:"Viewport duration: "
80+
~value:(Time.to_string current)
81+
(fun s ->
82+
match Time.of_string s with
83+
| Ok d ->
84+
View.set_duration v (d *. 1e9);
85+
redraw ();
86+
Minibuffer.hide minibuffer
87+
| Error message ->
88+
let box =
89+
GWindow.message_dialog ()
90+
~message
91+
~parent:window
92+
~buttons:GWindow.Buttons.close
93+
in
94+
box#connect#response ==> (fun _ -> box#destroy ());
95+
box#show ()
96+
)
97+
in
98+
5299
window#event#connect#key_press ==> (fun ev ->
53100
let keyval = GdkEvent.Key.keyval ev in
54101
if keyval = GdkKeysyms._F5 then (
@@ -57,7 +104,20 @@ let create ~title tracefile =
57104
set_scollbars ();
58105
redraw ();
59106
true
60-
) else false
107+
) else if Minibuffer.is_open minibuffer then (
108+
if keyval = GdkKeysyms._Escape then (
109+
Minibuffer.hide minibuffer;
110+
true
111+
) else false
112+
) else (
113+
if keyval = GdkKeysyms._s then (
114+
show_start ();
115+
true
116+
) else if keyval = GdkKeysyms._d then (
117+
show_duration ();
118+
true
119+
) else false
120+
)
61121
);
62122

63123
area#event#add [`SMOOTH_SCROLL; `BUTTON1_MOTION; `BUTTON_PRESS];
@@ -113,7 +173,7 @@ let create ~title tracefile =
113173
set_scroll_y vadjustment#value;
114174
redraw ();
115175
);
116-
176+
117177
let height =
118178
int_of_float @@ min
119179
(float (Gdk.Screen.height ()) *. 0.8)

gtk/minibuffer.ml

Lines changed: 35 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,35 @@
1+
let ( ==> ) signal callback =
2+
ignore (signal ~callback : GtkSignal.id)
3+
4+
type t = {
5+
widget : GPack.box;
6+
label : GMisc.label;
7+
entry : GEdit.entry;
8+
mutable action : (string -> unit);
9+
}
10+
11+
let create ~packing () =
12+
let widget = GPack.hbox ()
13+
~packing
14+
~border_width:4
15+
~show:false
16+
in
17+
let label = GMisc.label ~packing:widget#pack ~text:"?" () in
18+
let entry = GEdit.entry ~packing:(widget#pack ~expand:true) () in
19+
let t = { widget; label; entry; action = ignore } in
20+
entry#connect#activate ==> (fun () -> t.action entry#text);
21+
t
22+
23+
let show t ~label ~value action =
24+
t.action <- action;
25+
t.label#set_text label;
26+
t.entry#set_text value;
27+
t.widget#misc#show ();
28+
t.entry#misc#grab_focus ()
29+
30+
let hide t =
31+
t.action <- ignore;
32+
t.widget#misc#hide ()
33+
34+
let is_open t =
35+
t.widget#misc#visible

gtk/minibuffer.mli

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
1+
type t
2+
3+
val create : packing:(GObj.widget -> unit) -> unit -> t
4+
5+
val show : t -> label:string -> value:string -> (string -> unit) -> unit
6+
(** [show t ~label ~value action] shows the mini-buffer with the given label and initial value.
7+
When the user presses return, [action] is called with the new value. *)
8+
9+
val hide : t -> unit
10+
11+
val is_open : t -> bool

lib/time.ml

Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,22 @@
1+
let of_string s =
2+
match
3+
Scanf.sscanf_opt s "%f %s" @@ fun v units ->
4+
match units with
5+
| ""
6+
| "s" -> Ok v
7+
| "m" -> Ok (v *. 60.)
8+
| "ms" -> Ok (v /. 1e3)
9+
| "us" -> Ok (v /. 1e6)
10+
| "ns" -> Ok (v /. 1e9)
11+
| x -> Fmt.error "Unknown time unit %S" x
12+
with
13+
| None -> Fmt.error "Invalid duration %S" s
14+
| Some x -> x
15+
16+
let pp f x =
17+
if x >= 1.0 then Fmt.pf f "%gs" x
18+
else if x >= 1e-3 then Fmt.pf f "%gms" (x *. 1e3)
19+
else if x >= 1e-6 then Fmt.pf f "%gus" (x *. 1e6)
20+
else Fmt.pf f "%gns" (x *. 1e9)
21+
22+
let to_string = Fmt.to_to_string pp

lib/view.ml

Lines changed: 8 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -42,11 +42,17 @@ let zoom_to t z =
4242
let zoom t delta =
4343
zoom_to t (t.zoom +. delta)
4444

45+
let set_duration t duration =
46+
let ppns = (t.width -. 2. *. h_margin) /. duration in
47+
zoom_to t (log ppns /. log 10.)
48+
49+
let get_duration t =
50+
(t.width -. 2. *. h_margin) /. t.pixels_per_ns
51+
4552
let zoom_to_fit ?(start_time=0.0) ?duration t =
4653
let start_time = min start_time t.layout.duration in
4754
let duration = Option.value duration ~default:(t.layout.duration -. start_time) in
48-
let ppns = (t.width -. 2. *. h_margin) /. duration in
49-
zoom_to t (log ppns /. log 10.);
55+
set_duration t duration;
5056
t.start_time <- start_time -. timespan_of_width t h_margin
5157

5258
let max_x_scroll t =

src/main.ml

Lines changed: 1 addition & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -4,20 +4,7 @@ let ( $ ) = Term.app
44
let ( $$ ) f x = Term.const f $ x
55

66
let time =
7-
let parse s =
8-
Scanf.sscanf_opt s "%f %s" @@ fun v units ->
9-
match units with
10-
| ""
11-
| "s" -> Ok v
12-
| "m" -> Ok (v *. 60.)
13-
| "ms" -> Ok (v /. 1e3)
14-
| "us" -> Ok (v /. 1e6)
15-
| "ns" -> Ok (v /. 1e9)
16-
| x -> Fmt.error "Unknown time unit %S" x
17-
in
18-
let parse s = Option.value (parse s) ~default:(Fmt.error "Invalid duration %S" s) in
19-
let print f x = Fmt.pf f "%fns" x in
20-
Arg.conv' (parse, print)
7+
Arg.conv' (Eio_trace.Time.of_string, Eio_trace.Time.pp)
218

229
let tracefile =
2310
let doc = "The path of the trace file." in

0 commit comments

Comments
 (0)