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 int _filter_index;
94 /// The number of filters registered
95 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 /// Renders the unshrunk preview image to a windows HTBITMAP
279 /// which can be painted in the preview pain.
280 /// Main app thread only.
281 void render_preview();
283 /// Formats the caption in UTF-16 for the preview image
284 /// @param caption The buffer to format the caption string into
285 /// @param caption_size The number of wchar_ts in the caption buffer
286 /// @return Returns the number of characters in caption string
287 int format_caption(wchar_t *caption, int caption_size);
288 };
291 /*#########################################################################
292 ### F I L E S A V E
293 #########################################################################*/
295 /// An Inkscape compatible wrapper around MS Windows GetSaveFileName API
296 class FileSaveDialogImplWin32 : public FileSaveDialog, public FileDialogBaseWin32
297 {
299 public:
300 FileSaveDialogImplWin32(Gtk::Window &parent,
301 const Glib::ustring &dir,
302 FileDialogType fileTypes,
303 const char *title,
304 const Glib::ustring &default_key);
306 /// Destructor
307 virtual ~FileSaveDialogImplWin32();
309 /// Shows the file dialog, and blocks until a file
310 /// has been selected.
311 /// @return Returns true if the the user selected a
312 /// file, or false if the user pressed cancel.
313 bool show();
315 /// Get the path of the current directory
316 virtual Glib::ustring getCurrentDirectory()
317 { return FileDialogBaseWin32::getCurrentDirectory(); }
319 /// Gets the currently selected extension. Valid after an [OK]
320 /// @return Returns a pointer to the selected extension, or NULL
321 /// if the selected filter requires an automatic type detection
322 virtual Inkscape::Extension::Extension* getSelectionType()
323 { return FileDialogBaseWin32::getSelectionType(); }
325 virtual void setSelectionType( Inkscape::Extension::Extension *key );
327 private:
329 /// Create a filter menu for this type of dialog
330 void createFilterMenu();
332 /// The controller function for the thread which calls
333 /// GetSaveFileName
334 void GetSaveFileName_thread();
336 };
339 }
340 }
341 }
343 #endif
345 /*
346 Local Variables:
347 mode:c++
348 c-file-style:"stroustrup"
349 c-file-offsets:((innamespace . 0)(inline-open . 0)(case-label . +))
350 indent-tabs-mode:nil
351 fill-column:99
352 End:
353 */
354 // vim: filetype=cpp:expandtab:shiftwidth=4:tabstop=8:softtabstop=4 :