7
7
8
8
#include < algorithm>
9
9
10
- FileChooser::FileChooser (std::string title, std::vector<std::string> extensions)
10
+ FileChooser::FileChooser (FileChooser::Mode mode)
11
+ : _mode(mode)
12
+ {
13
+ }
14
+
15
+ FileChooser::FileChooser (std::string title, const std::string& initialDirectory, Mode mode)
11
16
: _title(std::move(title))
12
- , _extensions(std::move(extensions))
17
+ , _mode(mode)
18
+ {
19
+ if (!initialDirectory.empty ())
20
+ {
21
+ ChangeDirectory (initialDirectory);
22
+ }
23
+ }
24
+
25
+ void FileChooser::Title (const std::string& title)
13
26
{
27
+ _title = title;
28
+ }
29
+
30
+ void FileChooser::CurrentDirectory (const std::string& path)
31
+ {
32
+ if (path.empty ())
33
+ {
34
+ return ;
35
+ }
36
+
37
+ ChangeDirectory (path);
38
+ }
39
+
40
+ void FileChooser::Context (const std::string& context)
41
+ {
42
+ _context = context;
43
+ }
44
+
45
+ const std::string& FileChooser::Context () const
46
+ {
47
+ return _context;
48
+ }
49
+
50
+ void FileChooser::AllowedExtensions (std::vector<std::string> extensions)
51
+ {
52
+ _extensions = std::move (extensions);
53
+ }
54
+
55
+ const std::vector<std::string>& FileChooser::AllowedExtensions () const
56
+ {
57
+ return _extensions;
58
+ }
59
+
60
+
61
+ void FileChooser::MultiSelect (bool enabled)
62
+ {
63
+ _multiSelect = enabled;
64
+ }
65
+
66
+ bool FileChooser::MultiSelect () const
67
+ {
68
+ return _multiSelect;
14
69
}
15
70
16
71
void FileChooser::Show ()
17
72
{
73
+ _selectedFiles.clear ();
18
74
_visible = true ;
19
75
}
20
76
77
+ void FileChooser::Close ()
78
+ {
79
+ ImGui::CloseCurrentPopup ();
80
+ _visible = false ;
81
+ }
82
+
21
83
bool FileChooser::Draw ()
22
84
{
23
85
if (!_visible)
@@ -32,7 +94,9 @@ bool FileChooser::Draw()
32
94
ChangeDirectory (Poco::Path::home ());
33
95
}
34
96
35
- if (ImGui::Begin (_title.c_str (), &_visible), ImGuiWindowFlags_NoCollapse)
97
+ ImGui::OpenPopup (_title.c_str ());
98
+
99
+ if (ImGui::BeginPopupModal (_title.c_str (), &_visible, ImGuiWindowFlags_NoCollapse))
36
100
{
37
101
DrawNavButtons ();
38
102
@@ -41,12 +105,14 @@ bool FileChooser::Draw()
41
105
char pathBuffer[2048 ]{};
42
106
strncpy (pathBuffer, _currentDir.toString ().c_str (), std::min<size_t >(2047 , _currentDir.toString ().size ()));
43
107
108
+ ImGui::SetNextItemWidth (-1 );
109
+
44
110
if (ImGui::InputText (" ##path" , &pathBuffer[0 ], IM_ARRAYSIZE (pathBuffer)), ImGuiInputTextFlags_EnterReturnsTrue)
45
111
{
46
112
ChangeDirectory (std::string (pathBuffer));
47
113
}
48
114
49
- if (ImGui::BeginListBox (" ##filelist" , ImVec2 (-1 , -1 )))
115
+ if (ImGui::BeginListBox (" ##filelist" , ImVec2 (-1 , -ImGui::GetTextLineHeight () - ImGui::GetStyle (). FramePadding . y * 2 - 4 )))
50
116
{
51
117
if (_currentDir.toString ().empty ())
52
118
{
@@ -71,26 +137,56 @@ bool FileChooser::Draw()
71
137
}
72
138
73
139
ImGui::EndListBox ();
140
+
141
+ ImGui::PushStyleColor (ImGuiCol_Button, 0xFF000080 );
142
+ if (ImGui::Button (" Cancel" ))
143
+ {
144
+ _selectedFiles.clear ();
145
+ fileSelected = true ;
146
+ Close ();
147
+ }
148
+ ImGui::PopStyleColor ();
149
+ ImGui::SameLine ();
150
+ if (ImGui::Button (" Select" ))
151
+ {
152
+ for (auto index : _selectedFileIndices)
153
+ {
154
+ _selectedFiles.emplace_back (_currentFileList.at (index ));
155
+ }
156
+
157
+ if (_selectedFileIndices.empty () && _mode == Mode::Directory)
158
+ {
159
+ _selectedFiles.emplace_back (Poco::Path (_currentDir).makeDirectory ());
160
+ }
161
+ else
162
+ {
163
+ // ToDo: Display "Select at least one entry from the list"
164
+ }
165
+
166
+ fileSelected = true ;
167
+ Close ();
168
+ }
169
+
170
+ ImGui::EndPopup ();
74
171
}
75
172
}
76
173
else
77
174
{
78
- _visible = false ;
175
+ Close () ;
79
176
}
80
177
81
- ImGui::End ();
82
178
83
179
return fileSelected;
84
180
}
85
181
86
- const Poco::File& FileChooser::SelectedFile () const
182
+ const std::vector< Poco::File> & FileChooser::SelectedFiles () const
87
183
{
88
- return _selectedFile ;
184
+ return _selectedFiles ;
89
185
}
90
186
91
187
void FileChooser::DrawNavButtons ()
92
188
{
93
- ImGui::Checkbox (" Show hidden files " , &_showhidden );
189
+ ImGui::Checkbox (" Show hidden" , &_showHidden );
94
190
95
191
// Root path buttons first
96
192
std::vector<std::string> roots;
@@ -131,7 +227,7 @@ bool FileChooser::PopulateFileList()
131
227
int index = 0 ;
132
228
for (const auto & file : _currentFileList)
133
229
{
134
- bool isSelected = _selectedFileIndex == index ;
230
+ bool isSelected = (_selectedFileIndices. find ( index ) != _selectedFileIndices. end ()) ;
135
231
bool isDirectory = false ;
136
232
try
137
233
{
@@ -152,10 +248,11 @@ bool FileChooser::PopulateFileList()
152
248
153
249
if (ImGui::Selectable (filename.c_str (), isSelected, ImGuiSelectableFlags_AllowDoubleClick))
154
250
{
155
- _selectedFileIndex = index ;
251
+ UpdateListSelection ( index , isSelected) ;
156
252
157
253
if (ImGui::IsMouseDoubleClicked (0 ))
158
254
{
255
+ _selectedFiles.clear ();
159
256
if (isDirectory)
160
257
{
161
258
newDir = filePath;
@@ -164,8 +261,8 @@ bool FileChooser::PopulateFileList()
164
261
}
165
262
else
166
263
{
167
- _selectedFile = filePath;
168
- poco_debug_f1 (_logger, " User selected file: %s" , _selectedFile. path ());
264
+ _selectedFiles. emplace_back ( filePath) ;
265
+ poco_debug_f1 (_logger, " User selected file: %s" , filePath. toString ());
169
266
fileSelected = true ;
170
267
_visible = false ;
171
268
}
@@ -183,12 +280,22 @@ bool FileChooser::PopulateFileList()
183
280
return fileSelected;
184
281
}
185
282
186
- void FileChooser::ChangeDirectory (const Poco::Path& newDirectory)
283
+ void FileChooser::ChangeDirectory (Poco::Path newDirectory)
187
284
{
285
+ newDirectory.makeDirectory ();
286
+
287
+ if (_currentDir.toString () == newDirectory.toString ())
288
+ {
289
+ return ;
290
+ }
291
+
188
292
_currentDir = newDirectory;
189
- _currentDir.makeDirectory ();
190
293
191
294
_currentFileList.clear ();
295
+ _selectedFileIndices.clear ();
296
+ _selectedFileIndex = -1 ;
297
+
298
+ poco_information_f1 (_logger, " Changing dir: %s" , newDirectory.toString ());
192
299
193
300
if (_currentDir.toString ().empty ())
194
301
{
@@ -219,13 +326,13 @@ void FileChooser::ChangeDirectory(const Poco::Path& newDirectory)
219
326
{
220
327
}
221
328
222
- if (!isDirectory && (!isHidden || _showhidden ))
329
+ if ((!isHidden || _showHidden ))
223
330
{
224
- if (_extensions.empty ())
331
+ if ((_mode != Mode::Directory && _extensions.empty ()) || isDirectory )
225
332
{
226
333
_currentFileList.push_back (*directoryIterator);
227
334
}
228
- else
335
+ else if (_mode != Mode::Directory)
229
336
{
230
337
auto fileExtension = directoryIterator.path ().getExtension ();
231
338
for (const auto & extension : _extensions)
@@ -240,4 +347,52 @@ void FileChooser::ChangeDirectory(const Poco::Path& newDirectory)
240
347
241
348
++directoryIterator;
242
349
}
243
- }
350
+ }
351
+
352
+ void FileChooser::UpdateListSelection (int index, bool isSelected)
353
+ {
354
+ // Reset selection on simple click
355
+ if (!ImGui::IsKeyDown (ImGuiKey_LeftCtrl) && !ImGui::IsKeyDown (ImGuiKey_RightCtrl) && !ImGui::IsKeyDown (ImGuiKey_LeftShift) && !ImGui::IsKeyDown (ImGuiKey_RightShift))
356
+ {
357
+ _selectedFileIndices.clear ();
358
+ _selectedFileIndices.insert (index );
359
+ }
360
+
361
+ // Multiple selection on shift+click
362
+ if (ImGui::IsKeyDown (ImGuiKey_LeftShift) || ImGui::IsKeyDown (ImGuiKey_RightShift) && _selectedFileIndex >= 0 )
363
+ {
364
+ if (!ImGui::IsKeyDown (ImGuiKey_LeftCtrl) && !ImGui::IsKeyDown (ImGuiKey_RightCtrl))
365
+ {
366
+ // Replace selection if ctrl is not pressed
367
+ _selectedFileIndices.clear ();
368
+ }
369
+
370
+ if (!_multiSelect)
371
+ {
372
+ _selectedFileIndex = index ;
373
+ }
374
+
375
+ for (int selIndex = std::min (_selectedFileIndex, index ); selIndex <= std::max (_selectedFileIndex, index ); selIndex++)
376
+ {
377
+ _selectedFileIndices.insert (selIndex);
378
+ }
379
+ }
380
+ // Toggle selection with ctrl+click
381
+ else if (ImGui::IsKeyDown (ImGuiKey_LeftCtrl) || ImGui::IsKeyDown (ImGuiKey_RightCtrl))
382
+ {
383
+ if (isSelected)
384
+ {
385
+ _selectedFileIndices.erase (index );
386
+ }
387
+ else
388
+ {
389
+ if (!_multiSelect)
390
+ {
391
+ _selectedFileIndices.clear ();
392
+ }
393
+ _selectedFileIndices.insert (index );
394
+ }
395
+ }
396
+
397
+ _selectedFileIndex = index ;
398
+ }
0 commit comments