1 // -*- C++ -*- 2 /* GG is a GUI for OpenGL. 3 Copyright (C) 2003-2008 T. Zachary Laine 4 5 This library is free software; you can redistribute it and/or 6 modify it under the terms of the GNU Lesser General Public License 7 as published by the Free Software Foundation; either version 2.1 8 of the License, or (at your option) any later version. 9 10 This library is distributed in the hope that it will be useful, 11 but WITHOUT ANY WARRANTY; without even the implied warranty of 12 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 13 Lesser General Public License for more details. 14 15 You should have received a copy of the GNU Lesser General Public 16 License along with this library; if not, write to the Free 17 Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 18 02111-1307 USA 19 20 If you do not wish to comply with the terms of the LGPL please 21 contact the author as other terms are available for a fee. 22 23 Zach Laine 24 whatwasthataddress@gmail.com */ 25 26 /** \file FileDlg.h \brief Contains the standard GG file dialog. */ 27 28 #ifndef _GG_FileDlg_h_ 29 #define _GG_FileDlg_h_ 30 31 #include <GG/DropDownList.h> 32 33 #include <boost/filesystem/path.hpp> 34 35 36 namespace GG { 37 38 class TextControl; 39 class Edit; 40 class Button; 41 class Font; 42 43 /** \brief The default file open/save dialog box. 44 45 This dialog, like all the common GG dialogs, is modal. It asks the user 46 for one or more filenames, which the caller may retrieve with a call to 47 Result() after the dialog is closed. Note that all strings displayed 48 during the run of the FileDlg are customizable. Sometimes, the FileDlg 49 will pop up a message box (a ThreeButtonDlg) and notify the user of 50 something or ask for input. These message strings are also customizable. 51 Some of these strings include the filename as part of the message. When 52 replacing these strings with your own, you need to include the placement 53 of the filename in the message with the character sequence "%1%" (see 54 boost.format for details). */ 55 class GG_API FileDlg : public Wnd 56 { 57 public: 58 /** \name Structors */ ///@{ 59 /** Basic ctor. Parameters \a directory and \a filename pass an initial 60 directory and filename to the dialog, if desired (such as when "Save 61 As..." is selected in an app, and there is a current filename). If \a 62 directory is specified, it is taken as-is if it is absolute, or 63 relative to boost::filesystem::initial_path() if it is relative. If 64 \a directory is "", the initial directory is WorkingDirectory(). \a 65 save indicates whether this is a save or load dialog; \a multi 66 indicates whether multiple file selections are allowed. \throw 67 GG::FileDlg::BadInitialDirectory Throws when \a directory is 68 invalid. */ 69 FileDlg(const std::string& directory, const std::string& filename, bool save, bool multi, const std::shared_ptr<Font>& font, 70 Clr color, Clr border_color, Clr text_color = CLR_BLACK); 71 //@} 72 void CompleteConstruction() override; 73 74 /** \name Accessors */ ///@{ 75 std::set<std::string> Result() const; ///< returns a set of strings that contains the files chosen by the user; there will be only one file if \a multi == false was passed to the ctor 76 77 /** Returns true iff this FileDlg will select directories instead of files. */ 78 bool SelectDirectories() const; 79 80 /** Returns true iff this FileDlg will append the missing extension to a 81 file when in save mode. Note that action is only taken if there is a 82 single file filter containing exactly one wildcard in its first 83 position (i.e. it is of the form "*foo"). If precondition is 84 satisfied, any filename the user selects that does not end in "foo" 85 will have "foo" appended to it. */ 86 bool AppendMissingSaveExtension() const; 87 //@} 88 89 /** \name Mutators */ ///@{ 90 void Render() override; 91 void KeyPress(Key key, std::uint32_t key_code_point, Flags<ModKey> mod_keys) override; 92 93 /** Set this to true if this FileDlg should select directories instead of 94 files. Note that this will only have an effect in file-open mode. */ 95 void SelectDirectories(bool directories); 96 97 /** Set this to true if this FileDlg should append the missing extension 98 to a file when in save mode. Note that action is only taken if there 99 is a single file filter containing exactly one wildcard in its first 100 position (i.e. it is of the form "*foo"). If precondition is 101 satisfied, any filename the user selects that does not end in "foo" 102 will have "foo" appended to it. */ 103 void AppendMissingSaveExtension(bool append); 104 105 /** Sets the allowed file types. Each pair in the \a types parameter 106 contains a description of the file type in its .first member, and 107 wildcarded file types in its .second member. For example, an entry 108 might be ("Text Files (*.txt)", "*.txt"). Only the '*' character is 109 supported as a wildcard. More than one wildcard expression can be 110 specified in a filter; if so, they must be separated by a comma and 111 exactly one space (", "). Each filter is considered OR-ed together 112 with the others, so passing "*.tga, *.png" specifies listing any file 113 that is either a Targa or a PNG file. Note that an empty filter is 114 considered to match all files, so ("All Files", "") is perfectly 115 correct. */ 116 void SetFileFilters(const std::vector<std::pair<std::string, std::string>>& filters); 117 //@} 118 119 /** Returns the current directory (the one that will be used by default on 120 the next invocation of FileDlg::Run()) */ 121 static const boost::filesystem::path& WorkingDirectory(); 122 123 /** Converts a string to a path in a cross platform safe manner. */ 124 static const boost::filesystem::path StringToPath(const std::string& str); 125 126 /** \name Exceptions */ ///@{ 127 /** The base class for FileDlg exceptions. */ 128 GG_ABSTRACT_EXCEPTION(Exception); 129 130 /** Thrown when the initial directory for the dialog is bad. */ 131 GG_CONCRETE_EXCEPTION(BadInitialDirectory, GG::FileDlg, Exception); 132 //@} 133 134 protected: 135 static const X DEFAULT_WIDTH; ///< default width for the dialog 136 static const Y DEFAULT_HEIGHT; ///< default height for the dialog 137 138 private: 139 void DoLayout(); 140 void AttachSignalChildren(); 141 void DetachSignalChildren(); 142 void OkClicked(); 143 void OkHandler(bool double_click); 144 void CancelClicked(); 145 void FileSetChanged(const ListBox::SelectionSet& files); 146 void FileDoubleClicked(DropDownList::iterator it, const GG::Pt& pt, const GG::Flags<GG::ModKey>& modkeys); 147 void FilesEditChanged(const std::string& str); 148 void FilterChanged(DropDownList::iterator it); 149 void SetWorkingDirectory(const boost::filesystem::path& p); 150 void PopulateFilters(); 151 void UpdateList(); 152 void UpdateDirectoryText(); 153 void OpenDirectory(); 154 155 Clr m_color; 156 Clr m_border_color; 157 Clr m_text_color; 158 std::shared_ptr<Font> m_font; 159 160 bool m_save = false; 161 std::vector<std::pair<std::string, std::string>> 162 m_file_filters; 163 std::set<std::string> 164 m_result; 165 bool m_select_directories = false;; 166 bool m_append_missing_save_extension = false;; 167 bool m_in_win32_drive_selection = false;; 168 169 std::string m_save_str; 170 std::string m_open_str; 171 172 std::shared_ptr<TextControl> m_curr_dir_text; 173 std::shared_ptr<ListBox> m_files_list; 174 std::shared_ptr<Edit> m_files_edit; 175 std::shared_ptr<DropDownList> m_filter_list; 176 std::shared_ptr<Button> m_ok_button; 177 std::shared_ptr<Button> m_cancel_button; 178 std::shared_ptr<TextControl> m_files_label; 179 std::shared_ptr<TextControl> m_file_types_label; 180 181 std::string m_init_directory; ///< directory passed to constructor 182 std::string m_init_filename; ///< filename passed to constructor 183 184 static boost::filesystem::path s_working_dir; ///< declared static so each instance of FileDlg opens up the same directory 185 }; 186 187 } // namespace GG 188 189 #endif 190