1 /* 2 * OpenClonk, http://www.openclonk.org 3 * 4 * Copyright (c) 2008-2009, RedWolf Design GmbH, http://www.clonk.de/ 5 * Copyright (c) 2009-2016, The OpenClonk Team and contributors 6 * 7 * Distributed under the terms of the ISC license; see accompanying file 8 * "COPYING" for details. 9 * 10 * "Clonk" is a registered trademark of Matthes Bender, used with permission. 11 * See accompanying file "TRADEMARK" for details. 12 * 13 * To redistribute this file separately, substitute the full license texts 14 * for the above references. 15 */ 16 // file selection dialogs 17 18 #ifndef INC_C4FileSelDlg 19 #define INC_C4FileSelDlg 20 21 #include "gui/C4Gui.h" 22 #include "c4group/C4Components.h" 23 24 // callback handler for file selection dialog 25 class C4FileSel_BaseCB 26 { 27 public: 28 C4FileSel_BaseCB() = default; 29 virtual ~C4FileSel_BaseCB() = default; 30 31 public: 32 virtual void OnFileSelected(const char *szFilename) = 0; 33 }; 34 35 template <class CB> class C4FileSel_CBEx : public C4FileSel_BaseCB 36 { 37 public: 38 typedef void (CB::*FileSelFunc)(const char *szFilename, int32_t idToken); 39 40 private: 41 CB *pCBClass; 42 FileSelFunc SelFunc; 43 int32_t idToken; 44 public: OnFileSelected(const char * szFilename)45 void OnFileSelected(const char *szFilename) override 46 { if (pCBClass && SelFunc) (pCBClass->*SelFunc)(szFilename, idToken); } 47 48 public: C4FileSel_CBEx(CB * pCBClass,FileSelFunc SelFunc,int32_t idToken)49 C4FileSel_CBEx(CB * pCBClass, FileSelFunc SelFunc, int32_t idToken) : pCBClass(pCBClass), SelFunc(SelFunc), idToken(idToken) { } 50 }; 51 52 // dialog to select one or more files 53 class C4FileSelDlg : public C4GUI::Dialog 54 { 55 public: 56 class ListItem : public C4GUI::Control 57 { 58 protected: 59 StdStrBuf sFilename; // full path to file 60 IsFocusOnClick()61 bool IsFocusOnClick() override { return false; } // do not focus; keep focus on listbox 62 63 public: 64 ListItem(const char *szFilename); 65 ~ListItem() override; 66 GetFilename()67 const char *GetFilename() { return sFilename.getData(); } 68 69 // multisel-checkbox-options IsChecked()70 virtual bool IsChecked() const { return false; } SetChecked(bool fChecked)71 virtual void SetChecked(bool fChecked) {} IsGrayed()72 virtual bool IsGrayed() const { return false; } UserToggleCheck()73 virtual bool UserToggleCheck() { return false; } 74 }; 75 76 class DefaultListItem : public ListItem 77 { 78 private: 79 typedef ListItem BaseClass; 80 class C4GUI::Icon *pIco; class C4GUI::Label *pLbl; 81 class C4GUI::CheckBox *pCheck; 82 class C4KeyBinding *pKeyCheck; // space activates/deactivates selected file 83 bool fGrayed; 84 85 protected: 86 void UpdateOwnPos() override; 87 88 public: 89 DefaultListItem(const char *szFilename, bool fTruncateExtension, bool fCheckbox, bool fGrayed, C4GUI::Icons eIcon); 90 ~DefaultListItem() override; 91 92 bool IsChecked() const override; 93 void SetChecked(bool fChecked) override; IsGrayed()94 bool IsGrayed() const override { return fGrayed; } 95 bool UserToggleCheck() override; 96 }; 97 98 private: 99 typedef C4GUI::Dialog BaseClass; 100 101 C4KeyBinding *pKeyRefresh, *pKeyEnterOverride; 102 103 C4GUI::ComboBox *pLocationComboBox; 104 C4GUI::ListBox *pFileListBox; 105 C4GUI::TextWindow *pSelectionInfoBox; 106 C4GUI::Button *btnOK; 107 108 StdCopyStrBuf sTitle; // dlg title 109 110 StdCopyStrBuf sPath; // current path 111 struct Location 112 { 113 StdCopyStrBuf sName; 114 StdCopyStrBuf sPath; 115 }; 116 Location *pLocations; 117 int32_t iLocationCount; 118 int32_t iCurrentLocationIndex; 119 120 121 ListItem *pSelection; 122 C4FileSel_BaseCB *pSelCallback; 123 124 void UpdateFileList(); // rebuild file listbox from sPath 125 126 protected: 127 void OnShown() override; 128 void UserClose(bool fOK) override; // allow OK only if something is sth is selected 129 void OnClosed(bool fOK) override; // callback when dlg got closed 130 GetFileMask()131 virtual const char *GetFileMask() const { return nullptr; } IsMultiSelection()132 virtual bool IsMultiSelection() const { return false; } // if true, files are checked/unchecked using checkboxes IsItemGrayed(const char * szFilename)133 virtual bool IsItemGrayed(const char *szFilename) const { return false; } 134 virtual void UpdateSelection(); HasNoneItem()135 virtual bool HasNoneItem() const { return false; } // if true, an empty item can be selected HasPreviewArea()136 virtual bool HasPreviewArea() const { return true; } HasExtraOptions()137 virtual bool HasExtraOptions() const { return false; } AddExtraOptions(const C4Rect & rcOptionsRect)138 virtual void AddExtraOptions(const C4Rect &rcOptionsRect) {} GetFileItemIcon()139 virtual C4GUI::Icons GetFileItemIcon() const { return C4GUI::Ico_None; } GetFileSelColWidth()140 virtual int32_t GetFileSelColWidth() const { return 0; } // width of each file selection element; 0 for default all listbox 141 OnSelChange(class C4GUI::Element * pEl)142 void OnSelChange(class C4GUI::Element *pEl) { UpdateSelection(); } 143 void OnSelDblClick(class C4GUI::Element *pEl); KeyRefresh()144 bool KeyRefresh() { UpdateFileList(); return true; } 145 void OnLocationComboFill(C4GUI::ComboBox_FillCB *pFiller); 146 bool OnLocationComboSelChange(C4GUI::ComboBox *pForCombo, int32_t idNewSelection); 147 148 void AddLocation(const char *szName, const char *szPath); // add location to be shown in dropdown list 149 void AddCheckedLocation(const char *szName, const char *szPath); // add location to be shown in dropdown list, only if path exists and isn't added yet 150 int32_t GetCurrentLocationIndex() const; 151 void SetCurrentLocation(int32_t idx, bool fRefresh); 152 153 virtual ListItem *CreateListItem(const char *szFilename); BeginFileListUpdate()154 virtual void BeginFileListUpdate() {} EndFileListUpdate()155 virtual void EndFileListUpdate() {} 156 157 public: 158 C4FileSelDlg(const char *szRootPath, const char *szTitle, C4FileSel_BaseCB *pSelCallback, bool fInitElements=true); 159 ~C4FileSelDlg() override; 160 void InitElements(); 161 162 void SetPath(const char *szNewPath, bool fRefresh=true); 163 void SetSelection(const char *szNewSelection, bool fFilenameOnly); 164 StdStrBuf GetSelection(const char *szFixedSelection, bool fFilenameOnly) const; // get single selected file for single selection dlg ';'-separated list for multi selection dlg 165 }; 166 167 // dialog to select a player file 168 class C4PlayerSelDlg : public C4FileSelDlg 169 { 170 protected: GetFileMask()171 const char *GetFileMask() const override { return C4CFN_PlayerFiles; } GetFileItemIcon()172 C4GUI::Icons GetFileItemIcon() const override { return C4GUI::Ico_Player; } 173 174 public: 175 C4PlayerSelDlg(C4FileSel_BaseCB *pSelCallback); 176 }; 177 178 // dialog to select definition files 179 class C4DefinitionSelDlg : public C4FileSelDlg 180 { 181 private: 182 StdStrBuf sFixedSelection; // initial selection which cannot be deselected 183 184 protected: 185 void OnShown() override; GetFileMask()186 const char *GetFileMask() const override { return C4CFN_DefFiles; } IsMultiSelection()187 bool IsMultiSelection() const override { return true; } 188 bool IsItemGrayed(const char *szFilename) const override; GetFileItemIcon()189 C4GUI::Icons GetFileItemIcon() const override { return C4GUI::Ico_Definition; } 190 191 public: 192 C4DefinitionSelDlg(C4FileSel_BaseCB *pSelCallback, const char *szFixedSelection); 193 194 static bool SelectDefinitions(C4GUI::Screen *pOnScreen, StdStrBuf *pSelection); 195 }; 196 197 // dialog to select portrait files 198 class C4PortraitSelDlg : public C4FileSelDlg 199 { 200 public: 201 enum { ImagePreviewSize = 100 }; 202 203 private: 204 class ListItem : public C4FileSelDlg::ListItem 205 { 206 private: 207 bool fError; // loading error 208 bool fLoaded; // image loaded but not yet scaled 209 C4FacetSurface fctImage; // portrait, if loaded 210 C4FacetSurface fctLoadedImage; // image as loaded by background thread. Must be scaled by main thread 211 StdCopyStrBuf sFilenameLabelText; 212 213 protected: 214 void DrawElement(C4TargetFacet &cgo) override; 215 216 public: 217 ListItem(const char *szFilename); 218 219 void Load(); 220 }; 221 222 // portrait loader thread 223 class LoaderThread : public StdThread 224 { 225 private: 226 std::list<ListItem *> LoadItems; // items to be loaded by this thread 227 228 public: 229 LoaderThread() = default; ~LoaderThread()230 ~LoaderThread() override { Stop(); } 231 232 void ClearLoadItems(); // stops thread 233 void AddLoadItem(ListItem *pItem); // not to be called when thread is running! 234 235 public: 236 void Execute() override; 237 }; 238 239 private: 240 LoaderThread ImageLoader; 241 242 protected: 243 void OnClosed(bool fOK) override; GetFileMask()244 const char *GetFileMask() const override { return C4CFN_ImageFiles; } HasNoneItem()245 bool HasNoneItem() const override { return true; } // if true, a special <none> item can be selected HasPreviewArea()246 bool HasPreviewArea() const override { return false; } // no preview area. Preview images directly GetFileSelColWidth()247 int32_t GetFileSelColWidth() const override { return ImagePreviewSize; } // width of each file selection element 248 249 C4FileSelDlg::ListItem *CreateListItem(const char *szFilename) override; 250 void BeginFileListUpdate() override; 251 void EndFileListUpdate() override; 252 253 void OnIdle() override; 254 255 public: 256 C4PortraitSelDlg(C4FileSel_BaseCB *pSelCallback); 257 258 static bool SelectPortrait(C4GUI::Screen *pOnScreen, StdStrBuf *pSelection); 259 }; 260 261 #endif // INC_C4FileSelDlg 262