Browse Source

Merge branch 'master' into fixes/TextLineCaretNavigation

Benedikt Stebner 5 years ago
parent
commit
cbca337772

+ 1 - 1
src/Avalonia.Themes.Default/TitleBar.xaml

@@ -15,7 +15,7 @@
           <Panel x:Name="PART_MouseTracker" Height="1" VerticalAlignment="Top" />
           <Panel x:Name="PART_Container">
             <Border x:Name="PART_Background" Background="{TemplateBinding Background}" />
-            <CaptionButtons x:Name="PART_CaptionButtons" VerticalAlignment="Top" HorizontalAlignment="Right" Foreground="{TemplateBinding Foreground}" MaxHeight="30" />
+            <CaptionButtons x:Name="PART_CaptionButtons" VerticalAlignment="Top" HorizontalAlignment="Right" Foreground="{TemplateBinding Foreground}" />
           </Panel>
         </Panel>
       </ControlTemplate>

+ 1 - 1
src/Avalonia.Themes.Fluent/TitleBar.xaml

@@ -15,7 +15,7 @@
           <Panel x:Name="PART_MouseTracker" Height="1" VerticalAlignment="Top" />
           <Panel x:Name="PART_Container">
             <Border x:Name="PART_Background" Background="{TemplateBinding Background}" />
-            <CaptionButtons x:Name="PART_CaptionButtons" VerticalAlignment="Top" HorizontalAlignment="Right" Foreground="{TemplateBinding Foreground}" MaxHeight="30" />
+            <CaptionButtons x:Name="PART_CaptionButtons" VerticalAlignment="Top" HorizontalAlignment="Right" Foreground="{TemplateBinding Foreground}" />
           </Panel>
         </Panel>
       </ControlTemplate>

+ 3 - 0
src/Avalonia.X11/NativeDialogs/Gtk.cs

@@ -204,6 +204,9 @@ namespace Avalonia.X11.NativeDialogs
         
         [DllImport(GtkName)]
         public static extern IntPtr gtk_file_chooser_add_filter(IntPtr chooser, IntPtr filter);
+
+        [DllImport(GtkName)]
+        public static extern IntPtr gtk_file_chooser_get_filter(IntPtr chooser);
         
         [DllImport(GtkName)]
         public static extern void gtk_widget_realize(IntPtr gtkWidget);

+ 40 - 5
src/Avalonia.X11/NativeDialogs/GtkNativeFileDialogs.cs

@@ -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,7 +112,30 @@ 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, Window parent)
         {
             await EnsureInitialized();
@@ -113,7 +147,8 @@ namespace Avalonia.X11.NativeDialogs
                     dialog is OpenFileDialog ? GtkFileChooserAction.Open : GtkFileChooserAction.Save,
                     (dialog as OpenFileDialog)?.AllowMultiple ?? false,
                     Path.Combine(string.IsNullOrEmpty(dialog.Directory) ? "" : dialog.Directory,
-                        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, Window parent)
@@ -125,7 +160,7 @@ namespace Avalonia.X11.NativeDialogs
             return await await RunOnGlibThread(async () =>
             {
                 var res = await ShowDialog(dialog.Title, platformImpl,
-                    GtkFileChooserAction.SelectFolder, false, dialog.Directory, null);
+                    GtkFileChooserAction.SelectFolder, false, dialog.Directory, null, null);
                 return res?.FirstOrDefault();
             });
         }