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