Skip to content

Commit

Permalink
Merge pull request #2738 from cwensley/curtis/mac-opensavefiledialog-…
Browse files Browse the repository at this point in the history
…fixes

Mac: Open/SaveFileDialog fixes
  • Loading branch information
cwensley authored Feb 5, 2025
2 parents 5b3fb1e + bef3d44 commit 1b425ff
Show file tree
Hide file tree
Showing 5 changed files with 75 additions and 96 deletions.
115 changes: 44 additions & 71 deletions src/Eto.Mac/Forms/MacFileDialog.cs
Original file line number Diff line number Diff line change
Expand Up @@ -33,56 +33,38 @@ public abstract class MacFileDialog<TControl, TWidget> : WidgetHandler<TControl,
where TWidget: FileDialog
{
List<string> macfilters;
readonly NSPopUpButton fileTypes;
readonly DropDown fileTypes;

protected MacFileDialog()
{
fileTypes = new NSPopUpButton();
fileTypes = new DropDown();
fileTypes.SelectedIndexChanged += (sender, e) => OnFileTypeChanged();
}

void Create()
{
if (Control.AccessoryView != null)
return;

var fileTypeView = new NSView();
fileTypeView.AutoresizingMask = NSViewResizingMask.HeightSizable | NSViewResizingMask.WidthSizable;

const int padding = 15;

if (Widget.Filters.Count > 0)
{
var label = new NSTextField();
label.StringValue = "Format";
label.DrawsBackground = false;
label.Bordered = false;
label.Bezeled = false;
label.Editable = false;
label.Selectable = false;
label.SizeToFit();
fileTypeView.AddSubview(label);

fileTypes.SizeToFit();
fileTypes.Activated += (sender, e) =>
{
SetCurrentItem();
Control.ValidateVisibleColumns();
Control.Update();
};
fileTypeView.AddSubview(fileTypes);
fileTypes.SetFrameOrigin(new CGPoint((nfloat)label.Frame.Width + 10, padding));

label.SetFrameOrigin(new CGPoint(0, (nfloat)(padding + (fileTypes.Frame.Height - label.Frame.Height) / 2)));

fileTypeView.Frame = new CGRect(0, 0, (nfloat)(fileTypes.Frame.Width + label.Frame.Width + 10), (nfloat)(fileTypes.Frame.Height + padding * 2));

Control.AccessoryView = fileTypeView;
SetCurrentItem();
if (Control.AccessoryView != null)
return;

var layout = new TableLayout { Padding = 15, Spacing = new Size(2, 2) };
layout.Rows.Add(new TableRow(null, fileTypes, null));

Control.AccessoryView = layout.ToNative(true);
SetAllowedFileTypes();
}
else
Control.AccessoryView = null;
}

protected virtual void OnFileTypeChanged()
{
SetAllowedFileTypes();
Control.ValidateVisibleColumns();
Control.Update();
}

string fileName;

public virtual string FileName
Expand All @@ -93,7 +75,7 @@ public virtual string FileName

public Uri Directory
{
get => new Uri(Control.DirectoryUrl.AbsoluteString);
get => (Uri)Control.DirectoryUrl;
set => Control.DirectoryUrl = new NSUrl(value.AbsoluteUri);
}

Expand All @@ -111,44 +93,38 @@ public string GetDefaultExtension()
return null;
}

public List<string> MacFilters
{
get { return macfilters; }
}
public List<string> MacFilters => macfilters;

public void SetCurrentItem()
internal void SetAllowedFileTypes()
{
macfilters = Widget.CurrentFilter.Extensions?.Select(r => r.TrimStart('*', '.')).ToList();

if (macfilters == null || macfilters.Count == 0 || macfilters.Contains(""))
var filters = Widget.CurrentFilter?.Extensions?.Select(r => r.TrimStart('*', '.')).ToList();
if (filters != null && (filters.Count == 0 || filters.Contains("")))
{
macfilters = null;
// MacOS throws exception when setting to null (ugh)
Messaging.void_objc_msgSend_IntPtr(Control.Handle, Selector.GetHandle("setAllowedFileTypes:"), IntPtr.Zero);
filters = null;
}
else
Control.AllowedFileTypes = macfilters.Distinct().ToArray();

if (macfilters == filters)
return;
macfilters = filters;

#if MACOS_NET
Control.AllowedContentTypes = macfilters.Distinct().Select(UniformTypeIdentifiers.UTType.CreateFromExtension).ToArray()
?? Array.Empty<UniformTypeIdentifiers.UTType>();
#else

Control.AllowedFileTypes = macfilters?.Distinct().ToArray();
#endif
}

public int CurrentFilterIndex
{
get
{
var title = fileTypes.TitleOfSelectedItem;
var item = Widget.Filters.FirstOrDefault(r => r.Name == title);
if (item == null)
return -1;
return Widget.Filters.IndexOf(item);
}
set
{
fileTypes.SelectItem(Widget.Filters[value].Name);
}
get => fileTypes.SelectedIndex;
set => fileTypes.SelectedIndex = value;
}

public bool CheckFileExists
{
get { return false; }
get { return true; }
set { }
}

Expand All @@ -172,24 +148,21 @@ public virtual DialogResult ShowDialog(Window parent)
return ret == 1 ? DialogResult.Ok : DialogResult.Cancel;
}

protected override void Dispose(bool disposing)
{
//base.Dispose (disposing);
}

public void InsertFilter(int index, FileFilter filter)
{
fileTypes.InsertItem(filter.Name, index);
fileTypes.Items.Insert(index, new ListItem { Text = filter.Name } );
if (fileTypes.SelectedIndex == -1)
fileTypes.SelectedIndex = index;
}

public void RemoveFilter(int index)
{
fileTypes.RemoveItem(index);
fileTypes.Items.RemoveAt(index);
}

public void ClearFilters()
{
fileTypes.RemoveAllItems();
fileTypes.Items.Clear();
}
}
}
2 changes: 0 additions & 2 deletions src/Eto.Mac/Forms/OpenFileDialogHandler.cs
Original file line number Diff line number Diff line change
Expand Up @@ -8,8 +8,6 @@ protected override NSOpenPanel CreateControl()
return NSOpenPanel.OpenPanel;
}

protected override bool DisposeControl { get { return false; } }

public bool MultiSelect
{
get { return Control.AllowsMultipleSelection; }
Expand Down
11 changes: 7 additions & 4 deletions src/Eto.Mac/Forms/OpenWithDialogHandler.cs
Original file line number Diff line number Diff line change
Expand Up @@ -6,11 +6,14 @@ public class OpenWithDialogHandler : WidgetHandler<NSOpenPanel, OpenWithDialog,

public DialogResult ShowDialog(Window parent)
{
Control = new NSOpenPanel();
Control.ReleasedWhenClosed = true;
Control.DirectoryUrl = new NSUrl("/Applications");
Control.Prompt = "Choose Application";
Control = NSOpenPanel.OpenPanel;
Control.DirectoryUrl = NSUrl.FromFilename("/Applications");
Control.Prompt = Application.Instance.Localize(Widget, "Choose Application");
#if MACOS_NET
Control.AllowedContentTypes = new [] { UniformTypeIdentifiers.UTTypes.Application };
#else
Control.AllowedFileTypes = new[] { "app" };
#endif

if (Control.RunModal() == 1)
Process.Start("open", "-a \"" + Control.Url.Path + "\" \"" + FilePath + "\"");
Expand Down
16 changes: 14 additions & 2 deletions src/Eto.Mac/Forms/SaveFileDialogHandler.cs
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@ public override string FileName
var name = value;
if (!string.IsNullOrEmpty(name))
{
SetAllowedFileTypes();
var dir = Path.GetDirectoryName(name);
if (!string.IsNullOrEmpty(dir) && System.IO.Directory.Exists(dir))
Directory = new Uri(dir);
Expand All @@ -25,15 +26,14 @@ public override string FileName
}
}

protected override bool DisposeControl { get { return false; } }

protected override NSSavePanel CreateControl()
{
return NSSavePanel.SavePanel;
}

protected override void Initialize()
{
Control.ExtensionHidden = false;
Control.AllowsOtherFileTypes = true;
Control.CanSelectHiddenExtension = true;
base.Initialize();
Expand All @@ -50,5 +50,17 @@ public override DialogResult ShowDialog(Window parent)

return result;
}

protected override void OnFileTypeChanged()
{
base.OnFileTypeChanged();
var extension = Widget.CurrentFilter?.Extensions?.FirstOrDefault()?.TrimStart('*', '.');
if (!string.IsNullOrEmpty(extension))
{
var fileName = Control.NameFieldStringValue;
if (fileName != null)
Control.NameFieldStringValue = $"{Path.GetFileNameWithoutExtension(fileName)}.{extension}";
}
}
}
}
27 changes: 10 additions & 17 deletions test/Eto.Test/Sections/Dialogs/FileDialogSection.cs
Original file line number Diff line number Diff line change
Expand Up @@ -104,12 +104,12 @@ Control OpenFileWithFilters()
{
Filters =
{
new FileFilter("All Formats", "png", "jpg", "jpeg", "gif", "tiff"),
new FileFilter("All Formats", ".png", ".jpg", ".jpeg", ".gif", ".tiff"),
new FileFilter("All Files", "*"),
"PNG Files|png",
new FileFilter("JPeg Files", "jpg", "jpeg"),
new FileFilter("GIF Files", "gif"),
new FileFilter("TIFF Files", "tiff"),
"PNG Files|.png",
new FileFilter("JPeg Files", ".jpg", ".jpeg"),
new FileFilter("GIF Files", ".gif"),
new FileFilter("TIFF Files", ".tiff"),
}
};
SetAttributes(dialog);
Expand All @@ -135,17 +135,14 @@ Control SaveFileWithFilters()
new FileFilter("JPeg Files", ".jpg", ".jpeg"),
new FileFilter("GIF Files", ".gif"),
new FileFilter("TIFF Files", ".tiff"),
new FileFilter("CS Files", ".cs"),
}
};
SetAttributes(dialog);

var result = dialog.ShowDialog(ParentWindow);
if (result == DialogResult.Ok)
{
Log.Write(dialog, "Result: {0}, CurrentFilter: {1}, FileName: {2}", result, dialog.CurrentFilter, dialog.FileName);
}
else
Log.Write(dialog, "Result: {0}", result);
Log.Write(dialog, "Result: {0}, CurrentFilter: {1}, FileName: {2}", result, dialog.CurrentFilter, dialog.FileName);
dialog.Dispose();
};
return button;
}
Expand All @@ -158,12 +155,8 @@ Control SaveFile()
var dialog = new SaveFileDialog();
SetAttributes(dialog);
var result = dialog.ShowDialog(ParentWindow);
if (result == DialogResult.Ok)
{
Log.Write(dialog, "Result: {0}, FileName: {1}", result, dialog.FileName);
}
else
Log.Write(dialog, "Result: {0}", result);
Log.Write(dialog, "Result: {0}, FileName: {1}", result, dialog.FileName);
dialog.Dispose();
};
return button;
}
Expand Down

0 comments on commit 1b425ff

Please sign in to comment.