1 /*
2     DSDL
3     Copyright (C) 2025 Inochi2D Project <luna@foxgirls.gay>
4 
5     This software is provided 'as-is', without any express or implied
6     warranty.  In no event will the authors be held liable for any damages
7     arising from the use of this software.
8 
9     Permission is granted to anyone to use this software for any purpose,
10     including commercial applications, and to alter it and redistribute it
11     freely, subject to the following restrictions:
12 
13     1. The origin of this software must not be misrepresented; you must not
14         claim that you wrote the original software. If you use this software
15         in a product, an acknowledgment in the product documentation would be
16         appreciated but is not required.
17     2. Altered source versions must be plainly marked as such, and must not be
18         misrepresented as being the original software.
19     3. This notice may not be removed or altered from any source distribution.
20 
21     ==========================================================================
22 
23     Simple DirectMedia Layer
24     Copyright (C) 1997-2025 Sam Lantinga <slouken@libsdl.org>
25 
26     This software is provided 'as-is', without any express or implied
27     warranty.  In no event will the authors be held liable for any damages
28     arising from the use of this software.
29 
30     Permission is granted to anyone to use this software for any purpose,
31     including commercial applications, and to alter it and redistribute it
32     freely, subject to the following restrictions:
33 
34     1. The origin of this software must not be misrepresented; you must not
35         claim that you wrote the original software. If you use this software
36         in a product, an acknowledgment in the product documentation would be
37         appreciated but is not required.
38     2. Altered source versions must be plainly marked as such, and must not be
39         misrepresented as being the original software.
40     3. This notice may not be removed or altered from any source distribution.
41 */
42 
43 /**
44     SDL Dialog
45 
46     See_Also:
47         $(LINK2 https://wiki.libsdl.org/SDL3/CategoryDialog, SDL3 Dialog Documentation)
48     
49     Copyright: © 2025 Inochi2D Project, © 1997-2025 Sam Lantinga
50     License: Subject to the terms of the Zlib License, as written in the LICENSE file.
51     Authors: 
52         Luna Nielsen
53 */
54 module sdl.dialog;
55 import sdl.video;
56 import sdl.properties;
57 import sdl.stdc;
58 
59 extern(C) nothrow @nogc:
60 
61 /**
62     An entry for filters for file dialogs.
63 
64     `name` is a user-readable label for the filter (for example, "Office
65     document").
66 
67     `pattern` is a semicolon-separated list of file extensions (for example,
68     "doc;docx"). File extensions may only contain alphanumeric characters,
69     hyphens, underscores and periods. Alternatively, the whole string can be a
70     single asterisk ("*"), which serves as an "All files" filter.
71 
72     See_Also:
73         $(D SDL_DialogFileCallback)
74         $(D SDL_ShowOpenFileDialog)
75         $(D SDL_ShowSaveFileDialog)
76         $(D SDL_ShowOpenFolderDialog)
77         $(D SDL_ShowFileDialogWithProperties)
78 */
79 struct SDL_DialogFileFilter {
80     const(char)** name;
81     const(char)** pattern;
82 }
83 
84 /**
85     Callback used by file dialog functions.
86 
87     The specific usage is described in each function.
88 
89     If `filelist` is:
90 
91     - NULL, an error occurred. Details can be obtained with SDL_GetError().
92     - A pointer to NULL, the user either didn't choose any file or canceled the
93     dialog.
94     - A pointer to non-`NULL`, the user chose one or more files. The argument
95     is a null-terminated list of pointers to C strings, each containing a
96     path.
97 
98     The filelist argument should not be freed; it will automatically be freed
99     when the callback returns.
100 
101     The filter argument is the index of the filter that was selected, or -1 if
102     no filter was selected or if the platform or method doesn't support
103     fetching the selected filter.
104 
105     In Android, the `filelist` are `content://` URIs. They should be opened
106     using SDL_IOFromFile() with appropriate modes. This applies both to open
107     and save file dialog.
108 
109     Params:
110         userdata =  an app-provided pointer, for the callback's use.
111         filelist =  the file(s) chosen by the user.
112         filter =    index of the selected filter.
113 
114     See_Also:
115         $(D SDL_DialogFileFilter)
116         $(D SDL_ShowOpenFileDialog)
117         $(D SDL_ShowSaveFileDialog)
118         $(D SDL_ShowOpenFolderDialog)
119         $(D SDL_ShowFileDialogWithProperties)
120 */
121 alias SDL_DialogFileCallback = void function(void* userdata, const(const(char)*)* filelist, int filter);
122 
123 /**
124     Displays a dialog that lets the user select a file on their filesystem.
125 
126     This is an asynchronous function; it will return immediately, and the
127     result will be passed to the callback.
128 
129     The callback will be invoked with a null-terminated list of files the user
130     chose. The list will be empty if the user canceled the dialog, and it will
131     be NULL if an error occurred.
132 
133     Note that the callback may be called from a different thread than the one
134     the function was invoked on.
135 
136     Depending on the platform, the user may be allowed to input paths that
137     don't yet exist.
138 
139     On Linux, dialogs may require XDG Portals, which requires DBus, which
140     requires an event-handling loop. Apps that do not use SDL to handle events
141     should add a call to SDL_PumpEvents in their main loop.
142 
143     Params:
144         callback =          a function pointer to be invoked when the user selects a
145                             file and accepts, or cancels the dialog, or an error
146                             occurs.
147         userdata =          an optional pointer to pass extra data to the callback when
148                             it will be invoked.
149         window =            the window that the dialog should be modal for, may be NULL.
150                             Not all platforms support this option.
151         filters =           a list of filters, may be NULL. Not all platforms support
152                             this option, and platforms that do support it may allow the
153                             user to ignore the filters. If non-NULL, it must remain
154                             valid at least until the callback is invoked.
155         nfilters =          the number of filters. Ignored if filters is NULL.
156         default_location =  the default folder or file to start the dialog at,
157                             may be NULL. Not all platforms support this option.
158         allow_many =        if non-zero, the user will be allowed to select multiple
159                             entries. Not all platforms support this option.
160 
161     Threadsafety:
162         This function should be called only from the main thread. The
163         callback may be invoked from the same thread or from a
164         different one, depending on the OS's constraints.
165 
166     See_Also:
167         $(D SDL_DialogFileCallback)
168         $(D SDL_DialogFileFilter)
169         $(D SDL_ShowSaveFileDialog)
170         $(D SDL_ShowOpenFolderDialog)
171         $(D SDL_ShowFileDialogWithProperties)
172 */
173 extern void SDL_ShowOpenFileDialog(SDL_DialogFileCallback callback, void* userdata, SDL_Window* window, const(
174         SDL_DialogFileFilter)** filters, int nfilters, const(char)** default_location, bool allow_many);
175 
176 /**
177     Displays a dialog that lets the user choose a new or existing file on their
178     filesystem.
179 
180     This is an asynchronous function; it will return immediately, and the
181     result will be passed to the callback.
182 
183     The callback will be invoked with a null-terminated list of files the user
184     chose. The list will be empty if the user canceled the dialog, and it will
185     be NULL if an error occurred.
186 
187     Note that the callback may be called from a different thread than the one
188     the function was invoked on.
189 
190     The chosen file may or may not already exist.
191 
192     On Linux, dialogs may require XDG Portals, which requires DBus, which
193     requires an event-handling loop. Apps that do not use SDL to handle events
194     should add a call to SDL_PumpEvents in their main loop.
195 
196     Params:
197         callback =          a function pointer to be invoked when the user selects a
198                             file and accepts, or cancels the dialog, or an error
199                             occurs.
200         userdata =          an optional pointer to pass extra data to the callback when
201                             it will be invoked.
202         window =            the window that the dialog should be modal for, may be NULL.
203                             Not all platforms support this option.
204         filters =           a list of filters, may be NULL. Not all platforms support
205                             this option, and platforms that do support it may allow the
206                             user to ignore the filters. If non-NULL, it must remain
207                             valid at least until the callback is invoked.
208         nfilters =          the number of filters. Ignored if filters is NULL.
209         default_location =  the default folder or file to start the dialog at,
210                             may be NULL. Not all platforms support this option.
211 
212     Threadsafety:
213         This function should be called only from the main thread. The
214         callback may be invoked from the same thread or from a
215         different one, depending on the OS's constraints.
216 
217     See_Also:
218         $(D SDL_DialogFileCallback)
219         $(D SDL_DialogFileFilter)
220         $(D SDL_ShowOpenFileDialog)
221         $(D SDL_ShowOpenFolderDialog)
222         $(D SDL_ShowFileDialogWithProperties)
223 */
224 extern void SDL_ShowSaveFileDialog(SDL_DialogFileCallback callback, void* userdata, SDL_Window* window, const(
225         SDL_DialogFileFilter)** filters, int nfilters, const(char)** default_location);
226 
227 /**
228     Displays a dialog that lets the user select a folder on their filesystem.
229 
230     This is an asynchronous function; it will return immediately, and the
231     result will be passed to the callback.
232 
233     The callback will be invoked with a null-terminated list of files the user
234     chose. The list will be empty if the user canceled the dialog, and it will
235     be NULL if an error occurred.
236 
237     Note that the callback may be called from a different thread than the one
238     the function was invoked on.
239 
240     Depending on the platform, the user may be allowed to input paths that
241     don't yet exist.
242 
243     On Linux, dialogs may require XDG Portals, which requires DBus, which
244     requires an event-handling loop. Apps that do not use SDL to handle events
245     should add a call to SDL_PumpEvents in their main loop.
246 
247     Params:
248         callback =          a function pointer to be invoked when the user selects a
249                             file and accepts, or cancels the dialog, or an error
250                             occurs.
251         userdata =          an optional pointer to pass extra data to the callback when
252                             it will be invoked.
253         window =            the window that the dialog should be modal for, may be NULL.
254                             Not all platforms support this option.
255         default_location =  the default folder or file to start the dialog at,
256                             may be NULL. Not all platforms support this option.
257         allow_many =        if non-zero, the user will be allowed to select multiple
258                             entries. Not all platforms support this option.
259 
260     Threadsafety:
261         This function should be called only from the main thread. The
262         callback may be invoked from the same thread or from a
263         different one, depending on the OS's constraints.
264     
265     See_Also:
266         $(D SDL_DialogFileCallback)
267         $(D SDL_ShowOpenFileDialog)
268         $(D SDL_ShowSaveFileDialog)
269         $(D SDL_ShowFileDialogWithProperties)
270 */
271 extern void SDL_ShowOpenFolderDialog(SDL_DialogFileCallback callback, void* userdata, SDL_Window* window, const(
272         char)** default_location, bool allow_many);
273 
274 /**
275     Various types of file dialogs.
276 
277     This is used by SDL_ShowFileDialogWithProperties() to decide what kind of
278     dialog to present to the user.
279 
280     See_Also:
281         $(D SDL_ShowFileDialogWithProperties)
282 */
283 enum SDL_FileDialogType {
284     SDL_FILEDIALOG_OPENFILE,
285     SDL_FILEDIALOG_SAVEFILE,
286     SDL_FILEDIALOG_OPENFOLDER
287 }
288 
289 /**
290     Create and launch a file dialog with the specified properties.
291 
292     These are the supported properties:
293 
294     -   `SDL_PROP_FILE_DIALOG_FILTERS_POINTER`: a pointer to a list of
295         SDL_DialogFileFilter structs, which will be used as filters for
296         file-based selections. Ignored if the dialog is an "Open Folder" dialog.
297         If non-NULL, the array of filters must remain valid at least until the
298         callback is invoked.
299     -   `SDL_PROP_FILE_DIALOG_NFILTERS_NUMBER`: the number of filters in the
300         array of filters, if it exists.
301     -   `SDL_PROP_FILE_DIALOG_WINDOW_POINTER`: the window that the dialog should
302         be modal for.
303     -   `SDL_PROP_FILE_DIALOG_LOCATION_STRING`: the default folder or file to
304         start the dialog at.
305     -   `SDL_PROP_FILE_DIALOG_MANY_BOOLEAN`: true to allow the user to select
306         more than one entry.
307     -   `SDL_PROP_FILE_DIALOG_TITLE_STRING`: the title for the dialog.
308     -   `SDL_PROP_FILE_DIALOG_ACCEPT_STRING`: the label that the accept button
309         should have.
310     -   `SDL_PROP_FILE_DIALOG_CANCEL_STRING`: the label that the cancel button
311         should have.
312 
313     Note that each platform may or may not support any of the properties.
314 
315     Params:
316         type =      the type of file dialog.
317         callback =  a function pointer to be invoked when the user selects a
318                     file and accepts, or cancels the dialog, or an error
319                     occurs.
320         userdata =  an optional pointer to pass extra data to the callback when
321                     it will be invoked.
322         props =     the properties to use.
323 
324     Threadsafety:
325         This function should be called only from the main thread. The
326         callback may be invoked from the same thread or from a
327         different one, depending on the OS's constraints.
328 
329     See_Also:
330         $(D SDL_FileDialogType)
331         $(D SDL_DialogFileCallback)
332         $(D SDL_DialogFileFilter)
333         $(D SDL_ShowOpenFileDialog)
334         $(D SDL_ShowSaveFileDialog)
335         $(D SDL_ShowOpenFolderDialog)
336 */
337 extern void SDL_ShowFileDialogWithProperties(SDL_FileDialogType type, SDL_DialogFileCallback callback, void* userdata, SDL_PropertiesID props);
338 
339 enum SDL_PROP_FILE_DIALOG_FILTERS_POINTER = "SDL.filedialog.filters";
340 enum SDL_PROP_FILE_DIALOG_NFILTERS_NUMBER = "SDL.filedialog.nfilters";
341 enum SDL_PROP_FILE_DIALOG_WINDOW_POINTER = "SDL.filedialog.window";
342 enum SDL_PROP_FILE_DIALOG_LOCATION_STRING = "SDL.filedialog.location";
343 enum SDL_PROP_FILE_DIALOG_MANY_BOOLEAN = "SDL.filedialog.many";
344 enum SDL_PROP_FILE_DIALOG_TITLE_STRING = "SDL.filedialog.title";
345 enum SDL_PROP_FILE_DIALOG_ACCEPT_STRING = "SDL.filedialog.accept";
346 enum SDL_PROP_FILE_DIALOG_CANCEL_STRING = "SDL.filedialog.cancel";