/
FileDialogs.ml
111 lines (101 loc) · 4.04 KB
/
FileDialogs.ml
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
(*** FileDialogs.ml contains a handful of GTK routines for handling the opening
* and closing of files, in particular throwing up dialogs, capturing filenames,
* passing the filenames to the appropriate MapFormat.map object, and handling
* resultant errors. ***)
(* this stores the path that we were looking at in the file dialog last time, so
* that we don't keep jumping back to pwd when editing multiple maps *)
let path = ref None
(* this throws up a pretty useless failure dialog. TODO: could easily be
* enhanced by allowing varying error messages :) *)
let fail_dialog str () =
let dialog =
GWindow.message_dialog
~message:("Failed to perform file operation: " ^ str)
~message_type:`ERROR ~buttons:GWindow.Buttons.close
~modal:true ~title:Resources.warning () in
dialog#run (); (* don't care about the result *)
dialog#destroy ()
(* routines for reading and writing light libraries *)
let load_light_library filename =
let fh = open_in_bin filename in
let length = in_channel_length fh in
let lights = MapFormat.read_chunk fh length MapFormat.light_length
MapTypes.lite_reader in
close_in fh;
lights
let save_light_library filename lights =
let fh = open_out_bin filename in
Array.iter (MapTypes.lite_writer fh) lights;
close_out fh
(* generic open/save dialogs *)
let open_file_dialog f title _ =
(* actually construct the dialog *)
let dialog = GWindow.file_selection ~title () in
(* read in the path from our last use *)
begin match !path with None -> () | Some path ->
dialog#set_filename path end;
begin match dialog#run () with
|`OK ->
(* open the file *)
begin try f dialog#filename
with exn -> fail_dialog (Printexc.to_string exn) () end;
|_ -> () (* we were cancelled :( *)
end;
(* store the path for next time *)
path := Some dialog#filename;
dialog#destroy ()
(* almost the same, but for the save dialog *)
let save_file_dialog f title _ =
let dialog = GWindow.file_selection ~title () in
(* use the path from last time *)
begin match !path with None -> () | Some path ->
dialog#set_filename path end;
begin match dialog#run () with
|`OK ->
(* attempt to write the file out to disk *)
begin try f dialog#filename
with exn -> fail_dialog (Printexc.to_string exn) () end
|_ -> ()
end;
(* store the path for next time *)
path := Some dialog#filename;
dialog#destroy ()
(* open/save dialogs for maps *)
let open_map_dialog set_title redraw =
open_file_dialog (fun filename ->
MapFormat.read_from_file filename;
set_title ("Smithy: " ^ filename)) "Open Map" ();
redraw ()
let save_map_dialog set_title _ =
save_file_dialog (fun filename ->
MapFormat.write_to_file filename;
set_title ("Smithy: " ^ filename)) "Save Map" ()
(* open/save dialogs for light libraries *)
let load_and_append_light_lib redraw =
open_file_dialog (fun filename ->
let lights = load_light_library filename in
MapFormat.lights := Array.append !MapFormat.lights lights)
"Load and Append Light Library" ();
redraw ()
let load_and_replace_light_lib redraw =
open_file_dialog (fun filename ->
let lights = load_light_library filename in
MapFormat.lights := lights)
"Load and Replace Light Library" ();
redraw ()
let save_light_lib _ =
save_file_dialog (fun filename ->
save_light_library filename !MapFormat.lights)
"Save Light Library" ()
(* for the Save option instead of Save As *)
let silent_save set_title _ =
if !MapFormat.filename = "" then
(* if our map has a filename associated with it, just save to that
* location again *)
save_map_dialog set_title ()
else
(* otherwise, ask the user for such a filename *)
MapFormat.write_to_file !MapFormat.filename
let new_map redraw =
MapFormat.reset_structures ();
redraw ()