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