1 /**
2 * Implementation of the file dialog interfaces defined in filedialog.h for Win32
3 *
4 * Authors:
5 * Joel Holdsworth
6 * The Inkscape Organization
7 *
8 * Copyright (C) 2004-2008 The Inkscape Organization
9 *
10 * Released under GNU GPL, read the file 'COPYING' for more information
11 */
13 #ifdef WIN32
15 #include "gc-core.h"
16 #include <windows.h>
18 namespace Inkscape
19 {
20 namespace UI
21 {
22 namespace Dialog
23 {
25 /*#########################################################################
26 ### F I L E D I A L O G B A S E C L A S S
27 #########################################################################*/
29 /// This class is the base implementation of a MS Windows
30 /// file dialog.
31 class FileDialogBaseWin32
32 {
33 protected:
34 /// Abstract Constructor
35 /// @param parent The parent window for the dialog
36 /// @param dir The directory to begin browing from
37 /// @param title The title caption for the dialog in UTF-8
38 /// @param type The dialog type
39 /// @param preferenceBase The preferences key
40 FileDialogBaseWin32(Gtk::Window &parent, const Glib::ustring &dir,
41 const char *title, FileDialogType type,
42 gchar const *preferenceBase);
44 /// Destructor
45 ~FileDialogBaseWin32();
47 public:
49 /// Gets the currently selected extension. Valid after an [OK]
50 /// @return Returns a pointer to the selected extension, or NULL
51 /// if the selected filter requires an automatic type detection
52 Inkscape::Extension::Extension* getSelectionType();
54 /// Get the path of the current directory
55 Glib::ustring getCurrentDirectory();
57 protected:
58 /// The dialog type
59 FileDialogType dialogType;
61 /// A pointer to the GTK main-loop context object. This
62 /// is used to keep the rest of the inkscape UI running
63 /// while the file dialog is displayed
64 GMainLoop *_main_loop;
66 /// The result of the call to GetOpenFileName. If true
67 /// the user clicked OK, if false the user clicked cancel
68 bool _result;
70 /// The parent window
71 Gtk::Window &parent;
73 /// The windows handle of the parent window
74 HWND _ownerHwnd;
76 /// The path of the directory that is currently being
77 /// browsed
78 Glib::ustring _current_directory;
80 /// The title of the dialog in UTF-16
81 wchar_t *_title;
83 /// The path of the currently selected file in UTF-16
84 wchar_t _path_string[_MAX_PATH];
86 /// The filter string for GetOpenFileName in UTF-16
87 wchar_t *_filter;
89 /// The index of the currently selected filter.
90 /// This value must be greater than or equal to 1,
91 /// and less than or equal to _filter_count.
92 unsigned int _filter_index;
94 /// The number of filters registered
95 unsigned int _filter_count;
97 /// An array of the extensions associated with the
98 /// file types of each filter. So the Nth entry of
99 /// this array corresponds to the extension of the Nth
100 /// filter in the list. NULL if no specific extension is
101 /// specified/
102 Inkscape::Extension::Extension **_extension_map;
104 /// The currently selected extension. Valid after an [OK]
105 Inkscape::Extension::Extension *_extension;
106 };
109 /*#########################################################################
110 ### F I L E O P E N
111 #########################################################################*/
113 /// An Inkscape compatible wrapper around MS Windows GetOpenFileName API
114 class FileOpenDialogImplWin32 : public FileOpenDialog, public FileDialogBaseWin32
115 {
116 public:
117 /// Constructor
118 /// @param parent The parent window for the dialog
119 /// @param dir The directory to begin browing from
120 /// @param title The title caption for the dialog in UTF-8
121 /// @param type The dialog type
122 FileOpenDialogImplWin32(Gtk::Window &parent,
123 const Glib::ustring &dir,
124 FileDialogType fileTypes,
125 const char *title);
127 /// Destructor
128 virtual ~FileOpenDialogImplWin32();
130 /// Shows the file dialog, and blocks until a file
131 /// has been selected.
132 /// @return Returns true if the the user selected a
133 /// file, or false if the user pressed cancel.
134 bool show();
136 /// Gets a list of the selected file names
137 /// @return Returns an STL vector filled with the
138 /// GTK names of the selected files
139 std::vector<Glib::ustring> getFilenames();
141 /// Get the path of the current directory
142 virtual Glib::ustring getCurrentDirectory()
143 { return FileDialogBaseWin32::getCurrentDirectory(); }
145 /// Gets the currently selected extension. Valid after an [OK]
146 /// @return Returns a pointer to the selected extension, or NULL
147 /// if the selected filter requires an automatic type detection
148 virtual Inkscape::Extension::Extension* getSelectionType()
149 { return FileDialogBaseWin32::getSelectionType(); }
151 private:
153 /// Create a filter menu for this type of dialog
154 void createFilterMenu();
156 /// The handle of the preview pane window
157 HWND _preview_wnd;
159 /// The handle of the file dialog window
160 HWND _file_dialog_wnd;
162 /// A pointer to the standard window proc of the
163 /// unhooked file dialog
164 WNDPROC _base_window_proc;
166 /// The handle of the bitmap of the "show preview"
167 /// toggle button
168 HBITMAP _show_preview_button_bitmap;
170 /// The handle of the toolbar's window
171 HWND _toolbar_wnd;
173 /// This flag is set true when the preview should be
174 /// shown, or false when it should be hidden
175 static bool _show_preview;
178 /// The current width of the preview pane in pixels
179 int _preview_width;
181 /// The current height of the preview pane in pixels
182 int _preview_height;
184 /// The handle of the windows to display within the
185 /// preview pane, or NULL if no image should be displayed
186 HBITMAP _preview_bitmap;
188 /// The windows shell icon for the selected file
189 HICON _preview_file_icon;
191 /// The size of the preview file in kilobytes
192 unsigned long _preview_file_size;
195 /// The width of the document to be shown in the preview panel
196 double _preview_document_width;
198 /// The width of the document to be shown in the preview panel
199 double _preview_document_height;
201 /// The width of the rendered preview image in pixels
202 int _preview_image_width;
204 /// The height of the rendered preview image in pixels
205 int _preview_image_height;
207 /// A GDK Pixbuf of the rendered preview to be displayed
208 Glib::RefPtr<Gdk::Pixbuf> _preview_bitmap_image;
210 /// This flag is set true if a file has been selected
211 bool _file_selected;
213 /// This flag is set true when the GetOpenFileName call
214 /// has returned
215 bool _finished;
217 /// This mutex is used to ensure that the worker thread
218 /// that calls GetOpenFileName cannot collide with the
219 /// main Inkscape thread
220 Glib::Mutex *_mutex;
223 /// The controller function for the thread which calls
224 /// GetOpenFileName
225 void GetOpenFileName_thread();
227 /// Registers the Windows Class of the preview panel window
228 static void register_preview_wnd_class();
230 /// A message proc which is called by the standard dialog
231 /// proc
232 static UINT_PTR CALLBACK GetOpenFileName_hookproc(HWND hdlg, UINT uiMsg, WPARAM wParam, LPARAM lParam);
234 /// A message proc which wraps the standard dialog proc,
235 /// but intercepts some calls
236 static LRESULT CALLBACK file_dialog_subclass_proc(HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam);
238 /// The message proc for the preview panel window
239 static LRESULT CALLBACK preview_wnd_proc(HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam);
241 /// Lays out the controls in the file dialog given it's
242 /// current size
243 /// GetOpenFileName thread only.
244 void layout_dialog();
246 /// Enables or disables the file preview.
247 /// GetOpenFileName thread only.
248 void enable_preview(bool enable);
250 /// This function is called in the App thread when a file had
251 /// been selected
252 void file_selected();
254 /// Loads and renders the unshrunk preview image.
255 /// Main app thread only.
256 void load_preview();
258 /// Frees all the allocated objects associated with the file
259 /// currently being previewed
260 /// Main app thread only.
261 void free_preview();
263 /// Loads preview for an SVG or SVGZ file.
264 /// Main app thread only.
265 /// @return Returns true if the SVG loaded successfully
266 bool set_svg_preview();
268 /// A callback to allow this class to dispose of the
269 /// memory block of the rendered SVG bitmap
270 /// @buffer buffer The buffer to free
271 static void destroy_svg_rendering(const guint8 *buffer);
273 /// Loads the preview for a raster image
274 /// Main app thread only.
275 /// @return Returns true if the image loaded successfully
276 bool set_image_preview();
278 /// Loads the preview for a meta file
279 /// Main app thread only.
280 /// @return Returns true if the image loaded successfully
281 bool set_emf_preview();
283 /// This flag is set true when a meta file is previewed
284 bool _preview_emf_image;
286 /// Renders the unshrunk preview image to a windows HTBITMAP
287 /// which can be painted in the preview pain.
288 /// Main app thread only.
289 void render_preview();
291 /// Formats the caption in UTF-16 for the preview image
292 /// @param caption The buffer to format the caption string into
293 /// @param caption_size The number of wchar_ts in the caption buffer
294 /// @return Returns the number of characters in caption string
295 int format_caption(wchar_t *caption, int caption_size);
296 };
299 /*#########################################################################
300 ### F I L E S A V E
301 #########################################################################*/
303 /// An Inkscape compatible wrapper around MS Windows GetSaveFileName API
304 class FileSaveDialogImplWin32 : public FileSaveDialog, public FileDialogBaseWin32
305 {
307 public:
308 FileSaveDialogImplWin32(Gtk::Window &parent,
309 const Glib::ustring &dir,
310 FileDialogType fileTypes,
311 const char *title,
312 const Glib::ustring &default_key,
313 const char *docTitle);
315 /// Destructor
316 virtual ~FileSaveDialogImplWin32();
318 /// Shows the file dialog, and blocks until a file
319 /// has been selected.
320 /// @return Returns true if the the user selected a
321 /// file, or false if the user pressed cancel.
322 bool show();
324 /// Get the path of the current directory
325 virtual Glib::ustring getCurrentDirectory()
326 { return FileDialogBaseWin32::getCurrentDirectory(); }
328 /// Gets the currently selected extension. Valid after an [OK]
329 /// @return Returns a pointer to the selected extension, or NULL
330 /// if the selected filter requires an automatic type detection
331 virtual Inkscape::Extension::Extension* getSelectionType()
332 { return FileDialogBaseWin32::getSelectionType(); }
334 virtual void setSelectionType( Inkscape::Extension::Extension *key );
336 private:
337 /// A handle to the title label and edit box
338 HWND _title_label;
339 HWND _title_edit;
341 /// Create a filter menu for this type of dialog
342 void createFilterMenu();
344 /// The controller function for the thread which calls
345 /// GetSaveFileName
346 void GetSaveFileName_thread();
348 /// A message proc which is called by the standard dialog
349 /// proc
350 static UINT_PTR CALLBACK GetSaveFileName_hookproc(HWND hdlg, UINT uiMsg, WPARAM wParam, LPARAM lParam);
352 };
355 }
356 }
357 }
359 #endif
361 /*
362 Local Variables:
363 mode:c++
364 c-file-style:"stroustrup"
365 c-file-offsets:((innamespace . 0)(inline-open . 0)(case-label . +))
366 indent-tabs-mode:nil
367 fill-column:99
368 End:
369 */
370 // vim: filetype=cpp:expandtab:shiftwidth=4:tabstop=8:softtabstop=4 :