Skip to content

Commit 36041b5

Browse files
authored
Merge pull request #32 from talex5/save-image
Add export image to GTK menu
2 parents aa7db99 + 00ceb3a commit 36041b5

File tree

4 files changed

+85
-26
lines changed

4 files changed

+85
-26
lines changed

README.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -126,6 +126,7 @@ Phases that usually involve sleeping are shown with a yellow background, but som
126126

127127
## Controls
128128

129+
- Right click for a menu
129130
- F5 : reload the trace file
130131
- s : start-time (elapsed time at left edge of window since trace start)
131132
- d : duration (duration to show in the currently visible area of the window)

gtk/gtk_ui.ml

Lines changed: 51 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -3,20 +3,24 @@ open Eio_trace
33
let ( ==> ) signal callback =
44
ignore (signal ~callback : GtkSignal.id)
55

6+
let (let*) = Result.bind
7+
68
let ui_xml = {|
79
<ui>
810
<popup name='PopupMenu'>
11+
<menuitem action='export-image' />
912
<menuitem action='viewport-set-start' />
1013
<menuitem action='viewport-set-duration' />
1114
</popup>
1215
</ui>
1316
|}
1417

1518
let create ~title tracefile =
19+
let last_export = ref None in
1620
let actions = GAction.action_group ~name:"main" () in
1721
let ui = GAction.ui_manager () in
1822
ui#insert_action_group actions 0;
19-
let _id : GAction.ui_id = ui#add_ui_from_string ui_xml; in
23+
let _id : GAction.ui_id = ui#add_ui_from_string ui_xml in
2024

2125
let window = GWindow.window () in
2226
window#add_accel_group ui#get_accel_group;
@@ -112,6 +116,50 @@ let create ~title tracefile =
112116
)
113117
in
114118

119+
let alert message =
120+
let dialog = GWindow.message_dialog ~title:"Error" ~buttons:GWindow.Buttons.ok ~message () in
121+
dialog#show ();
122+
match dialog#run () with
123+
| `DELETE_EVENT | `OK -> dialog#destroy ()
124+
in
125+
126+
let save_image () =
127+
let dialog = GWindow.file_chooser_dialog ~title:"Export image" ~action:`SAVE ~parent:window () in
128+
begin match !last_export with
129+
| None ->
130+
let dir = Filename.dirname tracefile in
131+
ignore (dialog#set_current_folder dir : bool);
132+
dialog#set_current_name ((Filename.basename tracefile |> Filename.remove_extension) ^ ".svg")
133+
| Some path ->
134+
ignore (dialog#set_filename path : bool)
135+
end;
136+
dialog#add_select_button_stock `SAVE `OK;
137+
dialog#set_default_response `OK;
138+
dialog#add_button_stock `CANCEL `CANCEL;
139+
dialog#connect#response ==> (function
140+
| `DELETE_EVENT | `CANCEL ->
141+
dialog#destroy ()
142+
| `OK ->
143+
match
144+
match dialog#get_filenames with
145+
| [path] ->
146+
let* fmt = Save.format_of_string (Filename.extension path) in
147+
last_export := Some path;
148+
Save.export_image v fmt path
149+
| _ -> Error "Must select one path"
150+
with
151+
| Ok () -> dialog#destroy ()
152+
| Error msg -> alert msg
153+
);
154+
dialog#show ();
155+
in
156+
157+
GAction.add_action "export-image" actions
158+
~label:"Export image as..."
159+
~accel:"<control>e"
160+
~stock:`SAVE_AS
161+
~callback:(fun _a -> save_image ());
162+
115163
GAction.add_action "viewport-set-start" actions
116164
~label:"Set start time..."
117165
~callback:(fun _a -> show_start ());
@@ -134,7 +182,8 @@ let create ~title tracefile =
134182
true
135183
) else false
136184
) else (
137-
if keyval = GdkKeysyms._s then (
185+
if GdkEvent.Key.state ev <> [] then false
186+
else if keyval = GdkKeysyms._s then (
138187
show_start ();
139188
true
140189
) else if keyval = GdkKeysyms._d then (

gtk/main.ml

Lines changed: 5 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -2,10 +2,9 @@ open Eio_trace
22

33
let (_ : string) = GMain.init ()
44

5-
let format_of_string = function
6-
| ".svg" -> `Svg
7-
| ".png" -> `Png
8-
| x -> Fmt.failwith "Unknown format %S (should be .svg or .png)" x
5+
let or_die = function
6+
| Ok x -> x
7+
| Error msg -> failwith msg
98

109
let show ?args tracefile =
1110
let title =
@@ -25,33 +24,15 @@ let render ?output ~start_time ?duration ~format tracefile =
2524
| Some x -> x
2625
| None -> Filename.remove_extension tracefile ^ format
2726
in
28-
let format = format_of_string format in
27+
let format = Save.format_of_string format |> or_die in
2928
let l = Layout.load (tracefile) in
3029
let v =
3130
View.of_layout l
3231
~width:1280.
3332
~height:((float l.height +. 0.5) *. View.pixels_per_row +. 2. *. View.v_margin)
3433
in
3534
View.zoom_to_fit v ~start_time ?duration;
36-
let create =
37-
match format with
38-
| `Svg -> Cairo.SVG.create output
39-
| `Png -> fun ~w ~h -> Cairo.Image.create RGB24 ~w:(int_of_float w) ~h:(int_of_float h)
40-
in
41-
let surface =
42-
create
43-
~w:v.width
44-
~h:v.height
45-
in
46-
let cr = Cairo.create surface in
47-
Cairo.rectangle cr 0.0 0.0 ~w:v.width ~h:v.height;
48-
Cairo.clip cr;
49-
Render_cairo.render v cr;
50-
begin match format with
51-
| `Svg -> ()
52-
| `Png -> Cairo.PNG.write surface output
53-
end;
54-
Cairo.Surface.finish surface;
35+
Save.export_image v format output |> or_die;
5536
Printf.printf "Wrote %S\n" output
5637

5738
let () =

gtk/save.ml

Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,28 @@
1+
let format_of_string = function
2+
| ".svg" -> Ok `Svg
3+
| ".png" -> Ok `Png
4+
| x -> Fmt.error "Unknown format %S (should be .svg or .png)" x
5+
6+
let export_image (v : Eio_trace.View.t) fmt path =
7+
try
8+
let create =
9+
match fmt with
10+
| `Svg -> Cairo.SVG.create path
11+
| `Png -> fun ~w ~h -> Cairo.Image.create RGB24 ~w:(int_of_float w) ~h:(int_of_float h)
12+
in
13+
let surface =
14+
create
15+
~w:v.width
16+
~h:v.height
17+
in
18+
let cr = Cairo.create surface in
19+
Cairo.rectangle cr 0.0 0.0 ~w:v.width ~h:v.height;
20+
Cairo.clip cr;
21+
Render_cairo.render v cr;
22+
begin match fmt with
23+
| `Svg -> ()
24+
| `Png -> Cairo.PNG.write surface path
25+
end;
26+
Ok (Cairo.Surface.finish surface)
27+
with ex ->
28+
Error (Printexc.to_string ex)

0 commit comments

Comments
 (0)