|
|
|
@ -16,7 +16,7 @@ namespace Avalonia.X11.NativeDialogs |
|
|
|
{ |
|
|
|
private Task<bool> _initialized; |
|
|
|
private unsafe Task<string[]> ShowDialog(string title, IWindowImpl parent, GtkFileChooserAction action, |
|
|
|
bool multiSelect, string initialFileName, IEnumerable<FileDialogFilter> filters) |
|
|
|
bool multiSelect, string initialFileName, IEnumerable<FileDialogFilter> filters, string defaultExtension) |
|
|
|
{ |
|
|
|
IntPtr dlg; |
|
|
|
using (var name = new Utf8Buffer(title)) |
|
|
|
@ -35,11 +35,13 @@ namespace Avalonia.X11.NativeDialogs |
|
|
|
foreach (var d in disposables) d.Dispose(); |
|
|
|
disposables.Clear(); |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
var filtersDic = new Dictionary<IntPtr, FileDialogFilter>(); |
|
|
|
if(filters != null) |
|
|
|
foreach (var f in filters) |
|
|
|
{ |
|
|
|
var filter = gtk_file_filter_new(); |
|
|
|
filtersDic[filter] = f; |
|
|
|
using (var b = new Utf8Buffer(f.Name)) |
|
|
|
gtk_file_filter_set_name(filter, b); |
|
|
|
|
|
|
|
@ -74,6 +76,15 @@ namespace Avalonia.X11.NativeDialogs |
|
|
|
} |
|
|
|
g_slist_free(gs); |
|
|
|
result = resultList.ToArray(); |
|
|
|
|
|
|
|
// GTK doesn't auto-append the extension, so we need to do that manually
|
|
|
|
if (action == GtkFileChooserAction.Save) |
|
|
|
{ |
|
|
|
var currentFilter = gtk_file_chooser_get_filter(dlg); |
|
|
|
filtersDic.TryGetValue(currentFilter, out var selectedFilter); |
|
|
|
for (var c = 0; c < result.Length; c++) |
|
|
|
result[c] = NameWithExtension(result[c], defaultExtension, selectedFilter); |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
gtk_widget_hide(dlg); |
|
|
|
@ -101,6 +112,29 @@ namespace Avalonia.X11.NativeDialogs |
|
|
|
gtk_window_present(dlg); |
|
|
|
return tcs.Task; |
|
|
|
} |
|
|
|
|
|
|
|
string NameWithExtension(string path, string defaultExtension, FileDialogFilter filter) |
|
|
|
{ |
|
|
|
var name = Path.GetFileName(path); |
|
|
|
if (name != null && !name.Contains(".")) |
|
|
|
{ |
|
|
|
if (filter?.Extensions?.Count > 0) |
|
|
|
{ |
|
|
|
if (defaultExtension != null |
|
|
|
&& filter.Extensions.Contains(defaultExtension)) |
|
|
|
return path + "." + defaultExtension.TrimStart('.'); |
|
|
|
|
|
|
|
var ext = filter.Extensions.FirstOrDefault(x => x != "*"); |
|
|
|
if (ext != null) |
|
|
|
return path + "." + ext.TrimStart('.'); |
|
|
|
} |
|
|
|
|
|
|
|
if (defaultExtension != null) |
|
|
|
path += "." + defaultExtension.TrimStart('.'); |
|
|
|
} |
|
|
|
|
|
|
|
return path; |
|
|
|
} |
|
|
|
|
|
|
|
public async Task<string[]> ShowFileDialogAsync(FileDialog dialog, IWindowImpl parent) |
|
|
|
{ |
|
|
|
@ -110,7 +144,8 @@ namespace Avalonia.X11.NativeDialogs |
|
|
|
dialog is OpenFileDialog ? GtkFileChooserAction.Open : GtkFileChooserAction.Save, |
|
|
|
(dialog as OpenFileDialog)?.AllowMultiple ?? false, |
|
|
|
Path.Combine(string.IsNullOrEmpty(dialog.InitialDirectory) ? "" : dialog.InitialDirectory, |
|
|
|
string.IsNullOrEmpty(dialog.InitialFileName) ? "" : dialog.InitialFileName), dialog.Filters)); |
|
|
|
string.IsNullOrEmpty(dialog.InitialFileName) ? "" : dialog.InitialFileName), dialog.Filters, |
|
|
|
(dialog as SaveFileDialog)?.DefaultExtension)); |
|
|
|
} |
|
|
|
|
|
|
|
public async Task<string> ShowFolderDialogAsync(OpenFolderDialog dialog, IWindowImpl parent) |
|
|
|
@ -119,7 +154,7 @@ namespace Avalonia.X11.NativeDialogs |
|
|
|
return await await RunOnGlibThread(async () => |
|
|
|
{ |
|
|
|
var res = await ShowDialog(dialog.Title, parent, |
|
|
|
GtkFileChooserAction.SelectFolder, false, dialog.InitialDirectory, null); |
|
|
|
GtkFileChooserAction.SelectFolder, false, dialog.InitialDirectory, null, null); |
|
|
|
return res?.FirstOrDefault(); |
|
|
|
}); |
|
|
|
} |
|
|
|
|