Code

Fixed off-by-one filter bug with the windows native file dialogs, and tidied code...
[inkscape.git] / src / ui / dialog / filedialogimpl-win32.h
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;
60         
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;
93         
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;
103         
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
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;
212         
213         /// This flag is set true when the GetOpenFileName call
214     /// has returned
215     bool _finished;
216         
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
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 };
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 :