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 /// This mutex is used to ensure that the worker thread
62 /// that calls GetOpenFileName cannot collide with the
63 /// main Inkscape thread
64 Glib::Mutex *_mutex;
66 /// This flag is set true when the GetOpenFileName call
67 /// has returned
68 bool _finished;
70 /// A pointer to the GTK main-loop context object. This
71 /// is used to keep the rest of the inkscape UI running
72 /// while the file dialog is displayed
73 GMainLoop *_main_loop;
75 /// The result of the call to GetOpenFileName. If true
76 /// the user clicked OK, if false the user clicked cancel
77 bool _result;
79 /// The parent window
80 Gtk::Window &parent;
82 /// The windows handle of the parent window
83 HWND _ownerHwnd;
85 /// The path of the directory that is currently being
86 /// browsed
87 Glib::ustring _current_directory;
89 /// The title of the dialog in UTF-16
90 wchar_t *_title;
92 /// The path of the currently selected file in UTF-16
93 wchar_t _path_string[_MAX_PATH];
95 /// The filter string for GetOpenFileName in UTF-16
96 wchar_t *_filter;
98 /// The index of the currently selected filter
99 int _filterIndex;
101 /// An array of the extensions associated with the
102 /// file types of each filter. So the Nth entry of
103 /// this array corresponds to the extension of the Nth
104 /// filter in the list. NULL if no specific extension is
105 /// specified/
106 Inkscape::Extension::Extension **_extension_map;
108 /// The currently selected extension. Valid after an [OK]
109 Inkscape::Extension::Extension *_extension;
110 };
113 /*#########################################################################
114 ### F I L E O P E N
115 #########################################################################*/
117 /// An Inkscape compatible wrapper around MS Windows GetOpenFileName API
118 class FileOpenDialogImplWin32 : public FileOpenDialog, public FileDialogBaseWin32
119 {
120 public:
121 /// Constructor
122 /// @param parent The parent window for the dialog
123 /// @param dir The directory to begin browing from
124 /// @param title The title caption for the dialog in UTF-8
125 /// @param type The dialog type
126 FileOpenDialogImplWin32(Gtk::Window &parent,
127 const Glib::ustring &dir,
128 FileDialogType fileTypes,
129 const char *title);
131 /// Destructor
132 virtual ~FileOpenDialogImplWin32();
134 /// Shows the file dialog, and blocks until a file
135 /// has been selected.
136 /// @return Returns true if the the user selected a
137 /// file, or false if the user pressed cancel.
138 bool show();
140 /// Gets a list of the selected file names
141 /// @return Returns an STL vector filled with the
142 /// GTK names of the selected files
143 std::vector<Glib::ustring> getFilenames();
145 /// Get the path of the current directory
146 virtual Glib::ustring getCurrentDirectory()
147 { return FileDialogBaseWin32::getCurrentDirectory(); }
149 /// Gets the currently selected extension. Valid after an [OK]
150 /// @return Returns a pointer to the selected extension, or NULL
151 /// if the selected filter requires an automatic type detection
152 virtual Inkscape::Extension::Extension* getSelectionType()
153 { return FileDialogBaseWin32::getSelectionType(); }
155 private:
157 /// Create a filter menu for this type of dialog
158 void createFilterMenu();
160 /// The handle of the preview pane window
161 HWND _preview_wnd;
163 /// The handle of the file dialog window
164 HWND _file_dialog_wnd;
166 /// A pointer to the standard window proc of the
167 /// unhooked file dialog
168 WNDPROC _base_window_proc;
170 /// The handle of the bitmap of the "show preview"
171 /// toggle button
172 HBITMAP _show_preview_button_bitmap;
174 /// The handle of the toolbar's window
175 HWND _toolbar_wnd;
177 /// This flag is set true when the preview should be
178 /// shown, or false when it should be hidden
179 static bool _show_preview;
182 /// The current width of the preview pane in pixels
183 int _preview_width;
185 /// The current height of the preview pane in pixels
186 int _preview_height;
188 /// The handle of the windows to display within the
189 /// preview pane, or NULL if no image should be displayed
190 HBITMAP _preview_bitmap;
192 /// The windows shell icon for the selected file
193 HICON _preview_file_icon;
195 /// The size of the preview file in kilobytes
196 unsigned long _preview_file_size;
199 /// The width of the document to be shown in the preview panel
200 double _preview_document_width;
202 /// The width of the document to be shown in the preview panel
203 double _preview_document_height;
205 /// The width of the rendered preview image in pixels
206 int _preview_image_width;
208 /// The height of the rendered preview image in pixels
209 int _preview_image_height;
211 /// A GDK Pixbuf of the rendered preview to be displayed
212 Glib::RefPtr<Gdk::Pixbuf> _preview_bitmap_image;
214 /// This flag is set true if a file has been selected
215 bool _file_selected;
218 /// The controller function for the thread which calls
219 /// GetOpenFileName
220 void GetOpenFileName_thread();
222 /// Registers the Windows Class of the preview panel window
223 static void register_preview_wnd_class();
225 /// A message proc which is called by the standard dialog
226 /// proc
227 static UINT_PTR CALLBACK GetOpenFileName_hookproc(HWND hdlg, UINT uiMsg, WPARAM wParam, LPARAM lParam);
229 /// A message proc which wraps the standard dialog proc,
230 /// but intercepts some calls
231 static LRESULT CALLBACK file_dialog_subclass_proc(HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam);
233 /// The message proc for the preview panel window
234 static LRESULT CALLBACK preview_wnd_proc(HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam);
236 /// Lays out the controls in the file dialog given it's
237 /// current size
238 /// GetOpenFileName thread only.
239 void layout_dialog();
241 /// Enables or disables the file preview.
242 /// GetOpenFileName thread only.
243 void enable_preview(bool enable);
245 /// This function is called in the App thread when a file had
246 /// been selected
247 void file_selected();
249 /// Loads and renders the unshrunk preview image.
250 /// Main app thread only.
251 void load_preview();
253 /// Frees all the allocated objects associated with the file
254 /// currently being previewed
255 /// Main app thread only.
256 void free_preview();
258 /// Loads preview for an SVG or SVGZ file.
259 /// Main app thread only.
260 /// @return Returns true if the SVG loaded successfully
261 bool set_svg_preview();
263 /// A callback to allow this class to dispose of the
264 /// memory block of the rendered SVG bitmap
265 /// @buffer buffer The buffer to free
266 static void destroy_svg_rendering(const guint8 *buffer);
268 /// Loads the preview for a raster image
269 /// Main app thread only.
270 /// @return Returns true if the image loaded successfully
271 bool set_image_preview();
273 /// Renders the unshrunk preview image to a windows HTBITMAP
274 /// which can be painted in the preview pain.
275 /// Main app thread only.
276 void render_preview();
278 /// Formats the caption in UTF-16 for the preview image
279 /// @param caption The buffer to format the caption string into
280 /// @param caption_size The number of wchar_ts in the caption buffer
281 /// @return Returns the number of characters in caption string
282 int format_caption(wchar_t *caption, int caption_size);
283 };
286 /*#########################################################################
287 ### F I L E S A V E
288 #########################################################################*/
290 /// An Inkscape compatible wrapper around MS Windows GetSaveFileName API
291 class FileSaveDialogImplWin32 : public FileSaveDialog, public FileDialogBaseWin32
292 {
294 public:
295 FileSaveDialogImplWin32(Gtk::Window &parent,
296 const Glib::ustring &dir,
297 FileDialogType fileTypes,
298 const char *title,
299 const Glib::ustring &default_key);
301 /// Destructor
302 virtual ~FileSaveDialogImplWin32();
304 /// Shows the file dialog, and blocks until a file
305 /// has been selected.
306 /// @return Returns true if the the user selected a
307 /// file, or false if the user pressed cancel.
308 bool show();
310 /// Get the path of the current directory
311 virtual Glib::ustring getCurrentDirectory()
312 { return FileDialogBaseWin32::getCurrentDirectory(); }
314 /// Gets the currently selected extension. Valid after an [OK]
315 /// @return Returns a pointer to the selected extension, or NULL
316 /// if the selected filter requires an automatic type detection
317 virtual Inkscape::Extension::Extension* getSelectionType()
318 { return FileDialogBaseWin32::getSelectionType(); }
320 virtual void setSelectionType( Inkscape::Extension::Extension *key );
322 private:
324 /**
325 * Create a filter menu for this type of dialog
326 */
327 void createFilterMenu();
329 void GetSaveFileName_thread();
330 };
333 }
334 }
335 }
337 #endif
339 /*
340 Local Variables:
341 mode:c++
342 c-file-style:"stroustrup"
343 c-file-offsets:((innamespace . 0)(inline-open . 0)(case-label . +))
344 indent-tabs-mode:nil
345 fill-column:99
346 End:
347 */
348 // vim: filetype=cpp:expandtab:shiftwidth=4:tabstop=8:softtabstop=4 :